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