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