1 /*
2 * Copyright 2017-2022 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_usart.h"
10
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.lpc_miniusart"
14 #endif
15
16 enum _usart_transfer_states
17 {
18 kUSART_TxIdle, /* TX idle. */
19 kUSART_TxBusy, /* TX busy. */
20 kUSART_RxIdle, /* RX idle. */
21 kUSART_RxBusy /* RX busy. */
22 };
23
24 /*******************************************************************************
25 * Variables
26 ******************************************************************************/
27
28 #if defined(FSL_SDK_ENABLE_USART_DRIVER_TRANSACTIONAL_APIS) && (FSL_SDK_ENABLE_USART_DRIVER_TRANSACTIONAL_APIS)
29 /* Array of USART handle. */
30 static usart_handle_t *s_usartHandle[FSL_FEATURE_SOC_USART_COUNT];
31
32 /*! @brief IRQ name array */
33 static const IRQn_Type s_usartIRQ[] = USART_IRQS;
34
35 /* Typedef for interrupt handler. */
36 typedef void (*usart_isr_t)(USART_Type *base, usart_handle_t *handle);
37
38 /* USART ISR for transactional APIs. */
39 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
40 static usart_isr_t s_usartIsr = (usart_isr_t)DefaultISR;
41 #else
42 static usart_isr_t s_usartIsr;
43 #endif
44 #endif /* FSL_SDK_ENABLE_USART_DRIVER_TRANSACTIONAL_APIS */
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 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
50 /* @brief Array to map USART instance number to CLOCK names */
51 static const clock_ip_name_t s_usartClock[] = USART_CLOCKS;
52 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
53
54 #if !(defined(FSL_SDK_DISABLE_DRIVER_RESET_CONTROL) && FSL_SDK_DISABLE_DRIVER_RESET_CONTROL)
55 /* @brief Array to map USART instance number to RESET names */
56 static const SYSCON_RSTn_t s_usartRest[] = UART_RSTS_N;
57 #endif /* FSL_SDK_DISABLE_DRIVER_RESET_CONTROL */
58
59 /*******************************************************************************
60 * Code
61 ******************************************************************************/
62
63 /* Get the index corresponding to the USART */
64 /*! brief Returns instance number for USART peripheral base address. */
USART_GetInstance(USART_Type * base)65 uint32_t USART_GetInstance(USART_Type *base)
66 {
67 uint32_t i;
68
69 for (i = 0U; i < (uint32_t)FSL_FEATURE_SOC_USART_COUNT; i++)
70 {
71 if ((uint32_t)base == s_usartBaseAddrs[i])
72 {
73 break;
74 }
75 }
76
77 assert(i < (uint32_t)FSL_FEATURE_SOC_USART_COUNT);
78 return i;
79 }
80
81 #if defined(FSL_SDK_ENABLE_USART_DRIVER_TRANSACTIONAL_APIS) && (FSL_SDK_ENABLE_USART_DRIVER_TRANSACTIONAL_APIS)
82 /*!
83 * brief Get the length of received data in RX ring buffer.
84 *
85 * param handle USART handle pointer.
86 * return Length of received data in RX ring buffer.
87 */
USART_TransferGetRxRingBufferLength(usart_handle_t * handle)88 size_t USART_TransferGetRxRingBufferLength(usart_handle_t *handle)
89 {
90 size_t size = 0U;
91
92 /* Check arguments */
93 assert(NULL != handle);
94 uint16_t tmprxRingBufferTail = handle->rxRingBufferTail;
95 uint16_t tmprxRingBufferHead = handle->rxRingBufferHead;
96
97 if (tmprxRingBufferTail > tmprxRingBufferHead)
98 {
99 size = (size_t)tmprxRingBufferHead + (handle->rxRingBufferSize) - (size_t)tmprxRingBufferTail;
100 }
101 else
102 {
103 size = (size_t)tmprxRingBufferHead - (size_t)tmprxRingBufferTail;
104 }
105 return size;
106 }
107
USART_TransferIsRxRingBufferFull(usart_handle_t * handle)108 static bool USART_TransferIsRxRingBufferFull(usart_handle_t *handle)
109 {
110 bool full = false;
111
112 /* Check arguments */
113 assert(NULL != handle);
114
115 if (USART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U))
116 {
117 full = true;
118 }
119 else
120 {
121 full = false;
122 }
123 return full;
124 }
125
126 /*!
127 * brief Sets up the RX ring buffer.
128 *
129 * This function sets up the RX ring buffer to a specific USART handle.
130 *
131 * When the RX ring buffer is used, data received are stored into the ring buffer even when the
132 * user doesn't call the USART_TransferReceiveNonBlocking() API. If there is already data received
133 * in the ring buffer, the user can get the received data from the ring buffer directly.
134 *
135 * note When using the RX ring buffer, one byte is reserved for internal use. In other
136 * words, if ringBufferSize is 32, then only 31 bytes are used for saving data.
137 *
138 * param base USART peripheral base address.
139 * param handle USART handle pointer.
140 * param ringBuffer Start address of the ring buffer for background receiving. Pass NULL to disable the ring buffer.
141 * param ringBufferSize size of the ring buffer.
142 */
USART_TransferStartRingBuffer(USART_Type * base,usart_handle_t * handle,uint8_t * ringBuffer,size_t ringBufferSize)143 void USART_TransferStartRingBuffer(USART_Type *base, usart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize)
144 {
145 /* Check arguments */
146 assert(NULL != base);
147 assert(NULL != handle);
148 assert(NULL != ringBuffer);
149
150 /* Setup the ringbuffer address */
151 handle->rxRingBuffer = ringBuffer;
152 handle->rxRingBufferSize = ringBufferSize;
153 handle->rxRingBufferHead = 0U;
154 handle->rxRingBufferTail = 0U;
155
156 /* Start receive data read interrupt and reveive overrun interrupt. */
157 USART_EnableInterrupts(base,
158 (uint32_t)kUSART_RxReadyInterruptEnable | (uint32_t)kUSART_HardwareOverRunInterruptEnable);
159 }
160
161 /*!
162 * brief Aborts the background transfer and uninstalls the ring buffer.
163 *
164 * This function aborts the background transfer and uninstalls the ring buffer.
165 *
166 * param base USART peripheral base address.
167 * param handle USART handle pointer.
168 */
USART_TransferStopRingBuffer(USART_Type * base,usart_handle_t * handle)169 void USART_TransferStopRingBuffer(USART_Type *base, usart_handle_t *handle)
170 {
171 /* Check arguments */
172 assert(NULL != base);
173 assert(NULL != handle);
174
175 /* If USART is in idle state, dsiable the interrupts for ring buffer. */
176 if (handle->rxState == (uint8_t)kUSART_RxIdle)
177 {
178 USART_DisableInterrupts(
179 base, (uint32_t)kUSART_RxReadyInterruptEnable | (uint32_t)kUSART_HardwareOverRunInterruptEnable);
180 }
181 handle->rxRingBuffer = NULL;
182 handle->rxRingBufferSize = 0U;
183 handle->rxRingBufferHead = 0U;
184 handle->rxRingBufferTail = 0U;
185 }
186 #endif /* FSL_SDK_ENABLE_USART_DRIVER_TRANSACTIONAL_APIS */
187
188 /*!
189 * brief Initializes a USART instance with user configuration structure and peripheral clock.
190 *
191 * This function configures the USART module with the user-defined settings. The user can configure the configuration
192 * structure and also get the default configuration by using the USART_GetDefaultConfig() function.
193 * Example below shows how to use this API to configure USART.
194 * code
195 * usart_config_t usartConfig;
196 * usartConfig.baudRate_Bps = 115200U;
197 * usartConfig.parityMode = kUSART_ParityDisabled;
198 * usartConfig.stopBitCount = kUSART_OneStopBit;
199 * USART_Init(USART1, &usartConfig, 20000000U);
200 * endcode
201 *
202 * param base USART peripheral base address.
203 * param config Pointer to user-defined configuration structure.
204 * param srcClock_Hz USART clock source frequency in HZ.
205 * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
206 * retval kStatus_InvalidArgument USART base address is not valid
207 * retval kStatus_Success Status USART initialize succeed
208 */
USART_Init(USART_Type * base,const usart_config_t * config,uint32_t srcClock_Hz)209 status_t USART_Init(USART_Type *base, const usart_config_t *config, uint32_t srcClock_Hz)
210 {
211 /* Check arguments */
212 assert(!((NULL == base) || (NULL == config) || (0U == srcClock_Hz)));
213 #if defined(FSL_FEATURE_USART_HAS_RXIDLETO_CHECK) && FSL_FEATURE_USART_HAS_RXIDLETO_CHECK
214 assert(8U > config->rxIdleTimeout);
215 #endif
216
217 status_t status = kStatus_Success;
218
219 uint32_t instance = USART_GetInstance(base);
220
221 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
222 /* Enable the clock. */
223 CLOCK_EnableClock(s_usartClock[instance]);
224 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
225
226 #if !(defined(FSL_SDK_DISABLE_DRIVER_RESET_CONTROL) && FSL_SDK_DISABLE_DRIVER_RESET_CONTROL)
227 /* Reset the module. */
228 RESET_PeripheralReset(s_usartRest[instance]);
229 #endif /* FSL_SDK_DISABLE_DRIVER_RESET_CONTROL */
230
231 /* Setup configuration and enable USART to configure other register. */
232 base->CFG = USART_CFG_PARITYSEL(config->parityMode) | USART_CFG_STOPLEN(config->stopBitCount) |
233 USART_CFG_SYNCEN((uint32_t)config->syncMode >> 1) |
234 USART_CFG_DATALEN((uint8_t)config->bitCountPerChar) | USART_CFG_LOOP(config->loopback) |
235 USART_CFG_SYNCMST(config->syncMode) | USART_CFG_CLKPOL(config->clockPolarity) |
236 USART_CFG_CTSEN(config->enableHardwareFlowControl) | USART_CFG_ENABLE_MASK;
237 #if defined(FSL_FEATURE_USART_HAS_RXIDLETO_CHECK) && FSL_FEATURE_USART_HAS_RXIDLETO_CHECK
238 base->CTL |= USART_CTL_RXIDLETOCFG(config->rxIdleTimeout);
239 #endif
240 #if defined(FSL_SDK_USART_DRIVER_ENABLE_BAUDRATE_AUTO_GENERATE) && (FSL_SDK_USART_DRIVER_ENABLE_BAUDRATE_AUTO_GENERATE)
241 if (0U != config->baudRate_Bps)
242 {
243 /* Setup baudrate */
244 if (kStatus_Success != USART_SetBaudRate(base, config->baudRate_Bps, srcClock_Hz))
245 {
246 status = kStatus_USART_BaudrateNotSupport;
247 }
248 }
249 #else
250 base->BRG = FSL_SDK_USART_BRG_VALUE;
251 #if defined(FSL_FEATURE_USART_HAS_OSR_REGISTER) && (FSL_FEATURE_USART_HAS_OSR_REGISTER)
252 base->OSR = FSL_SDK_USART_BRG_VALUE;
253 #endif /* FSL_FEATURE_USART_HAS_OSR_REGISTER */
254 #endif /* FSL_SDK_USART_DRIVER_ENABLE_BAUDRATE_AUTO_GENERATE */
255
256 if (status == kStatus_Success)
257 {
258 USART_EnableContinuousSCLK(base, config->enableContinuousSCLK);
259
260 /* Setup the USART transmit and receive. */
261 USART_EnableTx(base, config->enableTx);
262 USART_EnableRx(base, config->enableRx);
263 }
264
265 return status;
266 }
267
268 /*!
269 * brief Deinitializes a USART instance.
270 *
271 * This function waits for TX complete, 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 /* Wait for data transmit complete. */
280 while (0U == (base->STAT & USART_STAT_TXIDLE_MASK))
281 {
282 }
283 /* Disable the USART module. */
284 base->CFG &= ~(USART_CFG_ENABLE_MASK);
285
286 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
287 /* Disable the clock. */
288 CLOCK_DisableClock(s_usartClock[USART_GetInstance(base)]);
289 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
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 = 9600U;
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 * usartConfig->enableHardwareFlowControl = false;
305 * ...
306 * param config Pointer to configuration structure.
307 */
USART_GetDefaultConfig(usart_config_t * config)308 void USART_GetDefaultConfig(usart_config_t *config)
309 {
310 /* Check arguments */
311 assert(NULL != config);
312
313 /* Initializes the configure structure to zero. */
314 (void)memset(config, 0, sizeof(*config));
315
316 /* Set always all members ! */
317 config->baudRate_Bps = 9600U;
318 config->parityMode = kUSART_ParityDisabled;
319 config->stopBitCount = kUSART_OneStopBit;
320 config->bitCountPerChar = kUSART_8BitsPerChar;
321 config->loopback = false;
322 config->enableRx = false;
323 config->enableTx = false;
324 config->syncMode = kUSART_SyncModeDisabled;
325 config->enableContinuousSCLK = false;
326 config->clockPolarity = kUSART_RxSampleOnFallingEdge;
327 config->enableHardwareFlowControl = false;
328 #if defined(FSL_FEATURE_USART_HAS_RXIDLETO_CHECK) && FSL_FEATURE_USART_HAS_RXIDLETO_CHECK
329 config->rxIdleTimeout = 0U;
330 #endif
331 }
332
333 /*!
334 * brief Sets the USART instance baud rate.
335 *
336 * This function configures the USART module baud rate. This function is used to update
337 * the USART module baud rate after the USART module is initialized by the USART_Init.
338 * code
339 * USART_SetBaudRate(USART1, 115200U, 20000000U);
340 * endcode
341 *
342 * param base USART peripheral base address.
343 * param baudrate_Bps USART baudrate to be set.
344 * param srcClock_Hz USART clock source frequency in HZ.
345 * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
346 * retval kStatus_Success Set baudrate succeed.
347 * retval kStatus_InvalidArgument One or more arguments are invalid.
348 */
USART_SetBaudRate(USART_Type * base,uint32_t baudrate_Bps,uint32_t srcClock_Hz)349 status_t USART_SetBaudRate(USART_Type *base, uint32_t baudrate_Bps, uint32_t srcClock_Hz)
350 {
351 /* check arguments */
352 assert(!((NULL == base) || (0U == baudrate_Bps) || (0U == srcClock_Hz)));
353
354 #if defined(FSL_FEATURE_USART_HAS_OSR_REGISTER) && (FSL_FEATURE_USART_HAS_OSR_REGISTER)
355 uint32_t best_diff = (uint32_t)-1, best_osrval = 0xf, best_brgval = (uint32_t)-1;
356 uint32_t diff = 0U, brgval = 0U, osrval = 0U, baudrate = 0U;
357
358 /* If synchronous is enable, only BRG register is useful. */
359 if (0U != (base->CFG & USART_CFG_SYNCEN_MASK))
360 {
361 brgval = srcClock_Hz / baudrate_Bps;
362 base->BRG = brgval - 1U;
363 }
364 else
365 {
366 for (osrval = best_osrval; osrval >= 8U; osrval--)
367 {
368 brgval = (((srcClock_Hz * 10U) / ((osrval + 1U) * baudrate_Bps)) - 5U) / 10U;
369 if (brgval > 0xFFFFU)
370 {
371 continue;
372 }
373 baudrate = srcClock_Hz / ((osrval + 1U) * (brgval + 1U));
374 diff = baudrate_Bps < baudrate ? baudrate - baudrate_Bps : baudrate_Bps - baudrate;
375 if (diff < best_diff)
376 {
377 best_diff = diff;
378 best_osrval = osrval;
379 best_brgval = brgval;
380 }
381 }
382
383 /* value over range */
384 if (best_brgval > 0xFFFFU)
385 {
386 return kStatus_USART_BaudrateNotSupport;
387 }
388
389 /* If the baud rate caculated is not very precise, please select the FRG clock as
390 * the USART's source clock, and set the FRG frequency to a more suitable value.
391 */
392 assert(best_diff < ((baudrate_Bps / 100U) * 3U));
393
394 base->OSR = best_osrval;
395 base->BRG = best_brgval;
396 }
397 #else
398 uint32_t brgval = 0U;
399 /* If synchronous is enable. */
400 if (0U != (base->CFG & USART_CFG_SYNCEN_MASK))
401 {
402 brgval = srcClock_Hz / baudrate_Bps;
403 base->BRG = brgval - 1U;
404 }
405 else
406 {
407 /* In asynchronous mode, The baud rate divider divides the common USART
408 * peripheral clock by a factor of 16 multiplied by the baud rate value
409 * to provide the baud rate.
410 */
411 brgval = (srcClock_Hz >> 4U) / baudrate_Bps;
412
413 /* If the baud rate caculated is not very precise, Please set the FRG register for
414 * getting a more precise suitable frequency.
415 */
416 assert((((srcClock_Hz >> 4U) / brgval) - baudrate_Bps) < ((baudrate_Bps / 100U) * 3U));
417 base->BRG = brgval - 1U;
418 }
419 #endif /* FSL_FEATURE_USART_HAS_OSR_REGISTER */
420
421 return kStatus_Success;
422 }
423
424 /*!
425 * brief Writes to the TX register using a blocking method.
426 *
427 * This function polls the TX register, waits for the TX register to be empty.
428 *
429 * param base USART peripheral base address.
430 * param data Start address of the data to write.
431 * param length Size of the data to write.
432 * retval kStatus_USART_Timeout Transmission timed out and was aborted.
433 * retval kStatus_Success Successfully wrote all data.
434 */
USART_WriteBlocking(USART_Type * base,const uint8_t * data,size_t length)435 status_t USART_WriteBlocking(USART_Type *base, const uint8_t *data, size_t length)
436 {
437 /* Check arguments */
438 assert(!((NULL == base) || (NULL == data)));
439 #if UART_RETRY_TIMES
440 uint32_t waitTimes;
441 #endif
442
443 for (; length > 0U; length--)
444 {
445 /* Wait for TX is ready to transmit new data. */
446 #if UART_RETRY_TIMES
447 waitTimes = UART_RETRY_TIMES;
448 while ((0U == (base->STAT & USART_STAT_TXRDY_MASK)) && (0U != --waitTimes))
449 #else
450 while (0U == (base->STAT & USART_STAT_TXRDY_MASK))
451 #endif
452 {
453 }
454 #if UART_RETRY_TIMES
455 if (waitTimes == 0U)
456 {
457 return kStatus_USART_Timeout;
458 }
459 #endif
460 base->TXDAT = *data;
461 data++;
462 }
463 /* Wait to finish transfer */
464 #if UART_RETRY_TIMES
465 waitTimes = UART_RETRY_TIMES;
466 while ((0U == (base->STAT & USART_STAT_TXIDLE_MASK)) && (0U != --waitTimes))
467 #else
468 while (0U == (base->STAT & USART_STAT_TXIDLE_MASK))
469 #endif
470 {
471 }
472 #if UART_RETRY_TIMES
473 if (waitTimes == 0U)
474 {
475 return kStatus_USART_Timeout;
476 }
477 #endif
478 return kStatus_Success;
479 }
480
481 /*!
482 * brief Read RX data register using a blocking method.
483 *
484 * This function polls the RX register, waits for the RX register to be full.
485 *
486 * param base USART peripheral base address.
487 * param data Start address of the buffer to store the received data.
488 * param length Size of the buffer.
489 * retval kStatus_USART_FramingError Receiver overrun happened while receiving data.
490 * retval kStatus_USART_ParityError Noise error happened while receiving data.
491 * retval kStatus_USART_NoiseError Framing error happened while receiving data.
492 * retval kStatus_USART_RxError Overflow or underflow happened.
493 * retval kStatus_USART_Timeout Transmission timed out and was aborted.
494 * retval kStatus_Success Successfully received all data.
495 */
USART_ReadBlocking(USART_Type * base,uint8_t * data,size_t length)496 status_t USART_ReadBlocking(USART_Type *base, uint8_t *data, size_t length)
497 {
498 uint32_t statusFlag;
499 status_t status = kStatus_Success;
500
501 /* Check arguments */
502 assert(!((NULL == base) || (NULL == data)));
503
504 #if UART_RETRY_TIMES
505 uint32_t waitTimes;
506 #endif
507
508 for (; length > 0U; length--)
509 {
510 /* loop until receive is ready to read */
511 #if UART_RETRY_TIMES
512 waitTimes = UART_RETRY_TIMES;
513 while (((base->STAT & USART_STAT_RXRDY_MASK) == 0U) && (--waitTimes != 0U))
514 #else
515 while ((base->STAT & USART_STAT_RXRDY_MASK) == 0U)
516 #endif
517 {
518 }
519 #if UART_RETRY_TIMES
520 if (waitTimes == 0U)
521 {
522 status = kStatus_USART_Timeout;
523 break;
524 }
525 #endif
526 /* Check receive statusFlag */
527 statusFlag = base->STAT;
528 base->STAT |= statusFlag;
529 if ((statusFlag & USART_STAT_OVERRUNINT_MASK) != 0U)
530 {
531 status = kStatus_USART_HardwareOverrun;
532 break;
533 }
534 if ((statusFlag & USART_STAT_PARITYERRINT_MASK) != 0U)
535 {
536 status = kStatus_USART_ParityError;
537 }
538 if ((statusFlag & USART_STAT_FRAMERRINT_MASK) != 0U)
539 {
540 status = kStatus_USART_FramingError;
541 }
542 if ((statusFlag & USART_STAT_RXNOISEINT_MASK) != 0U)
543 {
544 status = kStatus_USART_NoiseError;
545 }
546 if (kStatus_Success == status)
547 {
548 *data = (uint8_t)base->RXDAT;
549 data++;
550 }
551 else
552 {
553 break;
554 }
555 }
556 return status;
557 }
558
559 #if defined(FSL_SDK_ENABLE_USART_DRIVER_TRANSACTIONAL_APIS) && (FSL_SDK_ENABLE_USART_DRIVER_TRANSACTIONAL_APIS)
560 /*!
561 * brief Initializes the USART handle.
562 *
563 * This function initializes the USART handle which can be used for other USART
564 * transactional APIs. Usually, for a specified USART instance,
565 * call this API once to get the initialized handle.
566 *
567 * param base USART peripheral base address.
568 * param handle USART handle pointer.
569 * param callback The callback function.
570 * param userData The parameter of the callback function.
571 */
USART_TransferCreateHandle(USART_Type * base,usart_handle_t * handle,usart_transfer_callback_t callback,void * userData)572 status_t USART_TransferCreateHandle(USART_Type *base,
573 usart_handle_t *handle,
574 usart_transfer_callback_t callback,
575 void *userData)
576 {
577 uint32_t instance = 0;
578
579 /* Check 'base' */
580 assert(!((NULL == base) || (NULL == handle)));
581
582 instance = USART_GetInstance(base);
583
584 (void)memset(handle, 0, sizeof(*handle));
585 /* Set the TX/RX state. */
586 handle->rxState = (uint8_t)kUSART_RxIdle;
587 handle->txState = (uint8_t)kUSART_TxIdle;
588 /* Set the callback and user data. */
589 handle->callback = callback;
590 handle->userData = userData;
591 /* Store the handle data to global variables. */
592 s_usartHandle[instance] = handle;
593 /* Mapping the interrupt function. */
594 s_usartIsr = USART_TransferHandleIRQ;
595 /* Enable interrupt in NVIC. */
596 (void)EnableIRQ(s_usartIRQ[instance]);
597
598 return kStatus_Success;
599 }
600
601 /*!
602 * brief Transmits a buffer of data using the interrupt method.
603 *
604 * This function sends data using an interrupt method. This is a non-blocking function, which
605 * returns directly without waiting for all data to be written to the TX register. When
606 * all data is written to the TX register in the IRQ handler, the USART driver calls the callback
607 * function and passes the ref kStatus_USART_TxIdle as status parameter.
608 *
609 * note The kStatus_USART_TxIdle is passed to the upper layer when all data is written
610 * to the TX register. However it does not ensure that all data are sent out. Before disabling the TX,
611 * check the kUSART_TransmissionCompleteFlag to ensure that the TX is finished.
612 *
613 * param base USART peripheral base address.
614 * param handle USART handle pointer.
615 * param xfer USART transfer structure. See #usart_transfer_t.
616 * retval kStatus_Success Successfully start the data transmission.
617 * retval kStatus_USART_TxBusy Previous transmission still not finished, data not all written to TX register yet.
618 * retval kStatus_InvalidArgument Invalid argument.
619 */
USART_TransferSendNonBlocking(USART_Type * base,usart_handle_t * handle,usart_transfer_t * xfer)620 status_t USART_TransferSendNonBlocking(USART_Type *base, usart_handle_t *handle, usart_transfer_t *xfer)
621 {
622 /* Check arguments */
623 assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));
624 /* Check xfer members */
625 assert(!((0U == xfer->dataSize) || (NULL == xfer->txData)));
626
627 /* Return error if current TX busy. */
628 if ((uint8_t)kUSART_TxBusy == handle->txState)
629 {
630 return kStatus_USART_TxBusy;
631 }
632 else
633 {
634 handle->txData = xfer->txData;
635 handle->txDataSize = xfer->dataSize;
636 handle->txDataSizeAll = xfer->dataSize;
637 handle->txState = (uint8_t)kUSART_TxBusy;
638
639 USART_EnableInterrupts(base, (uint32_t)kUSART_TxReadyInterruptEnable);
640 /* Clear transmit disable bit. */
641 base->CTL &= ~USART_CTL_TXDIS_MASK;
642 }
643 return kStatus_Success;
644 }
645
646 /*!
647 * brief Aborts the interrupt-driven data transmit.
648 *
649 * This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out
650 * how many bytes are still not sent out.
651 *
652 * param base USART peripheral base address.
653 * param handle USART handle pointer.
654 */
USART_TransferAbortSend(USART_Type * base,usart_handle_t * handle)655 void USART_TransferAbortSend(USART_Type *base, usart_handle_t *handle)
656 {
657 assert(NULL != handle);
658
659 USART_DisableInterrupts(base, (uint32_t)kUSART_TxReadyInterruptEnable);
660 /* Disable transmit after data being transmitted. */
661 USART_EnableTx(base, false);
662 handle->txDataSize = 0;
663 handle->txState = (uint8_t)kUSART_TxIdle;
664 }
665
666 /*!
667 * brief Get the number of bytes that have been written to USART TX register.
668 *
669 * This function gets the number of bytes that have been written to USART TX
670 * register by interrupt method.
671 *
672 * param base USART peripheral base address.
673 * param handle USART handle pointer.
674 * param count Send bytes count.
675 * retval kStatus_NoTransferInProgress No send in progress.
676 * retval kStatus_InvalidArgument Parameter is invalid.
677 * retval kStatus_Success Get successfully through the parameter \p count;
678 */
USART_TransferGetSendCount(USART_Type * base,usart_handle_t * handle,uint32_t * count)679 status_t USART_TransferGetSendCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)
680 {
681 assert(NULL != handle);
682 assert(NULL != count);
683
684 status_t status;
685
686 if ((uint8_t)kUSART_TxIdle == handle->txState)
687 {
688 status = kStatus_NoTransferInProgress;
689 }
690 else
691 {
692 *count = handle->txDataSizeAll - handle->txDataSize;
693 status = kStatus_Success;
694 }
695
696 return status;
697 }
698
699 /*!
700 * brief Receives a buffer of data using an interrupt method.
701 *
702 * This function receives data using an interrupt method. This is a non-blocking function, which
703 * returns without waiting for all data to be received.
704 * If the RX ring buffer is used and not empty, the data in the ring buffer is copied and
705 * the parameter p receivedBytes shows how many bytes are copied from the ring buffer.
706 * After copying, if the data in the ring buffer is not enough to read, the receive
707 * request is saved by the USART driver. When the new data arrives, the receive request
708 * is serviced first. When all data is received, the USART driver notifies the upper layer
709 * through a callback function and passes the status parameter ref kStatus_USART_RxIdle.
710 * For example, the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer.
711 * The 5 bytes are copied to the xfer->data and this function returns with the
712 * parameter p receivedBytes set to 5. For the left 5 bytes, newly arrived data is
713 * saved from the xfer->data[5]. When 5 bytes are received, the USART driver notifies the upper layer.
714 * If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
715 * to receive data to the xfer->data. When all data is received, the upper layer is notified.
716 *
717 * param base USART peripheral base address.
718 * param handle USART handle pointer.
719 * param xfer USART transfer structure, see #usart_transfer_t.
720 * param receivedBytes Bytes received from the ring buffer directly.
721 * retval kStatus_Success Successfully queue the transfer into transmit queue.
722 * retval kStatus_USART_RxBusy Previous receive request is not finished.
723 * retval kStatus_InvalidArgument Invalid argument.
724 */
USART_TransferReceiveNonBlocking(USART_Type * base,usart_handle_t * handle,usart_transfer_t * xfer,size_t * receivedBytes)725 status_t USART_TransferReceiveNonBlocking(USART_Type *base,
726 usart_handle_t *handle,
727 usart_transfer_t *xfer,
728 size_t *receivedBytes)
729 {
730 status_t status = kStatus_Success;
731 uint32_t i;
732 /* How many bytes to copy from ring buffer to user memory. */
733 size_t bytesToCopy = 0U;
734 /* How many bytes to receive. */
735 size_t bytesToReceive;
736 /* How many bytes currently have received. */
737 size_t bytesCurrentReceived;
738
739 /* Check arguments */
740 assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));
741 /* Check xfer members */
742 assert(!((0U == xfer->dataSize) || (NULL == xfer->rxData)));
743
744 /* How to get data:
745 1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize
746 to uart handle, enable interrupt to store received data to xfer->data. When
747 all data received, trigger callback.
748 2. If RX ring buffer is enabled and not empty, get data from ring buffer first.
749 If there are enough data in ring buffer, copy them to xfer->data and return.
750 If there are not enough data in ring buffer, copy all of them to xfer->data,
751 save the xfer->data remained empty space to uart handle, receive data
752 to this empty space and trigger callback when finished. */
753 if ((uint8_t)kUSART_RxBusy == handle->rxState)
754 {
755 status = kStatus_USART_RxBusy;
756 }
757 else
758 {
759 bytesToReceive = xfer->dataSize;
760 bytesCurrentReceived = 0U;
761 /* If RX ring buffer is used. */
762 if (handle->rxRingBuffer != NULL)
763 {
764 USART_DisableInterrupts(base, (uint32_t)kUSART_RxReadyInterruptEnable);
765 /* How many bytes in RX ring buffer currently. */
766 bytesToCopy = USART_TransferGetRxRingBufferLength(handle);
767 if (bytesToCopy != 0U)
768 {
769 bytesToCopy = MIN(bytesToReceive, bytesToCopy);
770 bytesToReceive -= bytesToCopy;
771 /* Copy data from ring buffer to user memory. */
772 for (i = 0U; i < bytesToCopy; i++)
773 {
774 xfer->rxData[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];
775 /* Wrap to 0. Not use modulo (%) because it might be large and slow. */
776 if ((size_t)handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
777 {
778 handle->rxRingBufferTail = 0U;
779 }
780 else
781 {
782 handle->rxRingBufferTail++;
783 }
784 }
785 }
786 /* If ring buffer does not have enough data, still need to read more data. */
787 if (bytesToReceive != 0U)
788 {
789 /* No data in ring buffer, save the request to UART handle. */
790 handle->rxData = xfer->rxData + bytesCurrentReceived;
791 handle->rxDataSize = bytesToReceive;
792 handle->rxDataSizeAll = xfer->dataSize;
793 handle->rxState = (uint8_t)kUSART_RxBusy;
794 }
795
796 USART_EnableInterrupts(base, (uint32_t)kUSART_RxReadyInterruptEnable);
797 /* Call user callback since all data are received. */
798 if (0U == bytesToReceive)
799 {
800 if (handle->callback != NULL)
801 {
802 handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);
803 }
804 }
805 }
806 /* Ring buffer not used. */
807 else
808 {
809 handle->rxData = xfer->rxData + bytesCurrentReceived;
810 handle->rxDataSize = bytesToReceive;
811 handle->rxDataSizeAll = bytesToReceive;
812 handle->rxState = (uint8_t)kUSART_RxBusy;
813
814 USART_EnableInterrupts(
815 base, (uint32_t)kUSART_RxReadyInterruptEnable | (uint32_t)kUSART_HardwareOverRunInterruptEnable);
816 }
817 /* Return the how many bytes have read. */
818 if (receivedBytes != NULL)
819 {
820 *receivedBytes = bytesCurrentReceived;
821 }
822 }
823 return status;
824 }
825
826 /*!
827 * brief Aborts the interrupt-driven data receiving.
828 *
829 * This function aborts the interrupt-driven data receiving. The user can get the remainBytes to find out
830 * how many bytes not received yet.
831 *
832 * param base USART peripheral base address.
833 * param handle USART handle pointer.
834 */
USART_TransferAbortReceive(USART_Type * base,usart_handle_t * handle)835 void USART_TransferAbortReceive(USART_Type *base, usart_handle_t *handle)
836 {
837 assert(NULL != handle);
838
839 /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
840 if (handle->rxRingBuffer == NULL)
841 {
842 USART_DisableInterrupts(
843 base, (uint32_t)kUSART_RxReadyInterruptEnable | (uint32_t)kUSART_HardwareOverRunInterruptEnable);
844 }
845
846 handle->rxDataSize = 0U;
847 handle->rxState = (uint8_t)kUSART_RxIdle;
848 }
849
850 /*!
851 * brief Get the number of bytes that have been received.
852 *
853 * This function gets the number of bytes that have been received.
854 *
855 * param base USART peripheral base address.
856 * param handle USART handle pointer.
857 * param count Receive bytes count.
858 * retval kStatus_NoTransferInProgress No receive in progress.
859 * retval kStatus_InvalidArgument Parameter is invalid.
860 * retval kStatus_Success Get successfully through the parameter \p count;
861 */
USART_TransferGetReceiveCount(USART_Type * base,usart_handle_t * handle,uint32_t * count)862 status_t USART_TransferGetReceiveCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)
863 {
864 assert(NULL != handle);
865 assert(NULL != count);
866 status_t status = kStatus_Success;
867
868 if ((uint8_t)kUSART_RxIdle == handle->rxState)
869 {
870 status = kStatus_NoTransferInProgress;
871 }
872 else
873 {
874 *count = handle->rxDataSizeAll - handle->rxDataSize;
875 }
876
877 return status;
878 }
879
880 /*!
881 * brief USART IRQ handle function.
882 *
883 * This function handles the USART transmit and receive IRQ request.
884 *
885 * param base USART peripheral base address.
886 * param handle USART handle pointer.
887 */
USART_TransferHandleIRQ(USART_Type * base,usart_handle_t * handle)888 void USART_TransferHandleIRQ(USART_Type *base, usart_handle_t *handle)
889 {
890 /* Check arguments */
891 assert((NULL != base) && (NULL != handle));
892
893 bool receiveEnabled = (handle->rxDataSize != 0U) || (handle->rxRingBuffer != NULL);
894 bool sendEnabled = (handle->txDataSize != 0U);
895 uint32_t status = USART_GetStatusFlags(base);
896 uint8_t tmpdata = (uint8_t)base->RXDAT;
897
898 /* If RX overrun. */
899 if (((uint32_t)kUSART_HardwareOverrunFlag & status) != 0U)
900 {
901 /* Clear rx error state. */
902 base->STAT |= USART_STAT_OVERRUNINT_MASK;
903 /* Trigger callback. */
904 if (handle->callback != NULL)
905 {
906 handle->callback(base, handle, kStatus_USART_RxError, handle->userData);
907 }
908 }
909 #if defined(FSL_FEATURE_USART_HAS_RXIDLETO_CHECK) && FSL_FEATURE_USART_HAS_RXIDLETO_CHECK
910 /* If RX idle time out */
911 if (((uint32_t)kUSART_RxIdleTimeoutFlag & status) != 0U)
912 {
913 /* Clear rx error state. */
914 base->STAT |= USART_STAT_RXIDLETO_MASK;
915 /* Trigger callback. */
916 if (handle->callback != NULL)
917 {
918 handle->callback(base, handle, kStatus_USART_RxIdleTimeout, handle->userData);
919 }
920 }
921 #endif
922 /* Receive data */
923 if ((receiveEnabled) && (((uint32_t)kUSART_RxReady & status) != 0U))
924 {
925 /* Receive to app bufffer if app buffer is present */
926 if (handle->rxDataSize != 0U)
927 {
928 *handle->rxData = tmpdata;
929 handle->rxDataSize--;
930 handle->rxData++;
931
932 if (handle->rxDataSize == 0U)
933 {
934 if (handle->rxRingBuffer == NULL)
935 {
936 USART_DisableInterrupts(base, (uint32_t)kUSART_RxReadyInterruptEnable |
937 (uint32_t)kUSART_HardwareOverRunInterruptEnable);
938 }
939 handle->rxState = (uint8_t)kUSART_RxIdle;
940 if (handle->callback != NULL)
941 {
942 handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);
943 }
944 }
945 }
946 /* Otherwise receive to ring buffer if ring buffer is present */
947 else
948 {
949 if (handle->rxRingBuffer != NULL)
950 {
951 if (USART_TransferIsRxRingBufferFull(handle))
952 {
953 if (handle->callback != NULL)
954 {
955 handle->callback(base, handle, kStatus_USART_RxRingBufferOverrun, handle->userData);
956 }
957 }
958 /* If ring buffer is still full after callback function, the oldest data is overridden. */
959 if (USART_TransferIsRxRingBufferFull(handle))
960 {
961 /* Increase handle->rxRingBufferTail to make room for new data. */
962 if ((size_t)handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
963 {
964 handle->rxRingBufferTail = 0U;
965 }
966 else
967 {
968 handle->rxRingBufferTail++;
969 }
970 }
971
972 handle->rxRingBuffer[handle->rxRingBufferHead] = tmpdata;
973
974 /* Increase handle->rxRingBufferHead. */
975 if ((size_t)handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
976 {
977 handle->rxRingBufferHead = 0U;
978 }
979 else
980 {
981 handle->rxRingBufferHead++;
982 }
983 }
984 }
985 }
986 /* Send data */
987 if (sendEnabled && (((uint32_t)kUSART_TxReady & status) != 0U))
988 {
989 base->TXDAT = *handle->txData;
990 handle->txDataSize--;
991 handle->txData++;
992
993 if (0U == handle->txDataSize)
994 {
995 USART_DisableInterrupts(base, (uint32_t)kUSART_TxReadyInterruptEnable);
996 handle->txState = (uint8_t)kUSART_TxIdle;
997 if (handle->callback != NULL)
998 {
999 handle->callback(base, handle, kStatus_USART_TxIdle, handle->userData);
1000 }
1001 }
1002 }
1003 }
1004
1005 #if defined(USART0)
1006 void USART0_DriverIRQHandler(void);
USART0_DriverIRQHandler(void)1007 void USART0_DriverIRQHandler(void)
1008 {
1009 s_usartIsr(USART0, s_usartHandle[0]);
1010 }
1011 #endif
1012
1013 #if defined(USART1)
1014 void USART1_DriverIRQHandler(void);
USART1_DriverIRQHandler(void)1015 void USART1_DriverIRQHandler(void)
1016 {
1017 s_usartIsr(USART1, s_usartHandle[1]);
1018 }
1019 #endif
1020
1021 #if defined(USART2)
1022 void USART2_DriverIRQHandler(void);
USART2_DriverIRQHandler(void)1023 void USART2_DriverIRQHandler(void)
1024 {
1025 s_usartIsr(USART2, s_usartHandle[2]);
1026 }
1027 #endif
1028
1029 #if defined(USART3)
1030 void PIN_INT6_USART3_DriverIRQHandler(void);
PIN_INT6_USART3_DriverIRQHandler(void)1031 void PIN_INT6_USART3_DriverIRQHandler(void)
1032 {
1033 s_usartIsr(USART3, s_usartHandle[3]);
1034 }
1035 #endif
1036
1037 #if defined(USART4)
1038 void PIN_INT7_USART4_DriverIRQHandler(void);
PIN_INT7_USART4_DriverIRQHandler(void)1039 void PIN_INT7_USART4_DriverIRQHandler(void)
1040 {
1041 s_usartIsr(USART4, s_usartHandle[4]);
1042 }
1043 #endif
1044 #endif /* FSL_SDK_ENABLE_USART_DRIVER_TRANSACTIONAL_APIS */
1045