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