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