drv_uspi.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  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-3-31 Philo First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_USPI)
  14. #define LOG_TAG "drv.uspi"
  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 "NuMicro.h"
  24. #include <nu_bitutil.h>
  25. #if defined(BSP_USING_USPI_PDMA)
  26. #include <drv_pdma.h>
  27. #endif
  28. /* Private define ---------------------------------------------------------------*/
  29. #ifndef NU_SPI_USE_PDMA_MIN_THRESHOLD
  30. #define NU_SPI_USE_PDMA_MIN_THRESHOLD (128)
  31. #endif
  32. enum
  33. {
  34. USPI_START = -1,
  35. #if defined(BSP_USING_USPI0)
  36. USPI0_IDX,
  37. #endif
  38. #if defined(BSP_USING_USPI1)
  39. USPI1_IDX,
  40. #endif
  41. USPI_CNT
  42. };
  43. /* Private typedef --------------------------------------------------------------*/
  44. struct nu_uspi
  45. {
  46. struct rt_spi_bus dev;
  47. char *name;
  48. USPI_T *uspi_base;
  49. struct rt_spi_configuration configuration;
  50. uint32_t dummy;
  51. #if defined(BSP_USING_USPI_PDMA)
  52. int16_t pdma_perp_tx;
  53. int8_t pdma_chanid_tx;
  54. int16_t pdma_perp_rx;
  55. int8_t pdma_chanid_rx;
  56. rt_sem_t m_psSemBus;
  57. #endif
  58. };
  59. typedef struct nu_uspi *uspi_t;
  60. /* Private functions ------------------------------------------------------------*/
  61. static rt_err_t nu_uspi_bus_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
  62. static rt_uint32_t nu_uspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message);
  63. static void nu_uspi_transmission_with_poll(struct nu_uspi *uspi_bus,
  64. uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word);
  65. static int nu_uspi_register_bus(struct nu_uspi *uspi_bus, const char *name);
  66. static void nu_uspi_drain_rxfifo(USPI_T *uspi_base);
  67. #if defined(BSP_USING_USPI_PDMA)
  68. static void nu_pdma_uspi_rx_cb(void *pvUserData, uint32_t u32EventFilter);
  69. static rt_err_t nu_pdma_uspi_rx_config(struct nu_uspi *uspi_bus, uint8_t *pu8Buf, int32_t i32RcvLen, uint8_t bytes_per_word);
  70. static rt_err_t nu_pdma_uspi_tx_config(struct nu_uspi *uspi_bus, const uint8_t *pu8Buf, int32_t i32SndLen, uint8_t bytes_per_word);
  71. static rt_size_t nu_uspi_pdma_transmit(struct nu_uspi *uspi_bus, const uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word);
  72. static rt_err_t nu_hw_uspi_pdma_allocate(struct nu_uspi *uspi_bus);
  73. #endif
  74. /* Public functions -------------------------------------------------------------*/
  75. /* Private variables ------------------------------------------------------------*/
  76. static struct rt_spi_ops nu_uspi_poll_ops =
  77. {
  78. .configure = nu_uspi_bus_configure,
  79. .xfer = nu_uspi_bus_xfer,
  80. };
  81. static struct nu_uspi nu_uspi_arr [] =
  82. {
  83. #if defined(BSP_USING_USPI0)
  84. {
  85. .name = "uspi0",
  86. .uspi_base = USPI0,
  87. #if defined(BSP_USING_USPI_PDMA)
  88. #if defined(BSP_USING_USPI0_PDMA)
  89. .pdma_perp_tx = PDMA_USCI0_TX,
  90. .pdma_perp_rx = PDMA_USCI0_RX,
  91. #else
  92. .pdma_perp_tx = NU_PDMA_UNUSED,
  93. .pdma_perp_rx = NU_PDMA_UNUSED,
  94. #endif //BSP_USING_USPI0_PDMA
  95. #endif //BSP_USING_USPI_PDMA
  96. },
  97. #endif
  98. #if defined(BSP_USING_USPI1)
  99. {
  100. .name = "uspi1",
  101. .uspi_base = USPI1,
  102. #if defined(BSP_USING_USPI_PDMA)
  103. #if defined(BSP_USING_USPI1_PDMA)
  104. .pdma_perp_tx = PDMA_USCI1_TX,
  105. .pdma_perp_rx = PDMA_USCI1_RX,
  106. #else
  107. .pdma_perp_tx = NU_PDMA_UNUSED,
  108. .pdma_perp_rx = NU_PDMA_UNUSED,
  109. #endif //BSP_USING_USPI1_PDMA
  110. #endif //BSP_USING_USPI_PDMA
  111. },
  112. #endif
  113. {0}
  114. }; /* uspi nu_uspi */
  115. static rt_err_t nu_uspi_bus_configure(struct rt_spi_device *device,
  116. struct rt_spi_configuration *configuration)
  117. {
  118. struct nu_uspi *uspi_bus;
  119. uint32_t u32SPIMode;
  120. uint32_t u32BusClock;
  121. rt_err_t ret = RT_EOK;
  122. void *pvUserData;
  123. RT_ASSERT(device != RT_NULL);
  124. RT_ASSERT(configuration != RT_NULL);
  125. uspi_bus = (struct nu_uspi *) device->bus;
  126. pvUserData = device->parent.user_data;
  127. /* Check mode */
  128. switch (configuration->mode & RT_SPI_MODE_3)
  129. {
  130. case RT_SPI_MODE_0:
  131. u32SPIMode = USPI_MODE_0;
  132. break;
  133. case RT_SPI_MODE_1:
  134. u32SPIMode = USPI_MODE_1;
  135. break;
  136. case RT_SPI_MODE_2:
  137. u32SPIMode = USPI_MODE_2;
  138. break;
  139. case RT_SPI_MODE_3:
  140. u32SPIMode = USPI_MODE_3;
  141. break;
  142. default:
  143. ret = RT_EIO;
  144. goto exit_nu_uspi_bus_configure;
  145. }
  146. /* Check data width */
  147. if (!(configuration->data_width == 8 ||
  148. configuration->data_width == 16))
  149. {
  150. ret = RT_EINVAL;
  151. goto exit_nu_uspi_bus_configure;
  152. }
  153. /* Try to set clock and get actual uspi bus clock */
  154. u32BusClock = USPI_SetBusClock(uspi_bus->uspi_base, configuration->max_hz);
  155. if (configuration->max_hz > u32BusClock)
  156. {
  157. LOG_W("%s clock max frequency is %dHz (!= %dHz)\n", uspi_bus->name, u32BusClock, configuration->max_hz);
  158. configuration->max_hz = u32BusClock;
  159. }
  160. /* Need to initialize new configuration? */
  161. if (rt_memcmp(configuration, &uspi_bus->configuration, sizeof(*configuration)) != 0)
  162. {
  163. rt_memcpy(&uspi_bus->configuration, configuration, sizeof(*configuration));
  164. USPI_Open(uspi_bus->uspi_base, USPI_MASTER, u32SPIMode, configuration->data_width, u32BusClock);
  165. if (configuration->mode & RT_SPI_CS_HIGH)
  166. {
  167. /* Set CS pin to LOW */
  168. if (pvUserData != RT_NULL)
  169. {
  170. // set to LOW */
  171. rt_pin_write(*((rt_base_t *)pvUserData), PIN_LOW);
  172. }
  173. else
  174. {
  175. USPI_SET_SS_LOW(uspi_bus->uspi_base);
  176. }
  177. }
  178. else
  179. {
  180. /* Set CS pin to HIGH */
  181. if (pvUserData != RT_NULL)
  182. {
  183. // set to HIGH */
  184. rt_pin_write(*((rt_base_t *)pvUserData), PIN_HIGH);
  185. }
  186. else
  187. {
  188. /* Set CS pin to HIGH */
  189. USPI_SET_SS_HIGH(uspi_bus->uspi_base);
  190. }
  191. }
  192. if (configuration->mode & RT_SPI_MSB)
  193. {
  194. /* Set sequence to MSB first */
  195. USPI_SET_MSB_FIRST(uspi_bus->uspi_base);
  196. }
  197. else
  198. {
  199. /* Set sequence to LSB first */
  200. USPI_SET_LSB_FIRST(uspi_bus->uspi_base);
  201. }
  202. }
  203. /* Clear USPI RX FIFO */
  204. nu_uspi_drain_rxfifo(uspi_bus->uspi_base);
  205. exit_nu_uspi_bus_configure:
  206. return -(ret);
  207. }
  208. #if defined(BSP_USING_USPI_PDMA)
  209. static void nu_pdma_uspi_rx_cb(void *pvUserData, uint32_t u32EventFilter)
  210. {
  211. rt_err_t result;
  212. struct nu_uspi *uspi_bus = (struct nu_uspi *)pvUserData;
  213. RT_ASSERT(uspi_bus != RT_NULL);
  214. result = rt_sem_release(uspi_bus->m_psSemBus);
  215. RT_ASSERT(result == RT_EOK);
  216. }
  217. static rt_err_t nu_pdma_uspi_rx_config(struct nu_uspi *uspi_bus, uint8_t *pu8Buf, int32_t i32RcvLen, uint8_t bytes_per_word)
  218. {
  219. rt_err_t result;
  220. rt_uint8_t *dst_addr = NULL;
  221. nu_pdma_memctrl_t memctrl = eMemCtl_Undefined;
  222. /* Get base address of uspi register */
  223. USPI_T *uspi_base = uspi_bus->uspi_base;
  224. rt_uint8_t uspi_pdma_rx_chid = uspi_bus->pdma_chanid_rx;
  225. result = nu_pdma_callback_register(uspi_pdma_rx_chid,
  226. nu_pdma_uspi_rx_cb,
  227. (void *)uspi_bus,
  228. NU_PDMA_EVENT_TRANSFER_DONE);
  229. if (result != RT_EOK)
  230. {
  231. goto exit_nu_pdma_uspi_rx_config;
  232. }
  233. if (pu8Buf == RT_NULL)
  234. {
  235. memctrl = eMemCtl_SrcFix_DstFix;
  236. dst_addr = (rt_uint8_t *) &uspi_bus->dummy;
  237. }
  238. else
  239. {
  240. memctrl = eMemCtl_SrcFix_DstInc;
  241. dst_addr = pu8Buf;
  242. }
  243. result = nu_pdma_channel_memctrl_set(uspi_pdma_rx_chid, memctrl);
  244. if (result != RT_EOK)
  245. {
  246. goto exit_nu_pdma_uspi_rx_config;
  247. }
  248. result = nu_pdma_transfer(uspi_pdma_rx_chid,
  249. bytes_per_word * 8,
  250. (uint32_t)&uspi_base->RXDAT,
  251. (uint32_t)dst_addr,
  252. i32RcvLen / bytes_per_word,
  253. 0);
  254. exit_nu_pdma_uspi_rx_config:
  255. return result;
  256. }
  257. static rt_err_t nu_pdma_uspi_tx_config(struct nu_uspi *uspi_bus, const uint8_t *pu8Buf, int32_t i32SndLen, uint8_t bytes_per_word)
  258. {
  259. rt_err_t result;
  260. rt_uint8_t *src_addr = NULL;
  261. nu_pdma_memctrl_t memctrl = eMemCtl_Undefined;
  262. /* Get base address of uspi register */
  263. USPI_T *uspi_base = uspi_bus->uspi_base;
  264. rt_uint8_t uspi_pdma_tx_chid = uspi_bus->pdma_chanid_tx;
  265. if (pu8Buf == RT_NULL)
  266. {
  267. uspi_bus->dummy = 0;
  268. memctrl = eMemCtl_SrcFix_DstFix;
  269. src_addr = (rt_uint8_t *)&uspi_bus->dummy;
  270. }
  271. else
  272. {
  273. memctrl = eMemCtl_SrcInc_DstFix;
  274. src_addr = (rt_uint8_t *)pu8Buf;
  275. }
  276. result = nu_pdma_channel_memctrl_set(uspi_pdma_tx_chid, memctrl);
  277. if (result != RT_EOK)
  278. {
  279. goto exit_nu_pdma_uspi_tx_config;
  280. }
  281. result = nu_pdma_transfer(uspi_pdma_tx_chid,
  282. bytes_per_word * 8,
  283. (uint32_t)src_addr,
  284. (uint32_t)&uspi_base->TXDAT,
  285. i32SndLen / bytes_per_word,
  286. 0);
  287. exit_nu_pdma_uspi_tx_config:
  288. return result;
  289. }
  290. /**
  291. * USPI PDMA transfer
  292. **/
  293. static rt_size_t nu_uspi_pdma_transmit(struct nu_uspi *uspi_bus, const uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word)
  294. {
  295. rt_err_t result = RT_EOK;
  296. rt_uint32_t u32Offset = 0;
  297. rt_uint32_t u32TransferCnt = length / bytes_per_word;
  298. rt_uint32_t u32TxCnt = 0;
  299. /* Get base address of uspi register */
  300. USPI_T *uspi_base = uspi_bus->uspi_base;
  301. do
  302. {
  303. u32TxCnt = (u32TransferCnt > NU_PDMA_MAX_TXCNT) ? NU_PDMA_MAX_TXCNT : u32TransferCnt;
  304. result = nu_pdma_uspi_rx_config(uspi_bus, (recv_addr == RT_NULL) ? recv_addr : &recv_addr[u32Offset], (u32TxCnt * bytes_per_word), bytes_per_word);
  305. RT_ASSERT(result == RT_EOK);
  306. result = nu_pdma_uspi_tx_config(uspi_bus, (send_addr == RT_NULL) ? send_addr : &send_addr[u32Offset], (u32TxCnt * bytes_per_word), bytes_per_word);
  307. RT_ASSERT(result == RT_EOK);
  308. /* Trigger TX/RX PDMA transfer. */
  309. USPI_TRIGGER_TX_RX_PDMA(uspi_base);
  310. /* Wait RX-PDMA transfer done */
  311. result = rt_sem_take(uspi_bus->m_psSemBus, RT_WAITING_FOREVER);
  312. RT_ASSERT(result == RT_EOK);
  313. /* Stop TX/RX DMA transfer. */
  314. USPI_DISABLE_TX_RX_PDMA(uspi_base);
  315. u32TransferCnt -= u32TxCnt;
  316. u32Offset += u32TxCnt;
  317. }
  318. while (u32TransferCnt > 0);
  319. return length;
  320. }
  321. static rt_err_t nu_hw_uspi_pdma_allocate(struct nu_uspi *uspi_bus)
  322. {
  323. /* Allocate USPI_TX nu_dma channel */
  324. if ((uspi_bus->pdma_chanid_tx = nu_pdma_channel_allocate(uspi_bus->pdma_perp_tx)) < 0)
  325. {
  326. goto exit_nu_hw_uspi_pdma_allocate;
  327. }
  328. /* Allocate USPI_RX nu_dma channel */
  329. else if ((uspi_bus->pdma_chanid_rx = nu_pdma_channel_allocate(uspi_bus->pdma_perp_rx)) < 0)
  330. {
  331. nu_pdma_channel_free(uspi_bus->pdma_chanid_tx);
  332. goto exit_nu_hw_uspi_pdma_allocate;
  333. }
  334. uspi_bus->m_psSemBus = rt_sem_create("uspibus_sem", 0, RT_IPC_FLAG_FIFO);
  335. RT_ASSERT(uspi_bus->m_psSemBus != RT_NULL);
  336. return RT_EOK;
  337. exit_nu_hw_uspi_pdma_allocate:
  338. return -(RT_ERROR);
  339. }
  340. #endif
  341. static void nu_uspi_drain_rxfifo(USPI_T *uspi_base)
  342. {
  343. while (USPI_IS_BUSY(uspi_base));
  344. // Drain USPI RX FIFO, make sure RX FIFO is empty
  345. while (!USPI_GET_RX_EMPTY_FLAG(uspi_base))
  346. {
  347. USPI_ClearRxBuf(uspi_base);
  348. }
  349. }
  350. static int nu_uspi_read(USPI_T *uspi_base, uint8_t *recv_addr, uint8_t bytes_per_word)
  351. {
  352. int size = 0;
  353. // Read RX data
  354. if (!USPI_GET_RX_EMPTY_FLAG(uspi_base))
  355. {
  356. uint32_t val;
  357. // Read data from USPI RX FIFO
  358. switch (bytes_per_word)
  359. {
  360. case 2:
  361. val = USPI_READ_RX(uspi_base);
  362. nu_set16_le(recv_addr, val);
  363. break;
  364. case 1:
  365. *recv_addr = USPI_READ_RX(uspi_base);
  366. break;
  367. default:
  368. LOG_E("Data length is not supported.\n");
  369. break;
  370. }
  371. size = bytes_per_word;
  372. }
  373. return size;
  374. }
  375. static int nu_uspi_write(USPI_T *uspi_base, const uint8_t *send_addr, uint8_t bytes_per_word)
  376. {
  377. // Wait USPI TX send data
  378. while (USPI_GET_TX_FULL_FLAG(uspi_base));
  379. // Input data to USPI TX
  380. switch (bytes_per_word)
  381. {
  382. case 2:
  383. USPI_WRITE_TX(uspi_base, nu_get16_le(send_addr));
  384. break;
  385. case 1:
  386. USPI_WRITE_TX(uspi_base, *((uint8_t *)send_addr));
  387. break;
  388. default:
  389. LOG_E("Data length is not supported.\n");
  390. break;
  391. }
  392. return bytes_per_word;
  393. }
  394. /**
  395. * @brief USPI bus polling
  396. * @param dev : The pointer of the specified USPI module.
  397. * @param send_addr : Source address
  398. * @param recv_addr : Destination address
  399. * @param length : Data length
  400. */
  401. static void nu_uspi_transmission_with_poll(struct nu_uspi *uspi_bus,
  402. uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word)
  403. {
  404. USPI_T *uspi_base = uspi_bus->uspi_base;
  405. // Write-only
  406. if ((send_addr != RT_NULL) && (recv_addr == RT_NULL))
  407. {
  408. while (length > 0)
  409. {
  410. send_addr += nu_uspi_write(uspi_base, send_addr, bytes_per_word);
  411. length -= bytes_per_word;
  412. }
  413. } // if (send_addr != RT_NULL && recv_addr == RT_NULL)
  414. // Read-only
  415. else if ((send_addr == RT_NULL) && (recv_addr != RT_NULL))
  416. {
  417. uspi_bus->dummy = 0;
  418. while (length > 0)
  419. {
  420. /* Input data to USPI TX FIFO */
  421. length -= nu_uspi_write(uspi_base, (const uint8_t *)&uspi_bus->dummy, bytes_per_word);
  422. /* Read data from USPI RX FIFO */
  423. while (USPI_GET_RX_EMPTY_FLAG(uspi_base));
  424. recv_addr += nu_uspi_read(uspi_base, recv_addr, bytes_per_word);
  425. }
  426. } // else if (send_addr == RT_NULL && recv_addr != RT_NULL)
  427. // Read&Write
  428. else
  429. {
  430. while (length > 0)
  431. {
  432. /* Input data to USPI TX FIFO */
  433. send_addr += nu_uspi_write(uspi_base, send_addr, bytes_per_word);
  434. length -= bytes_per_word;
  435. /* Read data from USPI RX FIFO */
  436. while (USPI_GET_RX_EMPTY_FLAG(uspi_base));
  437. recv_addr += nu_uspi_read(uspi_base, recv_addr, bytes_per_word);
  438. }
  439. } // else
  440. /* Wait USPI RX or drain USPI RX-FIFO */
  441. if (recv_addr)
  442. {
  443. // Wait USPI transmission done
  444. while (USPI_IS_BUSY(uspi_base))
  445. {
  446. while (!USPI_GET_RX_EMPTY_FLAG(uspi_base))
  447. {
  448. recv_addr += nu_uspi_read(uspi_base, recv_addr, bytes_per_word);
  449. }
  450. }
  451. while (!USPI_GET_RX_EMPTY_FLAG(uspi_base))
  452. {
  453. recv_addr += nu_uspi_read(uspi_base, recv_addr, bytes_per_word);
  454. }
  455. }
  456. else
  457. {
  458. /* Clear USPI RX FIFO */
  459. nu_uspi_drain_rxfifo(uspi_base);
  460. }
  461. }
  462. static void nu_uspi_transfer(struct nu_uspi *uspi_bus, uint8_t *tx, uint8_t *rx, int length, uint8_t bytes_per_word)
  463. {
  464. RT_ASSERT(uspi_bus != RT_NULL);
  465. #if defined(BSP_USING_USPI_PDMA)
  466. /* PDMA transfer constrains */
  467. if ((uspi_bus->pdma_chanid_rx >= 0) &&
  468. !((uint32_t)tx % bytes_per_word) &&
  469. !((uint32_t)rx % bytes_per_word) &&
  470. (length >= NU_SPI_USE_PDMA_MIN_THRESHOLD))
  471. nu_uspi_pdma_transmit(uspi_bus, tx, rx, length, bytes_per_word);
  472. else
  473. nu_uspi_transmission_with_poll(uspi_bus, tx, rx, length, bytes_per_word);
  474. #else
  475. nu_uspi_transmission_with_poll(uspi_bus, tx, rx, length, bytes_per_word);
  476. #endif
  477. }
  478. static rt_uint32_t nu_uspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  479. {
  480. struct nu_uspi *uspi_bus;
  481. struct rt_spi_configuration *configuration;
  482. uint8_t bytes_per_word;
  483. void *pvUserData;
  484. RT_ASSERT(device != RT_NULL);
  485. RT_ASSERT(device->bus != RT_NULL);
  486. RT_ASSERT(message != RT_NULL);
  487. uspi_bus = (struct nu_uspi *) device->bus;
  488. configuration = &uspi_bus->configuration;
  489. bytes_per_word = configuration->data_width / 8;
  490. pvUserData = device->parent.user_data;
  491. if ((message->length % bytes_per_word) != 0)
  492. {
  493. /* Say bye. */
  494. LOG_E("%s: error payload length(%d%%%d != 0).\n", uspi_bus->name, message->length, bytes_per_word);
  495. return 0;
  496. }
  497. if (message->length > 0)
  498. {
  499. if (message->cs_take && !(configuration->mode & RT_SPI_NO_CS))
  500. {
  501. if (pvUserData != RT_NULL)
  502. {
  503. if (configuration->mode & RT_SPI_CS_HIGH)
  504. {
  505. // set to HIGH */
  506. rt_pin_write(*((rt_base_t *)pvUserData), PIN_HIGH);
  507. }
  508. else
  509. {
  510. // set to LOW */
  511. rt_pin_write(*((rt_base_t *)pvUserData), PIN_LOW);
  512. }
  513. }
  514. else
  515. {
  516. if (configuration->mode & RT_SPI_CS_HIGH)
  517. {
  518. USPI_SET_SS_HIGH(uspi_bus->uspi_base);
  519. }
  520. else
  521. {
  522. USPI_SET_SS_LOW(uspi_bus->uspi_base);
  523. }
  524. }
  525. }
  526. nu_uspi_transfer(uspi_bus, (uint8_t *)message->send_buf, (uint8_t *)message->recv_buf, message->length, bytes_per_word);
  527. if (message->cs_release && !(configuration->mode & RT_SPI_NO_CS))
  528. {
  529. if (pvUserData != RT_NULL)
  530. {
  531. if (configuration->mode & RT_SPI_CS_HIGH)
  532. {
  533. // set to LOW */
  534. rt_pin_write(*((rt_base_t *)pvUserData), PIN_LOW);
  535. }
  536. else
  537. {
  538. // set to HIGH */
  539. rt_pin_write(*((rt_base_t *)pvUserData), PIN_HIGH);
  540. }
  541. }
  542. else
  543. {
  544. if (configuration->mode & RT_SPI_CS_HIGH)
  545. {
  546. USPI_SET_SS_LOW(uspi_bus->uspi_base);
  547. }
  548. else
  549. {
  550. USPI_SET_SS_HIGH(uspi_bus->uspi_base);
  551. }
  552. }
  553. }
  554. }
  555. return message->length;
  556. }
  557. static int nu_uspi_register_bus(struct nu_uspi *uspi_bus, const char *name)
  558. {
  559. return rt_spi_bus_register(&uspi_bus->dev, name, &nu_uspi_poll_ops);
  560. }
  561. /**
  562. * Hardware USPI Initial
  563. */
  564. static int rt_hw_uspi_init(void)
  565. {
  566. int i;
  567. for (i = (USPI_START + 1); i < USPI_CNT; i++)
  568. {
  569. nu_uspi_register_bus(&nu_uspi_arr[i], nu_uspi_arr[i].name);
  570. #if defined(BSP_USING_USPI_PDMA)
  571. nu_uspi_arr[i].pdma_chanid_tx = -1;
  572. nu_uspi_arr[i].pdma_chanid_rx = -1;
  573. if ((nu_uspi_arr[i].pdma_perp_tx != NU_PDMA_UNUSED) && (nu_uspi_arr[i].pdma_perp_rx != NU_PDMA_UNUSED))
  574. {
  575. if (nu_hw_uspi_pdma_allocate(&nu_uspi_arr[i]) != RT_EOK)
  576. {
  577. LOG_E("Failed to allocate DMA channels for %s. We will use poll-mode for this bus.\n", nu_uspi_arr[i].name);
  578. }
  579. }
  580. #endif
  581. }
  582. return 0;
  583. }
  584. INIT_DEVICE_EXPORT(rt_hw_uspi_init);
  585. #endif //#if defined(BSP_USING_USPI)