uart.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. /**************************************************************************//**
  2. * @file uart.c
  3. * @version V3.00
  4. * $Revision: 22 $
  5. * $Date: 15/08/11 10:26a $
  6. * @brief M451 series UART driver source file
  7. *
  8. * @note
  9. * Copyright (C) 2013~2015 Nuvoton Technology Corp. All rights reserved.
  10. *****************************************************************************/
  11. #include <stdio.h>
  12. #include "M451Series.h"
  13. /** @addtogroup Standard_Driver Standard Driver
  14. @{
  15. */
  16. /** @addtogroup UART_Driver UART Driver
  17. @{
  18. */
  19. /** @addtogroup UART_EXPORTED_FUNCTIONS UART Exported Functions
  20. @{
  21. */
  22. /**
  23. * @brief Clear UART specified interrupt flag
  24. *
  25. * @param[in] uart The pointer of the specified UART module.
  26. * @param[in] u32InterruptFlag The specified interrupt of UART module.
  27. * - \ref UART_INTSTS_LININT_Msk : LIN bus interrupt
  28. * - \ref UART_INTSTS_DATWKIF_Msk : Data Wake-up interrupt
  29. * - \ref UART_INTSTS_CTSWKIF_Msk : CTS Wake-up interrupt
  30. * - \ref UART_INTSTS_BUFERRINT_Msk : Buffer Error interrupt
  31. * - \ref UART_INTSTS_MODEMINT_Msk : Modem Status interrupt
  32. * - \ref UART_INTSTS_RLSINT_Msk : Receive Line Status interrupt
  33. *
  34. * @return None
  35. *
  36. * @details The function is used to clear UART specified interrupt flag.
  37. */
  38. void UART_ClearIntFlag(UART_T* uart , uint32_t u32InterruptFlag)
  39. {
  40. if(u32InterruptFlag & UART_INTSTS_RLSINT_Msk) /* Clear Receive Line Status Interrupt */
  41. {
  42. uart->FIFOSTS = UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_FEF_Msk;
  43. uart->FIFOSTS = UART_FIFOSTS_ADDRDETF_Msk;
  44. }
  45. if(u32InterruptFlag & UART_INTSTS_MODEMINT_Msk) /* Clear Modem Status Interrupt */
  46. uart->MODEMSTS |= UART_MODEMSTS_CTSDETF_Msk;
  47. if(u32InterruptFlag & UART_INTSTS_BUFERRINT_Msk) /* Clear Buffer Error Interrupt */
  48. {
  49. uart->FIFOSTS = UART_FIFOSTS_RXOVIF_Msk | UART_FIFOSTS_TXOVIF_Msk;
  50. }
  51. if(u32InterruptFlag & UART_INTSTS_CTSWKIF_Msk) /* Clear CTS Wake-up Interrupt */
  52. {
  53. uart->INTSTS = UART_INTSTS_CTSWKIF_Msk;
  54. }
  55. if(u32InterruptFlag & UART_INTSTS_DATWKIF_Msk) /* Clear Data Wake-up Interrupt */
  56. {
  57. uart->INTSTS = UART_INTSTS_DATWKIF_Msk;
  58. }
  59. if(u32InterruptFlag & UART_INTSTS_LININT_Msk) /* Clear LIN Bus Interrupt */
  60. {
  61. uart->INTSTS = UART_INTSTS_LINIF_Msk;
  62. uart->LINSTS = UART_LINSTS_BITEF_Msk | UART_LINSTS_BRKDETF_Msk |
  63. UART_LINSTS_SLVSYNCF_Msk | UART_LINSTS_SLVIDPEF_Msk |
  64. UART_LINSTS_SLVHEF_Msk | UART_LINSTS_SLVHDETF_Msk ;
  65. }
  66. }
  67. /**
  68. * @brief Disable UART interrupt
  69. *
  70. * @param[in] uart The pointer of the specified UART module.
  71. *
  72. * @return None
  73. *
  74. * @details The function is used to disable UART interrupt.
  75. */
  76. void UART_Close(UART_T* uart)
  77. {
  78. uart->INTEN = 0;
  79. }
  80. /**
  81. * @brief Disable UART auto flow control function
  82. *
  83. * @param[in] uart The pointer of the specified UART module.
  84. *
  85. * @return None
  86. *
  87. * @details The function is used to disable UART auto flow control.
  88. */
  89. void UART_DisableFlowCtrl(UART_T* uart)
  90. {
  91. uart->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
  92. }
  93. /**
  94. * @brief Disable UART specified interrupt
  95. *
  96. * @param[in] uart The pointer of the specified UART module.
  97. * @param[in] u32InterruptFlag The specified interrupt of UART module.
  98. * - \ref UART_INTEN_WKCTSIEN_Msk : CTS wake-up interrupt
  99. * - \ref UART_INTEN_WKDATIEN_Msk : Data wake-up interrupt
  100. * - \ref UART_INTEN_LINIEN_Msk : Lin bus interrupt
  101. * - \ref UART_INTEN_BUFERRIEN_Msk : Buffer Error interrupt
  102. * - \ref UART_INTEN_RXTOIEN_Msk : Rx time-out interrupt
  103. * - \ref UART_INTEN_MODEMIEN_Msk : Modem status interrupt
  104. * - \ref UART_INTEN_RLSIEN_Msk : Receive Line status interrupt
  105. * - \ref UART_INTEN_THREIEN_Msk : Tx empty interrupt
  106. * - \ref UART_INTEN_RDAIEN_Msk : Rx ready interrupt *
  107. *
  108. * @return None
  109. *
  110. * @details The function is used to disable UART specified interrupt and disable NVIC UART IRQ.
  111. */
  112. void UART_DisableInt(UART_T* uart, uint32_t u32InterruptFlag)
  113. {
  114. /* Disable UART specified interrupt */
  115. UART_DISABLE_INT(uart, u32InterruptFlag);
  116. /* Disable NVIC UART IRQ */
  117. if(uart == UART0)
  118. NVIC_DisableIRQ(UART0_IRQn);
  119. else if(uart == UART1)
  120. NVIC_DisableIRQ(UART1_IRQn);
  121. else if(uart == UART2)
  122. NVIC_DisableIRQ(UART2_IRQn);
  123. else
  124. NVIC_DisableIRQ(UART3_IRQn);
  125. }
  126. /**
  127. * @brief Enable UART auto flow control function
  128. *
  129. * @param[in] uart The pointer of the specified UART module.
  130. *
  131. * @return None
  132. *
  133. * @details The function is used to Enable UART auto flow control.
  134. */
  135. void UART_EnableFlowCtrl(UART_T* uart)
  136. {
  137. /* Set RTS pin output is low level active */
  138. uart->MODEM |= UART_MODEM_RTSACTLV_Msk;
  139. /* Set CTS pin input is low level active */
  140. uart->MODEMSTS |= UART_MODEMSTS_CTSACTLV_Msk;
  141. /* Set RTS and CTS auto flow control enable */
  142. uart->INTEN |= UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk;
  143. }
  144. /**
  145. * @brief The function is used to enable UART specified interrupt and enable NVIC UART IRQ.
  146. *
  147. * @param[in] uart The pointer of the specified UART module.
  148. * @param[in] u32InterruptFlag The specified interrupt of UART module:
  149. * - \ref UART_INTEN_WKCTSIEN_Msk : CTS wake-up interrupt
  150. * - \ref UART_INTEN_WKDATIEN_Msk : Data wake-up interrupt
  151. * - \ref UART_INTEN_LINIEN_Msk : Lin bus interrupt
  152. * - \ref UART_INTEN_BUFERRIEN_Msk : Buffer Error interrupt
  153. * - \ref UART_INTEN_RXTOIEN_Msk : Rx time-out interrupt
  154. * - \ref UART_INTEN_MODEMIEN_Msk : Modem status interrupt
  155. * - \ref UART_INTEN_RLSIEN_Msk : Receive Line status interrupt
  156. * - \ref UART_INTEN_THREIEN_Msk : Tx empty interrupt
  157. * - \ref UART_INTEN_RDAIEN_Msk : Rx ready interrupt *
  158. *
  159. * @return None
  160. *
  161. * @details The function is used to enable UART specified interrupt and enable NVIC UART IRQ.
  162. */
  163. void UART_EnableInt(UART_T* uart, uint32_t u32InterruptFlag)
  164. {
  165. /* Enable UART specified interrupt */
  166. UART_ENABLE_INT(uart, u32InterruptFlag);
  167. /* Enable NVIC UART IRQ */
  168. if(uart == UART0)
  169. NVIC_EnableIRQ(UART0_IRQn);
  170. else if(uart == UART1)
  171. NVIC_EnableIRQ(UART1_IRQn);
  172. else if(uart == UART2)
  173. NVIC_EnableIRQ(UART2_IRQn);
  174. else
  175. NVIC_EnableIRQ(UART3_IRQn);
  176. }
  177. /**
  178. * @brief Open and set UART function
  179. *
  180. * @param[in] uart The pointer of the specified UART module.
  181. * @param[in] u32baudrate The baudrate of UART module.
  182. *
  183. * @return None
  184. *
  185. * @details This function use to enable UART function and set baud-rate.
  186. */
  187. void UART_Open(UART_T* uart, uint32_t u32baudrate)
  188. {
  189. uint8_t u8UartClkSrcSel, u8UartClkDivNum;
  190. uint32_t u32ClkTbl[4] = {__HXT, 0, __LXT, __HIRC};
  191. uint32_t u32Baud_Div = 0;
  192. /* Get UART clock source selection */
  193. u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UARTSEL_Msk) >> CLK_CLKSEL1_UARTSEL_Pos;
  194. /* Get UART clock divider number */
  195. u8UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UARTDIV_Msk) >> CLK_CLKDIV0_UARTDIV_Pos;
  196. /* Select UART function */
  197. uart->FUNCSEL = UART_FUNCSEL_UART;
  198. /* Set UART line configuration */
  199. uart->LINE = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
  200. /* Set UART Rx and RTS trigger level */
  201. uart->FIFO &= ~(UART_FIFO_RFITL_Msk | UART_FIFO_RTSTRGLV_Msk);
  202. /* Get PLL clock frequency if UART clock source selection is PLL */
  203. if(u8UartClkSrcSel == 1)
  204. u32ClkTbl[u8UartClkSrcSel] = CLK_GetPLLClockFreq();
  205. /* Set UART baud rate */
  206. if(u32baudrate != 0)
  207. {
  208. u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32baudrate);
  209. if(u32Baud_Div > 0xFFFF)
  210. uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32baudrate));
  211. else
  212. uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div);
  213. }
  214. }
  215. /**
  216. * @brief Read UART data
  217. *
  218. * @param[in] uart The pointer of the specified UART module.
  219. * @param[in] pu8RxBuf The buffer to receive the data of receive FIFO.
  220. * @param[in] u32ReadBytes The the read bytes number of data.
  221. *
  222. * @return u32Count Receive byte count
  223. *
  224. * @details The function is used to read Rx data from RX FIFO and the data will be stored in pu8RxBuf.
  225. */
  226. uint32_t UART_Read(UART_T* uart, uint8_t *pu8RxBuf, uint32_t u32ReadBytes)
  227. {
  228. uint32_t u32Count, u32delayno;
  229. for(u32Count = 0; u32Count < u32ReadBytes; u32Count++)
  230. {
  231. u32delayno = 0;
  232. while(uart->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) /* Check RX empty => failed */
  233. {
  234. u32delayno++;
  235. if(u32delayno >= 0x40000000)
  236. return FALSE;
  237. }
  238. pu8RxBuf[u32Count] = uart->DAT; /* Get Data from UART RX */
  239. }
  240. return u32Count;
  241. }
  242. /**
  243. * @brief Set UART line configuration
  244. *
  245. * @param[in] uart The pointer of the specified UART module.
  246. * @param[in] u32baudrate The register value of baudrate of UART module.
  247. * If u32baudrate = 0, UART baudrate will not change.
  248. * @param[in] u32data_width The data length of UART module.
  249. * - \ref UART_WORD_LEN_5
  250. * - \ref UART_WORD_LEN_6
  251. * - \ref UART_WORD_LEN_7
  252. * - \ref UART_WORD_LEN_8
  253. * @param[in] u32parity The parity setting (none/odd/even/mark/space) of UART module.
  254. * - \ref UART_PARITY_NONE
  255. * - \ref UART_PARITY_ODD
  256. * - \ref UART_PARITY_EVEN
  257. * - \ref UART_PARITY_MARK
  258. * - \ref UART_PARITY_SPACE
  259. * @param[in] u32stop_bits The stop bit length (1/1.5/2 bit) of UART module.
  260. * - \ref UART_STOP_BIT_1
  261. * - \ref UART_STOP_BIT_1_5
  262. * - \ref UART_STOP_BIT_2
  263. *
  264. * @return None
  265. *
  266. * @details This function use to config UART line setting.
  267. */
  268. void UART_SetLine_Config(UART_T* uart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits)
  269. {
  270. uint8_t u8UartClkSrcSel, u8UartClkDivNum;
  271. uint32_t u32ClkTbl[4] = {__HXT, 0, __LXT, __HIRC};
  272. uint32_t u32Baud_Div = 0;
  273. /* Get UART clock source selection */
  274. u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UARTSEL_Msk) >> CLK_CLKSEL1_UARTSEL_Pos;
  275. /* Get UART clock divider number */
  276. u8UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UARTDIV_Msk) >> CLK_CLKDIV0_UARTDIV_Pos;
  277. /* Get PLL clock frequency if UART clock source selection is PLL */
  278. if(u8UartClkSrcSel == 1)
  279. u32ClkTbl[u8UartClkSrcSel] = CLK_GetPLLClockFreq();
  280. /* Set UART baud rate */
  281. if(u32baudrate != 0)
  282. {
  283. u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32baudrate);
  284. if(u32Baud_Div > 0xFFFF)
  285. uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32baudrate));
  286. else
  287. uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div);
  288. }
  289. /* Set UART line configuration */
  290. uart->LINE = u32data_width | u32parity | u32stop_bits;
  291. }
  292. /**
  293. * @brief Set Rx timeout count
  294. *
  295. * @param[in] uart The pointer of the specified UART module.
  296. * @param[in] u32TOC Rx timeout counter.
  297. *
  298. * @return None
  299. *
  300. * @details This function use to set Rx timeout count.
  301. */
  302. void UART_SetTimeoutCnt(UART_T* uart, uint32_t u32TOC)
  303. {
  304. /* Set time-out interrupt comparator */
  305. uart->TOUT = (uart->TOUT & ~UART_TOUT_TOIC_Msk) | (u32TOC);
  306. /* Set time-out counter enable */
  307. uart->INTEN |= UART_INTEN_TOCNTEN_Msk;
  308. }
  309. /**
  310. * @brief Select and configure IrDA function
  311. *
  312. * @param[in] uart The pointer of the specified UART module.
  313. * @param[in] u32Buadrate The baudrate of UART module.
  314. * @param[in] u32Direction The direction of UART module in IrDA mode:
  315. * - \ref UART_IRDA_TXEN
  316. * - \ref UART_IRDA_RXEN
  317. *
  318. * @return None
  319. *
  320. * @details The function is used to configure IrDA relative settings. It consists of TX or RX mode and baudrate.
  321. */
  322. void UART_SelectIrDAMode(UART_T* uart, uint32_t u32Buadrate, uint32_t u32Direction)
  323. {
  324. uint8_t u8UartClkSrcSel, u8UartClkDivNum;
  325. uint32_t u32ClkTbl[4] = {__HXT, 0, __LXT, __HIRC};
  326. uint32_t u32Baud_Div;
  327. /* Select IrDA function mode */
  328. uart->FUNCSEL = UART_FUNCSEL_IrDA;
  329. /* Get UART clock source selection */
  330. u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UARTSEL_Msk) >> CLK_CLKSEL1_UARTSEL_Pos;
  331. /* Get UART clock divider number */
  332. u8UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UARTDIV_Msk) >> CLK_CLKDIV0_UARTDIV_Pos;
  333. /* Get PLL clock frequency if UART clock source selection is PLL */
  334. if(u8UartClkSrcSel == 1)
  335. u32ClkTbl[u8UartClkSrcSel] = CLK_GetPLLClockFreq();
  336. /* Set UART IrDA baud rate in mode 0 */
  337. if(u32Buadrate != 0)
  338. {
  339. u32Baud_Div = UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32Buadrate);
  340. if(u32Baud_Div < 0xFFFF)
  341. uart->BAUD = (UART_BAUD_MODE0 | u32Baud_Div);
  342. }
  343. /* Configure IrDA relative settings */
  344. if(u32Direction == UART_IRDA_RXEN)
  345. {
  346. uart->IRDA |= UART_IRDA_RXINV_Msk; //Rx signal is inverse
  347. uart->IRDA &= ~UART_IRDA_TXEN_Msk;
  348. }
  349. else
  350. {
  351. uart->IRDA &= ~UART_IRDA_TXINV_Msk; //Tx signal is not inverse
  352. uart->IRDA |= UART_IRDA_TXEN_Msk;
  353. }
  354. }
  355. /**
  356. * @brief Select and configure RS485 function
  357. *
  358. * @param[in] uart The pointer of the specified UART module.
  359. * @param[in] u32Mode The operation mode(NMM/AUD/AAD).
  360. * - \ref UART_ALTCTL_RS485NMM_Msk
  361. * - \ref UART_ALTCTL_RS485AUD_Msk
  362. * - \ref UART_ALTCTL_RS485AAD_Msk
  363. * @param[in] u32Addr The RS485 address.
  364. *
  365. * @return None
  366. *
  367. * @details The function is used to set RS485 relative setting.
  368. */
  369. void UART_SelectRS485Mode(UART_T* uart, uint32_t u32Mode, uint32_t u32Addr)
  370. {
  371. /* Select UART RS485 function mode */
  372. uart->FUNCSEL = UART_FUNCSEL_RS485;
  373. /* Set RS585 configuration */
  374. uart->ALTCTL &= ~(UART_ALTCTL_RS485NMM_Msk | UART_ALTCTL_RS485AUD_Msk | UART_ALTCTL_RS485AAD_Msk | UART_ALTCTL_ADDRMV_Msk);
  375. uart->ALTCTL |= (u32Mode | (u32Addr << UART_ALTCTL_ADDRMV_Pos));
  376. }
  377. /**
  378. * @brief Select and configure LIN function
  379. *
  380. * @param[in] uart The pointer of the specified UART module.
  381. * @param[in] u32Mode The LIN direction :
  382. * - \ref UART_ALTCTL_LINTXEN_Msk
  383. * - \ref UART_ALTCTL_LINRXEN_Msk
  384. * @param[in] u32BreakLength The breakfield length.
  385. *
  386. * @return None
  387. *
  388. * @details The function is used to set LIN relative setting.
  389. */
  390. void UART_SelectLINMode(UART_T* uart, uint32_t u32Mode, uint32_t u32BreakLength)
  391. {
  392. /* Select LIN function mode */
  393. uart->FUNCSEL = UART_FUNCSEL_LIN;
  394. /* Select LIN function setting : Tx enable, Rx enable and break field length */
  395. uart->ALTCTL &= ~(UART_ALTCTL_LINTXEN_Msk | UART_ALTCTL_LINRXEN_Msk | UART_ALTCTL_BRKFL_Msk);
  396. uart->ALTCTL |= (u32Mode | (u32BreakLength << UART_ALTCTL_BRKFL_Pos));
  397. }
  398. /**
  399. * @brief Write UART data
  400. *
  401. * @param[in] uart The pointer of the specified UART module.
  402. * @param[in] pu8TxBuf The buffer to send the data to UART transmission FIFO.
  403. * @param[out] u32WriteBytes The byte number of data.
  404. *
  405. * @return u32Count transfer byte count
  406. *
  407. * @details The function is to write data into TX buffer to transmit data by UART.
  408. */
  409. uint32_t UART_Write(UART_T* uart, uint8_t *pu8TxBuf, uint32_t u32WriteBytes)
  410. {
  411. uint32_t u32Count, u32delayno;
  412. for(u32Count = 0; u32Count != u32WriteBytes; u32Count++)
  413. {
  414. u32delayno = 0;
  415. while((uart->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk) == 0) /* Wait Tx empty and Time-out manner */
  416. {
  417. u32delayno++;
  418. if(u32delayno >= 0x40000000)
  419. return FALSE;
  420. }
  421. uart->DAT = pu8TxBuf[u32Count]; /* Send UART Data from buffer */
  422. }
  423. return u32Count;
  424. }
  425. /*@}*/ /* end of group UART_EXPORTED_FUNCTIONS */
  426. /*@}*/ /* end of group UART_Driver */
  427. /*@}*/ /* end of group Standard_Driver */
  428. /*** (C) COPYRIGHT 2012~2015 Nuvoton Technology Corp. ***/