stm32_spi.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. /*
  2. * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
  3. * Copyright (C) 2010 by Nikolaj Zamotaev. All rights reserved.
  4. * Copyright (C) 2014 by Uwe Bonnes(bon@elektron.ikp.physik.tu-darmstadt.de).
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. *
  34. */
  35. /*
  36. * \file arch/cm3/stm/stm32_spi.c
  37. * \brief STM32 SPI handling. Only include from devices specific file
  38. * stm32_spiX.c.
  39. *
  40. * The SPI IP has no interrupt for SPI getting idle, so it takes some effort
  41. * to find the right moment to switch SPI and CS off. To do so, we always
  42. * count the received byte even if we transmit only.
  43. * DMA_Mode handles this case per se.
  44. * \verbatim
  45. * $Id: stm32_spi.c 5717 2014-05-23 14:55:51Z u_bonnes $
  46. * \endverbatim
  47. */
  48. #include <arch/cm3.h>
  49. #include <sys/timer.h>
  50. #include <cfg/spi.h>
  51. #include <arch/cm3/stm/stm32xxxx.h>
  52. #include <arch/cm3/stm/stm32_gpio.h>
  53. #include <dev/spibus_stm32.h>
  54. #include <sys/nutdebug.h>
  55. #include <stdlib.h>
  56. #include <errno.h>
  57. #if !defined(SPI_SCK_GPIO_AF)
  58. #define SPI_SCK_GPIO_AF SPI_GPIO_AF
  59. #endif
  60. #if !defined(SPI_MOSI_GPIO_AF)
  61. #define SPI_MOSI_GPIO_AF SPI_GPIO_AF
  62. #endif
  63. #if !defined(SPI_MISO_GPIO_AF)
  64. #define SPI_MISO_GPIO_AF SPI_GPIO_AF
  65. #endif
  66. /* Keep SPIBUS_CSx_INIT() undefined when PORT/PIN is not available*/
  67. #if defined(SPIBUS_CS0_PORT) && defined(SPIBUS_CS0_PIN)
  68. #define SPIBUS_CS0_INIT(x) GpioPinConfigSet(SPIBUS_CS0_PORT, SPIBUS_CS0_PIN, GPIO_CFG_OUTPUT | x)
  69. #define SPIBUS_CS0_SET() GpioPinSetHigh(SPIBUS_CS0_PORT, SPIBUS_CS0_PIN)
  70. #define SPIBUS_CS0_CLR() GpioPinSetLow (SPIBUS_CS0_PORT, SPIBUS_CS0_PIN)
  71. #else
  72. #define SPIBUS_CS0_SET()
  73. #define SPIBUS_CS0_CLR()
  74. #endif
  75. #if defined(SPIBUS_CS1_PORT) && defined(SPIBUS_CS1_PIN)
  76. #define SPIBUS_CS1_INIT(x) GpioPinConfigSet(SPIBUS_CS1_PORT, SPIBUS_CS1_PIN, GPIO_CFG_OUTPUT | x)
  77. #define SPIBUS_CS1_SET() GpioPinSetHigh(SPIBUS_CS1_PORT, SPIBUS_CS1_PIN)
  78. #define SPIBUS_CS1_CLR() GpioPinSetLow (SPIBUS_CS1_PORT, SPIBUS_CS1_PIN)
  79. #else
  80. #define SPIBUS_CS1_SET()
  81. #define SPIBUS_CS1_CLR()
  82. #endif
  83. #if defined(SPIBUS_CS2_PORT) && defined(SPIBUS_CS2_PIN)
  84. #define SPIBUS_CS2_INIT(x) GpioPinConfigSet(SPIBUS_CS2_PORT, SPIBUS_CS2_PIN, GPIO_CFG_OUTPUT | x)
  85. #define SPIBUS_CS2_SET() GpioPinSetHigh(SPIBUS_CS2_PORT, SPIBUS_CS2_PIN)
  86. #define SPIBUS_CS2_CLR() GpioPinSetLow (SPIBUS_CS2_PORT, SPIBUS_CS2_PIN)
  87. #else
  88. #define SPIBUS_CS2_SET()
  89. #define SPIBUS_CS2_CLR()
  90. #endif
  91. #if defined(SPIBUS_CS3_PORT) && defined(SPIBUS_CS3_PIN)
  92. #define SPIBUS_CS3_INIT(x) GpioPinConfigSet(SPIBUS_CS3_PORT, SPIBUS_CS3_PIN, GPIO_CFG_OUTPUT | x)
  93. #define SPIBUS_CS3_SET() GpioPinSetHigh(SPIBUS_CS3_PORT, SPIBUS_CS3_PIN)
  94. #define SPIBUS_CS3_CLR() GpioPinSetLow (SPIBUS_CS3_PORT, SPIBUS_CS3_PIN)
  95. #else
  96. #define SPIBUS_CS3_SET()
  97. #define SPIBUS_CS3_CLR()
  98. #endif
  99. #if SPIBUS_MODE == POLLING_MODE
  100. #elif SPIBUS_MODE == IRQ_MODE
  101. static uint8_t * volatile spi_txp;
  102. static uint8_t * volatile spi_rxp;
  103. static volatile size_t spi_rx_len;
  104. static volatile size_t spi_tx_len;
  105. static volatile size_t spi_len;
  106. static void Stm32SpiBusInterrupt(void *arg)
  107. {
  108. uint8_t b;
  109. SPI_TypeDef *spi = (SPI_TypeDef *)SPI_BASE;
  110. if(CM3BBGET(SPI_BASE, SPI_TypeDef, SR, _BI32(SPI_SR_RXNE))) {
  111. b = spi->DR;
  112. spi_len --;
  113. if (spi_rx_len) {
  114. if (spi_rxp) {
  115. *spi_rxp = b;
  116. spi_rxp++;
  117. spi_rx_len--;
  118. if (spi_rx_len == 1) {
  119. if (spi->CR1 & (SPI_CR1_BIDIMODE| SPI_CR1_RXONLY)) {
  120. /* Follow "Disabling the SPI" */
  121. while( GpioPinGet(SPIBUS_SCK_PORT, SPIBUS_SCK_PIN));
  122. while(!GpioPinGet(SPIBUS_SCK_PORT, SPIBUS_SCK_PIN));
  123. CM3BBCLR(SPI_BASE, SPI_TypeDef, CR1, _BI32(SPI_CR1_SPE));
  124. }
  125. }
  126. }
  127. }
  128. /* Terminate when the requested number of bytes have been received
  129. * even so perhaps we didn't need to store them.
  130. * That way we can make sure we don't deassert CS while SCK is still running.
  131. */
  132. if (spi_len == 0){
  133. spi->CR2 &= ~(SPI_CR2_TXEIE | SPI_CR2_RXNEIE);
  134. NutEventPostFromIrq((void **)arg);
  135. }
  136. }
  137. if (CM3BBGET(SPI_BASE, SPI_TypeDef, SR, _BI32(SPI_SR_TXE))) {
  138. if (spi_tx_len) {
  139. b = *spi_txp;
  140. /* After sending the last byte we need to wait for the last
  141. * receive interrupt, but we are not interested in the transmitter
  142. * empty interrupt
  143. */
  144. if (spi_tx_len == 1) {
  145. CM3BBSET(SPI_BASE, SPI_TypeDef, CR2, _BI32(SPI_CR2_RXNEIE));
  146. CM3BBCLR(SPI_BASE, SPI_TypeDef, CR2, _BI32(SPI_CR2_TXEIE));
  147. }
  148. /* Half word access via "spi->DR = b" shifts out two frames
  149. * on the F373! */
  150. *(uint8_t *) &spi->DR = b;
  151. spi_txp++;
  152. spi_tx_len --;
  153. }
  154. }
  155. }
  156. #else
  157. #include <arch/cm3/stm/stm32_dma.h>
  158. static void Stm32SpiBusDMAInterrupt(void *arg)
  159. {
  160. CM3BBCLR(SPI_BASE, SPI_TypeDef, CR1, _BI32(SPI_CR1_SPE));
  161. DMA_ClearFlag(SPI_DMA_RX_CHANNEL, DMA_TCIF);
  162. NutEventPostFromIrq((void **)arg);
  163. }
  164. #endif
  165. /*!
  166. * \brief Set the specified chip select to a given level.
  167. */
  168. static int Stm32SpiChipSelect(NUTSPINODE *node, int assert)
  169. {
  170. int res;
  171. int hi;
  172. if (node->node_mode & SPI_MODE_CSHIGH)
  173. hi = assert;
  174. else
  175. hi = !assert;
  176. switch (node->node_cs) {
  177. case 0:
  178. if(hi)
  179. SPIBUS_CS0_SET();
  180. else
  181. SPIBUS_CS0_CLR();
  182. res = 0;
  183. break;
  184. #if SPIBUS_CS1_SET !=0
  185. case 1:
  186. if(hi)
  187. SPIBUS_CS1_SET();
  188. else
  189. SPIBUS_CS1_CLR();
  190. res = 0;
  191. break;
  192. #endif
  193. #if SPIBUS_CS2_SET !=0
  194. case 2:
  195. if(hi)
  196. SPIBUS_CS2_SET();
  197. else
  198. SPIBUS_CS2_CLR();
  199. res = 0;
  200. break;
  201. #endif
  202. #if SPIBUS_CS3_SET !=0
  203. case 2:
  204. if(hi)
  205. SPIBUS_CS3_SET();
  206. else
  207. SPIBUS_CS3_CLR();
  208. res = 0;
  209. break;
  210. #endif
  211. default:
  212. res = -1;
  213. }
  214. return res;
  215. }
  216. /*! \brief Deselect a device on the SPI bus.
  217. *
  218. * Deactivates the chip select and unlocks the bus.
  219. *
  220. * \param node Specifies the SPI bus node.
  221. *
  222. * \return Always 0.
  223. */
  224. static int Stm32SpiBusDeselect(NUTSPINODE * node)
  225. {
  226. /* Sanity check. */
  227. NUTASSERT(node != NULL);
  228. NUTASSERT(node->node_bus != NULL);
  229. NutSpiBusWait(node, NUT_WAIT_INFINITE);
  230. /* Deactivate the node's chip select. */
  231. Stm32SpiChipSelect(node, 0);
  232. /* Release the bus. */
  233. NutEventPostAsync(&node->node_bus->bus_mutex);
  234. return 0;
  235. }
  236. /*! \brief Select a device on the SPI bus.
  237. *
  238. * Locks and activates the bus for the specified node.
  239. *
  240. * \param node Specifies the SPI bus node.
  241. * \param tmo Timeout in milliseconds. To disable timeout, set this
  242. * parameter to NUT_WAIT_INFINITE.
  243. *
  244. * \return 0 on success. In case of an error, -1 is returned and the bus
  245. * is not locked.
  246. */
  247. static int Stm32SpiBusSelect(NUTSPINODE * node, uint32_t tmo)
  248. {
  249. int rc;
  250. SPI_TypeDef* base;
  251. /* Sanity check. */
  252. NUTASSERT(node != NULL);
  253. NUTASSERT(node->node_bus != NULL);
  254. NUTASSERT(node->node_stat != NULL);
  255. base=(SPI_TypeDef*)(node->node_bus->bus_base);
  256. /* Allocate the bus. */
  257. rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
  258. if (rc) {
  259. errno = EIO;
  260. } else {
  261. STM32SPIREG *spireg = node->node_stat;
  262. /* If the mode update bit is set, then update our shadow registers. */
  263. if (node->node_mode & SPI_MODE_UPDATE) {
  264. Stm32SpiSetup(node);
  265. }
  266. /* Set SPI mode. */
  267. base->CR1 = spireg->CR1;
  268. base->CR1 |= SPI_CR1_SSI|SPI_CR1_MSTR;
  269. base->CR2 = spireg->CR2;
  270. base->I2SCFGR=spireg->I2SCFGR;
  271. base->I2SPR=spireg->I2SPR;
  272. /* Finally activate the node's chip select. */
  273. rc = Stm32SpiChipSelect(node, 1);
  274. if (rc) {
  275. /* Release the bus in case of an error. */
  276. NutEventPost(&node->node_bus->bus_mutex);
  277. }
  278. }
  279. return rc;
  280. }
  281. /*!
  282. * \brief Update SPI shadow registers.
  283. *
  284. * \param node Specifies the SPI bus node.
  285. *
  286. * \return Always 0.
  287. */
  288. static int Stm32SpiSetup(NUTSPINODE * node)
  289. {
  290. uint32_t clk;
  291. uint32_t clkdiv;
  292. SPI_TypeDef *spireg;
  293. NUTASSERT(node != NULL);
  294. NUTASSERT(node->node_stat != NULL);
  295. NUTASSERT(node->node_bus != NULL);
  296. NUTASSERT(node->node_bus->bus_base != 0);
  297. spireg = node->node_stat;
  298. #if defined(SPI_CR2_DS)
  299. spireg->CR1 &= ~( SPI_CR1_CPOL | SPI_CR1_CPHA | SPI_CR1_BR);
  300. spireg->CR2 &= ~SPI_CR2_DS;
  301. if((node->node_bits > 6) && (node->node_bits <= 16))
  302. spireg->CR2 |= (node->node_bits -1) <<8;
  303. #else
  304. spireg->CR1 &= ~(SPI_CR1_DFF | SPI_CR1_CPOL | SPI_CR1_CPHA | SPI_CR1_BR);
  305. switch(node->node_bits){
  306. case 8:
  307. spireg->CR1 &= ~(SPI_CR1_DFF);
  308. break;
  309. case 16:
  310. spireg->CR1 |= SPI_CR1_DFF;
  311. break;
  312. default:
  313. break;
  314. };
  315. #endif
  316. if (node->node_mode & SPI_MODE_CPOL) {
  317. spireg->CR1 |= SPI_CR1_CPOL;
  318. }
  319. if (node->node_mode & SPI_MODE_CPHA) {
  320. spireg->CR1 |= SPI_CR1_CPHA;
  321. }
  322. /* Query peripheral clock. */
  323. #if defined (MCU_STM32F0)
  324. clk = NutClockGet(NUT_HWCLK_PCLK1);
  325. #else
  326. if (node->node_bus->bus_base < APB2PERIPH_BASE)
  327. clk = NutClockGet(NUT_HWCLK_PCLK1);
  328. else
  329. clk = NutClockGet(NUT_HWCLK_PCLK2);
  330. #endif
  331. /* Calculate the SPI clock divider. Avoid rounding errors. */
  332. clkdiv = (clk + node->node_rate - 1) / node->node_rate;
  333. /* Choose the actual clock rate not greater than the requested rate */
  334. if (clkdiv > 128)
  335. clkdiv = 7;
  336. else if (clkdiv > 64)
  337. clkdiv = 6;
  338. else if (clkdiv > 32)
  339. clkdiv = 5;
  340. else if (clkdiv > 16)
  341. clkdiv = 4;
  342. else if (clkdiv > 8)
  343. clkdiv = 3;
  344. else if (clkdiv > 4)
  345. clkdiv = 2;
  346. else if (clkdiv > 2)
  347. clkdiv = 1;
  348. else
  349. clkdiv = 0;
  350. spireg->CR1 |= (clkdiv * SPI_CR1_BR_0);
  351. /* Update interface parameters. */
  352. node->node_rate = clk / (1 << (clkdiv + 1)) ;
  353. node->node_mode &= ~SPI_MODE_UPDATE;
  354. return 0;
  355. }
  356. /*!
  357. * \brief Initialize an SPI bus node.
  358. *
  359. * This routine is called for each SPI node, which is registered via
  360. * NutRegisterSpiDevice().
  361. *
  362. * \param node Specifies the SPI bus node.
  363. *
  364. * \return 0 on success or -1 if there is no valid chip select.
  365. */
  366. static int Stm32SpiBusNodeInit(NUTSPINODE * node)
  367. {
  368. int rc = 0;
  369. uint32_t init_flag;
  370. /* Sanity check. */
  371. NUTASSERT(node != NULL);
  372. NUTASSERT(node->node_bus != NULL);
  373. if ((node->node_mode & SPI_MODE_CSHIGH) == 0)
  374. init_flag = GPIO_CFG_INIT_HIGH;
  375. else
  376. init_flag = GPIO_CFG_INIT_LOW;
  377. (void) init_flag;
  378. switch (node->node_cs) {
  379. case 0:
  380. /* If CS0 is undefined, we assume permanent selection. */
  381. #if defined(SPIBUS_CS0_INIT)
  382. SPIBUS_CS0_INIT(init_flag);
  383. #endif
  384. break;
  385. #if defined(SPIBUS_CS1_INIT)
  386. case 1:
  387. SPIBUS_CS1_INIT(init_flag);
  388. break;
  389. #endif
  390. #if defined(SPIBUS_CS2_INIT)
  391. case 2:
  392. SPIBUS_CS2_INIT(init_flag);
  393. break;
  394. #endif
  395. #if defined(SPIBUS_CS3_INIT)
  396. case 3:
  397. SPIBUS_CS3_INIT(init_flag);
  398. break;
  399. #endif
  400. default:
  401. return -1;
  402. }
  403. /* Deactivate the node's chip select when initializing the port */
  404. rc = Stm32SpiChipSelect(node, 0);
  405. /* Test if the SPI Bus is already initialized*/
  406. if (SPI_ENABLE_CLK_GET() == 0) {
  407. /* Initialize Hardware */
  408. GpioPinConfigSet
  409. (SPIBUS_SCK_PORT, SPIBUS_SCK_PIN, GPIO_CFG_PERIPHAL | GPIO_CFG_OUTPUT |GPIO_CFG_INIT_LOW);//SCK
  410. GpioPinConfigSet
  411. (SPIBUS_MISO_PORT, SPIBUS_MISO_PIN, GPIO_CFG_PERIPHAL);//MISO
  412. GpioPinConfigSet
  413. (SPIBUS_MOSI_PORT, SPIBUS_MOSI_PIN, GPIO_CFG_PERIPHAL | GPIO_CFG_OUTPUT |GPIO_CFG_INIT_LOW);//MOSI
  414. #if defined(STM32F10X_CL)
  415. #if defined(SPIBUS_REMAP_BB)
  416. SPIBUS_REMAP_BB();
  417. #endif
  418. #else
  419. GPIO_PinAFConfig
  420. ((GPIO_TypeDef*)SPIBUS_SCK_PORT, SPIBUS_SCK_PIN, SPI_SCK_GPIO_AF);
  421. GPIO_PinAFConfig
  422. ((GPIO_TypeDef*)SPIBUS_MISO_PORT, SPIBUS_MISO_PIN, SPI_MISO_GPIO_AF);
  423. GPIO_PinAFConfig
  424. ((GPIO_TypeDef*)SPIBUS_MOSI_PORT, SPIBUS_MOSI_PIN, SPI_MOSI_GPIO_AF);
  425. #endif
  426. SPI_ENABLE_CLK_SET();
  427. }
  428. /* It should not hurt us being called more than once. Thus, we
  429. ** check wether any initialization had been taken place already. */
  430. if (rc == 0 && node->node_stat == NULL)
  431. {
  432. /* Allocate and set our shadow registers. */
  433. STM32SPIREG *spireg = malloc(sizeof(STM32SPIREG));
  434. if (spireg) {
  435. /* Set interface defaults. */
  436. spireg->CR1 = SPI_CR1_SSM | SPI_CR1_MSTR;
  437. /* FIXME: Check values needed*/
  438. #if defined(SPI_CR2_FRXTH)
  439. spireg->CR2 = SPI_CR2_FRXTH | 0x700;
  440. #else
  441. spireg->CR2 = 0;
  442. #endif
  443. spireg->I2SCFGR=0;
  444. spireg->I2SPR=2;
  445. /* Update with node's defaults. */
  446. node->node_stat = (void *)spireg;
  447. Stm32SpiSetup(node);
  448. #if SPIBUS_MODE == IRQ_MODE
  449. NUTSPIBUS *bus;
  450. bus = node->node_bus;
  451. NutRegisterIrqHandler(&sig_SPI, Stm32SpiBusInterrupt, &bus->bus_ready);
  452. NutIrqEnable(&sig_SPI);
  453. #elif SPIBUS_MODE == DMA_MODE
  454. DMA_Init();
  455. #endif
  456. }
  457. else {
  458. /* Out of memory? */
  459. rc = -1;
  460. }
  461. }
  462. return rc;
  463. }
  464. /*!
  465. * \brief Transfer data on the SPI bus using single buffered interrupt mode.
  466. *
  467. * A device must have been selected by calling At91SpiSelect().
  468. *
  469. * \param node Specifies the SPI bus node.
  470. * \param txbuf Pointer to the transmit buffer. If NULL, undetermined
  471. * byte values are transmitted.
  472. * \param rxbuf Pointer to the receive buffer. If NULL, then incoming
  473. * data is discarded.
  474. * \param xlen Number of bytes to transfer.
  475. *
  476. * \return Always 0.
  477. */
  478. static int Stm32SpiBusTransfer
  479. (NUTSPINODE * node, const void *txbuf, void *rxbuf, int xlen)
  480. {
  481. SPI_TypeDef* base;
  482. uint8_t *tx = (uint8_t *)txbuf;
  483. uint8_t *rx = (uint8_t *)rxbuf;
  484. int tx_only;
  485. int rx_only;
  486. /* Sanity check. */
  487. if (xlen == 0)
  488. return 0;
  489. NUTASSERT(node != NULL);
  490. NUTASSERT(node->node_bus != NULL);
  491. NUTASSERT(node->node_bus->bus_base != 0);
  492. base = (SPI_TypeDef*)node->node_bus->bus_base;
  493. tx_only = txbuf && !rxbuf;
  494. rx_only = (!txbuf || node->node_mode & SPI_MODE_HALFDUPLEX);
  495. /* Remove any remainders in DR */
  496. while (CM3BBGET(SPI_BASE, SPI_TypeDef, SR, _BI32(SPI_SR_RXNE)))
  497. (void) base->DR; /* Empty DR */
  498. #if SPIBUS_MODE == POLLING_MODE
  499. if (tx_only) {
  500. base->CR1 |= SPI_CR1_SPE;
  501. while( xlen > 0) {
  502. /* Half word access via "spi->DR = b" shifts out two frames
  503. * on the F373! */
  504. *(uint8_t *)&base->DR = *tx;
  505. xlen--;
  506. tx++;
  507. while ( (base->SR & SPI_SR_TXE ) == 0 ); /* Wait till TXE = 1*/
  508. }
  509. while (base->SR & SPI_SR_BSY); /* Wait till BSY = 0 */
  510. }
  511. else if (rx_only) {
  512. (void) base->DR; /* Empty DR */
  513. if (node->node_mode & SPI_MODE_HALFDUPLEX)
  514. base->CR1 |= SPI_CR1_BIDIMODE;
  515. else
  516. base->CR1 |= SPI_CR1_RXONLY;
  517. base->CR1 |= SPI_CR1_SPE;
  518. while( xlen > 0) {
  519. if(xlen < 2) {
  520. /* Follow procedure "Disabling the SPI" */
  521. while(!(GpioPinGet(SPIBUS_SCK_PORT,SPIBUS_SCK_PIN)));
  522. while(GpioPinGet(SPIBUS_SCK_PORT,SPIBUS_SCK_PIN));
  523. base->CR1 &= ~SPI_CR1_SPE;
  524. }
  525. xlen--;
  526. while ((base->SR & SPI_SR_RXNE) == 0 ); /* Wait till RXNE = 1*/
  527. if (rxbuf) {
  528. *rx = base->DR;
  529. rx++;
  530. }
  531. }
  532. }
  533. else {
  534. base->CR1 |= SPI_CR1_SPE;
  535. *(uint8_t *)&base->DR = *tx; /* Write first item */
  536. while( xlen > 0){
  537. tx++;
  538. xlen --;
  539. while ((base->SR & SPI_SR_TXE) == 0 ); /* Wait till TXE = 1*/
  540. if (xlen > 0)
  541. *(uint8_t *)&base->DR = *tx;
  542. while ((base->SR & SPI_SR_RXNE) == 0 );/* Wait till RXNE = 1*/
  543. *rx = base->DR;
  544. rx++;
  545. }
  546. while ((base->SR & SPI_SR_TXE) == 0 ); /* Wait till TXE = 1*/
  547. while (base->SR & SPI_SR_BSY); /* Wait till BSY = 0 */
  548. }
  549. #elif SPIBUS_MODE == IRQ_MODE
  550. spi_len = xlen;
  551. if (rx_only) {
  552. spi_rxp = rx;
  553. spi_rx_len = xlen;
  554. spi_tx_len = 0;
  555. if (node->node_mode & SPI_MODE_HALFDUPLEX)
  556. CM3BBSET(SPI_BASE, SPI_TypeDef, CR1, _BI32(SPI_CR1_BIDIMODE));
  557. else
  558. CM3BBSET(SPI_BASE, SPI_TypeDef, CR1, _BI32(SPI_CR1_RXONLY));
  559. CM3BBSET(SPI_BASE, SPI_TypeDef, CR2, _BI32(SPI_CR2_RXNEIE));
  560. CM3BBSET(SPI_BASE, SPI_TypeDef, CR1, _BI32(SPI_CR1_SPE));
  561. }
  562. else {
  563. uint8_t b = *tx++;
  564. spi_tx_len = xlen -1;
  565. spi_txp = tx;
  566. CM3BBSET(SPI_BASE, SPI_TypeDef, CR1, _BI32(SPI_CR1_SPE));
  567. if (tx_only) {
  568. spi_rx_len = 0;
  569. CM3BBSET(SPI_BASE, SPI_TypeDef, CR2, _BI32(SPI_CR2_TXEIE));
  570. }
  571. else {
  572. spi_rx_len = xlen;
  573. spi_rxp = rx;
  574. base->CR2 |= (SPI_CR2_RXNEIE | SPI_CR2_TXEIE);
  575. }
  576. *(uint8_t *)&base->DR = b;
  577. }
  578. NutEventWait(&node->node_bus->bus_ready, NUT_WAIT_INFINITE);
  579. #else
  580. (void) rx_only;
  581. (void) rx;
  582. NUTSPIBUS *bus;
  583. bus = node->node_bus;
  584. if (rx_only) {
  585. if (node->node_mode & SPI_MODE_HALFDUPLEX)
  586. CM3BBSET(SPI_BASE, SPI_TypeDef, CR1, _BI32(SPI_CR1_BIDIMODE));
  587. else
  588. CM3BBSET(SPI_BASE, SPI_TypeDef, CR1, _BI32(SPI_CR1_RXONLY));
  589. DMA_Setup( SPI_DMA_RX_CHANNEL, rx, (void*)(&base->DR), xlen , DMA_MINC);
  590. DMA_Enable( SPI_DMA_RX_CHANNEL);
  591. }
  592. else {
  593. DMA_Setup( SPI_DMA_TX_CHANNEL, (void*)(&base->DR), tx, xlen, DMA_MINC);
  594. DMA_Enable( SPI_DMA_TX_CHANNEL);
  595. if (tx_only) {
  596. uint32_t dummy;
  597. DMA_Setup( SPI_DMA_RX_CHANNEL, &dummy, (void*)(&base->DR), xlen, 0);
  598. }
  599. else
  600. DMA_Setup( SPI_DMA_RX_CHANNEL, rx, (void*)(&base->DR), xlen, DMA_MINC);
  601. CM3BBSET(SPI_BASE, SPI_TypeDef, CR2, _BI32(SPI_CR2_TXDMAEN));
  602. }
  603. /* Register the DMA interrupt after we have acquired the DMA channel.
  604. * Otherwise we may disrupt an on-going transaction to an other device on the same
  605. * channel.
  606. */
  607. NutRegisterIrqHandler(&sig_SPI_DMA_RX, Stm32SpiBusDMAInterrupt, &bus->bus_ready);
  608. NutIrqEnable(&sig_SPI_DMA_RX);
  609. DMA_Enable( SPI_DMA_RX_CHANNEL);
  610. DMA_IrqMask(SPI_DMA_RX_CHANNEL, DMA_TCIF, 1);
  611. CM3BBSET(SPI_BASE, SPI_TypeDef, CR2, _BI32(SPI_CR2_RXDMAEN));
  612. CM3BBSET(SPI_BASE, SPI_TypeDef, CR1, _BI32(SPI_CR1_SPE));
  613. NutEventWait(&node->node_bus->bus_ready, NUT_WAIT_INFINITE);
  614. #endif
  615. base->CR1 &= ~(SPI_CR1_SPE | SPI_CR1_RXONLY | SPI_CR1_BIDIMODE |
  616. SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
  617. return 0;
  618. }