stm32_usart3_spi.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /*
  2. * Copyright (C) 2010 by Nikolaj Zamotaev. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. *
  32. */
  33. /*
  34. * $Id: stm32_usart3_spi.c 5169 2013-05-20 20:14:10Z u_bonnes $
  35. */
  36. #include <arch/cm3.h>
  37. #include <sys/timer.h>
  38. #include <cfg/spi.h>
  39. #include <cfg/arch/gpio.h>
  40. #include <dev/spibus.h>
  41. #include <dev/gpio.h>
  42. #include <arch/cm3/stm/stm32f10x_rcc.h>
  43. #include <arch/cm3/stm/stm32f10x_usart.h>
  44. #include <dev/irqreg.h>
  45. #include <sys/event.h>
  46. #include <sys/nutdebug.h>
  47. #include <stdlib.h>
  48. #include <errno.h>
  49. static int Stm32SpiBusWait(NUTSPINODE * node, uint32_t tmo);
  50. //static HANDLE spi0_que;
  51. static HANDLE usart3_que;
  52. static uint8_t * volatile usart3_txp;
  53. static uint8_t * volatile usart3_rxp;
  54. static volatile size_t usart3_xc;
  55. int Stm32UsartBusWait(NUTSPINODE * node, uint32_t tmo);
  56. int Stm32UsartSpiSetup(NUTSPINODE * node);
  57. IRQ_HANDLER sig_USART3 = {
  58. #ifdef NUT_PERFMON
  59. 0, /* Interrupt counter, ir_count. */
  60. #endif
  61. NULL, /* Passed argument, ir_arg. */
  62. NULL, /* Handler subroutine, ir_handler. */
  63. NULL//SerialPeripheral2IrqCtl /* Interrupt control, ir_ctl. */
  64. };
  65. /*!
  66. * \brief Set the specified chip select to a given level.
  67. */
  68. int Stm32Usart3ChipSelect(uint_fast8_t cs, uint_fast8_t hi)
  69. {
  70. int rc = 0;
  71. switch (cs) {
  72. case 0:
  73. if (hi) {
  74. GpioPinSetHigh(NUTGPIO_PORTD,13);
  75. } else {
  76. GpioPinSetLow(NUTGPIO_PORTD,13);
  77. }
  78. break;
  79. default:
  80. errno = EIO;
  81. rc = -1;
  82. break;
  83. }
  84. return rc;
  85. }
  86. /*! \brief Deselect a device on the first SPI bus.
  87. *
  88. * Deactivates the chip select and unlocks the bus.
  89. *
  90. * \param node Specifies the SPI bus node.
  91. *
  92. * \return Always 0.
  93. */
  94. int Stm32Usart3BusDeselect(NUTSPINODE * node)
  95. {
  96. /* Sanity check. */
  97. NUTASSERT(node != NULL);
  98. NUTASSERT(node->node_bus != NULL);
  99. Stm32UsartBusWait(node, NUT_WAIT_INFINITE);
  100. /* Deactivate the node's chip select. */
  101. Stm32Usart3ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);
  102. /* Release the bus. */
  103. NutEventPost(&node->node_bus->bus_mutex);
  104. return 0;
  105. }
  106. /*! \brief Select a device on the first SPI bus.
  107. *
  108. * Locks and activates the bus for the specified node.
  109. *
  110. * \param node Specifies the SPI bus node.
  111. * \param tmo Timeout in milliseconds. To disable timeout, set this
  112. * parameter to NUT_WAIT_INFINITE.
  113. *
  114. * \return 0 on success. In case of an error, -1 is returned and the bus
  115. * is not locked.
  116. */
  117. int Stm32Usart3BusSelect(NUTSPINODE * node, uint32_t tmo)
  118. {
  119. int rc;
  120. USART_TypeDef* base;
  121. /* Sanity check. */
  122. NUTASSERT(node != NULL);
  123. NUTASSERT(node->node_bus != NULL);
  124. NUTASSERT(node->node_stat != NULL);
  125. /* Allocate the bus. */
  126. rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
  127. if (rc) {
  128. errno = EIO;
  129. } else {
  130. USART_TypeDef *spireg = node->node_stat;
  131. RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
  132. RCC->APB2ENR |= RCC_APB2ENR_GPIODEN | //USART RX,TX,CK
  133. RCC_APB2ENR_AFIOEN;
  134. //õ ÎÁÓ USART3 ×ÉÓÉÔ ÎÁ PD8,9,10
  135. AFIO->MAPR |= GPIO_FullRemap_USART3;
  136. //óÔÁ×ÉÍ ÎÁ ÁÌØÔÅÒÎÁÔÉ×ÎÕÀ ÆÕÎËÃÉÀ - ËÁË ÒÁÚ ÎÁ usart1
  137. //tx
  138. GpioPinConfigSet( NUTGPIO_PORTD, 8,
  139. GPIO_CFG_DISABLED|GPIO_CFG_OUTPUT);
  140. //rx
  141. GpioPinConfigSet( NUTGPIO_PORTD, 9,
  142. 0);
  143. //ck
  144. GpioPinConfigSet( NUTGPIO_PORTD, 10,
  145. GPIO_CFG_DISABLED|GPIO_CFG_OUTPUT);
  146. //îÁ ×ÙÈÏÄ - ÄÌÑ Chipselect-Á
  147. GpioPinConfigSet(NUTGPIO_PORTD, 13,
  148. GPIO_CFG_OUTPUT);//FIXME: check correct pin
  149. /* If the mode update bit is set, then update our shadow registers. */
  150. if (node->node_mode & SPI_MODE_UPDATE) {
  151. Stm32UsartSpiSetup(node);
  152. }
  153. /* Enable SPI. */
  154. base=node->node_bus->bus_base;
  155. //spireg->CR1|=(1<<6);//SPE -spi enable
  156. /* Set SPI mode. */
  157. base->CR2=spireg->CR2;
  158. base->BRR=spireg->BRR;
  159. base->CR1=spireg->CR1;
  160. /* Finally activate the node's chip select. */
  161. rc = Stm32Usart3ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) != 0);
  162. if (rc) {
  163. /* Release the bus in case of an error. */
  164. NutEventPost(&node->node_bus->bus_mutex);
  165. }
  166. }
  167. return rc;
  168. }
  169. /*!
  170. * \brief Update SPI shadow registers.
  171. *
  172. * \param node Specifies the SPI bus node.
  173. *
  174. * \return Always 0.
  175. */
  176. int Stm32UsartSpiSetup(NUTSPINODE * node)
  177. {
  178. uint32_t clk;
  179. uint8_t i;
  180. uint32_t clkdiv;
  181. USART_TypeDef *spireg;
  182. NUTASSERT(node != NULL);
  183. NUTASSERT(node->node_stat != NULL);
  184. NUTASSERT(node->node_bus != NULL);
  185. NUTASSERT(node->node_bus->bus_base != 0);
  186. spireg = node->node_stat;
  187. spireg->CR1 =USART_Mode_Rx|USART_Mode_Tx|(1<<13);//fixme: write real values
  188. spireg->CR2 = USART_Clock_Enable|USART_LastBit_Enable;
  189. spireg->BRR =16;
  190. switch(node->node_bits){
  191. case 8:
  192. spireg->CR1 &= ~(USART_WordLength_9b);
  193. spireg->CR1 &= ~(1<<10);
  194. break;
  195. case 9:
  196. spireg->CR1 |= USART_WordLength_9b;
  197. spireg->CR1 &= ~(1<<10);
  198. break;
  199. default:
  200. break;
  201. };
  202. if (node->node_mode & SPI_MODE_CPOL) {
  203. spireg->CR2 |= USART_CPOL_High;
  204. }
  205. if ((node->node_mode & SPI_MODE_CPHA) == 0) {
  206. spireg->CR2 |= USART_CPHA_2Edge;
  207. }
  208. /* Query peripheral clock. */
  209. clk = NutClockGet(NUT_HWCLK_PCLK1);
  210. /* Calculate the SPI clock divider. Avoid rounding errors. */
  211. clkdiv = clk/(node->node_rate);
  212. if (clkdiv < 16) {
  213. clkdiv=16;
  214. }
  215. spireg->BRR = clkdiv;
  216. /* Update interface parameters. */
  217. node->node_rate = clk / (clkdiv);
  218. node->node_mode &= ~SPI_MODE_UPDATE;
  219. return 0;
  220. }
  221. /*!
  222. * \brief Initialize an SPI bus node.
  223. *
  224. * This routine is called for each SPI node, which is registered via
  225. * NutRegisterSpiDevice().
  226. *
  227. * \param node Specifies the SPI bus node.
  228. *
  229. * \return 0 on success or -1 if there is no valid chip select.
  230. */
  231. int Stm32UsartBusNodeInit(NUTSPINODE * node)
  232. {
  233. int rc;
  234. NUTSPIBUS *bus;
  235. /* Sanity check. */
  236. NUTASSERT(node != NULL);
  237. NUTASSERT(node->node_bus != NULL);
  238. bus = node->node_bus;
  239. rc = Stm32Usart3ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);
  240. /* It should not hurt us being called more than once. Thus, we
  241. ** check wether any initialization had been taken place already. */
  242. if (rc == 0 && node->node_stat == NULL) {
  243. /* Allocate and set our shadow registers. */
  244. USART_TypeDef *spireg = malloc(sizeof(USART_TypeDef));
  245. if (spireg) {
  246. /* Set interface defaults. */
  247. spireg->CR1 =USART_Mode_Rx|USART_Mode_Tx|(1<<13);//fixme: write real values
  248. spireg->CR2 = USART_Clock_Enable|USART_LastBit_Enable;
  249. spireg->BRR = 16;
  250. /* Update with node's defaults. */
  251. node->node_stat = (void *)spireg;
  252. Stm32UsartSpiSetup(node);
  253. /*
  254. * Register and enable SPI interrupt handler.
  255. */
  256. //FIXME:add interrupt/dma support
  257. // if (bus->bus_base == SPI3_BASE) {
  258. // NutRegisterIrqHandler(bus->bus_sig, Stm32SpiBus2Interrupt, &bus->bus_ready);
  259. // outr(bus->bus_base + SPI_IDR_OFF, (unsigned int) - 1);
  260. // NutIrqEnable(bus->bus_sig);
  261. // } else {
  262. // NutRegisterIrqHandler(bus->bus_sig, Stm32SpiBus0Interrupt, &bus->bus_ready);
  263. // outr(bus->bus_base + SPI_IDR_OFF, (unsigned int) - 1);
  264. // NutIrqEnable(bus->bus_sig);
  265. // }
  266. } else {
  267. /* Out of memory? */
  268. rc = -1;
  269. }
  270. }
  271. return rc;
  272. }
  273. /*!
  274. * \brief Wait until all SPI bus transfers are done.
  275. *
  276. * \param node Specifies the SPI bus node.
  277. * \param tmo Timeout in milliseconds. To disable timeout, set this
  278. * parameter to NUT_WAIT_INFINITE.
  279. *
  280. * \return Always 0.
  281. */
  282. int Stm32UsartBusWait(NUTSPINODE * node, uint32_t tmo)
  283. {//FIXME: check this - do I really need it?
  284. /* USART_TypeDef* spi_bus;
  285. spi_bus=((USART_TypeDef *) node->node_bus->bus_base);
  286. while (spi_bus->SR & USART_FLAG_RXNE) {
  287. if (NutEventWait(&node->node_bus->bus_ready, tmo)) {
  288. return -1;
  289. }
  290. }
  291. while (!(spi_bus->SR & USART_FLAG_TXE) ){
  292. if (NutEventWait(&node->node_bus->bus_ready, tmo)) {
  293. return -1;
  294. }
  295. }*/
  296. //Not Needed - transfer does this
  297. //FIXME: add interrupt support
  298. return 0;
  299. }
  300. /*!
  301. * \brief Transfer data on the SPI bus using single buffered interrupt mode.
  302. *
  303. * A device must have been selected by calling At91SpiSelect().
  304. *
  305. * \param node Specifies the SPI bus node.
  306. * \param txbuf Pointer to the transmit buffer. If NULL, undetermined
  307. * byte values are transmitted.
  308. * \param rxbuf Pointer to the receive buffer. If NULL, then incoming
  309. * data is discarded.
  310. * \param xlen Number of bytes to transfer.
  311. *
  312. * \return Always 0.
  313. */
  314. int Stm32UsartBusTransfer(NUTSPINODE * node, const void *txbuf, void *rxbuf, int xlen)
  315. {
  316. USART_TypeDef* base;
  317. uint8_t b=0xff;
  318. uint8_t *txp = (uint8_t *) txbuf;
  319. uint8_t *rxp = (uint8_t *) rxbuf;
  320. /* Sanity check. */
  321. NUTASSERT(node != NULL);
  322. NUTASSERT(node->node_bus != NULL);
  323. NUTASSERT(node->node_bus->bus_base != 0);
  324. base = node->node_bus->bus_base;
  325. while (xlen--) {
  326. if (txp) {
  327. b = *txp++;
  328. }
  329. /* Transmission starts by writing the transmit data. */
  330. base->DR=b;
  331. /* Wait for receiver data register full. */
  332. while( (base->SR & USART_FLAG_RXNE) == 0) { ; }
  333. /* Read incoming data. */
  334. b = base->DR;
  335. //b=(uint8_t)SPI_I2S_ReceiveData(USART1);
  336. if (rxp) {
  337. *rxp++ = b;
  338. }
  339. }
  340. return 0;
  341. }
  342. NUTSPIBUS spiUsart3BusStm32 = {
  343. NULL, /*!< Bus mutex semaphore (bus_mutex). */
  344. NULL, /*!< Bus ready signal (bus_ready). */
  345. USART3_BASE, /*!< Bus base address (bus_base). */
  346. &sig_USART3, /*!< Bus interrupt handler (bus_sig). */
  347. Stm32UsartBusNodeInit, /*!< Initialize the bus (bus_initnode). */
  348. Stm32Usart3BusSelect, /*!< Select the specified device (bus_alloc). */
  349. Stm32Usart3BusDeselect, /*!< Deselect the specified device (bus_release). */
  350. Stm32UsartBusTransfer,
  351. Stm32UsartBusWait,
  352. NutSpiBusSetMode, /*!< Set SPI mode of a specified device (bus_set_mode). */
  353. NutSpiBusSetRate, /*!< Set clock rate of a specified device (bus_set_rate). */
  354. NutSpiBusSetBits /*!< Set number of data bits of a specified device (bus_set_bits). */
  355. };