drv_spi.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2020-6-15 YHKuo First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_SPI)
  14. #define LOG_TAG "drv.spi"
  15. #define DBG_ENABLE
  16. #define DBG_SECTION_NAME LOG_TAG
  17. #define DBG_LEVEL DBG_INFO
  18. #define DBG_COLOR
  19. #include <rtdbg.h>
  20. #include <rthw.h>
  21. #include <rtdevice.h>
  22. #include <rtdef.h>
  23. #include <drv_spi.h>
  24. /* Private define ---------------------------------------------------------------*/
  25. #ifndef NU_SPI_USE_PDMA_MIN_THRESHOLD
  26. #define NU_SPI_USE_PDMA_MIN_THRESHOLD (128)
  27. #endif
  28. enum
  29. {
  30. SPI_START = -1,
  31. #if defined(BSP_USING_SPI0)
  32. SPI0_IDX,
  33. #endif
  34. #if defined(BSP_USING_SPI1)
  35. SPI1_IDX,
  36. #endif
  37. #if defined(BSP_USING_SPI2)
  38. SPI2_IDX,
  39. #endif
  40. #if defined(BSP_USING_SPI3)
  41. SPI3_IDX,
  42. #endif
  43. SPI_CNT
  44. };
  45. /* Private typedef --------------------------------------------------------------*/
  46. /* Private functions ------------------------------------------------------------*/
  47. static void nu_spi_transmission_with_poll(struct nu_spi *spi_bus,
  48. uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word);
  49. static int nu_spi_register_bus(struct nu_spi *spi_bus, const char *name);
  50. static rt_uint32_t nu_spi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message);
  51. static rt_err_t nu_spi_bus_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
  52. #if defined(BSP_USING_SPI_PDMA)
  53. static void nu_pdma_spi_rx_cb(void *pvUserData, uint32_t u32EventFilter);
  54. static rt_err_t nu_pdma_spi_rx_config(struct nu_spi *spi_bus, uint8_t *pu8Buf, int32_t i32RcvLen, uint8_t bytes_per_word);
  55. static rt_err_t nu_pdma_spi_tx_config(struct nu_spi *spi_bus, const uint8_t *pu8Buf, int32_t i32SndLen, uint8_t bytes_per_word);
  56. static rt_size_t nu_spi_pdma_transmit(struct nu_spi *spi_bus, const uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word);
  57. #endif
  58. /* Public functions -------------------------------------------------------------*/
  59. void nu_spi_transfer(struct nu_spi *spi_bus, uint8_t *tx, uint8_t *rx, int length, uint8_t bytes_per_word);
  60. void nu_spi_drain_rxfifo(SPI_T *spi_base);
  61. /* Private variables ------------------------------------------------------------*/
  62. static struct rt_spi_ops nu_spi_poll_ops =
  63. {
  64. .configure = nu_spi_bus_configure,
  65. .xfer = nu_spi_bus_xfer,
  66. };
  67. static struct nu_spi nu_spi_arr [] =
  68. {
  69. #if defined(BSP_USING_SPI0)
  70. {
  71. .name = "spi0",
  72. .spi_base = SPI0,
  73. #if defined(BSP_USING_SPI_PDMA)
  74. #if defined(BSP_USING_SPI0_PDMA)
  75. .pdma_perp_tx = PDMA_SPI0_TX,
  76. .pdma_perp_rx = PDMA_SPI0_RX,
  77. #else
  78. .pdma_perp_tx = NU_PDMA_UNUSED,
  79. .pdma_perp_rx = NU_PDMA_UNUSED,
  80. #endif
  81. #endif
  82. },
  83. #endif
  84. #if defined(BSP_USING_SPI1)
  85. {
  86. .name = "spi1",
  87. .spi_base = SPI1,
  88. #if defined(BSP_USING_SPI_PDMA)
  89. #if defined(BSP_USING_SPI1_PDMA)
  90. .pdma_perp_tx = PDMA_SPI1_TX,
  91. .pdma_perp_rx = PDMA_SPI1_RX,
  92. #else
  93. .pdma_perp_tx = NU_PDMA_UNUSED,
  94. .pdma_perp_rx = NU_PDMA_UNUSED,
  95. #endif
  96. #endif
  97. },
  98. #endif
  99. #if defined(BSP_USING_SPI2)
  100. {
  101. .name = "spi2",
  102. .spi_base = SPI2,
  103. #if defined(BSP_USING_SPI_PDMA)
  104. #if defined(BSP_USING_SPI2_PDMA)
  105. .pdma_perp_tx = PDMA_SPI2_TX,
  106. .pdma_perp_rx = PDMA_SPI2_RX,
  107. #else
  108. .pdma_perp_tx = NU_PDMA_UNUSED,
  109. .pdma_perp_rx = NU_PDMA_UNUSED,
  110. #endif
  111. #endif
  112. },
  113. #endif
  114. #if defined(BSP_USING_SPI3)
  115. {
  116. .name = "spi3",
  117. .spi_base = SPI3,
  118. #if defined(BSP_USING_SPI_PDMA)
  119. #if defined(BSP_USING_SPI3_PDMA)
  120. .pdma_perp_tx = PDMA_SPI3_TX,
  121. .pdma_perp_rx = PDMA_SPI3_RX,
  122. #else
  123. .pdma_perp_tx = NU_PDMA_UNUSED,
  124. .pdma_perp_rx = NU_PDMA_UNUSED,
  125. #endif
  126. #endif
  127. },
  128. #endif
  129. {0}
  130. }; /* spi nu_spi */
  131. static rt_err_t nu_spi_bus_configure(struct rt_spi_device *device,
  132. struct rt_spi_configuration *configuration)
  133. {
  134. struct nu_spi *spi_bus;
  135. uint32_t u32SPIMode;
  136. uint32_t u32BusClock;
  137. rt_err_t ret = RT_EOK;
  138. void *pvUserData;
  139. RT_ASSERT(device != RT_NULL);
  140. RT_ASSERT(configuration != RT_NULL);
  141. spi_bus = (struct nu_spi *) device->bus;
  142. pvUserData = device->parent.user_data;
  143. /* Check mode */
  144. switch (configuration->mode & RT_SPI_MODE_3)
  145. {
  146. case RT_SPI_MODE_0:
  147. u32SPIMode = SPI_MODE_0;
  148. break;
  149. case RT_SPI_MODE_1:
  150. u32SPIMode = SPI_MODE_1;
  151. break;
  152. case RT_SPI_MODE_2:
  153. u32SPIMode = SPI_MODE_2;
  154. break;
  155. case RT_SPI_MODE_3:
  156. u32SPIMode = SPI_MODE_3;
  157. break;
  158. default:
  159. ret = RT_EIO;
  160. goto exit_nu_spi_bus_configure;
  161. }
  162. /* Check data width */
  163. if (!(configuration->data_width == 8 ||
  164. configuration->data_width == 16 ||
  165. configuration->data_width == 24 ||
  166. configuration->data_width == 32))
  167. {
  168. ret = RT_EINVAL;
  169. goto exit_nu_spi_bus_configure;
  170. }
  171. /* Try to set clock and get actual spi bus clock */
  172. u32BusClock = SPI_SetBusClock(spi_bus->spi_base, configuration->max_hz);
  173. if (configuration->max_hz > u32BusClock)
  174. {
  175. LOG_W("%s clock max frequency is %dHz (!= %dHz)\n", spi_bus->name, u32BusClock, configuration->max_hz);
  176. configuration->max_hz = u32BusClock;
  177. }
  178. /* Need to initialize new configuration? */
  179. if (rt_memcmp(configuration, &spi_bus->configuration, sizeof(*configuration)) != 0)
  180. {
  181. rt_memcpy(&spi_bus->configuration, configuration, sizeof(*configuration));
  182. SPI_Open(spi_bus->spi_base, SPI_MASTER, u32SPIMode, configuration->data_width, u32BusClock);
  183. if (configuration->mode & RT_SPI_CS_HIGH)
  184. {
  185. /* Set CS pin to LOW */
  186. if (pvUserData != RT_NULL)
  187. {
  188. // set to LOW */
  189. rt_pin_write(*((rt_base_t *)pvUserData), PIN_LOW);
  190. }
  191. else
  192. {
  193. SPI_SET_SS_LOW(spi_bus->spi_base);
  194. }
  195. }
  196. else
  197. {
  198. /* Set CS pin to HIGH */
  199. if (pvUserData != RT_NULL)
  200. {
  201. // set to HIGH */
  202. rt_pin_write(*((rt_base_t *)pvUserData), PIN_HIGH);
  203. }
  204. else
  205. {
  206. /* Set CS pin to HIGH */
  207. SPI_SET_SS_HIGH(spi_bus->spi_base);
  208. }
  209. }
  210. if (configuration->mode & RT_SPI_MSB)
  211. {
  212. /* Set sequence to MSB first */
  213. SPI_SET_MSB_FIRST(spi_bus->spi_base);
  214. }
  215. else
  216. {
  217. /* Set sequence to LSB first */
  218. SPI_SET_LSB_FIRST(spi_bus->spi_base);
  219. }
  220. }
  221. /* Clear SPI RX FIFO */
  222. nu_spi_drain_rxfifo(spi_bus->spi_base);
  223. exit_nu_spi_bus_configure:
  224. return -(ret);
  225. }
  226. #if defined(BSP_USING_SPI_PDMA)
  227. static void nu_pdma_spi_rx_cb(void *pvUserData, uint32_t u32EventFilter)
  228. {
  229. rt_err_t result;
  230. struct nu_spi *spi_bus = (struct nu_spi *)pvUserData;
  231. RT_ASSERT(spi_bus != RT_NULL);
  232. result = rt_sem_release(spi_bus->m_psSemBus);
  233. RT_ASSERT(result == RT_EOK);
  234. }
  235. static rt_err_t nu_pdma_spi_rx_config(struct nu_spi *spi_bus, uint8_t *pu8Buf, int32_t i32RcvLen, uint8_t bytes_per_word)
  236. {
  237. rt_err_t result = RT_EOK;
  238. rt_uint8_t *dst_addr = NULL;
  239. nu_pdma_memctrl_t memctrl = eMemCtl_Undefined;
  240. /* Get base address of spi register */
  241. SPI_T *spi_base = spi_bus->spi_base;
  242. rt_uint8_t spi_pdma_rx_chid = spi_bus->pdma_chanid_rx;
  243. result = nu_pdma_callback_register(spi_pdma_rx_chid,
  244. nu_pdma_spi_rx_cb,
  245. (void *)spi_bus,
  246. NU_PDMA_EVENT_TRANSFER_DONE);
  247. if (result != RT_EOK)
  248. {
  249. goto exit_nu_pdma_spi_rx_config;
  250. }
  251. if (pu8Buf == RT_NULL)
  252. {
  253. memctrl = eMemCtl_SrcFix_DstFix;
  254. dst_addr = (rt_uint8_t *) &spi_bus->dummy;
  255. }
  256. else
  257. {
  258. memctrl = eMemCtl_SrcFix_DstInc;
  259. dst_addr = pu8Buf;
  260. }
  261. result = nu_pdma_channel_memctrl_set(spi_pdma_rx_chid, memctrl);
  262. if (result != RT_EOK)
  263. {
  264. goto exit_nu_pdma_spi_rx_config;
  265. }
  266. result = nu_pdma_transfer(spi_pdma_rx_chid,
  267. bytes_per_word * 8,
  268. (uint32_t)&spi_base->RX,
  269. (uint32_t)dst_addr,
  270. i32RcvLen / bytes_per_word,
  271. 0);
  272. exit_nu_pdma_spi_rx_config:
  273. return result;
  274. }
  275. static rt_err_t nu_pdma_spi_tx_config(struct nu_spi *spi_bus, const uint8_t *pu8Buf, int32_t i32SndLen, uint8_t bytes_per_word)
  276. {
  277. rt_err_t result = RT_EOK;
  278. rt_uint8_t *src_addr = NULL;
  279. nu_pdma_memctrl_t memctrl = eMemCtl_Undefined;
  280. /* Get base address of spi register */
  281. SPI_T *spi_base = spi_bus->spi_base;
  282. rt_uint8_t spi_pdma_tx_chid = spi_bus->pdma_chanid_tx;
  283. if (pu8Buf == RT_NULL)
  284. {
  285. spi_bus->dummy = 0;
  286. memctrl = eMemCtl_SrcFix_DstFix;
  287. src_addr = (rt_uint8_t *)&spi_bus->dummy;
  288. }
  289. else
  290. {
  291. memctrl = eMemCtl_SrcInc_DstFix;
  292. src_addr = (rt_uint8_t *)pu8Buf;
  293. }
  294. result = nu_pdma_channel_memctrl_set(spi_pdma_tx_chid, memctrl);
  295. if (result != RT_EOK)
  296. {
  297. goto exit_nu_pdma_spi_tx_config;
  298. }
  299. result = nu_pdma_transfer(spi_pdma_tx_chid,
  300. bytes_per_word * 8,
  301. (uint32_t)src_addr,
  302. (uint32_t)&spi_base->TX,
  303. i32SndLen / bytes_per_word,
  304. 0);
  305. exit_nu_pdma_spi_tx_config:
  306. return result;
  307. }
  308. /**
  309. * SPI PDMA transfer
  310. */
  311. static rt_size_t nu_spi_pdma_transmit(struct nu_spi *spi_bus, const uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word)
  312. {
  313. rt_err_t result = RT_EOK;
  314. rt_uint32_t u32Offset = 0;
  315. rt_uint32_t u32TransferCnt = length / bytes_per_word;
  316. rt_uint32_t u32TxCnt = 0;
  317. /* Get base address of spi register */
  318. SPI_T *spi_base = spi_bus->spi_base;
  319. do
  320. {
  321. u32TxCnt = (u32TransferCnt > NU_PDMA_MAX_TXCNT) ? NU_PDMA_MAX_TXCNT : u32TransferCnt;
  322. result = nu_pdma_spi_rx_config(spi_bus, (recv_addr == RT_NULL) ? recv_addr : &recv_addr[u32Offset], (u32TxCnt * bytes_per_word), bytes_per_word);
  323. RT_ASSERT(result == RT_EOK);
  324. result = nu_pdma_spi_tx_config(spi_bus, (send_addr == RT_NULL) ? send_addr : &send_addr[u32Offset], (u32TxCnt * bytes_per_word), bytes_per_word);
  325. RT_ASSERT(result == RT_EOK);
  326. /* Trigger TX/RX PDMA transfer. */
  327. SPI_TRIGGER_TX_RX_PDMA(spi_base);
  328. /* Wait RX-PDMA transfer done */
  329. result = rt_sem_take(spi_bus->m_psSemBus, RT_WAITING_FOREVER);
  330. RT_ASSERT(result == RT_EOK);
  331. /* Stop TX/RX DMA transfer. */
  332. SPI_DISABLE_TX_RX_PDMA(spi_base);
  333. u32TransferCnt -= u32TxCnt;
  334. u32Offset += u32TxCnt;
  335. }
  336. while (u32TransferCnt > 0);
  337. return length;
  338. }
  339. rt_err_t nu_hw_spi_pdma_allocate(struct nu_spi *spi_bus)
  340. {
  341. /* Allocate SPI_TX nu_dma channel */
  342. if ((spi_bus->pdma_chanid_tx = nu_pdma_channel_allocate(spi_bus->pdma_perp_tx)) < 0)
  343. {
  344. goto exit_nu_hw_spi_pdma_allocate;
  345. }
  346. /* Allocate SPI_RX nu_dma channel */
  347. else if ((spi_bus->pdma_chanid_rx = nu_pdma_channel_allocate(spi_bus->pdma_perp_rx)) < 0)
  348. {
  349. nu_pdma_channel_free(spi_bus->pdma_chanid_tx);
  350. goto exit_nu_hw_spi_pdma_allocate;
  351. }
  352. spi_bus->m_psSemBus = rt_sem_create("spibus_sem", 0, RT_IPC_FLAG_FIFO);
  353. RT_ASSERT(spi_bus->m_psSemBus != RT_NULL);
  354. return RT_EOK;
  355. exit_nu_hw_spi_pdma_allocate:
  356. return -(RT_ERROR);
  357. }
  358. #endif /* #if defined(BSP_USING_SPI_PDMA) */
  359. void nu_spi_drain_rxfifo(SPI_T *spi_base)
  360. {
  361. while (SPI_IS_BUSY(spi_base));
  362. // Drain SPI RX FIFO, make sure RX FIFO is empty
  363. while (!SPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
  364. {
  365. SPI_ClearRxFIFO(spi_base);
  366. }
  367. }
  368. static int nu_spi_read(SPI_T *spi_base, uint8_t *recv_addr, uint8_t bytes_per_word)
  369. {
  370. int size = 0;
  371. // Read RX data
  372. if (!SPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
  373. {
  374. uint32_t val;
  375. // Read data from SPI RX FIFO
  376. switch (bytes_per_word)
  377. {
  378. case 4:
  379. val = SPI_READ_RX(spi_base);
  380. nu_set32_le(recv_addr, val);
  381. break;
  382. case 3:
  383. val = SPI_READ_RX(spi_base);
  384. nu_set24_le(recv_addr, val);
  385. break;
  386. case 2:
  387. val = SPI_READ_RX(spi_base);
  388. nu_set16_le(recv_addr, val);
  389. break;
  390. case 1:
  391. *recv_addr = SPI_READ_RX(spi_base);
  392. break;
  393. default:
  394. LOG_E("Data length is not supported.\n");
  395. break;
  396. }
  397. size = bytes_per_word;
  398. }
  399. return size;
  400. }
  401. static int nu_spi_write(SPI_T *spi_base, const uint8_t *send_addr, uint8_t bytes_per_word)
  402. {
  403. // Wait SPI TX send data
  404. while (SPI_GET_TX_FIFO_FULL_FLAG(spi_base));
  405. // Input data to SPI TX
  406. switch (bytes_per_word)
  407. {
  408. case 4:
  409. SPI_WRITE_TX(spi_base, nu_get32_le(send_addr));
  410. break;
  411. case 3:
  412. SPI_WRITE_TX(spi_base, nu_get24_le(send_addr));
  413. break;
  414. case 2:
  415. SPI_WRITE_TX(spi_base, nu_get16_le(send_addr));
  416. break;
  417. case 1:
  418. SPI_WRITE_TX(spi_base, *((uint8_t *)send_addr));
  419. break;
  420. default:
  421. LOG_E("Data length is not supported.\n");
  422. break;
  423. }
  424. return bytes_per_word;
  425. }
  426. /**
  427. * @brief SPI bus polling
  428. * @param dev : The pointer of the specified SPI module.
  429. * @param send_addr : Source address
  430. * @param recv_addr : Destination address
  431. * @param length : Data length
  432. */
  433. static void nu_spi_transmission_with_poll(struct nu_spi *spi_bus,
  434. uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word)
  435. {
  436. SPI_T *spi_base = spi_bus->spi_base;
  437. // Write-only
  438. if ((send_addr != RT_NULL) && (recv_addr == RT_NULL))
  439. {
  440. while (length > 0)
  441. {
  442. send_addr += nu_spi_write(spi_base, send_addr, bytes_per_word);
  443. length -= bytes_per_word;
  444. }
  445. } // if (send_addr != RT_NULL && recv_addr == RT_NULL)
  446. // Read-only
  447. else if ((send_addr == RT_NULL) && (recv_addr != RT_NULL))
  448. {
  449. spi_bus->dummy = 0;
  450. while (length > 0)
  451. {
  452. /* Input data to SPI TX FIFO */
  453. length -= nu_spi_write(spi_base, (const uint8_t *)&spi_bus->dummy, bytes_per_word);
  454. /* Read data from RX FIFO */
  455. recv_addr += nu_spi_read(spi_base, recv_addr, bytes_per_word);
  456. }
  457. } // else if (send_addr == RT_NULL && recv_addr != RT_NULL)
  458. // Read&Write
  459. else
  460. {
  461. while (length > 0)
  462. {
  463. /* Input data to SPI TX FIFO */
  464. send_addr += nu_spi_write(spi_base, send_addr, bytes_per_word);
  465. length -= bytes_per_word;
  466. /* Read data from RX FIFO */
  467. recv_addr += nu_spi_read(spi_base, recv_addr, bytes_per_word);
  468. }
  469. } // else
  470. /* Wait RX or drain RX-FIFO */
  471. if (recv_addr)
  472. {
  473. // Wait SPI transmission done
  474. while (SPI_IS_BUSY(spi_base))
  475. {
  476. while (!SPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
  477. {
  478. recv_addr += nu_spi_read(spi_base, recv_addr, bytes_per_word);
  479. }
  480. }
  481. while (!SPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
  482. {
  483. recv_addr += nu_spi_read(spi_base, recv_addr, bytes_per_word);
  484. }
  485. }
  486. else
  487. {
  488. /* Clear SPI RX FIFO */
  489. nu_spi_drain_rxfifo(spi_base);
  490. }
  491. }
  492. void nu_spi_transfer(struct nu_spi *spi_bus, uint8_t *tx, uint8_t *rx, int length, uint8_t bytes_per_word)
  493. {
  494. RT_ASSERT(spi_bus != RT_NULL);
  495. #if defined(BSP_USING_SPI_PDMA)
  496. /* DMA transfer constrains */
  497. if ((spi_bus->pdma_chanid_rx >= 0) &&
  498. !((uint32_t)tx % bytes_per_word) &&
  499. !((uint32_t)rx % bytes_per_word) &&
  500. (bytes_per_word != 3) &&
  501. (length >= NU_SPI_USE_PDMA_MIN_THRESHOLD))
  502. nu_spi_pdma_transmit(spi_bus, tx, rx, length, bytes_per_word);
  503. else
  504. nu_spi_transmission_with_poll(spi_bus, tx, rx, length, bytes_per_word);
  505. #else
  506. nu_spi_transmission_with_poll(spi_bus, tx, rx, length, bytes_per_word);
  507. #endif
  508. }
  509. static rt_uint32_t nu_spi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  510. {
  511. struct nu_spi *spi_bus;
  512. struct rt_spi_configuration *configuration;
  513. uint8_t bytes_per_word;
  514. void *pvUserData;
  515. RT_ASSERT(device != RT_NULL);
  516. RT_ASSERT(device->bus != RT_NULL);
  517. RT_ASSERT(message != RT_NULL);
  518. spi_bus = (struct nu_spi *) device->bus;
  519. configuration = (struct rt_spi_configuration *)&spi_bus->configuration;
  520. bytes_per_word = configuration->data_width / 8;
  521. pvUserData = device->parent.user_data;
  522. if ((message->length % bytes_per_word) != 0)
  523. {
  524. /* Say bye. */
  525. LOG_E("%s: error payload length(%d%%%d != 0).\n", spi_bus->name, message->length, bytes_per_word);
  526. return 0;
  527. }
  528. if (message->length > 0)
  529. {
  530. if (message->cs_take && !(configuration->mode & RT_SPI_NO_CS))
  531. {
  532. if (pvUserData != RT_NULL)
  533. {
  534. if (configuration->mode & RT_SPI_CS_HIGH)
  535. {
  536. // set to HIGH */
  537. rt_pin_write(*((rt_base_t *)pvUserData), PIN_HIGH);
  538. }
  539. else
  540. {
  541. // set to LOW */
  542. rt_pin_write(*((rt_base_t *)pvUserData), PIN_LOW);
  543. }
  544. }
  545. else
  546. {
  547. if (configuration->mode & RT_SPI_CS_HIGH)
  548. {
  549. SPI_SET_SS_HIGH(spi_bus->spi_base);
  550. }
  551. else
  552. {
  553. SPI_SET_SS_LOW(spi_bus->spi_base);
  554. }
  555. }
  556. }
  557. nu_spi_transfer(spi_bus, (uint8_t *)message->send_buf, (uint8_t *)message->recv_buf, message->length, bytes_per_word);
  558. if (message->cs_release && !(configuration->mode & RT_SPI_NO_CS))
  559. {
  560. if (pvUserData != RT_NULL)
  561. {
  562. if (configuration->mode & RT_SPI_CS_HIGH)
  563. {
  564. // set to LOW */
  565. rt_pin_write(*((rt_base_t *)pvUserData), PIN_LOW);
  566. }
  567. else
  568. {
  569. // set to HIGH */
  570. rt_pin_write(*((rt_base_t *)pvUserData), PIN_HIGH);
  571. }
  572. }
  573. else
  574. {
  575. if (configuration->mode & RT_SPI_CS_HIGH)
  576. {
  577. SPI_SET_SS_LOW(spi_bus->spi_base);
  578. }
  579. else
  580. {
  581. SPI_SET_SS_HIGH(spi_bus->spi_base);
  582. }
  583. }
  584. }
  585. }
  586. return message->length;
  587. }
  588. static int nu_spi_register_bus(struct nu_spi *spi_bus, const char *name)
  589. {
  590. return rt_spi_bus_register(&spi_bus->dev, name, &nu_spi_poll_ops);
  591. }
  592. /**
  593. * Hardware SPI Initial
  594. */
  595. static int rt_hw_spi_init(void)
  596. {
  597. int i;
  598. for (i = (SPI_START + 1); i < SPI_CNT; i++)
  599. {
  600. nu_spi_register_bus(&nu_spi_arr[i], nu_spi_arr[i].name);
  601. #if defined(BSP_USING_SPI_PDMA)
  602. nu_spi_arr[i].pdma_chanid_tx = -1;
  603. nu_spi_arr[i].pdma_chanid_rx = -1;
  604. if ((nu_spi_arr[i].pdma_perp_tx != NU_PDMA_UNUSED) && (nu_spi_arr[i].pdma_perp_rx != NU_PDMA_UNUSED))
  605. {
  606. if (nu_hw_spi_pdma_allocate(&nu_spi_arr[i]) != RT_EOK)
  607. {
  608. LOG_W("Failed to allocate DMA channels for %s. We will use poll-mode for this bus.\n", nu_spi_arr[i].name);
  609. }
  610. }
  611. #endif
  612. }
  613. return 0;
  614. }
  615. INIT_DEVICE_EXPORT(rt_hw_spi_init);
  616. #endif //#if defined(BSP_USING_SPI)