1 /**************************************************************************//**
2  * @file     uart.c
3  * @version  V3.00
4  * @brief    M480 series UART driver source file
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 
10 #include <stdio.h>
11 #include "NuMicro.h"
12 
13 /** @addtogroup Standard_Driver Standard Driver
14   @{
15 */
16 
17 /** @addtogroup UART_Driver UART Driver
18   @{
19 */
20 
21 /** @addtogroup UART_EXPORTED_FUNCTIONS UART Exported Functions
22   @{
23 */
24 
25 /**
26  *    @brief        Clear UART specified interrupt flag
27  *
28  *    @param[in]    uart                The pointer of the specified UART module.
29  *    @param[in]    u32InterruptFlag    The specified interrupt of UART module.
30  *                                      - \ref UART_INTSTS_LININT_Msk    : LIN bus interrupt
31  *                                      - \ref UART_INTSTS_WKIF_Msk      : Wake-up interrupt
32  *                                      - \ref UART_INTSTS_BUFERRINT_Msk : Buffer Error interrupt
33  *                                      - \ref UART_INTSTS_MODEMINT_Msk  : Modem Status interrupt
34  *                                      - \ref UART_INTSTS_RLSINT_Msk    : Receive Line Status interrupt
35  *
36  *    @return       None
37  *
38  *    @details      The function is used to clear UART specified interrupt flag.
39  */
40 
UART_ClearIntFlag(UART_T * uart,uint32_t u32InterruptFlag)41 void UART_ClearIntFlag(UART_T* uart, uint32_t u32InterruptFlag)
42 {
43 
44     if(u32InterruptFlag & UART_INTSTS_RLSINT_Msk)   /* Clear Receive Line Status Interrupt */
45     {
46         uart->FIFOSTS = UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_PEF_Msk;
47         uart->FIFOSTS = UART_FIFOSTS_ADDRDETF_Msk;
48     }
49 
50     if(u32InterruptFlag & UART_INTSTS_MODEMINT_Msk)   /* Clear Modem Status Interrupt */
51     {
52         uart->MODEMSTS |= UART_MODEMSTS_CTSDETF_Msk;
53     }
54     else
55     {
56     }
57 
58     if(u32InterruptFlag & UART_INTSTS_BUFERRINT_Msk)   /* Clear Buffer Error Interrupt */
59     {
60         uart->FIFOSTS = UART_FIFOSTS_RXOVIF_Msk | UART_FIFOSTS_TXOVIF_Msk;
61     }
62 
63     if(u32InterruptFlag & UART_INTSTS_WKINT_Msk)   /* Clear Wake-up Interrupt */
64     {
65         uart->WKSTS = UART_WKSTS_CTSWKF_Msk  | UART_WKSTS_DATWKF_Msk  |
66                       UART_WKSTS_RFRTWKF_Msk |UART_WKSTS_RS485WKF_Msk |
67                       UART_WKSTS_TOUTWKF_Msk;
68     }
69 
70     if(u32InterruptFlag & UART_INTSTS_LININT_Msk)   /* Clear LIN Bus Interrupt */
71     {
72         uart->INTSTS = UART_INTSTS_LINIF_Msk;
73         uart->LINSTS = UART_LINSTS_BITEF_Msk    | UART_LINSTS_BRKDETF_Msk  |
74                        UART_LINSTS_SLVSYNCF_Msk | UART_LINSTS_SLVIDPEF_Msk |
75                        UART_LINSTS_SLVHEF_Msk   | UART_LINSTS_SLVHDETF_Msk ;
76     }
77 }
78 
79 
80 /**
81  *  @brief      Disable UART interrupt
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 interrupt.
88  */
UART_Close(UART_T * uart)89 void UART_Close(UART_T* uart)
90 {
91     uart->INTEN = 0ul;
92 }
93 
94 
95 /**
96  *  @brief      Disable UART auto flow control function
97  *
98  *  @param[in]  uart The pointer of the specified UART module.
99  *
100  *  @return     None
101  *
102  *  @details    The function is used to disable UART auto flow control.
103  */
UART_DisableFlowCtrl(UART_T * uart)104 void UART_DisableFlowCtrl(UART_T* uart)
105 {
106     uart->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
107 }
108 
109 
110 /**
111  *    @brief        Disable UART specified interrupt
112  *
113  *    @param[in]    uart                The pointer of the specified UART module.
114  *    @param[in]    u32InterruptFlag    The specified interrupt of UART module.
115  *                                      - \ref UART_INTEN_WKIEN_Msk      : Wake-up interrupt
116  *                                      - \ref UART_INTEN_LINIEN_Msk     : Lin bus interrupt
117  *                                      - \ref UART_INTEN_BUFERRIEN_Msk  : Buffer Error interrupt
118  *                                      - \ref UART_INTEN_RXTOIEN_Msk    : Rx time-out interrupt
119  *                                      - \ref UART_INTEN_MODEMIEN_Msk   : Modem status interrupt
120  *                                      - \ref UART_INTEN_RLSIEN_Msk     : Receive Line status interrupt
121  *                                      - \ref UART_INTEN_THREIEN_Msk    : Tx empty interrupt
122  *                                      - \ref UART_INTEN_RDAIEN_Msk     : Rx ready interrupt *
123  *
124  *    @return       None
125  *
126  *    @details      The function is used to disable UART specified interrupt and disable NVIC UART IRQ.
127  */
UART_DisableInt(UART_T * uart,uint32_t u32InterruptFlag)128 void UART_DisableInt(UART_T*  uart, uint32_t u32InterruptFlag)
129 {
130     /* Disable UART specified interrupt */
131     UART_DISABLE_INT(uart, u32InterruptFlag);
132 }
133 
134 
135 /**
136  *    @brief        Enable UART auto flow control function
137  *
138  *    @param[in]    uart    The pointer of the specified UART module.
139  *
140  *    @return       None
141  *
142  *    @details      The function is used to Enable UART auto flow control.
143  */
UART_EnableFlowCtrl(UART_T * uart)144 void UART_EnableFlowCtrl(UART_T* uart)
145 {
146     /* Set RTS pin output is low level active */
147     uart->MODEM |= UART_MODEM_RTSACTLV_Msk;
148 
149     /* Set CTS pin input is low level active */
150     uart->MODEMSTS |= UART_MODEMSTS_CTSACTLV_Msk;
151 
152     /* Set RTS and CTS auto flow control enable */
153     uart->INTEN |= UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk;
154 }
155 
156 
157 /**
158  *    @brief        The function is used to enable UART specified interrupt and enable NVIC UART IRQ.
159  *
160  *    @param[in]    uart                The pointer of the specified UART module.
161  *    @param[in]    u32InterruptFlag    The specified interrupt of UART module:
162  *                                      - \ref UART_INTEN_WKIEN_Msk      : Wake-up interrupt
163  *                                      - \ref UART_INTEN_LINIEN_Msk     : Lin bus interrupt
164  *                                      - \ref UART_INTEN_BUFERRIEN_Msk  : Buffer Error interrupt
165  *                                      - \ref UART_INTEN_RXTOIEN_Msk    : Rx time-out interrupt
166  *                                      - \ref UART_INTEN_MODEMIEN_Msk   : Modem status interrupt
167  *                                      - \ref UART_INTEN_RLSIEN_Msk     : Receive Line status interrupt
168  *                                      - \ref UART_INTEN_THREIEN_Msk    : Tx empty interrupt
169  *                                      - \ref UART_INTEN_RDAIEN_Msk     : Rx ready interrupt *
170  *
171  *    @return       None
172  *
173  *    @details      The function is used to enable UART specified interrupt and enable NVIC UART IRQ.
174  */
UART_EnableInt(UART_T * uart,uint32_t u32InterruptFlag)175 void UART_EnableInt(UART_T*  uart, uint32_t u32InterruptFlag)
176 {
177     /* Enable UART specified interrupt */
178     UART_ENABLE_INT(uart, u32InterruptFlag);
179 }
180 
181 
182 /**
183  *    @brief        Open and set UART function
184  *
185  *    @param[in]    uart            The pointer of the specified UART module.
186  *    @param[in]    u32baudrate     The baudrate of UART module.
187  *
188  *    @return       None
189  *
190  *    @details      This function use to enable UART function and set baud-rate.
191  */
UART_Open(UART_T * uart,uint32_t u32baudrate)192 void UART_Open(UART_T* uart, uint32_t u32baudrate)
193 {
194     uint32_t u32UartClkSrcSel=0ul, u32UartClkDivNum=0ul;
195     uint32_t u32ClkTbl[4] = {__HXT, 0ul, __LXT, __HIRC};
196     uint32_t u32Baud_Div = 0ul;
197 
198 
199     if(uart==(UART_T*)UART0)
200     {
201         /* Get UART clock source selection */
202         u32UartClkSrcSel = ((uint32_t)(CLK->CLKSEL1 & CLK_CLKSEL1_UART0SEL_Msk)) >> CLK_CLKSEL1_UART0SEL_Pos;
203         /* Get UART clock divider number */
204         u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART0DIV_Msk) >> CLK_CLKDIV0_UART0DIV_Pos;
205     }
206     else if(uart==(UART_T*)UART1)
207     {
208         /* Get UART clock source selection */
209         u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART1SEL_Msk) >> CLK_CLKSEL1_UART1SEL_Pos;
210         /* Get UART clock divider number */
211         u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART1DIV_Msk) >> CLK_CLKDIV0_UART1DIV_Pos;
212     }
213     else if(uart==(UART_T*)UART2)
214     {
215         /* Get UART clock source selection */
216         u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART2SEL_Msk) >> CLK_CLKSEL3_UART2SEL_Pos;
217         /* Get UART clock divider number */
218         u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART2DIV_Msk) >> CLK_CLKDIV4_UART2DIV_Pos;
219     }
220     else if(uart==(UART_T*)UART3)
221     {
222         /* Get UART clock source selection */
223         u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART3SEL_Msk) >> CLK_CLKSEL3_UART3SEL_Pos;
224         /* Get UART clock divider number */
225         u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART3DIV_Msk) >> CLK_CLKDIV4_UART3DIV_Pos;
226     }
227     else if(uart==(UART_T*)UART4)
228     {
229         /* Get UART clock source selection */
230         u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART4SEL_Msk) >> CLK_CLKSEL3_UART4SEL_Pos;
231         /* Get UART clock divider number */
232         u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART4DIV_Msk) >> CLK_CLKDIV4_UART4DIV_Pos;
233     }
234     else if(uart==(UART_T*)UART5)
235     {
236         /* Get UART clock source selection */
237         u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART5SEL_Msk) >> CLK_CLKSEL3_UART5SEL_Pos;
238         /* Get UART clock divider number */
239         u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART5DIV_Msk) >> CLK_CLKDIV4_UART5DIV_Pos;
240     }
241 
242     /* Select UART function */
243     uart->FUNCSEL = UART_FUNCSEL_UART;
244 
245     /* Set UART line configuration */
246     uart->LINE = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
247 
248     /* Set UART Rx and RTS trigger level */
249     uart->FIFO &= ~(UART_FIFO_RFITL_Msk | UART_FIFO_RTSTRGLV_Msk);
250 
251     /* Get PLL clock frequency if UART clock source selection is PLL */
252     if(u32UartClkSrcSel == 1ul)
253     {
254         u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq();
255     }
256 
257     /* Set UART baud rate */
258     if(u32baudrate != 0ul)
259     {
260         u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate);
261 
262         if(u32Baud_Div > 0xFFFFul)
263         {
264             uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate));
265         }
266         else
267         {
268             uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div);
269         }
270     }
271 }
272 
273 
274 /**
275  *    @brief        Read UART data
276  *
277  *    @param[in]    uart            The pointer of the specified UART module.
278  *    @param[in]    pu8RxBuf        The buffer to receive the data of receive FIFO.
279  *    @param[in]    u32ReadBytes    The the read bytes number of data.
280  *
281  *    @return       u32Count Receive byte count
282  *
283  *    @details      The function is used to read Rx data from RX FIFO and the data will be stored in pu8RxBuf.
284  */
UART_Read(UART_T * uart,uint8_t pu8RxBuf[],uint32_t u32ReadBytes)285 uint32_t UART_Read(UART_T* uart, uint8_t pu8RxBuf[], uint32_t u32ReadBytes)
286 {
287     uint32_t  u32Count, u32delayno;
288     uint32_t  u32Exit = 0ul;
289 
290     for(u32Count = 0ul; u32Count < u32ReadBytes; u32Count++)
291     {
292         u32delayno = 0ul;
293 
294         while(uart->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk)   /* Check RX empty => failed */
295         {
296             u32delayno++;
297             if(u32delayno >= 0x40000000ul)
298             {
299                 u32Exit = 1ul;
300                 break;
301             }
302             else
303             {
304             }
305         }
306 
307         if(u32Exit == 1ul)
308         {
309             break;
310         }
311         else
312         {
313             pu8RxBuf[u32Count] = (uint8_t)uart->DAT; /* Get Data from UART RX  */
314         }
315     }
316 
317     return u32Count;
318 
319 }
320 
321 
322 /**
323  *    @brief        Set UART line configuration
324  *
325  *    @param[in]    uart            The pointer of the specified UART module.
326  *    @param[in]    u32baudrate     The register value of baudrate of UART module.
327  *                                  If u32baudrate = 0, UART baudrate will not change.
328  *    @param[in]    u32data_width   The data length of UART module.
329  *                                  - \ref UART_WORD_LEN_5
330  *                                  - \ref UART_WORD_LEN_6
331  *                                  - \ref UART_WORD_LEN_7
332  *                                  - \ref UART_WORD_LEN_8
333  *    @param[in]    u32parity       The parity setting (none/odd/even/mark/space) of UART module.
334  *                                  - \ref UART_PARITY_NONE
335  *                                  - \ref UART_PARITY_ODD
336  *                                  - \ref UART_PARITY_EVEN
337  *                                  - \ref UART_PARITY_MARK
338  *                                  - \ref UART_PARITY_SPACE
339  *    @param[in]    u32stop_bits    The stop bit length (1/1.5/2 bit) of UART module.
340  *                                  - \ref UART_STOP_BIT_1
341  *                                  - \ref UART_STOP_BIT_1_5
342  *                                  - \ref UART_STOP_BIT_2
343  *
344  *    @return       None
345  *
346  *    @details      This function use to config UART line setting.
347  */
UART_SetLineConfig(UART_T * uart,uint32_t u32baudrate,uint32_t u32data_width,uint32_t u32parity,uint32_t u32stop_bits)348 void UART_SetLineConfig(UART_T* uart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t  u32stop_bits)
349 {
350     uint32_t u32UartClkSrcSel=0ul, u32UartClkDivNum=0ul;
351     uint32_t u32ClkTbl[4ul] = {__HXT, 0ul, __LXT, __HIRC};
352     uint32_t u32Baud_Div = 0ul;
353 
354 
355     if(uart==(UART_T*)UART0)
356     {
357         /* Get UART clock source selection */
358         u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART0SEL_Msk) >> CLK_CLKSEL1_UART0SEL_Pos;
359         /* Get UART clock divider number */
360         u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART0DIV_Msk) >> CLK_CLKDIV0_UART0DIV_Pos;
361     }
362     else if(uart==(UART_T*)UART1)
363     {
364         /* Get UART clock source selection */
365         u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART1SEL_Msk) >> CLK_CLKSEL1_UART1SEL_Pos;
366         /* Get UART clock divider number */
367         u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART1DIV_Msk) >> CLK_CLKDIV0_UART1DIV_Pos;
368     }
369     else if(uart==(UART_T*)UART2)
370     {
371         /* Get UART clock source selection */
372         u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART2SEL_Msk) >> CLK_CLKSEL3_UART2SEL_Pos;
373         /* Get UART clock divider number */
374         u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART2DIV_Msk) >> CLK_CLKDIV4_UART2DIV_Pos;
375     }
376     else if(uart==(UART_T*)UART3)
377     {
378         /* Get UART clock source selection */
379         u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART3SEL_Msk) >> CLK_CLKSEL3_UART3SEL_Pos;
380         /* Get UART clock divider number */
381         u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART3DIV_Msk) >> CLK_CLKDIV4_UART3DIV_Pos;
382     }
383     else if(uart==(UART_T*)UART4)
384     {
385         /* Get UART clock source selection */
386         u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART4SEL_Msk) >> CLK_CLKSEL3_UART4SEL_Pos;
387         /* Get UART clock divider number */
388         u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART4DIV_Msk) >> CLK_CLKDIV4_UART4DIV_Pos;
389     }
390     else if(uart==(UART_T*)UART5)
391     {
392         /* Get UART clock source selection */
393         u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART5SEL_Msk) >> CLK_CLKSEL3_UART5SEL_Pos;
394         /* Get UART clock divider number */
395         u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART5DIV_Msk) >> CLK_CLKDIV4_UART5DIV_Pos;
396     }
397 
398     /* Get PLL clock frequency if UART clock source selection is PLL */
399     if(u32UartClkSrcSel == 1ul)
400     {
401         u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq();
402     }
403     else
404     {
405     }
406 
407     /* Set UART baud rate */
408     if(u32baudrate != 0ul)
409     {
410         u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate);
411 
412         if(u32Baud_Div > 0xFFFFul)
413         {
414             uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate));
415         }
416         else
417         {
418             uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div);
419         }
420     }
421 
422     /* Set UART line configuration */
423     uart->LINE = u32data_width | u32parity | u32stop_bits;
424 }
425 
426 
427 /**
428  *    @brief        Set Rx timeout count
429  *
430  *    @param[in]    uart    The pointer of the specified UART module.
431  *    @param[in]    u32TOC  Rx timeout counter.
432  *
433  *    @return       None
434  *
435  *    @details      This function use to set Rx timeout count.
436  */
UART_SetTimeoutCnt(UART_T * uart,uint32_t u32TOC)437 void UART_SetTimeoutCnt(UART_T* uart, uint32_t u32TOC)
438 {
439     /* Set time-out interrupt comparator */
440     uart->TOUT = (uart->TOUT & ~UART_TOUT_TOIC_Msk) | (u32TOC);
441 
442     /* Set time-out counter enable */
443     uart->INTEN |= UART_INTEN_TOCNTEN_Msk;
444 }
445 
446 
447 /**
448  *    @brief        Select and configure IrDA function
449  *
450  *    @param[in]    uart            The pointer of the specified UART module.
451  *    @param[in]    u32Buadrate     The baudrate of UART module.
452  *    @param[in]    u32Direction    The direction of UART module in IrDA mode:
453  *                                  - \ref UART_IRDA_TXEN
454  *                                  - \ref UART_IRDA_RXEN
455  *
456  *    @return       None
457   *
458  *    @details      The function is used to configure IrDA relative settings. It consists of TX or RX mode and baudrate.
459  */
UART_SelectIrDAMode(UART_T * uart,uint32_t u32Buadrate,uint32_t u32Direction)460 void UART_SelectIrDAMode(UART_T* uart, uint32_t u32Buadrate, uint32_t u32Direction)
461 {
462     uint32_t u32UartClkSrcSel=0ul, u32UartClkDivNum=0ul;
463     uint32_t u32ClkTbl[4ul] = {__HXT, 0ul, __LXT, __HIRC};
464     uint32_t u32Baud_Div;
465 
466     /* Select IrDA function mode */
467     uart->FUNCSEL = UART_FUNCSEL_IrDA;
468 
469 
470     if(uart==UART0)
471     {
472         /* Get UART clock source selection */
473         u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART0SEL_Msk) >> CLK_CLKSEL1_UART0SEL_Pos;
474         /* Get UART clock divider number */
475         u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART0DIV_Msk) >> CLK_CLKDIV0_UART0DIV_Pos;
476     }
477     else if(uart==UART1)
478     {
479         /* Get UART clock source selection */
480         u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART1SEL_Msk) >> CLK_CLKSEL1_UART1SEL_Pos;
481         /* Get UART clock divider number */
482         u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART1DIV_Msk) >> CLK_CLKDIV0_UART1DIV_Pos;
483     }
484     else if(uart==UART2)
485     {
486         /* Get UART clock source selection */
487         u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART2SEL_Msk) >> CLK_CLKSEL3_UART2SEL_Pos;
488         /* Get UART clock divider number */
489         u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART2DIV_Msk) >> CLK_CLKDIV4_UART2DIV_Pos;
490     }
491     else if(uart==UART3)
492     {
493         /* Get UART clock source selection */
494         u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART3SEL_Msk) >> CLK_CLKSEL3_UART3SEL_Pos;
495         /* Get UART clock divider number */
496         u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART3DIV_Msk) >> CLK_CLKDIV4_UART3DIV_Pos;
497     }
498     else if(uart==UART4)
499     {
500         /* Get UART clock source selection */
501         u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART4SEL_Msk) >> CLK_CLKSEL3_UART4SEL_Pos;
502         /* Get UART clock divider number */
503         u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART4DIV_Msk) >> CLK_CLKDIV4_UART4DIV_Pos;
504     }
505     else if(uart==UART5)
506     {
507         /* Get UART clock source selection */
508         u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART5SEL_Msk) >> CLK_CLKSEL3_UART5SEL_Pos;
509         /* Get UART clock divider number */
510         u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART5DIV_Msk) >> CLK_CLKDIV4_UART5DIV_Pos;
511     }
512 
513 
514     /* Get PLL clock frequency if UART clock source selection is PLL */
515     if(u32UartClkSrcSel == 1ul)
516     {
517         u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq();
518     }
519     else
520     {
521     }
522 
523     /* Set UART IrDA baud rate in mode 0 */
524     if(u32Buadrate != 0ul)
525     {
526         u32Baud_Div = UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32Buadrate);
527 
528         if(u32Baud_Div < 0xFFFFul)
529         {
530             uart->BAUD = (UART_BAUD_MODE0 | u32Baud_Div);
531         }
532         else
533         {
534         }
535     }
536 
537     /* Configure IrDA relative settings */
538     if(u32Direction == UART_IRDA_RXEN)
539     {
540         uart->IRDA |= UART_IRDA_RXINV_Msk;     /*Rx signal is inverse*/
541         uart->IRDA &= ~UART_IRDA_TXEN_Msk;
542     }
543     else
544     {
545         uart->IRDA &= ~UART_IRDA_TXINV_Msk;    /*Tx signal is not inverse*/
546         uart->IRDA |= UART_IRDA_TXEN_Msk;
547     }
548 
549 }
550 
551 
552 /**
553  *    @brief        Select and configure RS485 function
554  *
555  *    @param[in]    uart        The pointer of the specified UART module.
556  *    @param[in]    u32Mode     The operation mode(NMM/AUD/AAD).
557  *                              - \ref UART_ALTCTL_RS485NMM_Msk
558  *                              - \ref UART_ALTCTL_RS485AUD_Msk
559  *                              - \ref UART_ALTCTL_RS485AAD_Msk
560  *    @param[in]    u32Addr     The RS485 address.
561  *
562  *    @return       None
563  *
564  *    @details      The function is used to set RS485 relative setting.
565  */
UART_SelectRS485Mode(UART_T * uart,uint32_t u32Mode,uint32_t u32Addr)566 void UART_SelectRS485Mode(UART_T* uart, uint32_t u32Mode, uint32_t u32Addr)
567 {
568     /* Select UART RS485 function mode */
569     uart->FUNCSEL = UART_FUNCSEL_RS485;
570 
571     /* Set RS585 configuration */
572     uart->ALTCTL &= ~(UART_ALTCTL_RS485NMM_Msk | UART_ALTCTL_RS485AUD_Msk | UART_ALTCTL_RS485AAD_Msk | UART_ALTCTL_ADDRMV_Msk);
573     uart->ALTCTL |= (u32Mode | (u32Addr << UART_ALTCTL_ADDRMV_Pos));
574 }
575 
576 
577 /**
578  *    @brief        Select and configure LIN function
579  *
580  *    @param[in]    uart            The pointer of the specified UART module.
581  *    @param[in]    u32Mode         The LIN direction :
582  *                                  - \ref UART_ALTCTL_LINTXEN_Msk
583  *                                  - \ref UART_ALTCTL_LINRXEN_Msk
584  *    @param[in]    u32BreakLength  The break field length.
585  *
586  *    @return       None
587  *
588  *    @details      The function is used to set LIN relative setting.
589  */
UART_SelectLINMode(UART_T * uart,uint32_t u32Mode,uint32_t u32BreakLength)590 void UART_SelectLINMode(UART_T* uart, uint32_t u32Mode, uint32_t u32BreakLength)
591 {
592     /* Select LIN function mode */
593     uart->FUNCSEL = UART_FUNCSEL_LIN;
594 
595     /* Select LIN function setting : Tx enable, Rx enable and break field length */
596     uart->ALTCTL &= ~(UART_ALTCTL_LINTXEN_Msk | UART_ALTCTL_LINRXEN_Msk | UART_ALTCTL_BRKFL_Msk);
597     uart->ALTCTL |= (u32Mode | (u32BreakLength << UART_ALTCTL_BRKFL_Pos));
598 }
599 
600 
601 /**
602  *    @brief        Write UART data
603  *
604  *    @param[in]    uart            The pointer of the specified UART module.
605  *    @param[in]    pu8TxBuf        The buffer to send the data to UART transmission FIFO.
606  *    @param[out]   u32WriteBytes   The byte number of data.
607  *
608  *    @return       u32Count transfer byte count
609  *
610  *    @details      The function is to write data into TX buffer to transmit data by UART.
611  */
UART_Write(UART_T * uart,uint8_t pu8TxBuf[],uint32_t u32WriteBytes)612 uint32_t UART_Write(UART_T* uart, uint8_t pu8TxBuf[], uint32_t u32WriteBytes)
613 {
614     uint32_t  u32Count, u32delayno;
615     uint32_t  u32Exit = 0ul;
616 
617     for(u32Count = 0ul; u32Count != u32WriteBytes; u32Count++)
618     {
619         u32delayno = 0ul;
620         while(uart->FIFOSTS & UART_FIFOSTS_TXFULL_Msk)   /* Check Tx Full */
621         {
622             u32delayno++;
623             if(u32delayno >= 0x40000000ul)
624             {
625                 u32Exit = 1ul;
626                 break;
627             }
628             else
629             {
630             }
631         }
632 
633         if(u32Exit == 1ul)
634         {
635             break;
636         }
637         else
638         {
639             uart->DAT = pu8TxBuf[u32Count];    /* Send UART Data from buffer */
640         }
641     }
642 
643     return u32Count;
644 }
645 
646 
647 /*@}*/ /* end of group UART_EXPORTED_FUNCTIONS */
648 
649 /*@}*/ /* end of group UART_Driver */
650 
651 /*@}*/ /* end of group Standard_Driver */
652 
653 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
654 
655 
656 
657