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