1 /*
2  * Copyright 2022-2024 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_lpuart.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.lpflexcomm_lpuart"
17 #endif
18 
19 /*!
20  * @brief Used for conversion from `lpflexcomm_irq_handler_t` to `lpuart_irq_handler_t`
21  */
22 typedef union lpuart_to_lpflexcomm
23 {
24     lpuart_irq_handler_t lpuart_handler;
25     lpflexcomm_irq_handler_t lpflexcomm_handler;
26 } lpuart_to_lpflexcomm_t;
27 
28 /* LPUART transfer state. */
29 enum
30 {
31     kLPUART_TxIdle, /*!< TX idle. */
32     kLPUART_TxBusy, /*!< TX busy. */
33     kLPUART_RxIdle, /*!< RX idle. */
34     kLPUART_RxBusy  /*!< RX busy. */
35 };
36 
37 /*******************************************************************************
38  * Prototypes
39  ******************************************************************************/
40 /*!
41  * @brief Check whether the RX ring buffer is full.
42  *
43  * @userData handle LPUART handle pointer.
44  * @retval true  RX ring buffer is full.
45  * @retval false RX ring buffer is not full.
46  */
47 static bool LPUART_TransferIsRxRingBufferFull(LPUART_Type *base, lpuart_handle_t *handle);
48 
49 /*!
50  * @brief Write to TX register using non-blocking method.
51  *
52  * This function writes data to the TX register directly, upper layer must make
53  * sure the TX register is empty or TX FIFO has empty room before calling this function.
54  *
55  * @note This function does not check whether all the data has been sent out to bus,
56  * so before disable TX, check kLPUART_TransmissionCompleteFlag to ensure the TX is
57  * finished.
58  *
59  * @param base LPUART peripheral base address.
60  * @param data Start address of the data to write.
61  * @param length Size of the buffer to be sent.
62  */
63 static void LPUART_WriteNonBlocking(LPUART_Type *base, const uint8_t *data, size_t length);
64 
65 /*!
66  * @brief Write to TX register using non-blocking method in 9bit or 10bit mode.
67  *
68  * @note This function only support 9bit or 10bit transfer.
69  *
70  * @param base LPUART peripheral base address.
71  * @param data Start address of the data to write.
72  * @param length Size of the buffer to be sent.
73  */
74 static void LPUART_WriteNonBlocking16bit(LPUART_Type *base, const uint16_t *data, size_t length);
75 
76 /*!
77  * @brief Read RX register using non-blocking method.
78  *
79  * This function reads data from the TX register directly, upper layer must make
80  * sure the RX register is full or TX FIFO has data before calling this function.
81  *
82  * @param base LPUART peripheral base address.
83  * @param data Start address of the buffer to store the received data.
84  * @param length Size of the buffer.
85  */
86 static void LPUART_ReadNonBlocking(LPUART_Type *base, uint8_t *data, size_t length);
87 
88 /*!
89  * @brief Read RX register using non-blocking method in 9bit or 10bit mode.
90  *
91  * @note This function only support 9bit or 10bit transfer.
92  *
93  * @param base LPUART peripheral base address.
94  * @param data Start address of the buffer to store the received data.
95  * @param length Size of the buffer.
96  */
97 static void LPUART_ReadNonBlocking16bit(LPUART_Type *base, uint16_t *data, size_t length);
98 
99 /*******************************************************************************
100  * Variables
101  ******************************************************************************/
102 /* Array of LPUART peripheral base address. */
103 static LPUART_Type *const s_lpuartBases[] = LPUART_BASE_PTRS;
104 
105 /* Array of LPUART IRQ number. */
106 const IRQn_Type s_lpuartIRQ[] = LPUART_RX_TX_IRQS;
107 
108 /*******************************************************************************
109  * Code
110  ******************************************************************************/
111 /*!
112  * brief Get the LPUART instance from peripheral base address.
113  *
114  * param base LPUART peripheral base address.
115  * return LPUART instance.
116  */
LPUART_GetInstance(LPUART_Type * base)117 uint32_t LPUART_GetInstance(LPUART_Type *base)
118 {
119     uint32_t instance;
120 
121     /* Find the instance index from base address mappings. */
122     for (instance = 0U; instance < ARRAY_SIZE(s_lpuartBases); instance++)
123     {
124         if (MSDK_REG_SECURE_ADDR(s_lpuartBases[instance]) == MSDK_REG_SECURE_ADDR(base))
125         {
126             break;
127         }
128     }
129 
130     assert(instance < ARRAY_SIZE(s_lpuartBases));
131 
132     return instance;
133 }
134 
135 /*!
136  * brief Get the length of received data in RX ring buffer.
137  *
138  * userData handle LPUART handle pointer.
139  * return Length of received data in RX ring buffer.
140  */
LPUART_TransferGetRxRingBufferLength(LPUART_Type * base,lpuart_handle_t * handle)141 size_t LPUART_TransferGetRxRingBufferLength(LPUART_Type *base, lpuart_handle_t *handle)
142 {
143     assert(NULL != handle);
144 
145     size_t size;
146     size_t tmpRxRingBufferSize   = handle->rxRingBufferSize;
147     uint16_t tmpRxRingBufferTail = handle->rxRingBufferTail;
148     uint16_t tmpRxRingBufferHead = handle->rxRingBufferHead;
149 
150     if (tmpRxRingBufferTail > tmpRxRingBufferHead)
151     {
152         size = ((size_t)tmpRxRingBufferHead + tmpRxRingBufferSize - (size_t)tmpRxRingBufferTail);
153     }
154     else
155     {
156         size = ((size_t)tmpRxRingBufferHead - (size_t)tmpRxRingBufferTail);
157     }
158 
159     return size;
160 }
161 
LPUART_TransferIsRxRingBufferFull(LPUART_Type * base,lpuart_handle_t * handle)162 static bool LPUART_TransferIsRxRingBufferFull(LPUART_Type *base, lpuart_handle_t *handle)
163 {
164     assert(NULL != handle);
165 
166     bool full;
167 
168     if (LPUART_TransferGetRxRingBufferLength(base, handle) == (handle->rxRingBufferSize - 1U))
169     {
170         full = true;
171     }
172     else
173     {
174         full = false;
175     }
176     return full;
177 }
178 
LPUART_WriteNonBlocking(LPUART_Type * base,const uint8_t * data,size_t length)179 static void LPUART_WriteNonBlocking(LPUART_Type *base, const uint8_t *data, size_t length)
180 {
181     assert(NULL != data);
182 
183     size_t i;
184 
185     /* The Non Blocking write data API assume user have ensured there is enough space in
186     peripheral to write. */
187     for (i = 0; i < length; i++)
188     {
189         base->DATA = data[i];
190     }
191 }
192 
LPUART_WriteNonBlocking16bit(LPUART_Type * base,const uint16_t * data,size_t length)193 static void LPUART_WriteNonBlocking16bit(LPUART_Type *base, const uint16_t *data, size_t length)
194 {
195     assert(NULL != data);
196 
197     size_t i;
198 
199     /* The Non Blocking write data API assume user have ensured there is enough space in
200     peripheral to write. */
201     for (i = 0; i < length; i++)
202     {
203         base->DATA = data[i];
204     }
205 }
206 
LPUART_ReadNonBlocking(LPUART_Type * base,uint8_t * data,size_t length)207 static void LPUART_ReadNonBlocking(LPUART_Type *base, uint8_t *data, size_t length)
208 {
209     assert(NULL != data);
210 
211     size_t i;
212 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
213     uint32_t ctrl        = base->CTRL;
214     bool isSevenDataBits = (((ctrl & LPUART_CTRL_M7_MASK) != 0U) ||
215                             (((ctrl & LPUART_CTRL_M_MASK) == 0U) && ((ctrl & LPUART_CTRL_PE_MASK) != 0U)));
216 #endif
217 
218     /* The Non Blocking read data API assume user have ensured there is enough space in
219     peripheral to write. */
220     for (i = 0; i < length; i++)
221     {
222 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
223         if (isSevenDataBits)
224         {
225             data[i] = (uint8_t)(base->DATA & 0x7FU);
226         }
227         else
228         {
229             data[i] = (uint8_t)base->DATA;
230         }
231 #else
232         data[i] = (uint8_t)(base->DATA);
233 #endif
234     }
235 }
236 
LPUART_ReadNonBlocking16bit(LPUART_Type * base,uint16_t * data,size_t length)237 static void LPUART_ReadNonBlocking16bit(LPUART_Type *base, uint16_t *data, size_t length)
238 {
239     assert(NULL != data);
240 
241     size_t i;
242     /* The Non Blocking read data API assume user have ensured there is enough space in
243     peripheral to write. */
244     for (i = 0; i < length; i++)
245     {
246         data[i] = (uint16_t)(base->DATA & 0x03FFU);
247     }
248 }
249 /*!
250  * brief Initializes an LPUART instance with the user configuration structure and the peripheral clock.
251  *
252  * This function configures the LPUART module with user-defined settings. Call the LPUART_GetDefaultConfig() function
253  * to configure the configuration structure and get the default configuration.
254  * The example below shows how to use this API to configure the LPUART.
255  * code
256  *  lpuart_config_t lpuartConfig;
257  *  lpuartConfig.baudRate_Bps = 115200U;
258  *  lpuartConfig.parityMode = kLPUART_ParityDisabled;
259  *  lpuartConfig.dataBitsCount = kLPUART_EightDataBits;
260  *  lpuartConfig.isMsb = false;
261  *  lpuartConfig.stopBitCount = kLPUART_OneStopBit;
262  *  lpuartConfig.txFifoWatermark = 0;
263  *  lpuartConfig.rxFifoWatermark = 1;
264  *  LPUART_Init(LPUART1, &lpuartConfig, 20000000U);
265  * endcode
266  *
267  * param base LPUART peripheral base address.
268  * param config Pointer to a user-defined configuration structure.
269  * param srcClock_Hz LPUART clock source frequency in HZ.
270  * retval kStatus_LPUART_BaudrateNotSupport Baudrate is not support in current clock source.
271  * retval kStatus_Success LPUART initialize succeed
272  */
LPUART_Init(LPUART_Type * base,const lpuart_config_t * config,uint32_t srcClock_Hz)273 status_t LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz)
274 {
275     assert(NULL != config);
276     assert(0U < config->baudRate_Bps);
277 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
278     assert((uint8_t)FSL_FEATURE_LPUART_FIFO_SIZEn(base) > config->txFifoWatermark);
279     assert((uint8_t)FSL_FEATURE_LPUART_FIFO_SIZEn(base) > config->rxFifoWatermark);
280 #endif
281 
282     status_t status = kStatus_Success;
283     uint32_t temp;
284     uint16_t sbr, sbrTemp;
285     uint8_t osr, osrTemp;
286     uint32_t tempDiff, calculatedBaud, baudDiff;
287 
288     /* This LPUART instantiation uses a slightly different baud rate calculation
289      * The idea is to use the best OSR (over-sampling rate) possible
290      * Note, OSR is typically hard-set to 16 in other LPUART instantiations
291      * loop to find the best OSR value possible, one that generates minimum baudDiff
292      * iterate through the rest of the supported values of OSR */
293 
294     baudDiff = config->baudRate_Bps;
295     osr      = 0U;
296     sbr      = 0U;
297     for (osrTemp = 4U; osrTemp <= 32U; osrTemp++)
298     {
299         /* calculate the temporary sbr value   */
300         sbrTemp = (uint16_t)((srcClock_Hz * 2U / (config->baudRate_Bps * (uint32_t)osrTemp) + 1U) / 2U);
301         /*set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate*/
302         if (sbrTemp == 0U)
303         {
304             sbrTemp = 1U;
305         }
306         else if (sbrTemp > LPUART_BAUD_SBR_MASK)
307         {
308             sbrTemp = LPUART_BAUD_SBR_MASK;
309         }
310         else
311         {
312             /* For MISRA 15.7 */
313         }
314         /* Calculate the baud rate based on the temporary OSR and SBR values */
315         calculatedBaud = (srcClock_Hz / ((uint32_t)osrTemp * (uint32_t)sbrTemp));
316         tempDiff       = calculatedBaud > config->baudRate_Bps ? (calculatedBaud - config->baudRate_Bps) :
317                                                                  (config->baudRate_Bps - calculatedBaud);
318 
319         if (tempDiff <= baudDiff)
320         {
321             baudDiff = tempDiff;
322             osr      = osrTemp; /* update and store the best OSR value calculated */
323             sbr      = sbrTemp; /* update store the best SBR value calculated */
324         }
325     }
326 
327     /* Check to see if actual baud rate is within 3% of desired baud rate
328      * based on the best calculate OSR value */
329     if (baudDiff > ((config->baudRate_Bps / 100U) * 3U))
330     {
331         /* Unacceptable baud rate difference of more than 3%*/
332         status = kStatus_LPUART_BaudrateNotSupport;
333     }
334     else
335     {
336 #if !(defined(LPFLEXCOMM_INIT_NOT_USED_IN_DRIVER) && LPFLEXCOMM_INIT_NOT_USED_IN_DRIVER)
337         /* initialize flexcomm to LPUART mode */
338         status = LP_FLEXCOMM_Init(LPUART_GetInstance(base), LP_FLEXCOMM_PERIPH_LPUART);
339         if (kStatus_Success != status)
340         {
341             return status;
342         }
343 #endif /* LPFLEXCOMM_INIT_NOT_USED_IN_DRIVER */
344 
345 #if defined(FSL_FEATURE_LPUART_HAS_GLOBAL) && FSL_FEATURE_LPUART_HAS_GLOBAL
346         /*Reset all internal logic and registers, except the Global Register */
347         LPUART_SoftwareReset(base);
348 #else
349         /* Disable LPUART TX RX before setting. */
350         base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK);
351 #endif
352 
353         temp = base->BAUD;
354 
355         /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling.
356          * If so, then "BOTHEDGE" sampling must be turned on */
357         if ((osr > 3U) && (osr < 8U))
358         {
359             temp |= LPUART_BAUD_BOTHEDGE_MASK;
360         }
361 
362         /* program the osr value (bit value is one less than actual value) */
363         temp &= ~LPUART_BAUD_OSR_MASK;
364         temp |= LPUART_BAUD_OSR((uint32_t)osr - 1UL);
365 
366         /* write the sbr value to the BAUD registers */
367         temp &= ~LPUART_BAUD_SBR_MASK;
368         base->BAUD = temp | LPUART_BAUD_SBR(sbr);
369 
370         /* Set bit count and parity mode. */
371         base->BAUD &= ~LPUART_BAUD_M10_MASK;
372 
373         temp = base->CTRL & ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK | LPUART_CTRL_ILT_MASK |
374                               LPUART_CTRL_IDLECFG_MASK);
375 
376         temp |= (uint8_t)config->parityMode | LPUART_CTRL_IDLECFG(config->rxIdleConfig) |
377                 LPUART_CTRL_ILT(config->rxIdleType);
378 
379 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
380         if (kLPUART_SevenDataBits == config->dataBitsCount)
381         {
382             if (kLPUART_ParityDisabled != config->parityMode)
383             {
384                 temp &= ~LPUART_CTRL_M7_MASK; /* Seven data bits and one parity bit */
385             }
386             else
387             {
388                 temp |= LPUART_CTRL_M7_MASK;
389             }
390         }
391         else
392 #endif
393         {
394             if (kLPUART_ParityDisabled != config->parityMode)
395             {
396                 temp |= LPUART_CTRL_M_MASK; /* Eight data bits and one parity bit */
397             }
398         }
399 
400         base->CTRL = temp;
401 
402 #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT
403         /* set stop bit per char */
404         temp       = base->BAUD & ~LPUART_BAUD_SBNS_MASK;
405         base->BAUD = temp | LPUART_BAUD_SBNS((uint8_t)config->stopBitCount);
406 #endif
407 
408 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
409         /* Set tx/rx WATER watermark
410            Note:
411            Take care of the RX FIFO, RX interrupt request only assert when received bytes
412            equal or more than RX water mark, there is potential issue if RX water
413            mark larger than 1.
414            For example, if RX FIFO water mark is 2, upper layer needs 5 bytes and
415            5 bytes are received. the last byte will be saved in FIFO but not trigger
416            RX interrupt because the water mark is 2.
417          */
418         base->WATER = (((uint32_t)(config->rxFifoWatermark) << 16U) | config->txFifoWatermark);
419 
420         /* Enable tx/rx FIFO */
421         base->FIFO |= (LPUART_FIFO_TXFE_MASK | LPUART_FIFO_RXFE_MASK);
422 
423         /* Flush FIFO */
424         base->FIFO |= (LPUART_FIFO_TXFLUSH_MASK | LPUART_FIFO_RXFLUSH_MASK);
425 #endif
426 
427         /* Clear all status flags */
428         temp = (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK |
429                 LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK);
430 
431 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
432         temp |= LPUART_STAT_LBKDIF_MASK;
433 #endif
434 
435 #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING
436         temp |= (LPUART_STAT_MA1F_MASK | LPUART_STAT_MA2F_MASK);
437 #endif
438 
439 #if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT
440         /* Set the CTS configuration/TX CTS source. */
441         base->MODIR |= LPUART_MODIR_TXCTSC(config->txCtsConfig) | LPUART_MODIR_TXCTSSRC(config->txCtsSource);
442         if (true == config->enableRxRTS)
443         {
444             /* Enable the receiver RTS(request-to-send) function. */
445             base->MODIR |= LPUART_MODIR_RXRTSE_MASK;
446         }
447         if (true == config->enableTxCTS)
448         {
449             /* Enable the CTS(clear-to-send) function. */
450             base->MODIR |= LPUART_MODIR_TXCTSE_MASK;
451         }
452 #endif
453 
454         /* Set data bits order. */
455         if (true == config->isMsb)
456         {
457             temp |= LPUART_STAT_MSBF_MASK;
458         }
459         else
460         {
461             temp &= ~LPUART_STAT_MSBF_MASK;
462         }
463 
464         base->STAT |= temp;
465 
466         /* Enable TX/RX base on configure structure. */
467         temp = base->CTRL;
468         if (true == config->enableTx)
469         {
470             temp |= LPUART_CTRL_TE_MASK;
471         }
472 
473         if (true == config->enableRx)
474         {
475             temp |= LPUART_CTRL_RE_MASK;
476         }
477 
478         base->CTRL = temp;
479 #if defined(FSL_FEATURE_LPUART_HAS_TIMEOUT) && FSL_FEATURE_LPUART_HAS_TIMEOUT
480         /* Timeout configuration. */
481         base->REIR = (uint32_t)config->timeoutConfig.rxExtendedTimeoutValue;
482         base->TEIR = (uint32_t)config->timeoutConfig.txExtendedTimeoutValue;
483         base->TOCR |= (uint32_t)config->timeoutConfig.rxCounter0.enableCounter |
484                       ((uint32_t)config->timeoutConfig.rxCounter1.enableCounter << 1U) |
485                       ((uint32_t)config->timeoutConfig.txCounter0.enableCounter << 2U) |
486                       ((uint32_t)config->timeoutConfig.txCounter1.enableCounter << 3U);
487         base->TIMEOUT[0] = ((uint32_t)config->timeoutConfig.rxCounter0.timeoutCondition << 30U) |
488                            (uint32_t)config->timeoutConfig.rxCounter0.timeoutValue;
489         base->TIMEOUT[1] = ((uint32_t)config->timeoutConfig.rxCounter1.timeoutCondition << 30U) |
490                            (uint32_t)config->timeoutConfig.rxCounter1.timeoutValue;
491         base->TIMEOUT[2] = ((uint32_t)config->timeoutConfig.txCounter0.timeoutCondition << 30U) |
492                            (uint32_t)config->timeoutConfig.txCounter0.timeoutValue;
493         base->TIMEOUT[3] = ((uint32_t)config->timeoutConfig.txCounter1.timeoutCondition << 30U) |
494                            (uint32_t)config->timeoutConfig.txCounter1.timeoutValue;
495 #endif
496 
497         /* Siglewire configuration. */
498 #if defined(FSL_FEATURE_LPUART_HAS_HDCR) && FSL_FEATURE_LPUART_HAS_HDCR
499         base->HDCR = (uint32_t)config->rtsDelay << 8U;
500         if (config->enableSingleWire)
501         {
502             base->HDCR |= 0xFUL;
503         }
504 #endif
505     }
506     return status;
507 }
508 /*!
509  * brief Deinitializes a LPUART instance.
510  *
511  * This function waits for transmit to complete, disables TX and RX, and disables the LPUART clock.
512  *
513  * param base LPUART peripheral base address.
514  */
LPUART_Deinit(LPUART_Type * base)515 void LPUART_Deinit(LPUART_Type *base)
516 {
517     uint32_t temp;
518 
519 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
520     /* Wait tx FIFO send out*/
521     while (0U != ((base->WATER & LPUART_WATER_TXCOUNT_MASK) >> LPUART_WATER_TXWATER_SHIFT))
522     {
523     }
524 #endif
525     /* Wait last char shift out */
526     while (0U == (base->STAT & LPUART_STAT_TC_MASK))
527     {
528     }
529 
530     /* Clear all status flags */
531     temp = (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK |
532             LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK);
533 
534 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
535     temp |= LPUART_STAT_LBKDIF_MASK;
536 #endif
537 
538 #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING
539     temp |= (LPUART_STAT_MA1F_MASK | LPUART_STAT_MA2F_MASK);
540 #endif
541 
542     base->STAT |= temp;
543 
544     /* Disable the module. */
545     base->CTRL = 0U;
546 
547 #if !(defined(LPFLEXCOMM_INIT_NOT_USED_IN_DRIVER) && LPFLEXCOMM_INIT_NOT_USED_IN_DRIVER)
548     LP_FLEXCOMM_Deinit(LPUART_GetInstance(base));
549 #endif
550 }
551 
552 /*!
553  * brief Gets the default configuration structure.
554  *
555  * This function initializes the LPUART configuration structure to a default value. The default
556  * values are:
557  *   lpuartConfig->baudRate_Bps = 115200U;
558  *   lpuartConfig->parityMode = kLPUART_ParityDisabled;
559  *   lpuartConfig->dataBitsCount = kLPUART_EightDataBits;
560  *   lpuartConfig->isMsb = false;
561  *   lpuartConfig->stopBitCount = kLPUART_OneStopBit;
562  *   lpuartConfig->txFifoWatermark = 0;
563  *   lpuartConfig->rxFifoWatermark = 1;
564  *   lpuartConfig->rxIdleType = kLPUART_IdleTypeStartBit;
565  *   lpuartConfig->rxIdleConfig = kLPUART_IdleCharacter1;
566  *   lpuartConfig->enableTx = false;
567  *   lpuartConfig->enableRx = false;
568  *
569  * param config Pointer to a configuration structure.
570  */
LPUART_GetDefaultConfig(lpuart_config_t * config)571 void LPUART_GetDefaultConfig(lpuart_config_t *config)
572 {
573     assert(NULL != config);
574 
575     /* Initializes the configure structure to zero. */
576     (void)memset(config, 0, sizeof(*config));
577 
578     config->baudRate_Bps  = 115200U;
579     config->parityMode    = kLPUART_ParityDisabled;
580     config->dataBitsCount = kLPUART_EightDataBits;
581     config->isMsb         = false;
582 #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT
583     config->stopBitCount = kLPUART_OneStopBit;
584 #endif
585 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
586     config->txFifoWatermark = 0U;
587     config->rxFifoWatermark = 0U;
588 #endif
589 #if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT
590     config->enableRxRTS = false;
591     config->enableTxCTS = false;
592     config->txCtsConfig = kLPUART_CtsSampleAtStart;
593     config->txCtsSource = kLPUART_CtsSourcePin;
594 #endif
595     config->rxIdleType   = kLPUART_IdleTypeStartBit;
596     config->rxIdleConfig = kLPUART_IdleCharacter1;
597     config->enableTx     = false;
598     config->enableRx     = false;
599 }
600 
601 /*!
602  * brief Sets the LPUART instance baudrate.
603  *
604  * This function configures the LPUART module baudrate. This function is used to update
605  * the LPUART module baudrate after the LPUART module is initialized by the LPUART_Init.
606  * code
607  *  LPUART_SetBaudRate(LPUART1, 115200U, 20000000U);
608  * endcode
609  *
610  * param base LPUART peripheral base address.
611  * param baudRate_Bps LPUART baudrate to be set.
612  * param srcClock_Hz LPUART clock source frequency in HZ.
613  * retval kStatus_LPUART_BaudrateNotSupport Baudrate is not supported in the current clock source.
614  * retval kStatus_Success Set baudrate succeeded.
615  */
LPUART_SetBaudRate(LPUART_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz)616 status_t LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
617 {
618     assert(0U < baudRate_Bps);
619 
620     status_t status = kStatus_Success;
621     uint32_t temp, oldCtrl;
622     uint16_t sbr, sbrTemp;
623     uint8_t osr, osrTemp;
624     uint32_t tempDiff, calculatedBaud, baudDiff;
625 
626     /* This LPUART instantiation uses a slightly different baud rate calculation
627      * The idea is to use the best OSR (over-sampling rate) possible
628      * Note, OSR is typically hard-set to 16 in other LPUART instantiations
629      * loop to find the best OSR value possible, one that generates minimum baudDiff
630      * iterate through the rest of the supported values of OSR */
631 
632     baudDiff = baudRate_Bps;
633     osr      = 0U;
634     sbr      = 0U;
635     for (osrTemp = 4U; osrTemp <= 32U; osrTemp++)
636     {
637         /* calculate the temporary sbr value   */
638         sbrTemp = (uint16_t)((srcClock_Hz * 2U / (baudRate_Bps * (uint32_t)osrTemp) + 1U) / 2U);
639         /*set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate*/
640         if (sbrTemp == 0U)
641         {
642             sbrTemp = 1U;
643         }
644         else if (sbrTemp > LPUART_BAUD_SBR_MASK)
645         {
646             sbrTemp = LPUART_BAUD_SBR_MASK;
647         }
648         else
649         {
650             /* For MISRA 15.7 */
651         }
652 
653         /* Calculate the baud rate based on the temporary OSR and SBR values */
654         calculatedBaud = srcClock_Hz / ((uint32_t)osrTemp * (uint32_t)sbrTemp);
655 
656         tempDiff = calculatedBaud > baudRate_Bps ? (calculatedBaud - baudRate_Bps) : (baudRate_Bps - calculatedBaud);
657 
658         if (tempDiff <= baudDiff)
659         {
660             baudDiff = tempDiff;
661             osr      = osrTemp; /* update and store the best OSR value calculated */
662             sbr      = sbrTemp; /* update store the best SBR value calculated */
663         }
664     }
665 
666     /* Check to see if actual baud rate is within 3% of desired baud rate
667      * based on the best calculate OSR value */
668     if (baudDiff < (uint32_t)((baudRate_Bps / 100U) * 3U))
669     {
670         /* Store CTRL before disable Tx and Rx */
671         oldCtrl = base->CTRL;
672 
673         /* Disable LPUART TX RX before setting. */
674         base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK);
675 
676         temp = base->BAUD;
677 
678         /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling.
679          * If so, then "BOTHEDGE" sampling must be turned on */
680         if ((osr > 3U) && (osr < 8U))
681         {
682             temp |= LPUART_BAUD_BOTHEDGE_MASK;
683         }
684 
685         /* program the osr value (bit value is one less than actual value) */
686         temp &= ~LPUART_BAUD_OSR_MASK;
687         temp |= LPUART_BAUD_OSR((uint32_t)osr - 1UL);
688 
689         /* write the sbr value to the BAUD registers */
690         temp &= ~LPUART_BAUD_SBR_MASK;
691         base->BAUD = temp | LPUART_BAUD_SBR(sbr);
692 
693         /* Restore CTRL. */
694         base->CTRL = oldCtrl;
695     }
696     else
697     {
698         /* Unacceptable baud rate difference of more than 3%*/
699         status = kStatus_LPUART_BaudrateNotSupport;
700     }
701 
702     return status;
703 }
704 
705 /*!
706  * brief Enable 9-bit data mode for LPUART.
707  *
708  * This function set the 9-bit mode for LPUART module. The 9th bit is not used for parity thus can be modified by user.
709  *
710  * param base LPUART peripheral base address.
711  * param enable true to enable, flase to disable.
712  */
LPUART_Enable9bitMode(LPUART_Type * base,bool enable)713 void LPUART_Enable9bitMode(LPUART_Type *base, bool enable)
714 {
715     assert(base != NULL);
716 
717     uint32_t temp = 0U;
718 
719     if (enable)
720     {
721         /* Set LPUART_CTRL_M for 9-bit mode, clear LPUART_CTRL_PE to disable parity. */
722         temp = base->CTRL & ~((uint32_t)LPUART_CTRL_PE_MASK | (uint32_t)LPUART_CTRL_M_MASK);
723         temp |= (uint32_t)LPUART_CTRL_M_MASK;
724         base->CTRL = temp;
725     }
726     else
727     {
728         /* Clear LPUART_CTRL_M. */
729         base->CTRL &= ~(uint32_t)LPUART_CTRL_M_MASK;
730     }
731 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
732     /* Clear LPUART_CTRL_M7 to disable 7-bit mode. */
733     base->CTRL &= ~(uint32_t)LPUART_CTRL_M7_MASK;
734 #endif
735 #if defined(FSL_FEATURE_LPUART_HAS_10BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_10BIT_DATA_SUPPORT
736     /* Clear LPUART_BAUD_M10 to disable 10-bit mode. */
737     base->BAUD &= ~(uint32_t)LPUART_BAUD_M10_MASK;
738 #endif
739 }
740 
741 /*!
742  * brief Transmit an address frame in 9-bit data mode.
743  *
744  * param base LPUART peripheral base address.
745  * param address LPUART slave address.
746  */
LPUART_SendAddress(LPUART_Type * base,uint8_t address)747 void LPUART_SendAddress(LPUART_Type *base, uint8_t address)
748 {
749     assert(base != NULL);
750 
751     uint32_t temp = base->DATA & 0xFFFFFC00UL;
752     temp |= ((uint32_t)address | (1UL << LPUART_DATA_R8T8_SHIFT));
753     base->DATA = temp;
754 }
755 
756 /*!
757  * brief Enables LPUART interrupts according to a provided mask.
758  *
759  * This function enables the LPUART interrupts according to a provided mask. The mask
760  * is a logical OR of enumeration members. See the ref _lpuart_interrupt_enable.
761  * This examples shows how to enable TX empty interrupt and RX full interrupt:
762  * code
763  *     LPUART_EnableInterrupts(LPUART1,kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable);
764  * endcode
765  *
766  * param base LPUART peripheral base address.
767  * param mask The interrupts to enable. Logical OR of ref _uart_interrupt_enable.
768  */
LPUART_EnableInterrupts(LPUART_Type * base,uint32_t mask)769 void LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask)
770 {
771     uint32_t s_atomicOldInt;
772     /* Only consider the real interrupt enable bits. */
773     mask &= (uint32_t)kLPUART_AllInterruptEnable;
774 
775 #if defined(FSL_FEATURE_LPUART_HAS_MCR) && FSL_FEATURE_LPUART_HAS_MCR
776     /* Modem control interrupt enables */
777     base->MCR |= (mask & 0xFUL);
778 #endif
779 #if defined(FSL_FEATURE_LPUART_HAS_TIMEOUT) && FSL_FEATURE_LPUART_HAS_TIMEOUT
780     /* Timeout interrupt enables. */
781     base->TOSR |= ((mask >> 2U) & 0xF00UL);
782 #endif
783     /* Check int enable bits in base->BAUD */
784     uint32_t baudRegMask = 0UL;
785 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
786     baudRegMask |= ((mask << 8U) & LPUART_BAUD_LBKDIE_MASK);
787     /* Clear bit 7 from mask */
788     mask &= ~(uint32_t)kLPUART_LinBreakInterruptEnable;
789 #endif
790     baudRegMask |= ((mask << 8U) & LPUART_BAUD_RXEDGIE_MASK);
791     /* Clear bit 6 from mask */
792     mask &= ~(uint32_t)kLPUART_RxActiveEdgeInterruptEnable;
793 
794     s_atomicOldInt = DisableGlobalIRQ();
795     base->BAUD |= baudRegMask;
796     EnableGlobalIRQ(s_atomicOldInt);
797 
798 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
799     /* Check int enable bits in base->FIFO */
800 
801     s_atomicOldInt = DisableGlobalIRQ();
802     base->FIFO     = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) |
803                  (mask & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK));
804     EnableGlobalIRQ(s_atomicOldInt);
805 
806     /* Clear bit 9 and bit 8 from mask */
807     mask &= ~((uint32_t)kLPUART_TxFifoOverflowInterruptEnable | (uint32_t)kLPUART_RxFifoUnderflowInterruptEnable);
808 #endif
809 
810     /* Check int enable bits in base->CTRL */
811     s_atomicOldInt = DisableGlobalIRQ();
812     base->CTRL |= mask;
813     EnableGlobalIRQ(s_atomicOldInt);
814 }
815 
816 /*!
817  * brief Disables  LPUART interrupts according to a provided mask.
818  *
819  * This function disables the LPUART interrupts according to a provided mask. The mask
820  * is a logical OR of enumeration members. See ref _lpuart_interrupt_enable.
821  * This example shows how to disable the TX empty interrupt and RX full interrupt:
822  * code
823  *     LPUART_DisableInterrupts(LPUART1,kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable);
824  * endcode
825  *
826  * param base LPUART peripheral base address.
827  * param mask The interrupts to disable. Logical OR of ref _lpuart_interrupt_enable.
828  */
LPUART_DisableInterrupts(LPUART_Type * base,uint32_t mask)829 void LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask)
830 {
831     uint32_t s_atomicOldInt;
832     /* Only consider the real interrupt enable bits. */
833     mask &= (uint32_t)kLPUART_AllInterruptEnable;
834 
835 #if defined(FSL_FEATURE_LPUART_HAS_MCR) && FSL_FEATURE_LPUART_HAS_MCR
836     /* Modem control interrupts. */
837     base->MCR &= ~(mask & 0xFUL);
838 #endif
839 #if defined(FSL_FEATURE_LPUART_HAS_TIMEOUT) && FSL_FEATURE_LPUART_HAS_TIMEOUT
840     /* Timeout interrupt enables. */
841     base->TOSR &= ~((mask >> 2U) & 0xF00UL);
842 #endif
843 
844     /* Clear int enable bits in base->BAUD */
845     uint32_t baudRegMask = 0UL;
846 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
847     baudRegMask |= ((mask << 8U) & LPUART_BAUD_LBKDIE_MASK);
848     /* Clear bit 7 from mask */
849     mask &= ~(uint32_t)kLPUART_LinBreakInterruptEnable;
850 #endif
851     baudRegMask |= ((mask << 8U) & LPUART_BAUD_RXEDGIE_MASK);
852     /* Clear bit 6 from mask */
853     mask &= ~(uint32_t)kLPUART_RxActiveEdgeInterruptEnable;
854 
855     s_atomicOldInt = DisableGlobalIRQ();
856     base->BAUD &= ~baudRegMask;
857     EnableGlobalIRQ(s_atomicOldInt);
858 
859 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
860     /* Check int enable bits in base->FIFO */
861 
862     s_atomicOldInt = DisableGlobalIRQ();
863     base->FIFO     = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) &
864                  ~(mask & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK));
865     EnableGlobalIRQ(s_atomicOldInt);
866     /* Clear bit 9 and bit 8 from mask */
867     mask &= ~((uint32_t)kLPUART_TxFifoOverflowInterruptEnable | (uint32_t)kLPUART_RxFifoUnderflowInterruptEnable);
868 #endif
869 
870     /* Clear int enable bits in base->CTRL */
871     s_atomicOldInt = DisableGlobalIRQ();
872     base->CTRL &= ~mask;
873     EnableGlobalIRQ(s_atomicOldInt);
874 }
875 
876 /*!
877  * brief Gets enabled LPUART interrupts.
878  *
879  * This function gets the enabled LPUART interrupts. The enabled interrupts are returned
880  * as the logical OR value of the enumerators ref _lpuart_interrupt_enable. To check
881  * a specific interrupt enable status, compare the return value with enumerators
882  * in ref _lpuart_interrupt_enable.
883  * For example, to check whether the TX empty interrupt is enabled:
884  * code
885  *     uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(LPUART1);
886  *
887  *     if (kLPUART_TxDataRegEmptyInterruptEnable & enabledInterrupts)
888  *     {
889  *         ...
890  *     }
891  * endcode
892  *
893  * param base LPUART peripheral base address.
894  * return LPUART interrupt flags which are logical OR of the enumerators in ref _lpuart_interrupt_enable.
895  */
LPUART_GetEnabledInterrupts(LPUART_Type * base)896 uint32_t LPUART_GetEnabledInterrupts(LPUART_Type *base)
897 {
898     /* Check int enable bits in base->CTRL */
899     uint32_t temp = (uint32_t)(base->CTRL & 0xFF0C000UL);
900 
901 #if defined(FSL_FEATURE_LPUART_HAS_MCR) && FSL_FEATURE_LPUART_HAS_MCR
902     /* Check modem control interrupts. */
903     temp |= (base->MCR & 0xFUL);
904 #endif
905 #if defined(FSL_FEATURE_LPUART_HAS_TIMEOUT) && FSL_FEATURE_LPUART_HAS_TIMEOUT
906     /* Check timeout control interrupts. */
907     temp |= ((base->TOCR & 0xF00UL) << 2U);
908 #endif
909 
910     /* Check int enable bits in base->BAUD */
911     temp = (temp & ~(uint32_t)kLPUART_RxActiveEdgeInterruptEnable) | ((base->BAUD & LPUART_BAUD_RXEDGIE_MASK) >> 8U);
912 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
913     temp = (temp & ~(uint32_t)kLPUART_LinBreakInterruptEnable) | ((base->BAUD & LPUART_BAUD_LBKDIE_MASK) >> 8U);
914 #endif
915 
916 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
917     /* Check int enable bits in base->FIFO */
918     temp =
919         (temp & ~((uint32_t)kLPUART_TxFifoOverflowInterruptEnable | (uint32_t)kLPUART_RxFifoUnderflowInterruptEnable)) |
920         (base->FIFO & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK));
921 #endif
922 
923     return temp;
924 }
925 
926 /*!
927  * brief Gets LPUART status flags.
928  *
929  * This function gets all LPUART status flags. The flags are returned as the logical
930  * OR value of the enumerators ref _lpuart_flags. To check for a specific status,
931  * compare the return value with enumerators in the ref _lpuart_flags.
932  * For example, to check whether the TX is empty:
933  * code
934  *     if (kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(LPUART1))
935  *     {
936  *         ...
937  *     }
938  * endcode
939  *
940  * param base LPUART peripheral base address.
941  * return LPUART status flags which are ORed by the enumerators in the _lpuart_flags.
942  */
LPUART_GetStatusFlags(LPUART_Type * base)943 uint32_t LPUART_GetStatusFlags(LPUART_Type *base)
944 {
945     uint32_t temp;
946 
947     temp = (base->STAT & 0xC1FFC000UL);
948 #if defined(FSL_FEATURE_LPUART_HAS_MCR) && FSL_FEATURE_LPUART_HAS_MCR
949     temp |= ((base->MSR & 0xFUL) << 2U);
950 #endif
951 #if defined(FSL_FEATURE_LPUART_HAS_TIMEOUT) && FSL_FEATURE_LPUART_HAS_TIMEOUT
952     temp |= ((base->TOSR & 0xF00UL) << 2U);
953 #endif
954 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
955     temp |= (base->FIFO &
956              (LPUART_FIFO_TXEMPT_MASK | LPUART_FIFO_RXEMPT_MASK | LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) >>
957             16U;
958 #endif
959     /* Only keeps the status bits */
960     temp &= (uint32_t)kLPUART_AllFlags;
961     return temp;
962 }
963 
964 /*!
965  * brief Clears status flags with a provided mask.
966  *
967  * This function clears LPUART status flags with a provided mask. Automatically cleared flags
968  * can't be cleared by this function.
969  * Flags that can only cleared or set by hardware are:
970  *    kLPUART_TxDataRegEmptyFlag, kLPUART_TransmissionCompleteFlag, kLPUART_RxDataRegFullFlag,
971  *    kLPUART_RxActiveFlag, kLPUART_NoiseErrorInRxDataRegFlag, kLPUART_ParityErrorInRxDataRegFlag,
972  *    kLPUART_TxFifoEmptyFlag,kLPUART_RxFifoEmptyFlag
973  * Note: This API should be called when the Tx/Rx is idle, otherwise it takes no effects.
974  *
975  * param base LPUART peripheral base address.
976  * param mask the status flags to be cleared. The user can use the enumerators in the
977  *  _lpuart_status_flag_t to do the OR operation and get the mask.
978  * return 0 succeed, others failed.
979  * retval kStatus_LPUART_FlagCannotClearManually The flag can't be cleared by this function but
980  *         it is cleared automatically by hardware.
981  * retval kStatus_Success Status in the mask are cleared.
982  */
LPUART_ClearStatusFlags(LPUART_Type * base,uint32_t mask)983 status_t LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask)
984 {
985     uint32_t temp;
986     status_t status;
987 
988     /* Only deal with the clearable flags */
989     mask &= (uint32_t)kLPUART_AllClearFlags;
990 
991 #if defined(FSL_FEATURE_LPUART_HAS_MCR) && FSL_FEATURE_LPUART_HAS_MCR
992     /* Modem status */
993     base->MSR = ((mask >> 2U) & 0xFUL);
994 #endif
995 #if defined(FSL_FEATURE_LPUART_HAS_TIMEOUT) && FSL_FEATURE_LPUART_HAS_TIMEOUT
996     /* Timeout status */
997     base->TOSR = ((mask >> 2U) & 0xF00UL);
998 #endif
999 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
1000     /* Status bits in FIFO register */
1001     if ((mask & ((uint32_t)kLPUART_TxFifoOverflowFlag | (uint32_t)kLPUART_RxFifoUnderflowFlag)) != 0U)
1002     {
1003         /* Get the FIFO register value and mask the rx/tx FIFO flush bits and the status bits that can be W1C in case
1004            they are written 1 accidentally. */
1005         temp = (uint32_t)base->FIFO;
1006         temp &= (uint32_t)(~(LPUART_FIFO_TXFLUSH_MASK | LPUART_FIFO_RXFLUSH_MASK | LPUART_FIFO_TXOF_MASK |
1007                              LPUART_FIFO_RXUF_MASK));
1008         temp |= (mask << 16U) & (LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK);
1009         base->FIFO = temp;
1010     }
1011 #endif
1012     /* Status bits in STAT register */
1013     /* First get the STAT register value and mask all the bits that not represent status, then OR with the status bit
1014      * that is to be W1C */
1015     temp       = (base->STAT & 0x3E000000UL) | mask;
1016     base->STAT = temp;
1017     /* If some flags still pending. */
1018     if (0U != (mask & LPUART_GetStatusFlags(base)))
1019     {
1020         status = kStatus_LPUART_FlagCannotClearManually;
1021     }
1022     else
1023     {
1024         status = kStatus_Success;
1025     }
1026 
1027     return status;
1028 }
1029 
1030 /*!
1031  * brief Writes to the transmitter register using a blocking method.
1032  *
1033  * This function polls the transmitter register, first waits for the register to be empty or TX FIFO to have room,
1034  * and writes data to the transmitter buffer, then waits for the data to be sent out to bus.
1035  *
1036  * param base LPUART peripheral base address.
1037  * param data Start address of the data to write.
1038  * param length Size of the data to write.
1039  * retval kStatus_LPUART_Timeout Transmission timed out and was aborted.
1040  * retval kStatus_Success Successfully wrote all data.
1041  */
LPUART_WriteBlocking(LPUART_Type * base,const uint8_t * data,size_t length)1042 status_t LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length)
1043 {
1044     assert(NULL != data);
1045 
1046     const uint8_t *dataAddress = data;
1047     size_t transferSize        = length;
1048 
1049 #if UART_RETRY_TIMES
1050     uint32_t waitTimes;
1051 #endif
1052 
1053     while (0U != transferSize)
1054     {
1055 #if UART_RETRY_TIMES
1056         waitTimes = UART_RETRY_TIMES;
1057         while ((0U == (base->STAT & LPUART_STAT_TDRE_MASK)) && (0U != --waitTimes))
1058 #else
1059         while (0U == (base->STAT & LPUART_STAT_TDRE_MASK))
1060 #endif
1061         {
1062         }
1063 #if UART_RETRY_TIMES
1064         if (0U == waitTimes)
1065         {
1066             return kStatus_LPUART_Timeout;
1067         }
1068 #endif
1069         base->DATA = *(dataAddress);
1070         dataAddress++;
1071         transferSize--;
1072     }
1073     /* Ensure all the data in the transmit buffer are sent out to bus. */
1074 #if UART_RETRY_TIMES
1075     waitTimes = UART_RETRY_TIMES;
1076     while ((0U == (base->STAT & LPUART_STAT_TC_MASK)) && (0U != --waitTimes))
1077 #else
1078     while (0U == (base->STAT & LPUART_STAT_TC_MASK))
1079 #endif
1080     {
1081     }
1082 #if UART_RETRY_TIMES
1083     if (0U == waitTimes)
1084     {
1085         return kStatus_LPUART_Timeout;
1086     }
1087 #endif
1088     return kStatus_Success;
1089 }
1090 
1091 /*!
1092  * brief Writes to the transmitter register using a blocking method in 9bit or 10bit mode.
1093  *
1094  * note This function only support 9bit or 10bit transfer.
1095  *       Please make sure only 10bit of data is valid and other bits are 0.
1096  *
1097  * param base LPUART peripheral base address.
1098  * param data Start address of the data to write.
1099  * param length Size of the data to write.
1100  * retval kStatus_LPUART_Timeout Transmission timed out and was aborted.
1101  * retval kStatus_Success Successfully wrote all data.
1102  */
LPUART_WriteBlocking16bit(LPUART_Type * base,const uint16_t * data,size_t length)1103 status_t LPUART_WriteBlocking16bit(LPUART_Type *base, const uint16_t *data, size_t length)
1104 {
1105     assert(NULL != data);
1106 
1107     const uint16_t *dataAddress = data;
1108     size_t transferSize         = length;
1109 
1110 #if UART_RETRY_TIMES
1111     uint32_t waitTimes;
1112 #endif
1113 
1114     while (0U != transferSize)
1115     {
1116 #if UART_RETRY_TIMES
1117         waitTimes = UART_RETRY_TIMES;
1118         while ((0U == (base->STAT & LPUART_STAT_TDRE_MASK)) && (0U != --waitTimes))
1119 #else
1120         while (0U == (base->STAT & LPUART_STAT_TDRE_MASK))
1121 #endif
1122         {
1123         }
1124 #if UART_RETRY_TIMES
1125         if (0U == waitTimes)
1126         {
1127             return kStatus_LPUART_Timeout;
1128         }
1129 #endif
1130         base->DATA = *(dataAddress);
1131         dataAddress++;
1132         transferSize--;
1133     }
1134     /* Ensure all the data in the transmit buffer are sent out to bus. */
1135 #if UART_RETRY_TIMES
1136     waitTimes = UART_RETRY_TIMES;
1137     while ((0U == (base->STAT & LPUART_STAT_TC_MASK)) && (0U != --waitTimes))
1138 #else
1139     while (0U == (base->STAT & LPUART_STAT_TC_MASK))
1140 #endif
1141     {
1142     }
1143 #if UART_RETRY_TIMES
1144     if (0U == waitTimes)
1145     {
1146         return kStatus_LPUART_Timeout;
1147     }
1148 #endif
1149     return kStatus_Success;
1150 }
1151 
1152 /*!
1153  * brief Reads the receiver data register using a blocking method.
1154  *
1155  * This function polls the receiver register, waits for the receiver register full or receiver FIFO
1156  * has data, and reads data from the TX register.
1157  *
1158  * param base LPUART peripheral base address.
1159  * param data Start address of the buffer to store the received data.
1160  * param length Size of the buffer.
1161  * retval kStatus_LPUART_RxHardwareOverrun Receiver overrun happened while receiving data.
1162  * retval kStatus_LPUART_NoiseError Noise error happened while receiving data.
1163  * retval kStatus_LPUART_FramingError Framing error happened while receiving data.
1164  * retval kStatus_LPUART_ParityError Parity error happened while receiving data.
1165  * retval kStatus_LPUART_Timeout Transmission timed out and was aborted.
1166  * retval kStatus_Success Successfully received all data.
1167  */
LPUART_ReadBlocking(LPUART_Type * base,uint8_t * data,size_t length)1168 status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length)
1169 {
1170     assert(NULL != data);
1171 
1172     status_t status = kStatus_Success;
1173     uint32_t statusFlag;
1174     uint8_t *dataAddress = data;
1175 
1176 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
1177     uint32_t ctrl        = base->CTRL;
1178     bool isSevenDataBits = (((ctrl & LPUART_CTRL_M7_MASK) != 0U) ||
1179                             (((ctrl & LPUART_CTRL_M_MASK) == 0U) && ((ctrl & LPUART_CTRL_PE_MASK) != 0U)));
1180 #endif
1181 
1182 #if UART_RETRY_TIMES
1183     uint32_t waitTimes;
1184 #endif
1185 
1186     while (0U != (length--))
1187     {
1188 #if UART_RETRY_TIMES
1189         waitTimes = UART_RETRY_TIMES;
1190 #endif
1191 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
1192         while (0U == ((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT))
1193 #else
1194         while (0U == (base->STAT & LPUART_STAT_RDRF_MASK))
1195 #endif
1196         {
1197 #if UART_RETRY_TIMES
1198             if (0U == --waitTimes)
1199             {
1200                 status = kStatus_LPUART_Timeout;
1201                 break;
1202             }
1203 #endif
1204             statusFlag = LPUART_GetStatusFlags(base);
1205 
1206             if (0U != (statusFlag & (uint32_t)kLPUART_RxOverrunFlag))
1207             {
1208                 status = ((kStatus_Success == LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_RxOverrunFlag)) ?
1209                               (kStatus_LPUART_RxHardwareOverrun) :
1210                               (kStatus_LPUART_FlagCannotClearManually));
1211                 /* Other error flags(FE, NF, and PF) are prevented from setting once OR is set, no need to check other
1212                  * error flags*/
1213                 break;
1214             }
1215 
1216             if (0U != (statusFlag & (uint32_t)kLPUART_ParityErrorFlag))
1217             {
1218                 status = ((kStatus_Success == LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_ParityErrorFlag)) ?
1219                               (kStatus_LPUART_ParityError) :
1220                               (kStatus_LPUART_FlagCannotClearManually));
1221             }
1222 
1223             if (0U != (statusFlag & (uint32_t)kLPUART_FramingErrorFlag))
1224             {
1225                 status = ((kStatus_Success == LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_FramingErrorFlag)) ?
1226                               (kStatus_LPUART_FramingError) :
1227                               (kStatus_LPUART_FlagCannotClearManually));
1228             }
1229 
1230             if (0U != (statusFlag & (uint32_t)kLPUART_NoiseErrorFlag))
1231             {
1232                 status = ((kStatus_Success == LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_NoiseErrorFlag)) ?
1233                               (kStatus_LPUART_NoiseError) :
1234                               (kStatus_LPUART_FlagCannotClearManually));
1235             }
1236             if (kStatus_Success != status)
1237             {
1238                 break;
1239             }
1240         }
1241 
1242         if (kStatus_Success == status)
1243         {
1244 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
1245             if (isSevenDataBits)
1246             {
1247                 *(dataAddress) = (uint8_t)(base->DATA & 0x7FU);
1248                 dataAddress++;
1249             }
1250             else
1251             {
1252                 *(dataAddress) = (uint8_t)base->DATA;
1253                 dataAddress++;
1254             }
1255 #else
1256             *(dataAddress) = (uint8_t)base->DATA;
1257             dataAddress++;
1258 #endif
1259         }
1260         else
1261         {
1262             break;
1263         }
1264     }
1265 
1266     return status;
1267 }
1268 
1269 /*!
1270  * brief Reads the receiver data register in 9bit or 10bit mode.
1271  *
1272  * note This function only support 9bit or 10bit transfer.
1273  *
1274  * param base LPUART peripheral base address.
1275  * param data Start address of the buffer to store the received data by 16bit, only 10bit is valid.
1276  * param length Size of the buffer.
1277  * retval kStatus_LPUART_RxHardwareOverrun Receiver overrun happened while receiving data.
1278  * retval kStatus_LPUART_NoiseError Noise error happened while receiving data.
1279  * retval kStatus_LPUART_FramingError Framing error happened while receiving data.
1280  * retval kStatus_LPUART_ParityError Parity error happened while receiving data.
1281  * retval kStatus_LPUART_Timeout Transmission timed out and was aborted.
1282  * retval kStatus_Success Successfully received all data.
1283  */
LPUART_ReadBlocking16bit(LPUART_Type * base,uint16_t * data,size_t length)1284 status_t LPUART_ReadBlocking16bit(LPUART_Type *base, uint16_t *data, size_t length)
1285 {
1286     assert(NULL != data);
1287 
1288     status_t status = kStatus_Success;
1289     uint32_t statusFlag;
1290     uint16_t *dataAddress = data;
1291 
1292 #if UART_RETRY_TIMES
1293     uint32_t waitTimes;
1294 #endif
1295 
1296     while (0U != (length--))
1297     {
1298 #if UART_RETRY_TIMES
1299         waitTimes = UART_RETRY_TIMES;
1300 #endif
1301 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
1302         while (0U == ((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT))
1303 #else
1304         while (0U == (base->STAT & LPUART_STAT_RDRF_MASK))
1305 #endif
1306         {
1307 #if UART_RETRY_TIMES
1308             if (0U == --waitTimes)
1309             {
1310                 status = kStatus_LPUART_Timeout;
1311                 break;
1312             }
1313 #endif
1314             statusFlag = LPUART_GetStatusFlags(base);
1315 
1316             if (0U != (statusFlag & (uint32_t)kLPUART_RxOverrunFlag))
1317             {
1318                 /*
1319                  * $Branch Coverage Justification$
1320                  * $ref fsl_lpuart_c_ref_2$.
1321                  */
1322                 status = ((kStatus_Success == LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_RxOverrunFlag)) ?
1323                               (kStatus_LPUART_RxHardwareOverrun) :
1324                               (kStatus_LPUART_FlagCannotClearManually));
1325                 /* Other error flags(FE, NF, and PF) are prevented from setting once OR is set, no need to check other
1326                  * error flags*/
1327                 break;
1328             }
1329 
1330             if (0U != (statusFlag & (uint32_t)kLPUART_ParityErrorFlag))
1331             {
1332                 /*
1333                  * $Branch Coverage Justification$
1334                  * $ref fsl_lpuart_c_ref_2$.
1335                  */
1336                 status = ((kStatus_Success == LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_ParityErrorFlag)) ?
1337                               (kStatus_LPUART_ParityError) :
1338                               (kStatus_LPUART_FlagCannotClearManually));
1339             }
1340 
1341             if (0U != (statusFlag & (uint32_t)kLPUART_FramingErrorFlag))
1342             {
1343                 /*
1344                  * $Branch Coverage Justification$
1345                  * $ref fsl_lpuart_c_ref_2$.
1346                  */
1347                 status = ((kStatus_Success == LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_FramingErrorFlag)) ?
1348                               (kStatus_LPUART_FramingError) :
1349                               (kStatus_LPUART_FlagCannotClearManually));
1350             }
1351 
1352             if (0U != (statusFlag & (uint32_t)kLPUART_NoiseErrorFlag))
1353             {
1354                 /*
1355                  * $Branch Coverage Justification$
1356                  * $ref fsl_lpuart_c_ref_2$.
1357                  */
1358                 status = ((kStatus_Success == LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_NoiseErrorFlag)) ?
1359                               (kStatus_LPUART_NoiseError) :
1360                               (kStatus_LPUART_FlagCannotClearManually));
1361             }
1362             if (kStatus_Success != status)
1363             {
1364                 break;
1365             }
1366         }
1367         if (kStatus_Success == status)
1368         {
1369             *(dataAddress) = (uint16_t)(base->DATA & 0x03FFU);
1370             dataAddress++;
1371         }
1372         else
1373         {
1374             break;
1375         }
1376     }
1377 
1378     return status;
1379 }
1380 
1381 /*!
1382  * brief Initializes the LPUART handle.
1383  *
1384  * This function initializes the LPUART handle, which can be used for other LPUART
1385  * transactional APIs. Usually, for a specified LPUART instance,
1386  * call this API once to get the initialized handle.
1387  *
1388  * The LPUART driver supports the "background" receiving, which means that user can set up
1389  * an RX ring buffer optionally. Data received is stored into the ring buffer even when the
1390  * user doesn't call the LPUART_TransferReceiveNonBlocking() API. If there is already data received
1391  * in the ring buffer, the user can get the received data from the ring buffer directly.
1392  * The ring buffer is disabled if passing NULL as p ringBuffer.
1393  *
1394  * param base LPUART peripheral base address.
1395  * param handle LPUART handle pointer.
1396  * param callback Callback function.
1397  * param userData User data.
1398  */
LPUART_TransferCreateHandle(LPUART_Type * base,lpuart_handle_t * handle,lpuart_transfer_callback_t callback,void * userData)1399 void LPUART_TransferCreateHandle(LPUART_Type *base,
1400                                  lpuart_handle_t *handle,
1401                                  lpuart_transfer_callback_t callback,
1402                                  void *userData)
1403 {
1404     assert(NULL != handle);
1405 
1406     /* Get instance from peripheral base address. */
1407     uint32_t instance = LPUART_GetInstance(base);
1408 
1409     lpuart_to_lpflexcomm_t handler;
1410     handler.lpuart_handler = LPUART_TransferHandleIRQ;
1411 
1412 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
1413     uint32_t ctrl        = base->CTRL;
1414     bool isSevenDataBits = (((ctrl & LPUART_CTRL_M7_MASK) != 0U) ||
1415                             (((ctrl & LPUART_CTRL_M_MASK) == 0U) && ((ctrl & LPUART_CTRL_PE_MASK) != 0U)));
1416 #endif
1417 
1418     /* Zero the handle. */
1419     (void)memset(handle, 0, sizeof(lpuart_handle_t));
1420 
1421     /* Set the TX/RX state. */
1422     handle->rxState = (uint8_t)kLPUART_RxIdle;
1423     handle->txState = (uint8_t)kLPUART_TxIdle;
1424 
1425     /* Set the callback and user data. */
1426     handle->callback = callback;
1427     handle->userData = userData;
1428 
1429 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
1430     /* Initial seven data bits flag */
1431     handle->isSevenDataBits = isSevenDataBits;
1432 #endif
1433     handle->is16bitData = false;
1434 
1435     /* Save the handle in global variables to support the double weak mechanism. */
1436     LP_FLEXCOMM_SetIRQHandler(LPUART_GetInstance(base), handler.lpflexcomm_handler, handle, LP_FLEXCOMM_PERIPH_LPUART);
1437 
1438     /* Enable interrupt in NVIC. */
1439     (void)EnableIRQ(s_lpuartIRQ[instance]);
1440 }
1441 
1442 /*!
1443  * brief Sets up the RX ring buffer.
1444  *
1445  * This function sets up the RX ring buffer to a specific UART handle.
1446  *
1447  * When the RX ring buffer is used, data received is stored into the ring buffer even when
1448  * the user doesn't call the UART_TransferReceiveNonBlocking() API. If there is already data received
1449  * in the ring buffer, the user can get the received data from the ring buffer directly.
1450  *
1451  * note When using RX ring buffer, one byte is reserved for internal use. In other
1452  * words, if p ringBufferSize is 32, then only 31 bytes are used for saving data.
1453  *
1454  * param base LPUART peripheral base address.
1455  * param handle LPUART handle pointer.
1456  * param ringBuffer Start address of ring buffer for background receiving. Pass NULL to disable the ring buffer.
1457  * param ringBufferSize size of the ring buffer.
1458  */
LPUART_TransferStartRingBuffer(LPUART_Type * base,lpuart_handle_t * handle,uint8_t * ringBuffer,size_t ringBufferSize)1459 void LPUART_TransferStartRingBuffer(LPUART_Type *base,
1460                                     lpuart_handle_t *handle,
1461                                     uint8_t *ringBuffer,
1462                                     size_t ringBufferSize)
1463 {
1464     assert(NULL != handle);
1465     assert(NULL != ringBuffer);
1466 
1467     /* Setup the ring buffer address */
1468     handle->rxRingBuffer = ringBuffer;
1469     if (!handle->is16bitData)
1470     {
1471         handle->rxRingBufferSize = ringBufferSize;
1472     }
1473     else
1474     {
1475         handle->rxRingBufferSize = ringBufferSize / 2U;
1476     }
1477     handle->rxRingBufferHead = 0U;
1478     handle->rxRingBufferTail = 0U;
1479 
1480     /* Disable and re-enable the global interrupt to protect the interrupt enable register during read-modify-wrte. */
1481     uint32_t irqMask = DisableGlobalIRQ();
1482     /* Enable the interrupt to accept the data when user need the ring buffer. */
1483     base->CTRL |= (uint32_t)(LPUART_CTRL_RIE_MASK | LPUART_CTRL_ORIE_MASK);
1484     EnableGlobalIRQ(irqMask);
1485 }
1486 
1487 /*!
1488  * brief Aborts the background transfer and uninstalls the ring buffer.
1489  *
1490  * This function aborts the background transfer and uninstalls the ring buffer.
1491  *
1492  * param base LPUART peripheral base address.
1493  * param handle LPUART handle pointer.
1494  */
LPUART_TransferStopRingBuffer(LPUART_Type * base,lpuart_handle_t * handle)1495 void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle)
1496 {
1497     assert(NULL != handle);
1498 
1499     if (handle->rxState == (uint8_t)kLPUART_RxIdle)
1500     {
1501         /* Disable and re-enable the global interrupt to protect the interrupt enable register during read-modify-wrte.
1502          */
1503         uint32_t irqMask = DisableGlobalIRQ();
1504         base->CTRL &= ~(uint32_t)(LPUART_CTRL_RIE_MASK | LPUART_CTRL_ORIE_MASK);
1505         EnableGlobalIRQ(irqMask);
1506     }
1507 
1508     handle->rxRingBuffer     = NULL;
1509     handle->rxRingBufferSize = 0U;
1510     handle->rxRingBufferHead = 0U;
1511     handle->rxRingBufferTail = 0U;
1512 }
1513 
1514 /*!
1515  * brief Transmits a buffer of data using the interrupt method.
1516  *
1517  * This function send data using an interrupt method. This is a non-blocking function, which
1518  * returns directly without waiting for all data written to the transmitter register. When
1519  * all data is written to the TX register in the ISR, the LPUART driver calls the callback
1520  * function and passes the ref kStatus_LPUART_TxIdle as status parameter.
1521  *
1522  * note The kStatus_LPUART_TxIdle is passed to the upper layer when all data are written
1523  * to the TX register. However, there is no check to ensure that all the data sent out. Before disabling the TX,
1524  * check the kLPUART_TransmissionCompleteFlag to ensure that the transmit is finished.
1525  *
1526  * param base LPUART peripheral base address.
1527  * param handle LPUART handle pointer.
1528  * param xfer LPUART transfer structure, see #lpuart_transfer_t.
1529  * retval kStatus_Success Successfully start the data transmission.
1530  * retval kStatus_LPUART_TxBusy Previous transmission still not finished, data not all written to the TX register.
1531  * retval kStatus_InvalidArgument Invalid argument.
1532  */
LPUART_TransferSendNonBlocking(LPUART_Type * base,lpuart_handle_t * handle,lpuart_transfer_t * xfer)1533 status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_t *xfer)
1534 {
1535     assert(NULL != handle);
1536     assert(NULL != xfer);
1537     assert(NULL != xfer->txData);
1538     assert(0U != xfer->dataSize);
1539 
1540     status_t status;
1541 
1542     /* Return error if current TX busy. */
1543     if ((uint8_t)kLPUART_TxBusy == handle->txState)
1544     {
1545         status = kStatus_LPUART_TxBusy;
1546     }
1547     else
1548     {
1549         if (!handle->is16bitData)
1550         {
1551             handle->txData = xfer->txData;
1552         }
1553         else
1554         {
1555             handle->txData16 = xfer->txData16;
1556         }
1557         handle->txDataSize    = xfer->dataSize;
1558         handle->txDataSizeAll = xfer->dataSize;
1559         handle->txState       = (uint8_t)kLPUART_TxBusy;
1560 
1561         /* Disable and re-enable the global interrupt to protect the interrupt enable register during read-modify-wrte.
1562          */
1563         uint32_t irqMask = DisableGlobalIRQ();
1564         /* Enable transmitter interrupt. */
1565         base->CTRL |= (uint32_t)LPUART_CTRL_TIE_MASK;
1566         EnableGlobalIRQ(irqMask);
1567 
1568         status = kStatus_Success;
1569     }
1570 
1571     return status;
1572 }
1573 
1574 /*!
1575  * brief Aborts the interrupt-driven data transmit.
1576  *
1577  * This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out
1578  * how many bytes are not sent out.
1579  *
1580  * param base LPUART peripheral base address.
1581  * param handle LPUART handle pointer.
1582  */
LPUART_TransferAbortSend(LPUART_Type * base,lpuart_handle_t * handle)1583 void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle)
1584 {
1585     assert(NULL != handle);
1586 
1587     /* Disable and re-enable the global interrupt to protect the interrupt enable register during read-modify-wrte. */
1588     uint32_t irqMask = DisableGlobalIRQ();
1589     base->CTRL &= ~(uint32_t)(LPUART_CTRL_TIE_MASK | LPUART_CTRL_TCIE_MASK);
1590     EnableGlobalIRQ(irqMask);
1591 
1592     handle->txDataSize = 0;
1593     handle->txState    = (uint8_t)kLPUART_TxIdle;
1594 }
1595 
1596 /*!
1597  * brief Gets the number of bytes that have been sent out to bus.
1598  *
1599  * This function gets the number of bytes that have been sent out to bus by an interrupt method.
1600  *
1601  * param base LPUART peripheral base address.
1602  * param handle LPUART handle pointer.
1603  * param count Send bytes count.
1604  * retval kStatus_NoTransferInProgress No send in progress.
1605  * retval kStatus_InvalidArgument Parameter is invalid.
1606  * retval kStatus_Success Get successfully through the parameter \p count;
1607  */
LPUART_TransferGetSendCount(LPUART_Type * base,lpuart_handle_t * handle,uint32_t * count)1608 status_t LPUART_TransferGetSendCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count)
1609 {
1610     assert(NULL != handle);
1611     assert(NULL != count);
1612 
1613     status_t status      = kStatus_Success;
1614     size_t tmptxDataSize = handle->txDataSize;
1615 
1616     if ((uint8_t)kLPUART_TxIdle == handle->txState)
1617     {
1618         status = kStatus_NoTransferInProgress;
1619     }
1620     else
1621     {
1622 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
1623         *count = handle->txDataSizeAll - tmptxDataSize -
1624                  ((base->WATER & LPUART_WATER_TXCOUNT_MASK) >> LPUART_WATER_TXCOUNT_SHIFT);
1625 #else
1626         if ((base->STAT & (uint32_t)kLPUART_TxDataRegEmptyFlag) != 0U)
1627         {
1628             *count = handle->txDataSizeAll - tmptxDataSize;
1629         }
1630         else
1631         {
1632             *count = handle->txDataSizeAll - tmptxDataSize - 1U;
1633         }
1634 #endif
1635     }
1636 
1637     return status;
1638 }
1639 
1640 /*!
1641  * brief Receives a buffer of data using the interrupt method.
1642  *
1643  * This function receives data using an interrupt method. This is a non-blocking function
1644  * which returns without waiting to ensure that all data are received.
1645  * If the RX ring buffer is used and not empty, the data in the ring buffer is copied and
1646  * the parameter p receivedBytes shows how many bytes are copied from the ring buffer.
1647  * After copying, if the data in the ring buffer is not enough for read, the receive
1648  * request is saved by the LPUART driver. When the new data arrives, the receive request
1649  * is serviced first. When all data is received, the LPUART driver notifies the upper layer
1650  * through a callback function and passes a status parameter ref kStatus_UART_RxIdle.
1651  * For example, the upper layer needs 10 bytes but there are only 5 bytes in ring buffer.
1652  * The 5 bytes are copied to xfer->data, which returns with the
1653  * parameter p receivedBytes set to 5. For the remaining 5 bytes, the newly arrived data is
1654  * saved from xfer->data[5]. When 5 bytes are received, the LPUART driver notifies the upper layer.
1655  * If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
1656  * to receive data to xfer->data. When all data is received, the upper layer is notified.
1657  *
1658  * param base LPUART peripheral base address.
1659  * param handle LPUART handle pointer.
1660  * param xfer LPUART transfer structure, see #uart_transfer_t.
1661  * param receivedBytes Bytes received from the ring buffer directly.
1662  * retval kStatus_Success Successfully queue the transfer into the transmit queue.
1663  * retval kStatus_LPUART_RxBusy Previous receive request is not finished.
1664  * retval kStatus_InvalidArgument Invalid argument.
1665  */
LPUART_TransferReceiveNonBlocking(LPUART_Type * base,lpuart_handle_t * handle,lpuart_transfer_t * xfer,size_t * receivedBytes)1666 status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base,
1667                                            lpuart_handle_t *handle,
1668                                            lpuart_transfer_t *xfer,
1669                                            size_t *receivedBytes)
1670 {
1671     assert(NULL != handle);
1672     assert(NULL != xfer);
1673     assert(NULL != xfer->rxData);
1674     assert(0U != xfer->dataSize);
1675 
1676     uint32_t i;
1677     status_t status;
1678     uint32_t irqMask;
1679     /* How many bytes to copy from ring buffer to user memory. */
1680     size_t bytesToCopy = 0U;
1681     /* How many bytes to receive. */
1682     size_t bytesToReceive;
1683     /* How many bytes currently have received. */
1684     size_t bytesCurrentReceived;
1685 
1686     /* How to get data:
1687        1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize
1688           to lpuart handle, enable interrupt to store received data to xfer->data. When
1689           all data received, trigger callback.
1690        2. If RX ring buffer is enabled and not empty, get data from ring buffer first.
1691           If there are enough data in ring buffer, copy them to xfer->data and return.
1692           If there are not enough data in ring buffer, copy all of them to xfer->data,
1693           save the xfer->data remained empty space to lpuart handle, receive data
1694           to this empty space and trigger callback when finished. */
1695 
1696     if ((uint8_t)kLPUART_RxBusy == handle->rxState)
1697     {
1698         status = kStatus_LPUART_RxBusy;
1699     }
1700     else
1701     {
1702         bytesToReceive       = xfer->dataSize;
1703         bytesCurrentReceived = 0;
1704 
1705         /* If RX ring buffer is used. */
1706         if (NULL != handle->rxRingBuffer)
1707         {
1708             /* Disable and re-enable the global interrupt to protect the interrupt enable register during
1709              * read-modify-wrte. */
1710             irqMask = DisableGlobalIRQ();
1711             /* Disable LPUART RX IRQ, protect ring buffer. */
1712             base->CTRL &= ~(uint32_t)(LPUART_CTRL_RIE_MASK | LPUART_CTRL_ORIE_MASK);
1713             EnableGlobalIRQ(irqMask);
1714 
1715             /* How many bytes in RX ring buffer currently. */
1716             bytesToCopy = LPUART_TransferGetRxRingBufferLength(base, handle);
1717 
1718             if (0U != bytesToCopy)
1719             {
1720                 bytesToCopy = MIN(bytesToReceive, bytesToCopy);
1721 
1722                 bytesToReceive -= bytesToCopy;
1723 
1724                 /* Copy data from ring buffer to user memory. */
1725                 for (i = 0U; i < bytesToCopy; i++)
1726                 {
1727                     if (!handle->is16bitData)
1728                     {
1729                         xfer->rxData[bytesCurrentReceived] = handle->rxRingBuffer[handle->rxRingBufferTail];
1730                     }
1731                     else
1732                     {
1733                         xfer->rxData16[bytesCurrentReceived] = handle->rxRingBuffer16[handle->rxRingBufferTail];
1734                     }
1735                     bytesCurrentReceived++;
1736 
1737                     /* Wrap to 0. Not use modulo (%) because it might be large and slow. */
1738                     if (((uint32_t)handle->rxRingBufferTail + 1U) == handle->rxRingBufferSize)
1739                     {
1740                         handle->rxRingBufferTail = 0U;
1741                     }
1742                     else
1743                     {
1744                         handle->rxRingBufferTail++;
1745                     }
1746                 }
1747             }
1748 
1749             /* If ring buffer does not have enough data, still need to read more data. */
1750             if (0U != bytesToReceive)
1751             {
1752                 /* No data in ring buffer, save the request to LPUART handle. */
1753                 if (!handle->is16bitData)
1754                 {
1755                     handle->rxData = &xfer->rxData[bytesCurrentReceived];
1756                 }
1757                 else
1758                 {
1759                     handle->rxData16 = &xfer->rxData16[bytesCurrentReceived];
1760                 }
1761                 handle->rxDataSize    = bytesToReceive;
1762                 handle->rxDataSizeAll = xfer->dataSize;
1763                 handle->rxState       = (uint8_t)kLPUART_RxBusy;
1764             }
1765 
1766             /* Disable and re-enable the global interrupt to protect the interrupt enable register during
1767              * read-modify-wrte. */
1768             irqMask = DisableGlobalIRQ();
1769             /* Re-enable LPUART RX IRQ. */
1770             base->CTRL |= (uint32_t)(LPUART_CTRL_RIE_MASK | LPUART_CTRL_ORIE_MASK);
1771             EnableGlobalIRQ(irqMask);
1772 
1773             /* Call user callback since all data are received. */
1774             if (0U == bytesToReceive)
1775             {
1776                 if (NULL != handle->callback)
1777                 {
1778                     handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData);
1779                 }
1780             }
1781         }
1782         /* Ring buffer not used. */
1783         else
1784         {
1785             if (!handle->is16bitData)
1786             {
1787                 handle->rxData = &xfer->rxData[bytesCurrentReceived];
1788             }
1789             else
1790             {
1791                 handle->rxData16 = &xfer->rxData16[bytesCurrentReceived];
1792             }
1793             handle->rxDataSize    = bytesToReceive;
1794             handle->rxDataSizeAll = bytesToReceive;
1795             handle->rxState       = (uint8_t)kLPUART_RxBusy;
1796 
1797             /* Disable and re-enable the global interrupt to protect the interrupt enable register during
1798              * read-modify-wrte. */
1799             irqMask = DisableGlobalIRQ();
1800             /* Enable RX interrupt. */
1801             base->CTRL |= (uint32_t)(LPUART_CTRL_RIE_MASK | LPUART_CTRL_ILIE_MASK | LPUART_CTRL_ORIE_MASK);
1802             EnableGlobalIRQ(irqMask);
1803         }
1804 
1805         /* Return the how many bytes have read. */
1806         if (NULL != receivedBytes)
1807         {
1808             *receivedBytes = bytesCurrentReceived;
1809         }
1810 
1811         status = kStatus_Success;
1812     }
1813 
1814     return status;
1815 }
1816 
1817 /*!
1818  * brief Aborts the interrupt-driven data receiving.
1819  *
1820  * This function aborts the interrupt-driven data receiving. The user can get the remainBytes to find out
1821  * how many bytes not received yet.
1822  *
1823  * param base LPUART peripheral base address.
1824  * param handle LPUART handle pointer.
1825  */
LPUART_TransferAbortReceive(LPUART_Type * base,lpuart_handle_t * handle)1826 void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle)
1827 {
1828     assert(NULL != handle);
1829 
1830     /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
1831     if (NULL == handle->rxRingBuffer)
1832     {
1833         /* Disable and re-enable the global interrupt to protect the interrupt enable register during read-modify-wrte.
1834          */
1835         uint32_t irqMask = DisableGlobalIRQ();
1836         /* Disable RX interrupt. */
1837         base->CTRL &= ~(uint32_t)(LPUART_CTRL_RIE_MASK | LPUART_CTRL_ILIE_MASK | LPUART_CTRL_ORIE_MASK);
1838         EnableGlobalIRQ(irqMask);
1839     }
1840 
1841     handle->rxDataSize = 0U;
1842     handle->rxState    = (uint8_t)kLPUART_RxIdle;
1843 }
1844 
1845 /*!
1846  * brief Gets the number of bytes that have been received.
1847  *
1848  * This function gets the number of bytes that have been received.
1849  *
1850  * param base LPUART peripheral base address.
1851  * param handle LPUART handle pointer.
1852  * param count Receive bytes count.
1853  * retval kStatus_NoTransferInProgress No receive in progress.
1854  * retval kStatus_InvalidArgument Parameter is invalid.
1855  * retval kStatus_Success Get successfully through the parameter \p count;
1856  */
LPUART_TransferGetReceiveCount(LPUART_Type * base,lpuart_handle_t * handle,uint32_t * count)1857 status_t LPUART_TransferGetReceiveCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count)
1858 {
1859     assert(NULL != handle);
1860     assert(NULL != count);
1861 
1862     status_t status      = kStatus_Success;
1863     size_t tmprxDataSize = handle->rxDataSize;
1864 
1865     if ((uint8_t)kLPUART_RxIdle == handle->rxState)
1866     {
1867         status = kStatus_NoTransferInProgress;
1868     }
1869     else
1870     {
1871         *count = handle->rxDataSizeAll - tmprxDataSize;
1872     }
1873 
1874     return status;
1875 }
1876 
1877 /*!
1878  * brief LPUART IRQ handle function.
1879  *
1880  * This function handles the LPUART transmit and receive IRQ request.
1881  *
1882  * param instance LPUART instance.
1883  * param irqHandle LPUART handle pointer.
1884  */
LPUART_TransferHandleIRQ(uint32_t instance,void * irqHandle)1885 void LPUART_TransferHandleIRQ(uint32_t instance, void *irqHandle)
1886 {
1887     assert(NULL != irqHandle);
1888     assert(instance < ARRAY_SIZE(s_lpuartBases));
1889     LPUART_Type *base = s_lpuartBases[instance];
1890     uint8_t count;
1891     uint8_t tempCount;
1892     uint32_t status            = LPUART_GetStatusFlags(base);
1893     uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(base);
1894     uint16_t tpmRxRingBufferHead;
1895     uint32_t tpmData;
1896     uint32_t irqMask;
1897     lpuart_handle_t *handle = (lpuart_handle_t *)irqHandle;
1898 
1899     /* If RX overrun. */
1900     if ((uint32_t)kLPUART_RxOverrunFlag == ((uint32_t)kLPUART_RxOverrunFlag & status))
1901     {
1902         /* Clear overrun flag, otherwise the RX does not work. */
1903         base->STAT = ((base->STAT & 0x3FE00000U) | LPUART_STAT_OR_MASK);
1904 
1905         /* Trigger callback. */
1906         if (NULL != (handle->callback))
1907         {
1908             handle->callback(base, handle, kStatus_LPUART_RxHardwareOverrun, handle->userData);
1909         }
1910     }
1911 
1912     /* If IDLE flag is set and the IDLE interrupt is enabled. */
1913     if ((0U != ((uint32_t)kLPUART_IdleLineFlag & status)) &&
1914         (0U != ((uint32_t)kLPUART_IdleLineInterruptEnable & enabledInterrupts)))
1915     {
1916 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
1917         count = ((uint8_t)((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT));
1918 
1919         while ((0U != handle->rxDataSize) && (0U != count))
1920         {
1921             tempCount = (uint8_t)MIN(handle->rxDataSize, count);
1922 
1923             /* Using non block API to read the data from the registers. */
1924             if (!handle->is16bitData)
1925             {
1926                 LPUART_ReadNonBlocking(base, handle->rxData, tempCount);
1927                 handle->rxData = &handle->rxData[tempCount];
1928             }
1929             else
1930             {
1931                 LPUART_ReadNonBlocking16bit(base, handle->rxData16, tempCount);
1932                 handle->rxData16 = &handle->rxData16[tempCount];
1933             }
1934             handle->rxDataSize -= tempCount;
1935             count -= tempCount;
1936 
1937             /* If rxDataSize is 0, invoke rx idle callback.*/
1938             if (0U == (handle->rxDataSize))
1939             {
1940                 handle->rxState = (uint8_t)kLPUART_RxIdle;
1941 
1942                 if (NULL != handle->callback)
1943                 {
1944                     handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData);
1945                 }
1946             }
1947         }
1948 #endif
1949         /* Clear IDLE flag.*/
1950         base->STAT = ((base->STAT & 0x3FE00000U) | LPUART_STAT_IDLE_MASK);
1951 
1952         /* If rxDataSize is 0, disable rx ready, overrun and idle line interrupt.*/
1953         if (0U == handle->rxDataSize)
1954         {
1955             /* Disable and re-enable the global interrupt to protect the interrupt enable register during
1956              * read-modify-wrte. */
1957             irqMask = DisableGlobalIRQ();
1958             base->CTRL &= ~(uint32_t)(LPUART_CTRL_RIE_MASK | LPUART_CTRL_ILIE_MASK | LPUART_CTRL_ORIE_MASK);
1959             EnableGlobalIRQ(irqMask);
1960         }
1961         /* Invoke callback if callback is not NULL and rxDataSize is not 0. */
1962         else if (NULL != handle->callback)
1963         {
1964             handle->callback(base, handle, kStatus_LPUART_IdleLineDetected, handle->userData);
1965         }
1966         else
1967         {
1968             /* Avoid MISRA 15.7 */
1969         }
1970     }
1971     /* Receive data register full */
1972     if ((0U != ((uint32_t)kLPUART_RxDataRegFullFlag & status)) &&
1973         (0U != ((uint32_t)kLPUART_RxDataRegFullInterruptEnable & enabledInterrupts)))
1974     {
1975         /* Get the size that can be stored into buffer for this interrupt. */
1976 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
1977         count = ((uint8_t)((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT));
1978 #else
1979         count = 1;
1980 #endif
1981 
1982         /* If handle->rxDataSize is not 0, first save data to handle->rxData. */
1983         while ((0U != handle->rxDataSize) && (0U != count))
1984         {
1985 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
1986             tempCount = (uint8_t)MIN(handle->rxDataSize, count);
1987 #else
1988             tempCount = 1;
1989 #endif
1990 
1991             /* Using non block API to read the data from the registers. */
1992             if (!handle->is16bitData)
1993             {
1994                 LPUART_ReadNonBlocking(base, handle->rxData, tempCount);
1995                 handle->rxData = &handle->rxData[tempCount];
1996             }
1997             else
1998             {
1999                 LPUART_ReadNonBlocking16bit(base, handle->rxData16, tempCount);
2000                 handle->rxData16 = &handle->rxData16[tempCount];
2001             }
2002             handle->rxDataSize -= tempCount;
2003             count -= tempCount;
2004 
2005             /* If all the data required for upper layer is ready, trigger callback. */
2006             if (0U == handle->rxDataSize)
2007             {
2008                 handle->rxState = (uint8_t)kLPUART_RxIdle;
2009 
2010                 if (NULL != handle->callback)
2011                 {
2012                     handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData);
2013                 }
2014             }
2015         }
2016 
2017         /* If use RX ring buffer, receive data to ring buffer. */
2018         if (NULL != handle->rxRingBuffer)
2019         {
2020             while (0U != count--)
2021             {
2022                 /* If RX ring buffer is full, trigger callback to notify over run. */
2023                 if (LPUART_TransferIsRxRingBufferFull(base, handle))
2024                 {
2025                     if (NULL != handle->callback)
2026                     {
2027                         handle->callback(base, handle, kStatus_LPUART_RxRingBufferOverrun, handle->userData);
2028                     }
2029                 }
2030 
2031                 /* If ring buffer is still full after callback function, the oldest data is overridden. */
2032                 if (LPUART_TransferIsRxRingBufferFull(base, handle))
2033                 {
2034                     /* Increase handle->rxRingBufferTail to make room for new data. */
2035                     if (((uint32_t)handle->rxRingBufferTail + 1U) == handle->rxRingBufferSize)
2036                     {
2037                         handle->rxRingBufferTail = 0U;
2038                     }
2039                     else
2040                     {
2041                         handle->rxRingBufferTail++;
2042                     }
2043                 }
2044 
2045                 /* Read data. */
2046                 tpmRxRingBufferHead = handle->rxRingBufferHead;
2047                 tpmData             = base->DATA;
2048 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
2049                 if (handle->isSevenDataBits)
2050                 {
2051                     handle->rxRingBuffer[tpmRxRingBufferHead] = (uint8_t)(tpmData & 0x7FU);
2052                 }
2053                 else
2054                 {
2055                     if (!handle->is16bitData)
2056                     {
2057                         handle->rxRingBuffer[tpmRxRingBufferHead] = (uint8_t)tpmData;
2058                     }
2059                     else
2060                     {
2061                         handle->rxRingBuffer16[tpmRxRingBufferHead] = (uint16_t)(tpmData & 0x3FFU);
2062                     }
2063                 }
2064 #else
2065                 if (!handle->is16bitData)
2066                 {
2067                     handle->rxRingBuffer[tpmRxRingBufferHead] = (uint8_t)tpmData;
2068                 }
2069                 else
2070                 {
2071                     handle->rxRingBuffer16[tpmRxRingBufferHead] = (uint16_t)(tpmData & 0x3FFU);
2072                 }
2073 #endif
2074 
2075                 /* Increase handle->rxRingBufferHead. */
2076                 if (((uint32_t)handle->rxRingBufferHead + 1U) == handle->rxRingBufferSize)
2077                 {
2078                     handle->rxRingBufferHead = 0U;
2079                 }
2080                 else
2081                 {
2082                     handle->rxRingBufferHead++;
2083                 }
2084             }
2085         }
2086         /* If no receive requst pending, stop RX interrupt. */
2087         else if (0U == handle->rxDataSize)
2088         {
2089             /* Disable and re-enable the global interrupt to protect the interrupt enable register during
2090              * read-modify-wrte. */
2091             irqMask = DisableGlobalIRQ();
2092             base->CTRL &= ~(uint32_t)(LPUART_CTRL_RIE_MASK | LPUART_CTRL_ORIE_MASK | LPUART_CTRL_ILIE_MASK);
2093             EnableGlobalIRQ(irqMask);
2094         }
2095         else
2096         {
2097         }
2098     }
2099 
2100     /* Send data register empty and the interrupt is enabled. */
2101     if ((0U != ((uint32_t)kLPUART_TxDataRegEmptyFlag & status)) &&
2102         (0U != ((uint32_t)kLPUART_TxDataRegEmptyInterruptEnable & enabledInterrupts)))
2103     {
2104 /* Get the bytes that available at this moment. */
2105 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
2106         count = (uint8_t)FSL_FEATURE_LPUART_FIFO_SIZEn(base) -
2107                 (uint8_t)((base->WATER & LPUART_WATER_TXCOUNT_MASK) >> LPUART_WATER_TXCOUNT_SHIFT);
2108 #else
2109         count = 1;
2110 #endif
2111 
2112         while ((0U != handle->txDataSize) && (0U != count))
2113         {
2114 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
2115             tempCount = (uint8_t)MIN(handle->txDataSize, count);
2116 #else
2117             tempCount = 1;
2118 #endif
2119 
2120             /* Using non block API to write the data to the registers. */
2121             if (!handle->is16bitData)
2122             {
2123                 LPUART_WriteNonBlocking(base, handle->txData, tempCount);
2124                 handle->txData = &handle->txData[tempCount];
2125             }
2126             else
2127             {
2128                 LPUART_WriteNonBlocking16bit(base, handle->txData16, tempCount);
2129                 handle->txData16 = &handle->txData16[tempCount];
2130             }
2131             handle->txDataSize -= tempCount;
2132             count -= tempCount;
2133 
2134             /* If all the data are written to data register, notify user with the callback, then TX finished. */
2135             if (0U == handle->txDataSize)
2136             {
2137                 /* Disable and re-enable the global interrupt to protect the interrupt enable register during
2138                  * read-modify-wrte. */
2139                 irqMask = DisableGlobalIRQ();
2140                 /* Disable TX register empty interrupt and enable transmission completion interrupt. */
2141                 base->CTRL = (base->CTRL & ~LPUART_CTRL_TIE_MASK) | LPUART_CTRL_TCIE_MASK;
2142                 EnableGlobalIRQ(irqMask);
2143             }
2144         }
2145     }
2146 
2147     /* Transmission complete and the interrupt is enabled. */
2148     if ((0U != ((uint32_t)kLPUART_TransmissionCompleteFlag & status)) &&
2149         (0U != ((uint32_t)kLPUART_TransmissionCompleteInterruptEnable & enabledInterrupts)))
2150     {
2151         /* Set txState to idle only when all data has been sent out to bus. */
2152         handle->txState = (uint8_t)kLPUART_TxIdle;
2153 
2154         /* Disable and re-enable the global interrupt to protect the interrupt enable register during read-modify-wrte.
2155          */
2156         irqMask = DisableGlobalIRQ();
2157         /* Disable transmission complete interrupt. */
2158         base->CTRL &= ~(uint32_t)LPUART_CTRL_TCIE_MASK;
2159         EnableGlobalIRQ(irqMask);
2160 
2161         /* Trigger callback. */
2162         if (NULL != handle->callback)
2163         {
2164             handle->callback(base, handle, kStatus_LPUART_TxIdle, handle->userData);
2165         }
2166     }
2167 }
2168 
2169 /*!
2170  * brief LPUART Error IRQ handle function.
2171  *
2172  * This function handles the LPUART error IRQ request.
2173  *
2174  * param base LPUART peripheral base address.
2175  * param irqHandle LPUART handle pointer.
2176  */
LPUART_TransferHandleErrorIRQ(LPUART_Type * base,void * irqHandle)2177 void LPUART_TransferHandleErrorIRQ(LPUART_Type *base, void *irqHandle)
2178 {
2179     /* To be implemented by User. */
2180 }
2181