drv_spi.c 19 KB

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