drv_spi.c 20 KB

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