drv_uuart.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  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. * 2022-3-15 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_UUART)
  14. #include <rtdevice.h>
  15. #include <rthw.h>
  16. #include "NuMicro.h"
  17. #if defined(RT_SERIAL_USING_DMA)
  18. #include <drv_pdma.h>
  19. #endif
  20. /* Private define ---------------------------------------------------------------*/
  21. enum
  22. {
  23. UUART_START = -1,
  24. #if defined(BSP_USING_UUART0)
  25. UUART0_IDX,
  26. #endif
  27. UUART_CNT
  28. };
  29. /* Private typedef --------------------------------------------------------------*/
  30. struct nu_uuart
  31. {
  32. rt_serial_t dev;
  33. char *name;
  34. UUART_T *uuart_base;
  35. uint32_t uuart_rst;
  36. IRQn_Type uuart_irq_n;
  37. #if defined(RT_SERIAL_USING_DMA)
  38. uint32_t dma_flag;
  39. int16_t pdma_perp_tx;
  40. int8_t pdma_chanid_tx;
  41. int16_t pdma_perp_rx;
  42. int8_t pdma_chanid_rx;
  43. int32_t rx_write_offset;
  44. int32_t rxdma_trigger_len;
  45. nu_pdma_desc_t pdma_rx_desc;
  46. #endif
  47. };
  48. typedef struct nu_uuart *nu_uuart_t;
  49. /* Private functions ------------------------------------------------------------*/
  50. static rt_err_t nu_uuart_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
  51. static rt_err_t nu_uuart_control(struct rt_serial_device *serial, int cmd, void *arg);
  52. static int nu_uuart_send(struct rt_serial_device *serial, char c);
  53. static int nu_uuart_receive(struct rt_serial_device *serial);
  54. static void nu_uuart_isr(nu_uuart_t serial);
  55. #if defined(RT_SERIAL_USING_DMA)
  56. static rt_ssize_t nu_uuart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction);
  57. static void nu_pdma_uuart_rx_cb(void *pvOwner, uint32_t u32Events);
  58. static void nu_pdma_uuart_tx_cb(void *pvOwner, uint32_t u32Events);
  59. #endif
  60. /* Public functions ------------------------------------------------------------*/
  61. /* Private variables ------------------------------------------------------------*/
  62. static const struct rt_uart_ops nu_uuart_ops =
  63. {
  64. .configure = nu_uuart_configure,
  65. .control = nu_uuart_control,
  66. .putc = nu_uuart_send,
  67. .getc = nu_uuart_receive,
  68. #if defined(RT_SERIAL_USING_DMA)
  69. .dma_transmit = nu_uuart_dma_transmit
  70. #else
  71. .dma_transmit = RT_NULL
  72. #endif
  73. };
  74. static const struct serial_configure nu_uuart_default_config =
  75. RT_SERIAL_CONFIG_DEFAULT;
  76. static struct nu_uuart nu_uuart_arr [] =
  77. {
  78. #if defined(BSP_USING_UUART0)
  79. {
  80. .name = "uuart0",
  81. .uuart_base = UUART0,
  82. .uuart_rst = USCI0_RST,
  83. .uuart_irq_n = USCI0_IRQn,
  84. #if defined(RT_SERIAL_USING_DMA)
  85. #if defined(BSP_USING_UUART0_TX_DMA)
  86. .pdma_perp_tx = PDMA_USCI0_TX,
  87. #else
  88. .pdma_perp_tx = NU_PDMA_UNUSED,
  89. #endif
  90. #if defined(BSP_USING_UUART0_RX_DMA)
  91. .pdma_perp_rx = PDMA_USCI0_RX,
  92. .rx_write_offset = 0,
  93. #else
  94. .pdma_perp_rx = NU_PDMA_UNUSED,
  95. #endif
  96. #endif
  97. },
  98. #endif
  99. }; /* uuart nu_uuart */
  100. /* Interrupt Handle Function ----------------------------------------------------*/
  101. #if defined(BSP_USING_UUART0)
  102. /* USCI0 interrupt entry */
  103. void USCI0_IRQHandler(void)
  104. {
  105. /* enter interrupt */
  106. rt_interrupt_enter();
  107. nu_uuart_isr(&nu_uuart_arr[UUART0_IDX]);
  108. /* leave interrupt */
  109. rt_interrupt_leave();
  110. }
  111. #endif
  112. /**
  113. * All UUART interrupt service routine
  114. */
  115. static void nu_uuart_isr(nu_uuart_t serial)
  116. {
  117. /* Get base address of uuart register */
  118. UUART_T *uuart_base = ((nu_uuart_t)serial)->uuart_base;
  119. /* Get interrupt event */
  120. uint32_t u32IntSts = uuart_base->PROTSTS;
  121. uint32_t u32FIFOSts = uuart_base->BUFSTS;
  122. if (u32IntSts & (UUART_PROTSTS_PARITYERR_Msk | UUART_PROTSTS_FRMERR_Msk | UUART_PROTSTS_BREAK_Msk))
  123. {
  124. uuart_base->PROTSTS |= (UUART_PROTSTS_PARITYERR_Msk | UUART_PROTSTS_FRMERR_Msk | UUART_PROTSTS_BREAK_Msk);
  125. return;
  126. }
  127. /* Handle RX event */
  128. if (u32IntSts & UUART_PROTSTS_RXENDIF_Msk)
  129. {
  130. rt_hw_serial_isr(&serial->dev, RT_SERIAL_EVENT_RX_IND);
  131. }
  132. uuart_base->PROTSTS = u32IntSts;
  133. uuart_base->BUFSTS = u32FIFOSts;
  134. }
  135. /**
  136. * Configure uuart port
  137. */
  138. static rt_err_t nu_uuart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
  139. {
  140. rt_err_t ret = RT_EOK;
  141. uint32_t uuart_word_len = 0;
  142. uint32_t uuart_stop_bit = 0;
  143. uint32_t uuart_parity = 0;
  144. RT_ASSERT(serial);
  145. RT_ASSERT(cfg);
  146. /* Check baud rate */
  147. RT_ASSERT(cfg->baud_rate);
  148. /* Get base address of uuart register */
  149. UUART_T *uuart_base = ((nu_uuart_t)serial)->uuart_base;
  150. /* Check word len */
  151. switch (cfg->data_bits)
  152. {
  153. case DATA_BITS_5:
  154. rt_kprintf("Unsupported data length");
  155. goto exit_nu_uuart_configure;
  156. case DATA_BITS_6:
  157. uuart_word_len = UUART_WORD_LEN_6;
  158. break;
  159. case DATA_BITS_7:
  160. uuart_word_len = UUART_WORD_LEN_7;
  161. break;
  162. case DATA_BITS_8:
  163. uuart_word_len = UUART_WORD_LEN_8;
  164. break;
  165. default:
  166. rt_kprintf("Unsupported data length");
  167. ret = -RT_EINVAL;
  168. goto exit_nu_uuart_configure;
  169. }
  170. /* Check stop bit */
  171. switch (cfg->stop_bits)
  172. {
  173. case STOP_BITS_1:
  174. uuart_stop_bit = UUART_STOP_BIT_1;
  175. break;
  176. case STOP_BITS_2:
  177. uuart_stop_bit = UUART_STOP_BIT_2;
  178. break;
  179. default:
  180. rt_kprintf("Unsupported stop bit\n");
  181. ret = -RT_EINVAL;
  182. goto exit_nu_uuart_configure;
  183. }
  184. /* Check parity */
  185. switch (cfg->parity)
  186. {
  187. case PARITY_NONE:
  188. uuart_parity = UUART_PARITY_NONE;
  189. break;
  190. case PARITY_ODD:
  191. uuart_parity = UUART_PARITY_ODD;
  192. break;
  193. case PARITY_EVEN:
  194. uuart_parity = UUART_PARITY_EVEN;
  195. break;
  196. default:
  197. rt_kprintf("Unsupported parity\n");
  198. ret = -RT_EINVAL;
  199. goto exit_nu_uuart_configure;
  200. }
  201. /* Reset this module */
  202. SYS_ResetModule(((nu_uuart_t)serial)->uuart_rst);
  203. /* Open UUart and set UUART baud rate */
  204. UUART_Open(uuart_base, cfg->baud_rate);
  205. /* Set line configuration. */
  206. UUART_SetLine_Config(uuart_base, 0, uuart_word_len, uuart_parity, uuart_stop_bit);
  207. /* Enable NVIC interrupt. */
  208. NVIC_EnableIRQ(((nu_uuart_t)serial)->uuart_irq_n);
  209. exit_nu_uuart_configure:
  210. if (ret != RT_EOK)
  211. UUART_Close(uuart_base);
  212. return -(ret);
  213. }
  214. #if defined(RT_SERIAL_USING_DMA)
  215. static rt_err_t nu_pdma_uuart_rx_config(struct rt_serial_device *serial, uint8_t *pu8Buf, int32_t i32TriggerLen)
  216. {
  217. rt_err_t result = RT_EOK;
  218. struct nu_pdma_chn_cb sChnCB;
  219. nu_uuart_t psNuUUart = (nu_uuart_t)serial;
  220. /* Get base address of uart register */
  221. UUART_T *uuart_base = psNuUUart->uuart_base;
  222. /* Register ISR callback function */
  223. sChnCB.m_eCBType = eCBType_Event;
  224. sChnCB.m_pfnCBHandler = nu_pdma_uuart_rx_cb;
  225. sChnCB.m_pvUserData = (void *)serial;
  226. nu_pdma_filtering_set(psNuUUart->pdma_chanid_rx, NU_PDMA_EVENT_TRANSFER_DONE | NU_PDMA_EVENT_TIMEOUT);
  227. result = nu_pdma_callback_register(psNuUUart->pdma_chanid_rx, &sChnCB);
  228. if (result != RT_EOK)
  229. {
  230. goto exit_nu_pdma_uuart_rx_config;
  231. }
  232. if (serial->config.bufsz == 0)
  233. {
  234. result = nu_pdma_transfer(((nu_uuart_t)serial)->pdma_chanid_rx,
  235. 8,
  236. (uint32_t)&uuart_base->RXDAT,
  237. (uint32_t)pu8Buf,
  238. i32TriggerLen,
  239. 1000); //Idle-timeout, 1ms
  240. if (result != RT_EOK)
  241. {
  242. goto exit_nu_pdma_uuart_rx_config;
  243. }
  244. }
  245. else
  246. {
  247. /* For Serial RX FIFO - Single buffer recycle SG trigger */
  248. /* Link to next */
  249. nu_pdma_desc_t next = psNuUUart->pdma_rx_desc;
  250. result = nu_pdma_desc_setup(psNuUUart->pdma_chanid_rx,
  251. psNuUUart->pdma_rx_desc,
  252. 8,
  253. (uint32_t)&uuart_base->RXDAT,
  254. (uint32_t)pu8Buf,
  255. i32TriggerLen,
  256. next,
  257. 0);
  258. if (result != RT_EOK)
  259. {
  260. goto exit_nu_pdma_uuart_rx_config;
  261. }
  262. /* Assign head descriptor & go */
  263. result = nu_pdma_sg_transfer(psNuUUart->pdma_chanid_rx, psNuUUart->pdma_rx_desc, 1000);
  264. if (result != RT_EOK)
  265. {
  266. goto exit_nu_pdma_uuart_rx_config;
  267. }
  268. }
  269. /* Enable Receive Line interrupt & Start DMA RX transfer. */
  270. UUART_EnableInt(uuart_base, UUART_RLS_INT_MASK);
  271. UUART_PDMA_ENABLE(uuart_base, UUART_PDMACTL_RXPDMAEN_Msk | UUART_PDMACTL_PDMAEN_Msk);
  272. exit_nu_pdma_uuart_rx_config:
  273. return result;
  274. }
  275. static void nu_pdma_uuart_rx_cb(void *pvOwner, uint32_t u32Events)
  276. {
  277. rt_size_t recv_len = 0;
  278. rt_size_t transferred_rxbyte = 0;
  279. struct rt_serial_device *serial = (struct rt_serial_device *)pvOwner;
  280. nu_uuart_t puuart = (nu_uuart_t)serial;
  281. RT_ASSERT(serial);
  282. /* Get base address of uuart register */
  283. UUART_T *uuart_base = puuart->uuart_base;
  284. transferred_rxbyte = nu_pdma_transferred_byte_get(puuart->pdma_chanid_rx, puuart->rxdma_trigger_len);
  285. if (u32Events & (NU_PDMA_EVENT_TRANSFER_DONE | NU_PDMA_EVENT_TIMEOUT))
  286. {
  287. if (u32Events & NU_PDMA_EVENT_TRANSFER_DONE)
  288. {
  289. transferred_rxbyte = puuart->rxdma_trigger_len;
  290. }
  291. else if ((u32Events & NU_PDMA_EVENT_TIMEOUT) && !UUART_GET_RX_EMPTY(uuart_base))
  292. {
  293. return;
  294. }
  295. recv_len = transferred_rxbyte - puuart->rx_write_offset;
  296. puuart->rx_write_offset = transferred_rxbyte % puuart->rxdma_trigger_len;
  297. }
  298. if ((serial->config.bufsz == 0) && (u32Events & NU_PDMA_EVENT_TRANSFER_DONE))
  299. {
  300. recv_len = puuart->rxdma_trigger_len;
  301. }
  302. if (recv_len)
  303. {
  304. rt_hw_serial_isr(&puuart->dev, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8));
  305. }
  306. }
  307. static rt_err_t nu_pdma_uuart_tx_config(struct rt_serial_device *serial)
  308. {
  309. struct nu_pdma_chn_cb sChnCB;
  310. RT_ASSERT(serial);
  311. /* Register ISR callback function */
  312. sChnCB.m_eCBType = eCBType_Event;
  313. sChnCB.m_pfnCBHandler = nu_pdma_uuart_tx_cb;
  314. sChnCB.m_pvUserData = (void *)serial;
  315. nu_pdma_filtering_set(((nu_uuart_t)serial)->pdma_chanid_tx, NU_PDMA_EVENT_TRANSFER_DONE);
  316. return nu_pdma_callback_register(((nu_uuart_t)serial)->pdma_chanid_tx, &sChnCB);
  317. }
  318. static void nu_pdma_uuart_tx_cb(void *pvOwner, uint32_t u32Events)
  319. {
  320. nu_uuart_t puuart = (nu_uuart_t)pvOwner;
  321. RT_ASSERT(puuart);
  322. // Stop DMA TX transfer
  323. UUART_PDMA_DISABLE(puuart->uuart_base, UUART_PDMACTL_TXPDMAEN_Msk);
  324. if (u32Events & NU_PDMA_EVENT_TRANSFER_DONE)
  325. {
  326. rt_hw_serial_isr(&puuart->dev, RT_SERIAL_EVENT_TX_DMADONE);
  327. }
  328. }
  329. /**
  330. * UUart DMA transfer
  331. */
  332. static rt_ssize_t nu_uuart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction)
  333. {
  334. rt_err_t result = RT_EOK;
  335. nu_uuart_t psNuUUart = (nu_uuart_t)serial;
  336. RT_ASSERT(serial);
  337. RT_ASSERT(buf);
  338. /* Get base address of uuart register */
  339. UUART_T *uuart_base = psNuUUart->uuart_base;
  340. if (direction == RT_SERIAL_DMA_TX)
  341. {
  342. result = nu_pdma_transfer(psNuUUart->pdma_chanid_tx,
  343. 8,
  344. (uint32_t)buf,
  345. (uint32_t)&uuart_base->TXDAT,
  346. size,
  347. 0); // wait-forever
  348. // Start DMA TX transfer
  349. UUART_PDMA_ENABLE(uuart_base, UUART_PDMACTL_TXPDMAEN_Msk | UUART_PDMACTL_PDMAEN_Msk);
  350. }
  351. else if (direction == RT_SERIAL_DMA_RX)
  352. {
  353. UUART_DisableInt(uuart_base, UUART_RLS_INT_MASK);
  354. UUART_PDMA_DISABLE(uuart_base, UUART_PDMACTL_RXPDMAEN_Msk | UUART_PDMACTL_PDMAEN_Msk);
  355. // If config.bufsz = 0, serial will trigger once.
  356. psNuUUart->rxdma_trigger_len = size;
  357. psNuUUart->rx_write_offset = 0;
  358. result = nu_pdma_uuart_rx_config(serial, buf, size);
  359. }
  360. else
  361. {
  362. result = RT_ERROR;
  363. }
  364. return result;
  365. }
  366. static int nu_hw_uuart_dma_allocate(nu_uuart_t puuart)
  367. {
  368. RT_ASSERT(puuart);
  369. /* Allocate UUART_TX nu_dma channel */
  370. if (puuart->pdma_perp_tx != NU_PDMA_UNUSED)
  371. {
  372. puuart->pdma_chanid_tx = nu_pdma_channel_allocate(puuart->pdma_perp_tx);
  373. if (puuart->pdma_chanid_tx >= 0)
  374. {
  375. puuart->dma_flag |= RT_DEVICE_FLAG_DMA_TX;
  376. }
  377. }
  378. /* Allocate UUART_RX nu_dma channel */
  379. if (puuart->pdma_perp_rx != NU_PDMA_UNUSED)
  380. {
  381. puuart->pdma_chanid_rx = nu_pdma_channel_allocate(puuart->pdma_perp_rx);
  382. if (puuart->pdma_chanid_rx >= 0)
  383. {
  384. rt_err_t ret = RT_EOK;
  385. puuart->dma_flag |= RT_DEVICE_FLAG_DMA_RX;
  386. ret = nu_pdma_sgtbls_allocate(&puuart->pdma_rx_desc, 1);
  387. RT_ASSERT(ret == RT_EOK);
  388. }
  389. }
  390. return RT_EOK;
  391. }
  392. #endif
  393. /**
  394. * UUart interrupt control
  395. */
  396. static rt_err_t nu_uuart_control(struct rt_serial_device *serial, int cmd, void *arg)
  397. {
  398. nu_uuart_t psNuUUart = (nu_uuart_t)serial;
  399. rt_err_t result = RT_EOK;
  400. rt_ubase_t ctrl_arg = (rt_ubase_t)arg;
  401. RT_ASSERT(serial);
  402. /* Get base address of uuart register */
  403. UUART_T *uuart_base = psNuUUart->uuart_base;
  404. switch (cmd)
  405. {
  406. case RT_DEVICE_CTRL_CLR_INT:
  407. if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) /* Disable INT-RX */
  408. {
  409. UUART_DisableInt(uuart_base, UUART_RXEND_INT_MASK);
  410. }
  411. else if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) /* Disable DMA-RX */
  412. {
  413. /* Disable Receive Line interrupt & Stop DMA RX transfer. */
  414. #if defined(RT_SERIAL_USING_DMA)
  415. nu_pdma_channel_terminate(((nu_uuart_t)serial)->pdma_chanid_rx);
  416. UUART_PDMA_DISABLE(uuart_base, UUART_PDMACTL_RXPDMAEN_Msk);
  417. UUART_DisableInt(uuart_base, UUART_RLS_INT_MASK);
  418. #endif
  419. }
  420. break;
  421. case RT_DEVICE_CTRL_SET_INT:
  422. if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) /* Enable INT-RX */
  423. {
  424. UUART_EnableInt(uuart_base, UUART_RXEND_INT_MASK);
  425. }
  426. break;
  427. #if defined(RT_SERIAL_USING_DMA)
  428. case RT_DEVICE_CTRL_CONFIG:
  429. if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) /* Configure and trigger DMA-RX */
  430. {
  431. struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
  432. psNuUUart->rxdma_trigger_len = serial->config.bufsz;
  433. psNuUUart->rx_write_offset = 0;
  434. result = nu_pdma_uuart_rx_config(serial, &rx_fifo->buffer[0], psNuUUart->rxdma_trigger_len); // Config & trigger
  435. }
  436. else if (ctrl_arg == RT_DEVICE_FLAG_DMA_TX) /* Configure DMA-TX */
  437. {
  438. result = nu_pdma_uuart_tx_config(serial);
  439. }
  440. break;
  441. #endif
  442. case RT_DEVICE_CTRL_CLOSE:
  443. /* Disable NVIC interrupt. */
  444. NVIC_DisableIRQ(psNuUUart->uuart_irq_n);
  445. #if defined(RT_SERIAL_USING_DMA)
  446. UUART_DisableInt(uuart_base, UUART_RXEND_INT_MASK | UUART_RLS_INT_MASK);
  447. UUART_PDMA_DISABLE(uuart_base, UUART_PDMACTL_TXPDMAEN_Msk | UUART_PDMACTL_PDMAEN_Msk);
  448. nu_pdma_channel_terminate(psNuUUart->pdma_chanid_tx);
  449. nu_pdma_channel_terminate(psNuUUart->pdma_chanid_rx);
  450. #endif
  451. /* Reset this module */
  452. SYS_ResetModule(psNuUUart->uuart_rst);
  453. /* Close UUART port */
  454. UUART_Close(uuart_base);
  455. break;
  456. default:
  457. result = -RT_EINVAL;
  458. break;
  459. }
  460. return result;
  461. }
  462. /**
  463. * UUart put char
  464. */
  465. static int nu_uuart_send(struct rt_serial_device *serial, char c)
  466. {
  467. RT_ASSERT(serial);
  468. /* Get base address of uuart register */
  469. UUART_T *uuart_base = ((nu_uuart_t)serial)->uuart_base;
  470. /* Waiting if TX-FIFO is full. */
  471. while (UUART_IS_TX_FULL(uuart_base));
  472. /* Put char into TX-FIFO */
  473. UUART_WRITE(uuart_base, c);
  474. return 1;
  475. }
  476. /**
  477. * UUart get char
  478. */
  479. static int nu_uuart_receive(struct rt_serial_device *serial)
  480. {
  481. RT_ASSERT(serial);
  482. /* Get base address of uuart register */
  483. UUART_T *uuart_base = ((nu_uuart_t)serial)->uuart_base;
  484. /* Return failure if RX-FIFO is empty. */
  485. if (UUART_GET_RX_EMPTY(uuart_base))
  486. {
  487. return -1;
  488. }
  489. /* Get char from RX-FIFO */
  490. return UUART_READ(uuart_base);
  491. }
  492. /**
  493. * Hardware UUART Initialization
  494. */
  495. static int rt_hw_uuart_init(void)
  496. {
  497. int i;
  498. rt_uint32_t flag;
  499. rt_err_t ret = RT_EOK;
  500. for (i = (UUART_START + 1); i < UUART_CNT; i++)
  501. {
  502. flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX;
  503. nu_uuart_arr[i].dev.ops = &nu_uuart_ops;
  504. nu_uuart_arr[i].dev.config = nu_uuart_default_config;
  505. #if defined(RT_SERIAL_USING_DMA)
  506. nu_uuart_arr[i].dma_flag = 0;
  507. nu_hw_uuart_dma_allocate(&nu_uuart_arr[i]);
  508. flag |= nu_uuart_arr[i].dma_flag;
  509. #endif
  510. ret = rt_hw_serial_register(&nu_uuart_arr[i].dev, nu_uuart_arr[i].name, flag, NULL);
  511. RT_ASSERT(ret == RT_EOK);
  512. }
  513. return (int)ret;
  514. }
  515. INIT_DEVICE_EXPORT(rt_hw_uuart_init);
  516. #endif //#if defined(BSP_USING_UUART)