drv_leuart.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2011-12-09 onelife Initial creation for EFM32
  9. * 2011-12-27 onelife Utilize "LEUART_PRESENT" and "LEUART_COUNT"
  10. */
  11. /***************************************************************************//**
  12. * @addtogroup efm32
  13. * @{
  14. ******************************************************************************/
  15. /* Includes ------------------------------------------------------------------*/
  16. #include "board.h"
  17. #include "hdl_interrupt.h"
  18. #include "drv_leuart.h"
  19. #if (defined(RT_USING_LEUART0) || defined(RT_USING_LEUART1))
  20. #if !defined(LEUART_PRESENT)
  21. #error "LEUART module is not available"
  22. #endif
  23. /* Private typedef -----------------------------------------------------------*/
  24. /* Private define ------------------------------------------------------------*/
  25. /* Private macro -------------------------------------------------------------*/
  26. #ifdef RT_LEUART_DEBUG
  27. #define leuart_debug(format,args...) rt_kprintf(format, ##args)
  28. #else
  29. #define leuart_debug(format,args...)
  30. #endif
  31. /* Private variables ---------------------------------------------------------*/
  32. #if defined(RT_USING_LEUART0)
  33. #if (RT_USING_LEUART0 >= EFM32_LEUART_LOCATION_COUNT)
  34. #error "Wrong location number"
  35. #endif
  36. struct rt_device leuart0_device;
  37. static struct rt_semaphore leuart0_lock;
  38. #endif
  39. #if defined(RT_USING_LEUART1)
  40. #if (LEUART_COUNT <= 1)
  41. #error "Wrong unit number"
  42. #endif
  43. #if (RT_USING_LEUART1 >= EFM32_LEUART_LOCATION_COUNT)
  44. #error "Wrong location number"
  45. #endif
  46. struct rt_device leuart1_device;
  47. static struct rt_semaphore leuart1_lock;
  48. #endif
  49. /* Private function prototypes -----------------------------------------------*/
  50. /* Private functions ---------------------------------------------------------*/
  51. /***************************************************************************//**
  52. * @brief
  53. * Initialize LEUART device
  54. *
  55. * @details
  56. *
  57. * @note
  58. *
  59. * @param[in] dev
  60. * Pointer to device descriptor
  61. *
  62. * @return
  63. * Error code
  64. ******************************************************************************/
  65. static rt_err_t rt_leuart_init (rt_device_t dev)
  66. {
  67. struct efm32_leuart_device_t *leuart;
  68. leuart = (struct efm32_leuart_device_t *)(dev->user_data);
  69. if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
  70. {
  71. if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
  72. {
  73. struct efm32_leuart_dma_mode_t *dma_tx;
  74. dma_tx = (struct efm32_leuart_dma_mode_t *)(leuart->tx_mode);
  75. leuart->state |= LEUART_STATE_RX_BUSY;
  76. }
  77. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  78. {
  79. struct efm32_leuart_int_mode_t *int_rx;
  80. int_rx = (struct efm32_leuart_int_mode_t *)(leuart->rx_mode);
  81. int_rx->data_ptr = RT_NULL;
  82. }
  83. /* Enable LEUART */
  84. LEUART_Enable(leuart->leuart_device, leuartEnable);
  85. dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
  86. }
  87. return RT_EOK;
  88. }
  89. /***************************************************************************//**
  90. * @brief
  91. * Open LEUART device
  92. *
  93. * @details
  94. *
  95. * @note
  96. *
  97. * @param[in] dev
  98. * Pointer to device descriptor
  99. *
  100. * @param[in] oflag
  101. * Device open flag
  102. *
  103. * @return
  104. * Error code
  105. ******************************************************************************/
  106. static rt_err_t rt_leuart_open(rt_device_t dev, rt_uint16_t oflag)
  107. {
  108. RT_ASSERT(dev != RT_NULL);
  109. struct efm32_leuart_device_t *leuart;
  110. leuart = (struct efm32_leuart_device_t *)(dev->user_data);
  111. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  112. {
  113. IRQn_Type rxIrq;
  114. //if (leuart->state & LEUART_STATE_CONSOLE)
  115. { /* Allocate new RX buffer */
  116. struct efm32_leuart_int_mode_t *int_mode;
  117. int_mode = (struct efm32_leuart_int_mode_t *)(leuart->rx_mode);
  118. if ((int_mode->data_ptr = rt_malloc(LEUART_RX_BUFFER_SIZE)) == RT_NULL)
  119. {
  120. leuart_debug("LEUART%d err: no mem for RX BUF\n", leuart->unit);
  121. return -RT_ENOMEM;
  122. }
  123. rt_memset(int_mode->data_ptr, 0, LEUART_RX_BUFFER_SIZE);
  124. int_mode->data_size = LEUART_RX_BUFFER_SIZE;
  125. int_mode->read_index = 0;
  126. int_mode->save_index = 0;
  127. }
  128. /* Enable RX interrupt */
  129. leuart->leuart_device->IEN = LEUART_IEN_RXDATAV;
  130. /* Enable IRQ */
  131. switch (leuart->unit)
  132. {
  133. case 0:
  134. rxIrq = LEUART0_IRQn;
  135. break;
  136. #if (LEUART_COUNT > 1)
  137. case 1:
  138. rxIrq = LEUART1_IRQn;
  139. break;
  140. #endif
  141. }
  142. if (oflag != RT_DEVICE_OFLAG_WRONLY)
  143. {
  144. NVIC_ClearPendingIRQ(rxIrq);
  145. NVIC_SetPriority(rxIrq, EFM32_IRQ_PRI_DEFAULT);
  146. NVIC_EnableIRQ(rxIrq);
  147. }
  148. }
  149. /* Clear Flag */
  150. leuart->leuart_device->IFC = _LEUART_IFC_MASK;
  151. if ((dev->flag & RT_DEVICE_FLAG_DMA_TX) && (oflag != RT_DEVICE_OFLAG_RDONLY))
  152. {
  153. /* DMA IRQ is enabled by DMA_Init() */
  154. NVIC_SetPriority(DMA_IRQn, EFM32_IRQ_PRI_DEFAULT);
  155. }
  156. leuart->counter++;
  157. leuart_debug("LEUART%d: Open with flag %x\n", leuart->unit, oflag);
  158. return RT_EOK;
  159. }
  160. /***************************************************************************//**
  161. * @brief
  162. * Close LEUART device
  163. *
  164. * @details
  165. *
  166. * @note
  167. *
  168. * @param[in] dev
  169. * Pointer to device descriptor
  170. *
  171. * @return
  172. * Error code
  173. ******************************************************************************/
  174. static rt_err_t rt_leuart_close(rt_device_t dev)
  175. {
  176. RT_ASSERT(dev != RT_NULL);
  177. struct efm32_leuart_device_t *leuart;
  178. leuart = (struct efm32_leuart_device_t *)(dev->user_data);
  179. if (--leuart->counter == 0)
  180. {
  181. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  182. {
  183. struct efm32_leuart_int_mode_t *int_rx;
  184. int_rx = (struct efm32_leuart_int_mode_t *)leuart->rx_mode;
  185. rt_free(int_rx->data_ptr);
  186. int_rx->data_ptr = RT_NULL;
  187. }
  188. }
  189. return RT_EOK;
  190. }
  191. /***************************************************************************//**
  192. * @brief
  193. * Read from LEUART device
  194. *
  195. * @details
  196. *
  197. * @note
  198. *
  199. * @param[in] dev
  200. * Pointer to device descriptor
  201. *
  202. * @param[in] pos
  203. * Offset
  204. *
  205. * @param[in] buffer
  206. * Poniter to the buffer
  207. *
  208. * @param[in] size
  209. * Buffer size in byte
  210. *
  211. * @return
  212. * Number of read bytes
  213. ******************************************************************************/
  214. static rt_size_t rt_leuart_read (
  215. rt_device_t dev,
  216. rt_off_t pos,
  217. void *buffer,
  218. rt_size_t size)
  219. {
  220. struct efm32_leuart_device_t *leuart;
  221. rt_uint8_t *ptr;
  222. rt_err_t err_code;
  223. rt_size_t read_len;
  224. leuart = (struct efm32_leuart_device_t *)(dev->user_data);
  225. /* Lock device */
  226. if (rt_hw_interrupt_check())
  227. {
  228. err_code = rt_sem_take(leuart->lock, RT_WAITING_NO);
  229. }
  230. else
  231. {
  232. err_code = rt_sem_take(leuart->lock, RT_WAITING_FOREVER);
  233. }
  234. if (err_code != RT_EOK)
  235. {
  236. rt_set_errno(err_code);
  237. return 0;
  238. }
  239. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  240. {
  241. ptr = buffer;
  242. /* interrupt mode Rx */
  243. while (size)
  244. {
  245. rt_base_t level;
  246. struct efm32_leuart_int_mode_t *int_rx;
  247. int_rx = (struct efm32_leuart_int_mode_t *)\
  248. (((struct efm32_leuart_device_t *)(dev->user_data))->rx_mode);
  249. /* disable interrupt */
  250. level = rt_hw_interrupt_disable();
  251. if (int_rx->read_index != int_rx->save_index)
  252. {
  253. /* read a character */
  254. *ptr++ = int_rx->data_ptr[int_rx->read_index];
  255. size--;
  256. /* move to next position */
  257. int_rx->read_index ++;
  258. if (int_rx->read_index >= LEUART_RX_BUFFER_SIZE)
  259. {
  260. int_rx->read_index = 0;
  261. }
  262. }
  263. else
  264. {
  265. /* set error code */
  266. err_code = -RT_EEMPTY;
  267. /* enable interrupt */
  268. rt_hw_interrupt_enable(level);
  269. break;
  270. }
  271. /* enable interrupt */
  272. rt_hw_interrupt_enable(level);
  273. }
  274. read_len = (rt_uint32_t)ptr - (rt_uint32_t)buffer;
  275. }
  276. else
  277. {
  278. LEUART_TypeDef *leuart_device;
  279. leuart = (struct efm32_leuart_device_t *)(dev->user_data);
  280. leuart_device = ((struct efm32_leuart_device_t *)(dev->user_data))->leuart_device;
  281. ptr = buffer;
  282. /* polling mode */
  283. while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size)
  284. {
  285. while (leuart_device->STATUS & LEUART_STATUS_RXDATAV)
  286. {
  287. *ptr = leuart_device->RXDATA & 0xff;
  288. ptr ++;
  289. }
  290. }
  291. read_len = size;
  292. }
  293. /* Unlock device */
  294. rt_sem_release(leuart->lock);
  295. /* set error code */
  296. rt_set_errno(err_code);
  297. return read_len;
  298. }
  299. /***************************************************************************//**
  300. * @brief
  301. * Write to LEUART device
  302. *
  303. * @details
  304. *
  305. * @note
  306. *
  307. * @param[in] dev
  308. * Pointer to device descriptor
  309. *
  310. * @param[in] pos
  311. * Offset
  312. *
  313. * @param[in] buffer
  314. * Poniter to the buffer
  315. *
  316. * @param[in] size
  317. * Buffer size in byte
  318. *
  319. * @return
  320. * Number of written bytes
  321. ******************************************************************************/
  322. static rt_size_t rt_leuart_write (
  323. rt_device_t dev,
  324. rt_off_t pos,
  325. const void* buffer,
  326. rt_size_t size)
  327. {
  328. rt_err_t err_code;
  329. rt_size_t write_size;
  330. struct efm32_leuart_device_t* leuart;
  331. write_size = 0;
  332. leuart = (struct efm32_leuart_device_t*)(dev->user_data);
  333. /* Lock device */
  334. if (rt_hw_interrupt_check())
  335. {
  336. err_code = rt_sem_take(leuart->lock, RT_WAITING_NO);
  337. }
  338. else
  339. {
  340. err_code = rt_sem_take(leuart->lock, RT_WAITING_FOREVER);
  341. }
  342. if (err_code != RT_EOK)
  343. {
  344. rt_set_errno(err_code);
  345. return 0;
  346. }
  347. if ((dev->flag & RT_DEVICE_FLAG_DMA_TX) && (size > 2))
  348. { /* DMA mode Tx */
  349. struct efm32_leuart_dma_mode_t *dma_tx;
  350. if (dev->flag & RT_DEVICE_FLAG_STREAM)
  351. {
  352. if (*((rt_uint8_t *)buffer + size - 1) == '\n')
  353. {
  354. *((rt_uint8_t *)buffer + size - 1) = '\r';
  355. *((rt_uint8_t *)buffer + size++) = '\n';
  356. *((rt_uint8_t *)buffer + size) = 0;
  357. }
  358. }
  359. dma_tx = (struct efm32_leuart_dma_mode_t *)(leuart->tx_mode);
  360. dma_tx->data_ptr = (rt_uint32_t *)buffer;
  361. dma_tx->data_size = size;
  362. leuart->state |= LEUART_STATE_TX_BUSY;
  363. DMA_ActivateBasic(
  364. dma_tx->dma_channel,
  365. true,
  366. false,
  367. (void *)&(leuart->leuart_device->TXDATA),
  368. (void *)buffer,
  369. (rt_uint32_t)(size - 1));
  370. /* Wait, otherwise the TX buffer is overwrite */
  371. // if (leuart->state & LEUART_STATE_CONSOLE)
  372. // {
  373. while(leuart->state & LEUART_STATE_TX_BUSY);
  374. // }
  375. // else
  376. // {
  377. // while(leuart->state & LEUART_STATE_TX_BUSY)
  378. // {
  379. // rt_thread_sleep(LEUART_WAIT_TIME_TX);
  380. // }
  381. // }
  382. // TODO: This function blocks the process
  383. write_size = size;
  384. }
  385. else
  386. { /* polling mode */
  387. rt_uint8_t *ptr = (rt_uint8_t *)buffer;
  388. if (dev->flag & RT_DEVICE_FLAG_STREAM)
  389. {
  390. /* stream mode */
  391. while (size)
  392. {
  393. if (*ptr == '\n')
  394. {
  395. while (!(leuart->leuart_device->STATUS & LEUART_STATUS_TXBL));
  396. leuart->leuart_device->TXDATA = '\r';
  397. }
  398. while (!(leuart->leuart_device->STATUS & LEUART_STATUS_TXBL));
  399. leuart->leuart_device->TXDATA = (rt_uint32_t)*ptr;
  400. ++ptr; --size;
  401. }
  402. }
  403. else
  404. {
  405. /* write data directly */
  406. while (size)
  407. {
  408. while (!(leuart->leuart_device->STATUS & LEUART_STATUS_TXBL));
  409. leuart->leuart_device->TXDATA = (rt_uint32_t)*ptr;
  410. ++ptr; --size;
  411. }
  412. }
  413. write_size = (rt_size_t)ptr - (rt_size_t)buffer;
  414. }
  415. /* Unlock device */
  416. rt_sem_release(leuart->lock);
  417. /* set error code */
  418. rt_set_errno(err_code);
  419. return write_size;
  420. }
  421. /***************************************************************************//**
  422. * @brief
  423. * Configure LEUART device
  424. *
  425. * @details
  426. *
  427. * @note
  428. *
  429. * @param[in] dev
  430. * Pointer to device descriptor
  431. *
  432. * @param[in] cmd
  433. * IIC control command
  434. *
  435. * @param[in] args
  436. * Arguments
  437. *
  438. * @return
  439. * Error code
  440. ******************************************************************************/
  441. static rt_err_t rt_leuart_control (
  442. rt_device_t dev,
  443. rt_uint8_t cmd,
  444. void *args)
  445. {
  446. RT_ASSERT(dev != RT_NULL);
  447. rt_err_t err_code;
  448. struct efm32_leuart_device_t *leuart;
  449. leuart = (struct efm32_leuart_device_t *)(dev->user_data);
  450. /* Lock device */
  451. if (rt_hw_interrupt_check())
  452. {
  453. err_code = rt_sem_take(leuart->lock, RT_WAITING_NO);
  454. }
  455. else
  456. {
  457. err_code = rt_sem_take(leuart->lock, RT_WAITING_FOREVER);
  458. }
  459. if (err_code != RT_EOK)
  460. {
  461. return err_code;
  462. }
  463. switch (cmd)
  464. {
  465. case RT_DEVICE_CTRL_SUSPEND:
  466. /* Suspend device */
  467. dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
  468. LEUART_Enable(leuart->leuart_device, leuartDisable);
  469. break;
  470. case RT_DEVICE_CTRL_RESUME:
  471. /* Resume device */
  472. dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
  473. LEUART_Enable(leuart->leuart_device, leuartEnable);
  474. break;
  475. case RT_DEVICE_CTRL_LEUART_RBUFFER:
  476. /* Set RX buffer */
  477. {
  478. struct efm32_leuart_int_mode_t *int_rx;
  479. rt_uint8_t size;
  480. int_rx = (struct efm32_leuart_int_mode_t *)(leuart->rx_mode);
  481. size = (rt_uint8_t)((rt_uint32_t)args & 0xFFUL);
  482. /* Free previous RX buffer */
  483. if (int_rx->data_ptr != RT_NULL)
  484. {
  485. if (size == 0)
  486. { /* Free RX buffer */
  487. rt_free(int_rx->data_ptr);
  488. int_rx->data_ptr = RT_NULL;
  489. }
  490. else if (size != int_rx->data_size)
  491. {
  492. /* Re-allocate RX buffer */
  493. if ((int_rx->data_ptr = rt_realloc(int_rx->data_ptr, size)) \
  494. == RT_NULL)
  495. {
  496. leuart_debug("LEUART%d err: no mem for RX BUF\n", leuart->unit);
  497. err_code = -RT_ENOMEM;
  498. break;
  499. }
  500. // TODO: Is the following line necessary?
  501. //rt_memset(int_rx->data_ptr, 0, size);
  502. }
  503. }
  504. else
  505. {
  506. /* Allocate new RX buffer */
  507. if ((int_rx->data_ptr = rt_malloc(size)) == RT_NULL)
  508. {
  509. leuart_debug("LEUART%d err: no mem for RX BUF\n", leuart->unit);
  510. err_code = -RT_ENOMEM;
  511. break;
  512. }
  513. }
  514. int_rx->data_size = size;
  515. int_rx->read_index = 0;
  516. int_rx->save_index = 0;
  517. }
  518. break;
  519. }
  520. /* Unlock device */
  521. rt_sem_release(leuart->lock);
  522. return err_code;
  523. }
  524. /***************************************************************************//**
  525. * @brief
  526. * LEUART RX data valid interrupt handler
  527. *
  528. * @details
  529. *
  530. * @note
  531. *
  532. * @param[in] dev
  533. * Pointer to device descriptor
  534. ******************************************************************************/
  535. void rt_hw_leuart_rx_isr(rt_device_t dev)
  536. {
  537. struct efm32_leuart_device_t *leuart;
  538. struct efm32_leuart_int_mode_t *int_rx;
  539. rt_uint32_t flag;
  540. /* interrupt mode receive */
  541. RT_ASSERT(dev->flag & RT_DEVICE_FLAG_INT_RX);
  542. leuart = (struct efm32_leuart_device_t *)(dev->user_data);
  543. int_rx = (struct efm32_leuart_int_mode_t *)(leuart->rx_mode);
  544. RT_ASSERT(int_rx->data_ptr != RT_NULL);
  545. /* Set status */
  546. leuart->state |= LEUART_STATE_RX_BUSY;
  547. /* save into rx buffer */
  548. while (leuart->leuart_device->STATUS & LEUART_STATUS_RXDATAV)
  549. {
  550. rt_base_t level;
  551. /* disable interrupt */
  552. level = rt_hw_interrupt_disable();
  553. /* save character */
  554. int_rx->data_ptr[int_rx->save_index] = \
  555. (rt_uint8_t)(leuart->leuart_device->RXDATA & 0xFFUL);
  556. int_rx->save_index ++;
  557. if (int_rx->save_index >= LEUART_RX_BUFFER_SIZE)
  558. int_rx->save_index = 0;
  559. /* if the next position is read index, discard this 'read char' */
  560. if (int_rx->save_index == int_rx->read_index)
  561. {
  562. int_rx->read_index ++;
  563. if (int_rx->read_index >= LEUART_RX_BUFFER_SIZE)
  564. {
  565. int_rx->read_index = 0;
  566. }
  567. }
  568. /* enable interrupt */
  569. rt_hw_interrupt_enable(level);
  570. }
  571. /* invoke callback */
  572. if (dev->rx_indicate != RT_NULL)
  573. {
  574. rt_size_t rx_length;
  575. /* get rx length */
  576. rx_length = int_rx->read_index > int_rx->save_index ?
  577. LEUART_RX_BUFFER_SIZE - int_rx->read_index + int_rx->save_index : \
  578. int_rx->save_index - int_rx->read_index;
  579. dev->rx_indicate(dev, rx_length);
  580. }
  581. }
  582. /***************************************************************************//**
  583. * @brief
  584. * DMA for LEUART TX interrupt handler
  585. *
  586. * @details
  587. *
  588. * @note
  589. *
  590. * @param[in] dev
  591. * Pointer to device descriptor
  592. ******************************************************************************/
  593. void rt_hw_leuart_dma_tx_isr(rt_device_t dev)
  594. {
  595. /* DMA mode receive */
  596. struct efm32_leuart_device_t *leuart;
  597. struct efm32_leuart_dma_mode_t *dma_tx;
  598. RT_ASSERT(dev->flag & RT_DEVICE_FLAG_DMA_TX);
  599. leuart = (struct efm32_leuart_device_t *)(dev->user_data);
  600. dma_tx = (struct efm32_leuart_dma_mode_t *)(leuart->tx_mode);
  601. /* invoke call to notify tx complete */
  602. if (dev->tx_complete != RT_NULL)
  603. {
  604. dev->tx_complete(dev, dma_tx->data_ptr);
  605. }
  606. /* Set status */
  607. leuart->state &= ~(rt_uint32_t)LEUART_STATE_TX_BUSY;
  608. }
  609. /***************************************************************************//**
  610. * @brief
  611. * Register LEUART device
  612. *
  613. * @details
  614. *
  615. * @note
  616. *
  617. * @param[in] device
  618. * Pointer to device descriptor
  619. *
  620. * @param[in] name
  621. * Device name
  622. *
  623. * @param[in] flag
  624. * Configuration flags
  625. *
  626. * @param[in] leuart
  627. * Pointer to LEUART device descriptor
  628. *
  629. * @return
  630. * Error code
  631. ******************************************************************************/
  632. rt_err_t rt_hw_leuart_register(
  633. rt_device_t device,
  634. const char *name,
  635. rt_uint32_t flag,
  636. struct efm32_leuart_device_t *leuart)
  637. {
  638. RT_ASSERT(device != RT_NULL);
  639. if ((flag & RT_DEVICE_FLAG_DMA_RX) ||
  640. (flag & RT_DEVICE_FLAG_INT_TX))
  641. {
  642. RT_ASSERT(0);
  643. }
  644. device->type = RT_Device_Class_Char;
  645. device->rx_indicate = RT_NULL;
  646. device->tx_complete = RT_NULL;
  647. device->init = rt_leuart_init;
  648. device->open = rt_leuart_open;
  649. device->close = rt_leuart_close;
  650. device->read = rt_leuart_read;
  651. device->write = rt_leuart_write;
  652. device->control = rt_leuart_control;
  653. device->user_data = leuart;
  654. /* register a character device */
  655. return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
  656. }
  657. /***************************************************************************//**
  658. * @brief
  659. * Initialize the specified LEUART unit
  660. *
  661. * @details
  662. *
  663. * @note
  664. *
  665. * @param[in] device
  666. * Pointer to device descriptor
  667. *
  668. * @param[in] unitNumber
  669. * Unit number
  670. *
  671. * @param[in] location
  672. * Pin location number
  673. *
  674. * @param[in] flag
  675. * Configuration flag
  676. *
  677. * @param[in] dmaChannel
  678. * DMA channel number for TX
  679. *
  680. * @param[in] console
  681. * Indicate if using as console
  682. *
  683. * @return
  684. * Pointer to LEUART device
  685. ******************************************************************************/
  686. static struct efm32_leuart_device_t *rt_hw_leuart_unit_init(
  687. rt_device_t device,
  688. rt_uint8_t unitNumber,
  689. rt_uint8_t location,
  690. rt_uint32_t flag,
  691. rt_uint32_t dmaChannel,
  692. rt_uint8_t config)
  693. {
  694. struct efm32_leuart_device_t *leuart;
  695. struct efm32_leuart_dma_mode_t *dma_mode;
  696. DMA_CB_TypeDef *callback;
  697. CMU_Clock_TypeDef leuartClock;
  698. rt_uint32_t txDmaSelect;
  699. GPIO_Port_TypeDef port_tx, port_rx, port_clk, port_cs;
  700. rt_uint32_t pin_tx, pin_rx, pin_clk, pin_cs;
  701. LEUART_Init_TypeDef init = LEUART_INIT_DEFAULT;
  702. efm32_irq_hook_init_t hook;
  703. do
  704. {
  705. /* Allocate device */
  706. leuart = rt_malloc(sizeof(struct efm32_leuart_device_t));
  707. if (leuart == RT_NULL)
  708. {
  709. leuart_debug("LEUART%d err: no mem\n", unitNumber);
  710. break;
  711. }
  712. leuart->counter = 0;
  713. leuart->unit = unitNumber;
  714. leuart->state = config;
  715. leuart->tx_mode = RT_NULL;
  716. leuart->rx_mode = RT_NULL;
  717. /* Allocate TX */
  718. dma_mode = RT_NULL;
  719. if (flag & RT_DEVICE_FLAG_DMA_TX)
  720. {
  721. leuart->tx_mode = dma_mode = rt_malloc(sizeof(struct efm32_leuart_dma_mode_t));
  722. if (dma_mode == RT_NULL)
  723. {
  724. leuart_debug("LEUART%d err: no mem for DMA TX\n", unitNumber);
  725. break;
  726. }
  727. dma_mode->dma_channel = dmaChannel;
  728. }
  729. /* Allocate RX */
  730. if (flag & RT_DEVICE_FLAG_INT_RX)
  731. {
  732. leuart->rx_mode = rt_malloc(sizeof(struct efm32_leuart_int_mode_t));
  733. if (leuart->rx_mode == RT_NULL)
  734. {
  735. leuart_debug("LEUART%d err: no mem for INT RX\n, unitNumber");
  736. break;
  737. }
  738. }
  739. /* Initialization */
  740. if (unitNumber >= LEUART_COUNT)
  741. {
  742. break;
  743. }
  744. switch (unitNumber)
  745. {
  746. case 0:
  747. leuart->leuart_device = LEUART0;
  748. leuartClock = (CMU_Clock_TypeDef)cmuClock_LEUART0;
  749. txDmaSelect = DMAREQ_LEUART0_TXBL;
  750. port_tx = AF_LEUART0_TX_PORT(location);
  751. pin_tx = AF_LEUART0_TX_PIN(location);
  752. port_rx = AF_LEUART0_RX_PORT(location);
  753. pin_rx = AF_LEUART0_RX_PIN(location);
  754. break;
  755. #if (LEUART_COUNT > 1)
  756. case 1:
  757. leuart->leuart_device = LEUART1;
  758. leuartClock = (CMU_Clock_TypeDef)cmuClock_LEUART1;
  759. txDmaSelect = DMAREQ_LEUART1_TXBL;
  760. port_tx = AF_LEUART1_TX_PORT(location);
  761. pin_tx = AF_LEUART1_TX_PIN(location);
  762. port_rx = AF_LEUART1_RX_PORT(location);
  763. pin_rx = AF_LEUART1_RX_PIN(location);
  764. break;
  765. #endif
  766. default:
  767. break;
  768. }
  769. /* Do not prescale clock */
  770. CMU_ClockDivSet(leuartClock, cmuClkDiv_1);
  771. /* Enable LEUART clock */
  772. CMU_ClockEnable(leuartClock, true);
  773. /* Config GPIO */
  774. GPIO_PinModeSet(
  775. port_tx,
  776. pin_tx,
  777. gpioModePushPull,
  778. 0);
  779. GPIO_PinModeSet(
  780. port_rx,
  781. pin_rx,
  782. gpioModeInputPull,
  783. 1);
  784. /* Config interrupt and NVIC */
  785. if (flag & RT_DEVICE_FLAG_INT_RX)
  786. {
  787. hook.type = efm32_irq_type_leuart;
  788. hook.unit = unitNumber;
  789. hook.cbFunc = rt_hw_leuart_rx_isr;
  790. hook.userPtr = device;
  791. efm32_irq_hook_register(&hook);
  792. }
  793. /* Config DMA */
  794. if (flag & RT_DEVICE_FLAG_DMA_TX)
  795. {
  796. DMA_CfgChannel_TypeDef chnlCfg;
  797. DMA_CfgDescr_TypeDef descrCfg;
  798. hook.type = efm32_irq_type_dma;
  799. hook.unit = dmaChannel;
  800. hook.cbFunc = rt_hw_leuart_dma_tx_isr;
  801. hook.userPtr = device;
  802. efm32_irq_hook_register(&hook);
  803. callback = (DMA_CB_TypeDef *)rt_malloc(sizeof(DMA_CB_TypeDef));
  804. if (callback == RT_NULL)
  805. {
  806. leuart_debug("LEUART%d err: no mem for callback\n", unitNumber);
  807. break;
  808. }
  809. callback->cbFunc = DMA_IRQHandler_All;
  810. callback->userPtr = RT_NULL;
  811. callback->primary = 0;
  812. /* Setting up DMA channel */
  813. chnlCfg.highPri = false; /* Can't use with peripherals */
  814. chnlCfg.enableInt = true; /* Interrupt for callback function */
  815. chnlCfg.select = txDmaSelect;
  816. chnlCfg.cb = callback;
  817. DMA_CfgChannel(dmaChannel, &chnlCfg);
  818. /* Setting up DMA channel descriptor */
  819. descrCfg.dstInc = dmaDataIncNone;
  820. descrCfg.srcInc = dmaDataInc1;
  821. descrCfg.size = dmaDataSize1;
  822. descrCfg.arbRate = dmaArbitrate1;
  823. descrCfg.hprot = 0;
  824. DMA_CfgDescr(dmaChannel, true, &descrCfg);
  825. }
  826. /* Init specified LEUART unit */
  827. LEUART_Init(leuart->leuart_device, &init);
  828. /* Enable RX and TX pins and set location */
  829. leuart->leuart_device->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN | \
  830. (location << _LEUART_ROUTE_LOCATION_SHIFT);
  831. /* Clear RX/TX buffers */
  832. leuart->leuart_device->CMD = LEUART_CMD_CLEARRX | LEUART_CMD_CLEARTX;
  833. return leuart;
  834. } while(0);
  835. if (leuart->rx_mode)
  836. {
  837. rt_free(leuart->rx_mode);
  838. }
  839. if (leuart->tx_mode)
  840. {
  841. rt_free(leuart->tx_mode);
  842. }
  843. if (leuart)
  844. {
  845. rt_free(leuart);
  846. }
  847. if (callback)
  848. {
  849. rt_free(leuart);
  850. }
  851. leuart_debug("LEUART%d err: init failed!\n", unitNumber);
  852. return RT_NULL;
  853. }
  854. /***************************************************************************//**
  855. * @brief
  856. * Initialize all LEUART module related hardware and register LEUART device to
  857. * kernel
  858. *
  859. * @details
  860. *
  861. * @note
  862. ******************************************************************************/
  863. void rt_hw_leuart_init(void)
  864. {
  865. struct efm32_leuart_device_t *leuart;
  866. rt_uint32_t flag;
  867. rt_uint8_t config;
  868. do
  869. {
  870. #ifdef RT_USING_LEUART0
  871. config = 0;
  872. flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX;
  873. #if (RT_CONSOLE_DEVICE == EFM_LEUART0)
  874. config |= LEUART_STATE_CONSOLE;
  875. flag |= RT_DEVICE_FLAG_STREAM;
  876. #endif
  877. #ifdef RT_LEUART0_USING_DMA
  878. RT_ASSERT(RT_LEUART0_USING_DMA < DMA_CHAN_COUNT);
  879. flag |= RT_DEVICE_FLAG_DMA_TX;
  880. #else
  881. #define RT_LEUART0_USING_DMA EFM32_NO_DMA
  882. #endif
  883. /* Initialize and Register leuart0 */
  884. if ((leuart = rt_hw_leuart_unit_init(
  885. &leuart0_device,
  886. 0,
  887. RT_USING_LEUART0,
  888. flag,
  889. RT_LEUART0_USING_DMA,
  890. config)) != RT_NULL)
  891. {
  892. rt_hw_leuart_register(&leuart0_device, RT_LEUART0_NAME, flag, leuart);
  893. }
  894. else
  895. {
  896. break;
  897. }
  898. /* Initialize lock for leuart0 */
  899. leuart->lock = &leuart0_lock;
  900. if (rt_sem_init(leuart->lock, RT_LEUART0_NAME, 1, RT_IPC_FLAG_FIFO) != RT_EOK)
  901. {
  902. break;
  903. }
  904. #endif
  905. #if ((LEUART_COUNT > 1) && defined(RT_USING_LEUART1))
  906. config = 0;
  907. flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX;
  908. #if (RT_CONSOLE_DEVICE == EFM_LEUART1)
  909. config |= LEUART_STATE_CONSOLE;
  910. flag |= RT_DEVICE_FLAG_STREAM;
  911. #endif
  912. #ifdef RT_LEUART1_USING_DMA
  913. RT_ASSERT(RT_LEUART1_USING_DMA < DMA_CHAN_COUNT);
  914. flag |= RT_DEVICE_FLAG_DMA_TX;
  915. #else
  916. #define RT_LEUART1_USING_DMA EFM32_NO_DMA
  917. #endif
  918. /* Initialize and Register leuart1 */
  919. if ((leuart = rt_hw_leuart_unit_init(
  920. &leuart1_device,
  921. 1,
  922. RT_USING_LEUART1,
  923. flag,
  924. RT_LEUART1_USING_DMA,
  925. config)) != RT_NULL)
  926. {
  927. rt_hw_leuart_register(&leuart1_device, RT_LEUART1_NAME, flag, leuart);
  928. }
  929. else
  930. {
  931. break;
  932. }
  933. /* Initialize lock for leuart1 */
  934. leuart->lock = &leuart1_lock;
  935. if (rt_sem_init(leuart->lock, RT_LEUART1_NAME, 1, RT_IPC_FLAG_FIFO) != RT_EOK)
  936. {
  937. break;
  938. }
  939. #endif
  940. leuart_debug("LEUART: H/W init OK!\n");
  941. return;
  942. } while (0);
  943. rt_kprintf("LEUART: H/W init failed!\n");
  944. }
  945. #endif /* (defined(RT_USING_LEUART0) || defined(RT_USING_LEUART1)) */
  946. /***************************************************************************//**
  947. * @}
  948. ******************************************************************************/