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