drv_leuart.c 25 KB

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