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