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