drv_spi.c 19 KB

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