1 /**************************************************************************//**
2 * @file lpuart.c
3 * @version V3.00
4 * @brief LPUART 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 LPUART_Driver LPUART Driver
18 @{
19 */
20
21 /** @addtogroup LPUART_EXPORTED_FUNCTIONS LPUART Exported Functions
22 @{
23 */
24
25 /**
26 * @brief Clear LPUART specified interrupt flag
27 *
28 * @param[in] lpuart The pointer of the specified LPUART module.
29 * @param[in] u32InterruptFlag The specified interrupt of LPUART module.
30 * - \ref LPUART_INTSTS_WKIF_Msk : Wake-up interrupt
31 * - \ref LPUART_INTSTS_BUFERRINT_Msk : Buffer Error interrupt
32 * - \ref LPUART_INTSTS_MODEMINT_Msk : Modem Status interrupt
33 * - \ref LPUART_INTSTS_RLSINT_Msk : Receive Line Status interrupt
34 *
35 * @return None
36 *
37 * @details The function is used to clear LPUART specified interrupt flag.
38 */
39
LPUART_ClearIntFlag(LPUART_T * lpuart,uint32_t u32InterruptFlag)40 void LPUART_ClearIntFlag(LPUART_T* lpuart, uint32_t u32InterruptFlag)
41 {
42
43 if(u32InterruptFlag & LPUART_INTSTS_RLSINT_Msk) /* Clear Receive Line Status Interrupt */
44 {
45 lpuart->FIFOSTS = LPUART_FIFOSTS_BIF_Msk | LPUART_FIFOSTS_FEF_Msk | LPUART_FIFOSTS_PEF_Msk;
46 lpuart->FIFOSTS = LPUART_FIFOSTS_ADDRDETF_Msk;
47 }
48
49 if(u32InterruptFlag & LPUART_INTSTS_MODEMINT_Msk) /* Clear Modem Status Interrupt */
50 {
51 lpuart->MODEMSTS |= LPUART_MODEMSTS_CTSDETF_Msk;
52 }
53 else
54 {
55 }
56
57 if(u32InterruptFlag & LPUART_INTSTS_BUFERRINT_Msk) /* Clear Buffer Error Interrupt */
58 {
59 lpuart->FIFOSTS = LPUART_FIFOSTS_RXOVIF_Msk | LPUART_FIFOSTS_TXOVIF_Msk;
60 }
61
62 if(u32InterruptFlag & LPUART_INTSTS_WKINT_Msk) /* Clear Wake-up Interrupt */
63 {
64 lpuart->WKSTS = LPUART_WKSTS_CTSWKF_Msk | LPUART_WKSTS_DATWKF_Msk |
65 LPUART_WKSTS_RFRTWKF_Msk |LPUART_WKSTS_RS485WKF_Msk |
66 LPUART_WKSTS_TOUTWKF_Msk;
67 }
68
69 }
70
71
72 /**
73 * @brief Disable LPUART interrupt
74 *
75 * @param[in] lpuart The pointer of the specified LPUART module.
76 *
77 * @return None
78 *
79 * @details The function is used to disable LPUART interrupt.
80 */
LPUART_Close(LPUART_T * lpuart)81 void LPUART_Close(LPUART_T* lpuart)
82 {
83 lpuart->INTEN = 0ul;
84 }
85
86
87 /**
88 * @brief Disable LPUART auto flow control function
89 *
90 * @param[in] lpuart The pointer of the specified LPUART module.
91 *
92 * @return None
93 *
94 * @details The function is used to disable LPUART auto flow control.
95 */
LPUART_DisableFlowCtrl(LPUART_T * lpuart)96 void LPUART_DisableFlowCtrl(LPUART_T* lpuart)
97 {
98 lpuart->INTEN &= ~(LPUART_INTEN_ATORTSEN_Msk | LPUART_INTEN_ATOCTSEN_Msk);
99 }
100
101
102 /**
103 * @brief Disable LPUART specified interrupt
104 *
105 * @param[in] lpuart The pointer of the specified LPUART module.
106 * @param[in] u32InterruptFlag The specified interrupt of LPUART module.
107 * - \ref LPUART_INTEN_WKIEN_Msk : Wake-up interrupt
108 * - \ref LPUART_INTEN_BUFERRIEN_Msk : Buffer Error interrupt
109 * - \ref LPUART_INTEN_RXTOIEN_Msk : Rx time-out interrupt
110 * - \ref LPUART_INTEN_MODEMIEN_Msk : Modem status interrupt
111 * - \ref LPUART_INTEN_RLSIEN_Msk : Receive Line status interrupt
112 * - \ref LPUART_INTEN_THREIEN_Msk : Tx empty interrupt
113 * - \ref LPUART_INTEN_RDAIEN_Msk : Rx ready interrupt *
114 *
115 * @return None
116 *
117 * @details The function is used to disable LPUART specified interrupt and disable NVIC LPUART IRQ.
118 */
LPUART_DisableInt(LPUART_T * lpuart,uint32_t u32InterruptFlag)119 void LPUART_DisableInt(LPUART_T* lpuart, uint32_t u32InterruptFlag)
120 {
121 /* Disable LPUART specified interrupt */
122 LPUART_DISABLE_INT(lpuart, u32InterruptFlag);
123 }
124
125
126 /**
127 * @brief Enable LPUART auto flow control function
128 *
129 * @param[in] lpuart The pointer of the specified LPUART module.
130 *
131 * @return None
132 *
133 * @details The function is used to Enable LPUART auto flow control.
134 */
LPUART_EnableFlowCtrl(LPUART_T * lpuart)135 void LPUART_EnableFlowCtrl(LPUART_T* lpuart)
136 {
137 /* Set RTS pin output is low level active */
138 lpuart->MODEM |= LPUART_MODEM_RTSACTLV_Msk;
139
140 /* Set CTS pin input is low level active */
141 lpuart->MODEMSTS |= LPUART_MODEMSTS_CTSACTLV_Msk;
142
143 /* Set RTS and CTS auto flow control enable */
144 lpuart->INTEN |= LPUART_INTEN_ATORTSEN_Msk | LPUART_INTEN_ATOCTSEN_Msk;
145 }
146
147
148 /**
149 * @brief The function is used to enable LPUART specified interrupt and enable NVIC LPUART IRQ.
150 *
151 * @param[in] lpuart The pointer of the specified LPUART module.
152 * @param[in] u32InterruptFlag The specified interrupt of LPUART module:
153 * - \ref LPUART_INTEN_WKIEN_Msk : Wake-up interrupt
154 * - \ref LPUART_INTEN_BUFERRIEN_Msk : Buffer Error interrupt
155 * - \ref LPUART_INTEN_RXTOIEN_Msk : Rx time-out interrupt
156 * - \ref LPUART_INTEN_MODEMIEN_Msk : Modem status interrupt
157 * - \ref LPUART_INTEN_RLSIEN_Msk : Receive Line status interrupt
158 * - \ref LPUART_INTEN_THREIEN_Msk : Tx empty interrupt
159 * - \ref LPUART_INTEN_RDAIEN_Msk : Rx ready interrupt *
160 *
161 * @return None
162 *
163 * @details The function is used to enable LPUART specified interrupt and enable NVIC LPUART IRQ.
164 */
LPUART_EnableInt(LPUART_T * lpuart,uint32_t u32InterruptFlag)165 void LPUART_EnableInt(LPUART_T* lpuart, uint32_t u32InterruptFlag)
166 {
167 /* Enable LPUART specified interrupt */
168 LPUART_ENABLE_INT(lpuart, u32InterruptFlag);
169 }
170
171
172 /**
173 * @brief Open and set LPUART function
174 *
175 * @param[in] lpuart The pointer of the specified LPUART module.
176 * @param[in] u32baudrate The baudrate of LPUART module.
177 *
178 * @return None
179 *
180 * @details This function use to enable LPUART function and set baud-rate.
181 */
LPUART_Open(LPUART_T * lpuart,uint32_t u32baudrate)182 void LPUART_Open(LPUART_T* lpuart, uint32_t u32baudrate)
183 {
184 uint32_t u32UartClkSrcSel=0ul, u32UartClkDivNum=0ul;
185 uint32_t u32ClkTbl[4] = {__HIRC, __MIRC, __LXT};
186 uint32_t u32Baud_Div = 0ul;
187
188
189 if(lpuart==(LPUART_T*)LPUART0)
190 {
191 /* Get LPUART clock source selection */
192 u32UartClkSrcSel = ((uint32_t)(LPSCC->CLKSEL0 & LPSCC_CLKSEL0_LPUART0SEL_Msk)) >> LPSCC_CLKSEL0_LPUART0SEL_Pos;
193 /* Get LPUART clock divider number */
194 u32UartClkDivNum = (LPSCC->CLKDIV0 & LPSCC_CLKDIV0_LPUART0DIV_Msk) >> LPSCC_CLKDIV0_LPUART0DIV_Pos;
195 }
196
197
198 /* Select LPUART function */
199 lpuart->FUNCSEL = LPUART_FUNCSEL_LPUART;
200
201 /* Set LPUART line configuration */
202 lpuart->LINE = LPUART_WORD_LEN_8 | LPUART_PARITY_NONE | LPUART_STOP_BIT_1;
203
204 /* Set LPUART Rx and RTS trigger level */
205 lpuart->FIFO &= ~(LPUART_FIFO_RFITL_Msk | LPUART_FIFO_RTSTRGLV_Msk);
206
207 /* Set LPUART baud rate */
208 if(u32baudrate != 0ul)
209 {
210 u32Baud_Div = LPUART_BAUD_MODE2_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate);
211
212 if(u32Baud_Div > 0xFFFFul)
213 {
214 lpuart->BAUD = (LPUART_BAUD_MODE0 | LPUART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate));
215 }
216 else
217 {
218 lpuart->BAUD = (LPUART_BAUD_MODE2 | u32Baud_Div);
219 }
220 }
221 }
222
223
224 /**
225 * @brief Read LPUART data
226 *
227 * @param[in] lpuart The pointer of the specified LPUART module.
228 * @param[in] pu8RxBuf The buffer to receive the data of receive FIFO.
229 * @param[in] u32ReadBytes The the read bytes number of data.
230 *
231 * @return u32Count Receive byte count
232 *
233 * @details The function is used to read Rx data from RX FIFO and the data will be stored in pu8RxBuf.
234 */
LPUART_Read(LPUART_T * lpuart,uint8_t pu8RxBuf[],uint32_t u32ReadBytes)235 uint32_t LPUART_Read(LPUART_T* lpuart, uint8_t pu8RxBuf[], uint32_t u32ReadBytes)
236 {
237 uint32_t u32Count, u32delayno;
238 uint32_t u32Exit = 0ul;
239
240 for(u32Count = 0ul; u32Count < u32ReadBytes; u32Count++)
241 {
242 u32delayno = 0ul;
243
244 while(lpuart->FIFOSTS & LPUART_FIFOSTS_RXEMPTY_Msk) /* Check RX empty => failed */
245 {
246 u32delayno++;
247 if(u32delayno >= 0x40000000ul)
248 {
249 u32Exit = 1ul;
250 break;
251 }
252 else
253 {
254 }
255 }
256
257 if(u32Exit == 1ul)
258 {
259 break;
260 }
261 else
262 {
263 pu8RxBuf[u32Count] = (uint8_t)lpuart->DAT; /* Get Data from LPUART RX */
264 }
265 }
266
267 return u32Count;
268
269 }
270
271
272 /**
273 * @brief Set LPUART line configuration
274 *
275 * @param[in] lpuart The pointer of the specified LPUART module.
276 * @param[in] u32baudrate The register value of baudrate of LPUART module.
277 * If u32baudrate = 0, LPUART baudrate will not change.
278 * @param[in] u32data_width The data length of LPUART module.
279 * - \ref LPUART_WORD_LEN_5
280 * - \ref LPUART_WORD_LEN_6
281 * - \ref LPUART_WORD_LEN_7
282 * - \ref LPUART_WORD_LEN_8
283 * @param[in] u32parity The parity setting (none/odd/even/mark/space) of LPUART module.
284 * - \ref LPUART_PARITY_NONE
285 * - \ref LPUART_PARITY_ODD
286 * - \ref LPUART_PARITY_EVEN
287 * - \ref LPUART_PARITY_MARK
288 * - \ref LPUART_PARITY_SPACE
289 * @param[in] u32stop_bits The stop bit length (1/1.5/2 bit) of LPUART module.
290 * - \ref LPUART_STOP_BIT_1
291 * - \ref LPUART_STOP_BIT_1_5
292 * - \ref LPUART_STOP_BIT_2
293 *
294 * @return None
295 *
296 * @details This function use to config LPUART line setting.
297 */
LPUART_SetLine_Config(LPUART_T * lpuart,uint32_t u32baudrate,uint32_t u32data_width,uint32_t u32parity,uint32_t u32stop_bits)298 void LPUART_SetLine_Config(LPUART_T* lpuart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits)
299 {
300 uint32_t u32UartClkSrcSel=0ul, u32UartClkDivNum=0ul;
301 uint32_t u32ClkTbl[4] = {__HIRC, __MIRC, __LXT};
302 uint32_t u32Baud_Div = 0ul;
303
304
305 if(lpuart==(LPUART_T*)LPUART0)
306 {
307 /* Get LPUART clock source selection */
308 u32UartClkSrcSel = (LPSCC->CLKSEL0 & LPSCC_CLKSEL0_LPUART0SEL_Msk) >> LPSCC_CLKSEL0_LPUART0SEL_Pos;
309 /* Get LPUART clock divider number */
310 u32UartClkDivNum = (LPSCC->CLKDIV0 & LPSCC_CLKDIV0_LPUART0DIV_Msk) >> LPSCC_CLKDIV0_LPUART0DIV_Pos;
311 }
312
313
314 /* Set LPUART baud rate */
315 if(u32baudrate != 0ul)
316 {
317 u32Baud_Div = LPUART_BAUD_MODE2_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate);
318
319 if(u32Baud_Div > 0xFFFFul)
320 {
321 lpuart->BAUD = (LPUART_BAUD_MODE0 | LPUART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate));
322 }
323 else
324 {
325 lpuart->BAUD = (LPUART_BAUD_MODE2 | u32Baud_Div);
326 }
327 }
328
329 /* Set LPUART line configuration */
330 lpuart->LINE = u32data_width | u32parity | u32stop_bits;
331 }
332
333
334 /**
335 * @brief Set Rx timeout count
336 *
337 * @param[in] lpuart The pointer of the specified LPUART module.
338 * @param[in] u32TOC Rx timeout counter.
339 *
340 * @return None
341 *
342 * @details This function use to set Rx timeout count.
343 */
LPUART_SetTimeoutCnt(LPUART_T * lpuart,uint32_t u32TOC)344 void LPUART_SetTimeoutCnt(LPUART_T* lpuart, uint32_t u32TOC)
345 {
346 /* Set time-out interrupt comparator */
347 lpuart->TOUT = (lpuart->TOUT & ~LPUART_TOUT_TOIC_Msk) | (u32TOC);
348
349 /* Set time-out counter enable */
350 lpuart->INTEN |= LPUART_INTEN_TOCNTEN_Msk;
351 }
352
353
354 /**
355 * @brief Select and configure RS485 function
356 *
357 * @param[in] lpuart The pointer of the specified LPUART module.
358 * @param[in] u32Mode The operation mode(NMM/AUD/AAD).
359 * - \ref LPUART_ALTCTL_RS485NMM_Msk
360 * - \ref LPUART_ALTCTL_RS485AUD_Msk
361 * - \ref LPUART_ALTCTL_RS485AAD_Msk
362 * @param[in] u32Addr The RS485 address.
363 *
364 * @return None
365 *
366 * @details The function is used to set RS485 relative setting.
367 */
LPUART_SelectRS485Mode(LPUART_T * lpuart,uint32_t u32Mode,uint32_t u32Addr)368 void LPUART_SelectRS485Mode(LPUART_T* lpuart, uint32_t u32Mode, uint32_t u32Addr)
369 {
370 /* Select LPUART RS485 function mode */
371 lpuart->FUNCSEL = LPUART_FUNCSEL_RS485;
372
373 /* Set RS485 configuration */
374 lpuart->ALTCTL &= ~(LPUART_ALTCTL_RS485NMM_Msk | LPUART_ALTCTL_RS485AUD_Msk | LPUART_ALTCTL_RS485AAD_Msk | LPUART_ALTCTL_ADDRMV_Msk);
375 lpuart->ALTCTL |= (u32Mode | (u32Addr << LPUART_ALTCTL_ADDRMV_Pos));
376 }
377
378 /**
379 * @brief Write LPUART data
380 *
381 * @param[in] lpuart The pointer of the specified LPUART module.
382 * @param[in] pu8TxBuf The buffer to send the data to LPUART transmission FIFO.
383 * @param[out] u32WriteBytes The byte number of data.
384 *
385 * @return u32Count transfer byte count
386 *
387 * @details The function is to write data into TX buffer to transmit data by LPUART.
388 */
LPUART_Write(LPUART_T * lpuart,uint8_t pu8TxBuf[],uint32_t u32WriteBytes)389 uint32_t LPUART_Write(LPUART_T* lpuart, uint8_t pu8TxBuf[], uint32_t u32WriteBytes)
390 {
391 uint32_t u32Count, u32delayno;
392 uint32_t u32Exit = 0ul;
393
394 for(u32Count = 0ul; u32Count != u32WriteBytes; u32Count++)
395 {
396 u32delayno = 0ul;
397 while(lpuart->FIFOSTS & LPUART_FIFOSTS_TXFULL_Msk) /* Check Tx Full */
398 {
399 u32delayno++;
400 if(u32delayno >= 0x40000000ul)
401 {
402 u32Exit = 1ul;
403 break;
404 }
405 else
406 {
407 }
408 }
409
410 if(u32Exit == 1ul)
411 {
412 break;
413 }
414 else
415 {
416 lpuart->DAT = pu8TxBuf[u32Count]; /* Send LPUART Data from buffer */
417 }
418 }
419
420 return u32Count;
421 }
422 /**
423 * @brief Select Single Wire mode function
424 *
425 * @param[in] lpuart The pointer of the specified LPUART module.
426 *
427 * @return None
428 *
429 * @details The function is used to select Single Wire mode.
430 */
LPUART_SelectSingleWireMode(LPUART_T * lpuart)431 void LPUART_SelectSingleWireMode(LPUART_T *lpuart)
432 {
433
434 /* Select LPUART SingleWire function mode */
435 lpuart->FUNCSEL = ((lpuart->FUNCSEL & (~LPUART_FUNCSEL_FUNCSEL_Msk)) | LPUART_FUNCSEL_SINGLE_WIRE);
436
437 }
438 /*@}*/ /* end of group LPUART_EXPORTED_FUNCTIONS */
439
440 /*@}*/ /* end of group LPUART_Driver */
441
442 /*@}*/ /* end of group Standard_Driver */
443
444 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
445
446
447
448