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