1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2023 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_usart.h"
10 #include "fsl_device_registers.h"
11 #include "fsl_flexcomm.h"
12 
13 /*******************************************************************************
14  * Definitions
15  ******************************************************************************/
16 
17 /* Component ID definition, used by tools. */
18 #ifndef FSL_COMPONENT_ID
19 #define FSL_COMPONENT_ID "platform.drivers.flexcomm_usart"
20 #endif
21 
22 /*!
23  * @brief Used for conversion from `flexcomm_usart_irq_handler_t` to `flexcomm_irq_handler_t`
24  */
25 typedef union usart_to_flexcomm
26 {
27     flexcomm_usart_irq_handler_t usart_master_handler;
28     flexcomm_irq_handler_t flexcomm_handler;
29 } usart_to_flexcomm_t;
30 
31 enum
32 {
33     kUSART_TxIdle, /* TX idle. */
34     kUSART_TxBusy, /* TX busy. */
35     kUSART_RxIdle, /* RX idle. */
36     kUSART_RxBusy  /* RX busy. */
37 };
38 
39 /*******************************************************************************
40  * Variables
41  ******************************************************************************/
42 
43 /*! @brief IRQ name array */
44 static const IRQn_Type s_usartIRQ[] = USART_IRQS;
45 
46 /*! @brief Array to map USART instance number to base address. */
47 static const uint32_t s_usartBaseAddrs[FSL_FEATURE_SOC_USART_COUNT] = USART_BASE_ADDRS;
48 
49 /*******************************************************************************
50  * Code
51  ******************************************************************************/
52 
53 /* Get the index corresponding to the USART */
54 /*! brief Returns instance number for USART peripheral base address. */
USART_GetInstance(USART_Type * base)55 uint32_t USART_GetInstance(USART_Type *base)
56 {
57     uint32_t i;
58 
59     for (i = 0; i < (uint32_t)FSL_FEATURE_SOC_USART_COUNT; i++)
60     {
61         if ((uint32_t)base == s_usartBaseAddrs[i])
62         {
63             break;
64         }
65     }
66 
67     assert(i < (uint32_t)FSL_FEATURE_SOC_USART_COUNT);
68     return i;
69 }
70 
71 /*!
72  * brief Get the length of received data in RX ring buffer.
73  *
74  * param handle USART handle pointer.
75  * return Length of received data in RX ring buffer.
76  */
USART_TransferGetRxRingBufferLength(usart_handle_t * handle)77 size_t USART_TransferGetRxRingBufferLength(usart_handle_t *handle)
78 {
79     size_t size;
80 
81     /* Check arguments */
82     assert(NULL != handle);
83     uint16_t rxRingBufferHead = handle->rxRingBufferHead;
84     uint16_t rxRingBufferTail = handle->rxRingBufferTail;
85 
86     if (rxRingBufferTail > rxRingBufferHead)
87     {
88         size = (size_t)rxRingBufferHead + handle->rxRingBufferSize - (size_t)rxRingBufferTail;
89     }
90     else
91     {
92         size = (size_t)rxRingBufferHead - (size_t)rxRingBufferTail;
93     }
94     return size;
95 }
96 
USART_TransferIsRxRingBufferFull(usart_handle_t * handle)97 static bool USART_TransferIsRxRingBufferFull(usart_handle_t *handle)
98 {
99     bool full;
100 
101     /* Check arguments */
102     assert(NULL != handle);
103 
104     if (USART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U))
105     {
106         full = true;
107     }
108     else
109     {
110         full = false;
111     }
112     return full;
113 }
114 
115 /*!
116  * brief Sets up the RX ring buffer.
117  *
118  * This function sets up the RX ring buffer to a specific USART handle.
119  *
120  * When the RX ring buffer is used, data received are stored into the ring buffer even when the
121  * user doesn't call the USART_TransferReceiveNonBlocking() API. If there is already data received
122  * in the ring buffer, the user can get the received data from the ring buffer directly.
123  *
124  * note When using the RX ring buffer, one byte is reserved for internal use. In other
125  * words, if p ringBufferSize is 32, then only 31 bytes are used for saving data.
126  *
127  * param base USART peripheral base address.
128  * param handle USART handle pointer.
129  * param ringBuffer Start address of the ring buffer for background receiving. Pass NULL to disable the ring buffer.
130  * param ringBufferSize size of the ring buffer.
131  */
USART_TransferStartRingBuffer(USART_Type * base,usart_handle_t * handle,uint8_t * ringBuffer,size_t ringBufferSize)132 void USART_TransferStartRingBuffer(USART_Type *base, usart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize)
133 {
134     /* Check arguments */
135     assert(NULL != base);
136     assert(NULL != handle);
137     assert(NULL != ringBuffer);
138 
139     /* Setup the ringbuffer address */
140     handle->rxRingBuffer     = ringBuffer;
141     handle->rxRingBufferSize = ringBufferSize;
142     handle->rxRingBufferHead = 0U;
143     handle->rxRingBufferTail = 0U;
144     /* ring buffer is ready we can start receiving data */
145     base->FIFOINTENSET = USART_FIFOINTENSET_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;
146 }
147 
148 /*!
149  * brief Aborts the background transfer and uninstalls the ring buffer.
150  *
151  * This function aborts the background transfer and uninstalls the ring buffer.
152  *
153  * param base USART peripheral base address.
154  * param handle USART handle pointer.
155  */
USART_TransferStopRingBuffer(USART_Type * base,usart_handle_t * handle)156 void USART_TransferStopRingBuffer(USART_Type *base, usart_handle_t *handle)
157 {
158     /* Check arguments */
159     assert(NULL != base);
160     assert(NULL != handle);
161 
162     if (handle->rxState == (uint8_t)kUSART_RxIdle)
163     {
164         base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENCLR_RXERR_MASK;
165     }
166     handle->rxRingBuffer     = NULL;
167     handle->rxRingBufferSize = 0U;
168     handle->rxRingBufferHead = 0U;
169     handle->rxRingBufferTail = 0U;
170 }
171 
172 /*!
173  * brief Initializes a USART instance with user configuration structure and peripheral clock.
174  *
175  * This function configures the USART module with the user-defined settings. The user can configure the configuration
176  * structure and also get the default configuration by using the USART_GetDefaultConfig() function.
177  * Example below shows how to use this API to configure USART.
178  * code
179  *  usart_config_t usartConfig;
180  *  usartConfig.baudRate_Bps = 115200U;
181  *  usartConfig.parityMode = kUSART_ParityDisabled;
182  *  usartConfig.stopBitCount = kUSART_OneStopBit;
183  *  USART_Init(USART1, &usartConfig, 20000000U);
184  * endcode
185  *
186  * param base USART peripheral base address.
187  * param config Pointer to user-defined configuration structure.
188  * param srcClock_Hz USART clock source frequency in HZ.
189  * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
190  * retval kStatus_InvalidArgument USART base address is not valid
191  * retval kStatus_Success Status USART initialize succeed
192  */
USART_Init(USART_Type * base,const usart_config_t * config,uint32_t srcClock_Hz)193 status_t USART_Init(USART_Type *base, const usart_config_t *config, uint32_t srcClock_Hz)
194 {
195     int result;
196 
197     /* check arguments */
198     assert(!((NULL == base) || (NULL == config) || (0U == srcClock_Hz)));
199     if ((NULL == base) || (NULL == config) || (0U == srcClock_Hz))
200     {
201         return kStatus_InvalidArgument;
202     }
203 
204     /* initialize flexcomm to USART mode */
205     result = FLEXCOMM_Init(base, FLEXCOMM_PERIPH_USART);
206     if (kStatus_Success != result)
207     {
208         return result;
209     }
210 
211     if (config->enableTx)
212     {
213         /* empty and enable txFIFO */
214         base->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK | USART_FIFOCFG_ENABLETX_MASK;
215         /* setup trigger level */
216         base->FIFOTRIG &= ~(USART_FIFOTRIG_TXLVL_MASK);
217         base->FIFOTRIG |= USART_FIFOTRIG_TXLVL(config->txWatermark);
218         /* enable trigger interrupt */
219         base->FIFOTRIG |= USART_FIFOTRIG_TXLVLENA_MASK;
220     }
221 
222     /* empty and enable rxFIFO */
223     if (config->enableRx)
224     {
225         base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK | USART_FIFOCFG_ENABLERX_MASK;
226         /* setup trigger level */
227         base->FIFOTRIG &= ~(USART_FIFOTRIG_RXLVL_MASK);
228         base->FIFOTRIG |= USART_FIFOTRIG_RXLVL(config->rxWatermark);
229         /* enable trigger interrupt */
230         base->FIFOTRIG |= USART_FIFOTRIG_RXLVLENA_MASK;
231     }
232 #if defined(FSL_FEATURE_USART_HAS_FIFORXTIMEOUTCFG) && FSL_FEATURE_USART_HAS_FIFORXTIMEOUTCFG
233     USART_SetRxTimeoutConfig(base, &(config->rxTimeout));
234 #endif
235     /* setup configuration and enable USART */
236     base->CFG = USART_CFG_PARITYSEL(config->parityMode) | USART_CFG_STOPLEN(config->stopBitCount) |
237                 USART_CFG_DATALEN(config->bitCountPerChar) | USART_CFG_LOOP(config->loopback) |
238                 USART_CFG_SYNCEN((uint32_t)config->syncMode >> 1) | USART_CFG_SYNCMST((uint8_t)config->syncMode) |
239                 USART_CFG_CLKPOL(config->clockPolarity) | USART_CFG_MODE32K(config->enableMode32k) |
240                 USART_CFG_CTSEN(config->enableHardwareFlowControl) | USART_CFG_ENABLE_MASK;
241 
242     /* Setup baudrate */
243     if (config->enableMode32k)
244     {
245         if ((9600U % config->baudRate_Bps) == 0U)
246         {
247             base->BRG = 9600U / config->baudRate_Bps - 1U;
248         }
249         else
250         {
251             return kStatus_USART_BaudrateNotSupport;
252         }
253     }
254     else
255     {
256         result = USART_SetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
257         if (kStatus_Success != result)
258         {
259             return result;
260         }
261     }
262     /* Setting continuous Clock configuration. used for synchronous mode. */
263     USART_EnableContinuousSCLK(base, config->enableContinuousSCLK);
264 
265     return kStatus_Success;
266 }
267 
268 /*!
269  * brief Deinitializes a USART instance.
270  *
271  * This function waits for TX complete, disables TX and RX, and disables the USART clock.
272  *
273  * param base USART peripheral base address.
274  */
USART_Deinit(USART_Type * base)275 void USART_Deinit(USART_Type *base)
276 {
277     /* Check arguments */
278     assert(NULL != base);
279 
280     /* Don't wait for TX idle when peripheral is disabled. */
281     if ((base->CFG & (USART_CFG_ENABLE_MASK)) != 0U)
282     {
283 #if UART_RETRY_TIMES
284         uint32_t waitTimes = UART_RETRY_TIMES;
285         while ((0U == (base->STAT & USART_STAT_TXIDLE_MASK)) && (--waitTimes != 0U))
286 #else
287         while (0U == (base->STAT & USART_STAT_TXIDLE_MASK))
288 #endif
289         {
290         }
291     }
292     /* Disable interrupts, disable dma requests, disable peripheral */
293     base->FIFOINTENCLR = USART_FIFOINTENCLR_TXERR_MASK | USART_FIFOINTENCLR_RXERR_MASK | USART_FIFOINTENCLR_TXLVL_MASK |
294                          USART_FIFOINTENCLR_RXLVL_MASK;
295     base->FIFOCFG &= ~(USART_FIFOCFG_DMATX_MASK | USART_FIFOCFG_DMARX_MASK);
296     base->CFG &= ~(USART_CFG_ENABLE_MASK);
297 #if defined(FSL_FEATURE_USART_HAS_FIFORXTIMEOUTCFG) && FSL_FEATURE_USART_HAS_FIFORXTIMEOUTCFG
298     base->FIFORXTIMEOUTCFG = 0U;
299 #endif
300 }
301 
302 /*!
303  * brief Gets the default configuration structure.
304  *
305  * This function initializes the USART configuration structure to a default value. The default
306  * values are:
307  *   usartConfig->baudRate_Bps = 115200U;
308  *   usartConfig->parityMode = kUSART_ParityDisabled;
309  *   usartConfig->stopBitCount = kUSART_OneStopBit;
310  *   usartConfig->bitCountPerChar = kUSART_8BitsPerChar;
311  *   usartConfig->loopback = false;
312  *   usartConfig->enableTx = false;
313  *   usartConfig->enableRx = false;
314  *
315  * param config Pointer to configuration structure.
316  */
USART_GetDefaultConfig(usart_config_t * config)317 void USART_GetDefaultConfig(usart_config_t *config)
318 {
319     /* Check arguments */
320     assert(NULL != config);
321 
322     /* Initializes the configure structure to zero. */
323     (void)memset(config, 0, sizeof(*config));
324 
325     /* Set always all members ! */
326     config->baudRate_Bps              = 115200U;
327     config->parityMode                = kUSART_ParityDisabled;
328     config->stopBitCount              = kUSART_OneStopBit;
329     config->bitCountPerChar           = kUSART_8BitsPerChar;
330     config->loopback                  = false;
331     config->enableRx                  = false;
332     config->enableTx                  = false;
333     config->enableMode32k             = false;
334     config->txWatermark               = kUSART_TxFifo0;
335     config->rxWatermark               = kUSART_RxFifo1;
336     config->syncMode                  = kUSART_SyncModeDisabled;
337     config->enableContinuousSCLK      = false;
338     config->clockPolarity             = kUSART_RxSampleOnFallingEdge;
339     config->enableHardwareFlowControl = false;
340 #if defined(FSL_FEATURE_USART_HAS_FIFORXTIMEOUTCFG) && FSL_FEATURE_USART_HAS_FIFORXTIMEOUTCFG
341     config->rxTimeout.enable                = false;
342     config->rxTimeout.resetCounterOnEmpty   = true;
343     config->rxTimeout.resetCounterOnReceive = true;
344     config->rxTimeout.counter               = 0U;
345     config->rxTimeout.prescaler             = 0U;
346 #endif
347 }
348 #if defined(FSL_FEATURE_USART_HAS_FIFORXTIMEOUTCFG) && FSL_FEATURE_USART_HAS_FIFORXTIMEOUTCFG
349 /*!
350  * brief Calculate the USART instance RX timeout prescaler and counter.
351  *
352  * This function for calculate the USART RXFIFO timeout config. This function is used to calculate
353  * suitable prescaler and counter for target_us.
354  * Example below shows how to use this API to configure USART.
355  * code
356  *   usart_config_t config;
357  *   config.rxWatermark                     = kUSART_RxFifo2;
358  *   config.rxTimeout.enable                = true;
359  *   config.rxTimeout.resetCounterOnEmpty   = true;
360  *   config.rxTimeout.resetCounterOnReceive = true;
361  *   USART_CalcTimeoutConfig(200, &config.rxTimeout.prescaler, &config.rxTimeout.counter,
362  *                                    CLOCK_GetFreq(kCLOCK_BusClk));
363  * endcode
364  * param target_us  Time for rx timeout unit us.
365  * param rxTimeoutPrescaler The prescaler to be setted after function.
366  * param rxTimeoutcounter The counter to be setted after function.
367  * param srcClock_Hz The clockSrc for rx timeout.
368  */
USART_CalcTimeoutConfig(uint32_t target_us,uint8_t * rxTimeoutPrescaler,uint32_t * rxTimeoutcounter,uint32_t srcClock_Hz)369 void USART_CalcTimeoutConfig(uint32_t target_us,
370                              uint8_t *rxTimeoutPrescaler,
371                              uint32_t *rxTimeoutcounter,
372                              uint32_t srcClock_Hz)
373 {
374     uint32_t counter   = 0U;
375     uint32_t perscalar = 0U, calculate_us = 0U, us_diff = 0U, min_diff = 0xffffffffUL;
376     /* find the suitable value */
377     for (perscalar = 0U; perscalar < 256U; perscalar++)
378     {
379         counter      =  target_us * (srcClock_Hz / 1000000UL) / (16U * (perscalar + 1U));
380         calculate_us = 16U * (perscalar + 1U) * counter / (srcClock_Hz / 1000000UL);
381         us_diff      = (calculate_us > target_us) ? (calculate_us - target_us) : (target_us - calculate_us);
382         if (us_diff == 0U)
383         {
384             *rxTimeoutPrescaler = (uint8_t)perscalar;
385             *rxTimeoutcounter   = counter;
386             break;
387         }
388         else
389         {
390             if (min_diff > us_diff)
391             {
392                 min_diff            = us_diff;
393                 *rxTimeoutPrescaler = (uint8_t)perscalar;
394                 *rxTimeoutcounter   = counter;
395             }
396         }
397     }
398 }
399 /*!
400  * brief Sets the USART instance RX timeout config.
401  *
402  * This function configures the USART RXFIFO timeout config. This function is used to config
403  * the USART RXFIFO timeout config after the USART module is initialized by the USART_Init.
404  *
405  * param base USART peripheral base address.
406  * param config pointer to receive timeout configuration structure.
407  */
USART_SetRxTimeoutConfig(USART_Type * base,const usart_rx_timeout_config * config)408 void USART_SetRxTimeoutConfig(USART_Type *base, const usart_rx_timeout_config *config)
409 {
410     base->FIFORXTIMEOUTCFG = 0U;
411     base->FIFORXTIMEOUTCFG = USART_FIFORXTIMEOUTCFG_RXTIMEOUT_COW((config->resetCounterOnReceive) ? 0U : 1U) |
412                              USART_FIFORXTIMEOUTCFG_RXTIMEOUT_COE((config->resetCounterOnEmpty) ? 0U : 1U) |
413                              USART_FIFORXTIMEOUTCFG_RXTIMEOUT_EN(config->enable) |
414                              USART_FIFORXTIMEOUTCFG_RXTIMEOUT_VALUE(config->counter) |
415                              USART_FIFORXTIMEOUTCFG_RXTIMEOUT_PRESCALER(config->prescaler);
416 }
417 #endif
418 
419 /*!
420  * brief Sets the USART instance baud rate.
421  *
422  * This function configures the USART module baud rate. This function is used to update
423  * the USART module baud rate after the USART module is initialized by the USART_Init.
424  * code
425  *  USART_SetBaudRate(USART1, 115200U, 20000000U);
426  * endcode
427  *
428  * param base USART peripheral base address.
429  * param baudrate_Bps USART baudrate to be set.
430  * param srcClock_Hz USART clock source frequency in HZ.
431  * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
432  * retval kStatus_Success Set baudrate succeed.
433  * retval kStatus_InvalidArgument One or more arguments are invalid.
434  */
USART_SetBaudRate(USART_Type * base,uint32_t baudrate_Bps,uint32_t srcClock_Hz)435 status_t USART_SetBaudRate(USART_Type *base, uint32_t baudrate_Bps, uint32_t srcClock_Hz)
436 {
437     uint32_t best_diff = (uint32_t)-1, best_osrval = 0xf, best_brgval = (uint32_t)-1;
438     uint32_t osrval, brgval, diff, baudrate, allowed_error;
439 
440     /* check arguments */
441     assert(!((NULL == base) || (0U == baudrate_Bps) || (0U == srcClock_Hz)));
442     if ((NULL == base) || (0U == baudrate_Bps) || (0U == srcClock_Hz))
443     {
444         return kStatus_InvalidArgument;
445     }
446 
447     /* If synchronous master mode is enabled, only configure the BRG value. */
448     if ((base->CFG & USART_CFG_SYNCEN_MASK) != 0U)
449     {
450         if ((base->CFG & USART_CFG_SYNCMST_MASK) != 0U)
451         {
452             brgval    = srcClock_Hz / baudrate_Bps;
453             base->BRG = brgval - 1U;
454         }
455     }
456     else
457     {
458         /* Actual baud rate must be within 3% of desired baud rate based on the calculated OSR and BRG value */
459         allowed_error = ((baudrate_Bps / 100U) * 3U);
460 
461         for (osrval = best_osrval; osrval >= 4U; osrval--)
462         {
463             /*
464              * Smaller values of OSR can make the sampling position within a data bit less accurate and may
465              * potentially cause more noise errors or incorrect data.
466              * Break if the best baudrate's diff is in the allowed error range and the osrval is below 8,
467              * only use lower osrval if the baudrate cannot be obtained with an osrval of 8 or above. */
468             if ((osrval <= 8U) && (best_diff <= allowed_error))
469             {
470                 break;
471             }
472 
473             brgval = (((srcClock_Hz * 10U) / ((osrval + 1U) * baudrate_Bps)) - 5U) / 10U;
474             if (brgval > 0xFFFFU)
475             {
476                 continue;
477             }
478             baudrate = srcClock_Hz / ((osrval + 1U) * (brgval + 1U));
479             diff     = (baudrate_Bps < baudrate) ? (baudrate - baudrate_Bps) : (baudrate_Bps - baudrate);
480             if (diff < best_diff)
481             {
482                 best_diff   = diff;
483                 best_osrval = osrval;
484                 best_brgval = brgval;
485             }
486         }
487 
488         /* Check to see if actual baud rate is within 3% of desired baud rate
489          * based on the best calculated OSR and BRG value */
490         baudrate = srcClock_Hz / ((best_osrval + 1U) * (best_brgval + 1U));
491         diff     = (baudrate_Bps < baudrate) ? (baudrate - baudrate_Bps) : (baudrate_Bps - baudrate);
492         if (diff > allowed_error)
493         {
494             return kStatus_USART_BaudrateNotSupport;
495         }
496 
497         /* value over range */
498         if (best_brgval > 0xFFFFU)
499         {
500             return kStatus_USART_BaudrateNotSupport;
501         }
502 
503         base->OSR = best_osrval;
504         base->BRG = best_brgval;
505     }
506 
507     return kStatus_Success;
508 }
509 
510 /*!
511  * brief Enable 32 kHz mode which USART uses clock from the RTC oscillator as the clock source.
512  *
513  * Please note that in order to use a 32 kHz clock to operate USART properly, the RTC oscillator
514  * and its 32 kHz output must be manully enabled by user, by calling RTC_Init and setting
515  * SYSCON_RTCOSCCTRL_EN bit to 1.
516  * And in 32kHz clocking mode the USART can only work at 9600 baudrate or at the baudrate that
517  * 9600 can evenly divide, eg: 4800, 3200.
518  *
519  * param base USART peripheral base address.
520  * param baudRate_Bps USART baudrate to be set..
521  * param enableMode32k true is 32k mode, false is normal mode.
522  * param srcClock_Hz USART clock source frequency in HZ.
523  * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
524  * retval kStatus_Success Set baudrate succeed.
525  * retval kStatus_InvalidArgument One or more arguments are invalid.
526  */
USART_Enable32kMode(USART_Type * base,uint32_t baudRate_Bps,bool enableMode32k,uint32_t srcClock_Hz)527 status_t USART_Enable32kMode(USART_Type *base, uint32_t baudRate_Bps, bool enableMode32k, uint32_t srcClock_Hz)
528 {
529     status_t result = kStatus_Success;
530     base->CFG &= ~(USART_CFG_ENABLE_MASK);
531     if (enableMode32k)
532     {
533         base->CFG |= USART_CFG_MODE32K_MASK;
534         if ((9600U % baudRate_Bps) == 0U)
535         {
536             base->BRG = 9600U / baudRate_Bps - 1U;
537         }
538         else
539         {
540             return kStatus_USART_BaudrateNotSupport;
541         }
542     }
543     else
544     {
545         base->CFG &= ~(USART_CFG_MODE32K_MASK);
546         result = USART_SetBaudRate(base, baudRate_Bps, srcClock_Hz);
547         if (kStatus_Success != result)
548         {
549             return result;
550         }
551     }
552     base->CFG |= USART_CFG_ENABLE_MASK;
553     return result;
554 }
555 
556 /*!
557  * brief Enable 9-bit data mode for USART.
558  *
559  * This function set the 9-bit mode for USART module. The 9th bit is not used for parity thus can be modified by user.
560  *
561  * param base USART peripheral base address.
562  * param enable true to enable, false to disable.
563  */
USART_Enable9bitMode(USART_Type * base,bool enable)564 void USART_Enable9bitMode(USART_Type *base, bool enable)
565 {
566     assert(base != NULL);
567 
568     uint32_t temp = 0U;
569 
570     if (enable)
571     {
572         /* Set USART 9-bit mode, disable parity. */
573         temp = base->CFG & ~((uint32_t)USART_CFG_DATALEN_MASK | (uint32_t)USART_CFG_PARITYSEL_MASK);
574         temp |= (uint32_t)USART_CFG_DATALEN(0x2U);
575         base->CFG = temp;
576     }
577     else
578     {
579         /* Set USART to 8-bit mode. */
580         base->CFG &= ~((uint32_t)USART_CFG_DATALEN_MASK);
581         base->CFG |= (uint32_t)USART_CFG_DATALEN(0x1U);
582     }
583 }
584 
585 /*!
586  * brief Transmit an address frame in 9-bit data mode.
587  *
588  * param base USART peripheral base address.
589  * param address USART slave address.
590  */
USART_SendAddress(USART_Type * base,uint8_t address)591 void USART_SendAddress(USART_Type *base, uint8_t address)
592 {
593     assert(base != NULL);
594     base->FIFOWR = ((uint32_t)address | 0x100UL);
595 }
596 
597 /*!
598  * brief Writes to the TX register using a blocking method.
599  *
600  * This function polls the TX register, waits for the TX register to be empty or for the TX FIFO
601  * to have room and writes data to the TX buffer.
602  *
603  * param base USART peripheral base address.
604  * param data Start address of the data to write.
605  * param length Size of the data to write.
606  * retval kStatus_USART_Timeout Transmission timed out and was aborted.
607  * retval kStatus_InvalidArgument Invalid argument.
608  * retval kStatus_Success Successfully wrote all data.
609  */
USART_WriteBlocking(USART_Type * base,const uint8_t * data,size_t length)610 status_t USART_WriteBlocking(USART_Type *base, const uint8_t *data, size_t length)
611 {
612     /* Check arguments */
613     assert(!((NULL == base) || (NULL == data)));
614 #if UART_RETRY_TIMES
615     uint32_t waitTimes;
616 #endif
617     if ((NULL == base) || (NULL == data))
618     {
619         return kStatus_InvalidArgument;
620     }
621     /* Check whether txFIFO is enabled */
622     if (0U == (base->FIFOCFG & USART_FIFOCFG_ENABLETX_MASK))
623     {
624         return kStatus_InvalidArgument;
625     }
626     for (; length > 0U; length--)
627     {
628         /* Loop until txFIFO get some space for new data */
629 #if UART_RETRY_TIMES
630         waitTimes = UART_RETRY_TIMES;
631         while ((0U == (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK)) && (--waitTimes != 0U))
632 #else
633         while (0U == (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK))
634 #endif
635         {
636         }
637 #if UART_RETRY_TIMES
638         if (0U == waitTimes)
639         {
640             return kStatus_USART_Timeout;
641         }
642 #endif
643         base->FIFOWR = *data;
644         data++;
645     }
646     /* Wait to finish transfer */
647 #if UART_RETRY_TIMES
648     waitTimes = UART_RETRY_TIMES;
649     while ((0U == (base->STAT & USART_STAT_TXIDLE_MASK)) && (--waitTimes != 0U))
650 #else
651     while (0U == (base->STAT & USART_STAT_TXIDLE_MASK))
652 #endif
653     {
654     }
655 #if UART_RETRY_TIMES
656     if (0U == waitTimes)
657     {
658         return kStatus_USART_Timeout;
659     }
660 #endif
661     return kStatus_Success;
662 }
663 
664 /*!
665  * brief Read RX data register using a blocking method.
666  *
667  * This function polls the RX register, waits for the RX register to be full or for RX FIFO to
668  * have data and read data from the TX register.
669  *
670  * param base USART peripheral base address.
671  * param data Start address of the buffer to store the received data.
672  * param length Size of the buffer.
673  * retval kStatus_USART_FramingError Receiver overrun happened while receiving data.
674  * retval kStatus_USART_ParityError Noise error happened while receiving data.
675  * retval kStatus_USART_NoiseError Framing error happened while receiving data.
676  * retval kStatus_USART_RxError Overflow or underflow rxFIFO happened.
677  * retval kStatus_USART_Timeout Transmission timed out and was aborted.
678  * retval kStatus_Success Successfully received all data.
679  */
USART_ReadBlocking(USART_Type * base,uint8_t * data,size_t length)680 status_t USART_ReadBlocking(USART_Type *base, uint8_t *data, size_t length)
681 {
682     uint32_t statusFlag;
683     status_t status = kStatus_Success;
684 #if UART_RETRY_TIMES
685     uint32_t waitTimes;
686 #endif
687 
688     /* check arguments */
689     assert(!((NULL == base) || (NULL == data)));
690     if ((NULL == base) || (NULL == data))
691     {
692         return kStatus_InvalidArgument;
693     }
694 
695     /* Check whether rxFIFO is enabled */
696     if ((base->FIFOCFG & USART_FIFOCFG_ENABLERX_MASK) == 0U)
697     {
698         return kStatus_Fail;
699     }
700     for (; length > 0U; length--)
701     {
702         /* loop until rxFIFO have some data to read */
703 #if UART_RETRY_TIMES
704         waitTimes = UART_RETRY_TIMES;
705         while (((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) == 0U) && (--waitTimes != 0U))
706 #else
707         while ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) == 0U)
708 #endif
709         {
710         }
711 #if UART_RETRY_TIMES
712         if (waitTimes == 0U)
713         {
714             status = kStatus_USART_Timeout;
715             break;
716         }
717 #endif
718         /* check rxFIFO statusFlag */
719         if ((base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK) != 0U)
720         {
721             base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
722             base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;
723             status = kStatus_USART_RxError;
724             break;
725         }
726         /* check receive statusFlag */
727         statusFlag = base->STAT;
728         /* Clear all status flags */
729         base->STAT |= statusFlag;
730         if ((statusFlag & USART_STAT_PARITYERRINT_MASK) != 0U)
731         {
732             status = kStatus_USART_ParityError;
733         }
734         if ((statusFlag & USART_STAT_FRAMERRINT_MASK) != 0U)
735         {
736             status = kStatus_USART_FramingError;
737         }
738         if ((statusFlag & USART_STAT_RXNOISEINT_MASK) != 0U)
739         {
740             status = kStatus_USART_NoiseError;
741         }
742 
743         if (kStatus_Success == status)
744         {
745             *data = (uint8_t)base->FIFORD;
746             data++;
747         }
748         else
749         {
750             break;
751         }
752     }
753     return status;
754 }
755 
756 /*!
757  * brief Initializes the USART handle.
758  *
759  * This function initializes the USART handle which can be used for other USART
760  * transactional APIs. Usually, for a specified USART instance,
761  * call this API once to get the initialized handle.
762  *
763  * param base USART peripheral base address.
764  * param handle USART handle pointer.
765  * param callback The callback function.
766  * param userData The parameter of the callback function.
767  */
USART_TransferCreateHandle(USART_Type * base,usart_handle_t * handle,usart_transfer_callback_t callback,void * userData)768 status_t USART_TransferCreateHandle(USART_Type *base,
769                                     usart_handle_t *handle,
770                                     usart_transfer_callback_t callback,
771                                     void *userData)
772 {
773     /* Check 'base' */
774     assert(!((NULL == base) || (NULL == handle)));
775 
776     uint32_t instance = 0;
777     usart_to_flexcomm_t handler;
778     handler.usart_master_handler = USART_TransferHandleIRQ;
779 
780     if ((NULL == base) || (NULL == handle))
781     {
782         return kStatus_InvalidArgument;
783     }
784 
785     instance = USART_GetInstance(base);
786 
787     (void)memset(handle, 0, sizeof(*handle));
788     /* Set the TX/RX state. */
789     handle->rxState = (uint8_t)kUSART_RxIdle;
790     handle->txState = (uint8_t)kUSART_TxIdle;
791     /* Set the callback and user data. */
792     handle->callback    = callback;
793     handle->userData    = userData;
794     handle->rxWatermark = (uint8_t)USART_FIFOTRIG_RXLVL_GET(base);
795     handle->txWatermark = (uint8_t)USART_FIFOTRIG_TXLVL_GET(base);
796 
797     FLEXCOMM_SetIRQHandler(base, handler.flexcomm_handler, handle);
798 
799     /* Enable interrupt in NVIC. */
800     (void)EnableIRQ(s_usartIRQ[instance]);
801 
802     return kStatus_Success;
803 }
804 
805 /*!
806  * brief Transmits a buffer of data using the interrupt method.
807  *
808  * This function sends data using an interrupt method. This is a non-blocking function, which
809  * returns directly without waiting for all data to be written to the TX register. When
810  * all data is written to the TX register in the IRQ handler, the USART driver calls the callback
811  * function and passes the ref kStatus_USART_TxIdle as status parameter.
812  *
813  * param base USART peripheral base address.
814  * param handle USART handle pointer.
815  * param xfer USART transfer structure. See #usart_transfer_t.
816  * retval kStatus_Success Successfully start the data transmission.
817  * retval kStatus_USART_TxBusy Previous transmission still not finished, data not all written to TX register yet.
818  * retval kStatus_InvalidArgument Invalid argument.
819  */
USART_TransferSendNonBlocking(USART_Type * base,usart_handle_t * handle,usart_transfer_t * xfer)820 status_t USART_TransferSendNonBlocking(USART_Type *base, usart_handle_t *handle, usart_transfer_t *xfer)
821 {
822     /* Check arguments */
823     assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));
824     if ((NULL == base) || (NULL == handle) || (NULL == xfer))
825     {
826         return kStatus_InvalidArgument;
827     }
828     /* Check xfer members */
829     assert(!((0U == xfer->dataSize) || (NULL == xfer->txData)));
830     if ((0U == xfer->dataSize) || (NULL == xfer->txData))
831     {
832         return kStatus_InvalidArgument;
833     }
834 
835     uint32_t globalMask = DisableGlobalIRQ();
836 
837     /* Return error if current TX busy. */
838     if ((uint8_t)kUSART_TxBusy == handle->txState)
839     {
840         EnableGlobalIRQ(globalMask);
841         return kStatus_USART_TxBusy;
842     }
843     else
844     {
845         handle->txState       = (uint8_t)kUSART_TxBusy;
846         uint32_t usartMask = USART_GetEnabledInterrupts(base);
847         USART_DisableInterrupts(base, usartMask);
848         EnableGlobalIRQ(globalMask);
849 
850         handle->txData        = xfer->txData;
851         handle->txDataSize    = xfer->dataSize;
852         handle->txDataSizeAll = xfer->dataSize;
853         USART_EnableInterrupts(base, usartMask | (uint32_t)kUSART_TxLevelInterruptEnable);
854     }
855 
856     return kStatus_Success;
857 }
858 
859 /*!
860  * brief Aborts the interrupt-driven data transmit.
861  *
862  * This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out
863  * how many bytes are still not sent out.
864  *
865  * param base USART peripheral base address.
866  * param handle USART handle pointer.
867  */
USART_TransferAbortSend(USART_Type * base,usart_handle_t * handle)868 void USART_TransferAbortSend(USART_Type *base, usart_handle_t *handle)
869 {
870     assert(NULL != handle);
871 
872     /* Disable interrupts */
873     USART_DisableInterrupts(base, (uint32_t)kUSART_TxLevelInterruptEnable);
874     /* Empty txFIFO */
875     base->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK;
876 
877     handle->txDataSize = 0U;
878     handle->txState    = (uint8_t)kUSART_TxIdle;
879 }
880 
881 /*!
882  * brief Get the number of bytes that have been sent out to bus.
883  *
884  * This function gets the number of bytes that have been sent out to bus by interrupt method.
885  *
886  * param base USART peripheral base address.
887  * param handle USART handle pointer.
888  * param count Send bytes count.
889  * retval kStatus_NoTransferInProgress No send in progress.
890  * retval kStatus_InvalidArgument Parameter is invalid.
891  * retval kStatus_Success Get successfully through the parameter \p count;
892  */
USART_TransferGetSendCount(USART_Type * base,usart_handle_t * handle,uint32_t * count)893 status_t USART_TransferGetSendCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)
894 {
895     assert(NULL != handle);
896     assert(NULL != count);
897 
898     if ((uint8_t)kUSART_TxIdle == handle->txState)
899     {
900         return kStatus_NoTransferInProgress;
901     }
902 
903     *count = handle->txDataSizeAll - handle->txDataSize -
904              ((base->FIFOSTAT & USART_FIFOSTAT_TXLVL_MASK) >> USART_FIFOSTAT_TXLVL_SHIFT);
905 
906     return kStatus_Success;
907 }
908 
909 /*!
910  * brief Receives a buffer of data using an interrupt method.
911  *
912  * This function receives data using an interrupt method. This is a non-blocking function, which
913  *  returns without waiting for all data to be received.
914  * If the RX ring buffer is used and not empty, the data in the ring buffer is copied and
915  * the parameter p receivedBytes shows how many bytes are copied from the ring buffer.
916  * After copying, if the data in the ring buffer is not enough to read, the receive
917  * request is saved by the USART driver. When the new data arrives, the receive request
918  * is serviced first. When all data is received, the USART driver notifies the upper layer
919  * through a callback function and passes the status parameter ref kStatus_USART_RxIdle.
920  * For example, the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer.
921  * The 5 bytes are copied to the xfer->data and this function returns with the
922  * parameter p receivedBytes set to 5. For the left 5 bytes, newly arrived data is
923  * saved from the xfer->data[5]. When 5 bytes are received, the USART driver notifies the upper layer.
924  * If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
925  * to receive data to the xfer->data. When all data is received, the upper layer is notified.
926  *
927  * param base USART peripheral base address.
928  * param handle USART handle pointer.
929  * param xfer USART transfer structure, see #usart_transfer_t.
930  * param receivedBytes Bytes received from the ring buffer directly.
931  * retval kStatus_Success Successfully queue the transfer into transmit queue.
932  * retval kStatus_USART_RxBusy Previous receive request is not finished.
933  * retval kStatus_InvalidArgument Invalid argument.
934  */
USART_TransferReceiveNonBlocking(USART_Type * base,usart_handle_t * handle,usart_transfer_t * xfer,size_t * receivedBytes)935 status_t USART_TransferReceiveNonBlocking(USART_Type *base,
936                                           usart_handle_t *handle,
937                                           usart_transfer_t *xfer,
938                                           size_t *receivedBytes)
939 {
940     uint32_t i;
941     /* How many bytes to copy from ring buffer to user memory. */
942     size_t bytesToCopy = 0U;
943     /* How many bytes to receive. */
944     size_t bytesToReceive;
945     /* How many bytes currently have received. */
946     size_t bytesCurrentReceived;
947 
948     /* Check arguments */
949     assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));
950     if ((NULL == base) || (NULL == handle) || (NULL == xfer))
951     {
952         return kStatus_InvalidArgument;
953     }
954     /* Check xfer members */
955     assert(!((0U == xfer->dataSize) || (NULL == xfer->rxData)));
956     if ((0U == xfer->dataSize) || (NULL == xfer->rxData))
957     {
958         return kStatus_InvalidArgument;
959     }
960 
961     /* Enable address detect when address match is enabled. */
962     if ((base->CFG & (uint32_t)USART_CFG_AUTOADDR_MASK) != 0U)
963     {
964         base->CTL |= (uint32_t)USART_CTL_ADDRDET_MASK;
965     }
966 
967     uint32_t globalMask = DisableGlobalIRQ();
968 
969     /* How to get data:
970        1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize
971           to uart handle, enable interrupt to store received data to xfer->data. When
972           all data received, trigger callback.
973        2. If RX ring buffer is enabled and not empty, get data from ring buffer first.
974           If there are enough data in ring buffer, copy them to xfer->data and return.
975           If there are not enough data in ring buffer, copy all of them to xfer->data,
976           save the xfer->data remained empty space to uart handle, receive data
977           to this empty space and trigger callback when finished. */
978     if ((uint8_t)kUSART_RxBusy == handle->rxState)
979     {
980         EnableGlobalIRQ(globalMask);
981         return kStatus_USART_RxBusy;
982     }
983     else
984     {
985         handle->rxState       = (uint8_t)kUSART_RxBusy;
986         uint32_t usartMask = USART_GetEnabledInterrupts(base);
987         USART_DisableInterrupts(base, usartMask);
988         EnableGlobalIRQ(globalMask);
989 
990         bytesToReceive       = xfer->dataSize;
991         bytesCurrentReceived = 0U;
992         /* If RX ring buffer is used. */
993         if (handle->rxRingBuffer != NULL)
994         {
995             /* How many bytes in RX ring buffer currently. */
996             bytesToCopy = USART_TransferGetRxRingBufferLength(handle);
997             if (bytesToCopy != 0U)
998             {
999                 bytesToCopy = MIN(bytesToReceive, bytesToCopy);
1000                 bytesToReceive -= bytesToCopy;
1001                 /* Copy data from ring buffer to user memory. */
1002                 for (i = 0U; i < bytesToCopy; i++)
1003                 {
1004                     xfer->rxData[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];
1005                     /* Wrap to 0. Not use modulo (%) because it might be large and slow. */
1006                     if ((size_t)handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
1007                     {
1008                         handle->rxRingBufferTail = 0U;
1009                     }
1010                     else
1011                     {
1012                         handle->rxRingBufferTail++;
1013                     }
1014                 }
1015             }
1016             /* If ring buffer does not have enough data, still need to read more data. */
1017             if (bytesToReceive != 0U)
1018             {
1019                 /* No data in ring buffer, save the request to UART handle. */
1020                 handle->rxData        = xfer->rxData + bytesCurrentReceived;
1021                 handle->rxDataSize    = bytesToReceive;
1022                 handle->rxDataSizeAll = xfer->dataSize;
1023             }
1024             else
1025             {
1026                 handle->rxState = (uint8_t)kUSART_RxIdle;
1027             }
1028         }
1029         /* Ring buffer not used. */
1030         else
1031         {
1032             handle->rxData        = xfer->rxData + bytesCurrentReceived;
1033             handle->rxDataSize    = bytesToReceive;
1034             handle->rxDataSizeAll = bytesToReceive;
1035 
1036             /* Enable RX interrupt. */
1037             base->FIFOINTENSET = USART_FIFOINTENSET_RXLVL_MASK;
1038         }
1039 
1040         /* Re-enable USART IRQ. */
1041         USART_EnableInterrupts(base, usartMask);
1042 
1043         /* Return the how many bytes have read. */
1044         if (receivedBytes != NULL)
1045         {
1046             *receivedBytes = bytesCurrentReceived;
1047         }
1048 
1049         /* When using ring buffer and we received everything, call user callback. */
1050         if (handle->rxRingBuffer != NULL && bytesToReceive == 0U)
1051         {
1052             if (handle->callback != NULL)
1053             {
1054                 handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);
1055             }
1056         }
1057     }
1058 
1059     return kStatus_Success;
1060 }
1061 
1062 /*!
1063  * brief Aborts the interrupt-driven data receiving.
1064  *
1065  * This function aborts the interrupt-driven data receiving. The user can get the remainBytes to find out
1066  * how many bytes not received yet.
1067  *
1068  * param base USART peripheral base address.
1069  * param handle USART handle pointer.
1070  */
USART_TransferAbortReceive(USART_Type * base,usart_handle_t * handle)1071 void USART_TransferAbortReceive(USART_Type *base, usart_handle_t *handle)
1072 {
1073     assert(NULL != handle);
1074 
1075     /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
1076     if (NULL == handle->rxRingBuffer)
1077     {
1078         /* Disable interrupts */
1079         USART_DisableInterrupts(base, (uint32_t)kUSART_RxLevelInterruptEnable);
1080         /* Empty rxFIFO */
1081         base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
1082     }
1083 
1084     handle->rxDataSize = 0U;
1085     handle->rxState    = (uint8_t)kUSART_RxIdle;
1086 }
1087 
1088 /*!
1089  * brief Get the number of bytes that have been received.
1090  *
1091  * This function gets the number of bytes that have been received.
1092  *
1093  * param base USART peripheral base address.
1094  * param handle USART handle pointer.
1095  * param count Receive bytes count.
1096  * retval kStatus_NoTransferInProgress No receive in progress.
1097  * retval kStatus_InvalidArgument Parameter is invalid.
1098  * retval kStatus_Success Get successfully through the parameter \p count;
1099  */
USART_TransferGetReceiveCount(USART_Type * base,usart_handle_t * handle,uint32_t * count)1100 status_t USART_TransferGetReceiveCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)
1101 {
1102     assert(NULL != handle);
1103     assert(NULL != count);
1104 
1105     if ((uint8_t)kUSART_RxIdle == handle->rxState)
1106     {
1107         return kStatus_NoTransferInProgress;
1108     }
1109 
1110     *count = handle->rxDataSizeAll - handle->rxDataSize;
1111 
1112     return kStatus_Success;
1113 }
1114 
1115 /*!
1116  * brief USART IRQ handle function.
1117  *
1118  * This function handles the USART transmit and receive IRQ request.
1119  *
1120  * param base USART peripheral base address.
1121  * param handle USART handle pointer.
1122  */
USART_TransferHandleIRQ(USART_Type * base,usart_handle_t * handle)1123 void USART_TransferHandleIRQ(USART_Type *base, usart_handle_t *handle)
1124 {
1125     /* Check arguments */
1126     assert((NULL != base) && (NULL != handle));
1127 
1128     bool receiveEnabled = ((handle->rxDataSize != 0U) || (handle->rxRingBuffer != NULL));
1129     bool sendEnabled    = (handle->txDataSize != 0U);
1130     uint8_t rxdata;
1131     size_t tmpsize;
1132 
1133     /* If RX overrun. */
1134     if ((base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK) != 0U)
1135     {
1136         /* Clear rx error state. */
1137         base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;
1138         /* clear rxFIFO */
1139         base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
1140         /* Trigger callback. */
1141         if (handle->callback != NULL)
1142         {
1143             handle->callback(base, handle, kStatus_USART_RxError, handle->userData);
1144         }
1145     }
1146     /* TX under run, happens when slave is in synchronous mode and the data is not written in tx register in time. */
1147     if ((base->FIFOSTAT & USART_FIFOSTAT_TXERR_MASK) != 0U)
1148     {
1149         /* Clear tx error state. */
1150         base->FIFOSTAT |= USART_FIFOSTAT_TXERR_MASK;
1151         /* Trigger callback. */
1152         if (handle->callback != NULL)
1153         {
1154             handle->callback(base, handle, kStatus_USART_TxError, handle->userData);
1155         }
1156     }
1157     /* If noise error. */
1158     if ((base->STAT & USART_STAT_RXNOISEINT_MASK) != 0U)
1159     {
1160         /* Clear rx error state. */
1161         base->STAT |= USART_STAT_RXNOISEINT_MASK;
1162         /* clear rxFIFO */
1163         base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
1164         /* Trigger callback. */
1165         if (handle->callback != NULL)
1166         {
1167             handle->callback(base, handle, kStatus_USART_NoiseError, handle->userData);
1168         }
1169     }
1170     /* If framing error. */
1171     if ((base->STAT & USART_STAT_FRAMERRINT_MASK) != 0U)
1172     {
1173         /* Clear rx error state. */
1174         base->STAT |= USART_STAT_FRAMERRINT_MASK;
1175         /* clear rxFIFO */
1176         base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
1177         /* Trigger callback. */
1178         if (handle->callback != NULL)
1179         {
1180             handle->callback(base, handle, kStatus_USART_FramingError, handle->userData);
1181         }
1182     }
1183     /* If parity error. */
1184     if ((base->STAT & USART_STAT_PARITYERRINT_MASK) != 0U)
1185     {
1186         /* Clear rx error state. */
1187         base->STAT |= USART_STAT_PARITYERRINT_MASK;
1188         /* clear rxFIFO */
1189         base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
1190         /* Trigger callback. */
1191         if (handle->callback != NULL)
1192         {
1193             handle->callback(base, handle, kStatus_USART_ParityError, handle->userData);
1194         }
1195     }
1196     while ((receiveEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) != 0U)) ||
1197            (sendEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK) != 0U)))
1198     {
1199         /* Receive data */
1200         if (receiveEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) != 0U))
1201         {
1202             /* Clear address detect when RXFIFO has data. */
1203             base->CTL &= ~(uint32_t)USART_CTL_ADDRDET_MASK;
1204             /* Receive to app bufffer if app buffer is present */
1205             if (handle->rxDataSize != 0U)
1206             {
1207                 rxdata          = (uint8_t)base->FIFORD;
1208                 *handle->rxData = rxdata;
1209                 handle->rxDataSize--;
1210                 handle->rxData++;
1211                 receiveEnabled = ((handle->rxDataSize != 0U) || (handle->rxRingBuffer != NULL));
1212                 if (0U == handle->rxDataSize)
1213                 {
1214                     if (NULL == handle->rxRingBuffer)
1215                     {
1216                         base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;
1217                     }
1218                     handle->rxState = (uint8_t)kUSART_RxIdle;
1219                     if (handle->callback != NULL)
1220                     {
1221                         handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);
1222                     }
1223                 }
1224             }
1225             /* Otherwise receive to ring buffer if ring buffer is present */
1226             else
1227             {
1228                 if (handle->rxRingBuffer != NULL)
1229                 {
1230                     /* If RX ring buffer is full, trigger callback to notify over run. */
1231                     if (USART_TransferIsRxRingBufferFull(handle))
1232                     {
1233                         if (handle->callback != NULL)
1234                         {
1235                             handle->callback(base, handle, kStatus_USART_RxRingBufferOverrun, handle->userData);
1236                         }
1237                     }
1238                     /* If ring buffer is still full after callback function, the oldest data is overridden. */
1239                     if (USART_TransferIsRxRingBufferFull(handle))
1240                     {
1241                         /* Increase handle->rxRingBufferTail to make room for new data. */
1242                         if ((size_t)handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
1243                         {
1244                             handle->rxRingBufferTail = 0U;
1245                         }
1246                         else
1247                         {
1248                             handle->rxRingBufferTail++;
1249                         }
1250                     }
1251                     /* Read data. */
1252                     rxdata                                         = (uint8_t)base->FIFORD;
1253                     handle->rxRingBuffer[handle->rxRingBufferHead] = rxdata;
1254                     /* Increase handle->rxRingBufferHead. */
1255                     if ((size_t)handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
1256                     {
1257                         handle->rxRingBufferHead = 0U;
1258                     }
1259                     else
1260                     {
1261                         handle->rxRingBufferHead++;
1262                     }
1263                 }
1264             }
1265         }
1266         /* Send data */
1267         if (sendEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK) != 0U))
1268         {
1269             base->FIFOWR = *handle->txData;
1270             handle->txDataSize--;
1271             handle->txData++;
1272             sendEnabled = handle->txDataSize != 0U;
1273             if (!sendEnabled)
1274             {
1275                 base->FIFOINTENCLR = USART_FIFOINTENCLR_TXLVL_MASK;
1276 
1277                 base->INTENSET = USART_INTENSET_TXIDLEEN_MASK;
1278             }
1279         }
1280     }
1281 
1282     /* Tx idle and the interrupt is enabled. */
1283     if ((0U != (base->INTENSET & USART_INTENSET_TXIDLEEN_MASK)) && (0U != (base->INTSTAT & USART_INTSTAT_TXIDLE_MASK)))
1284     {
1285         /* Set txState to idle only when all data has been sent out to bus. */
1286         handle->txState = (uint8_t)kUSART_TxIdle;
1287         /* Disable tx idle interrupt */
1288         base->INTENCLR = USART_INTENCLR_TXIDLECLR_MASK;
1289 
1290         /* Trigger callback. */
1291         if (handle->callback != NULL)
1292         {
1293             handle->callback(base, handle, kStatus_USART_TxIdle, handle->userData);
1294         }
1295     }
1296 
1297     /* ring buffer is not used */
1298     if (NULL == handle->rxRingBuffer)
1299     {
1300         tmpsize = handle->rxDataSize;
1301 
1302         /* restore if rx transfer ends and rxLevel is different from default value */
1303         if ((tmpsize == 0U) && (USART_FIFOTRIG_RXLVL_GET(base) != handle->rxWatermark))
1304         {
1305             base->FIFOTRIG =
1306                 (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | USART_FIFOTRIG_RXLVL(handle->rxWatermark);
1307         }
1308         /* decrease level if rx transfer is bellow */
1309         if ((tmpsize != 0U) && (tmpsize < (USART_FIFOTRIG_RXLVL_GET(base) + 1U)))
1310         {
1311             base->FIFOTRIG = (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | (USART_FIFOTRIG_RXLVL(tmpsize - 1U));
1312         }
1313     }
1314 }
1315