1 /*
2 * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_lpuart.h"
10
11 /*******************************************************************************
12 * Definitions
13 ******************************************************************************/
14 /* LPUART transfer state. */
15 enum _lpuart_transfer_states
16 {
17 kLPUART_TxIdle, /*!< TX idle. */
18 kLPUART_TxBusy, /*!< TX busy. */
19 kLPUART_RxIdle, /*!< RX idle. */
20 kLPUART_RxBusy /*!< RX busy. */
21 };
22
23 /* Typedef for interrupt handler. */
24 typedef void (*lpuart_isr_t)(LPUART_Type *base, lpuart_handle_t *handle);
25
26 /*******************************************************************************
27 * Prototypes
28 ******************************************************************************/
29 /*!
30 * @brief Get the LPUART instance from peripheral base address.
31 *
32 * @param base LPUART peripheral base address.
33 * @return LPUART instance.
34 */
35 uint32_t LPUART_GetInstance(LPUART_Type *base);
36
37 /*!
38 * @brief Get the length of received data in RX ring buffer.
39 *
40 * @userData handle LPUART handle pointer.
41 * @return Length of received data in RX ring buffer.
42 */
43 static size_t LPUART_TransferGetRxRingBufferLength(LPUART_Type *base, lpuart_handle_t *handle);
44
45 /*!
46 * @brief Check whether the RX ring buffer is full.
47 *
48 * @userData handle LPUART handle pointer.
49 * @retval true RX ring buffer is full.
50 * @retval false RX ring buffer is not full.
51 */
52 static bool LPUART_TransferIsRxRingBufferFull(LPUART_Type *base, lpuart_handle_t *handle);
53
54 /*!
55 * @brief Write to TX register using non-blocking method.
56 *
57 * This function writes data to the TX register directly, upper layer must make
58 * sure the TX register is empty or TX FIFO has empty room before calling this function.
59 *
60 * @note This function does not check whether all the data has been sent out to bus,
61 * so before disable TX, check kLPUART_TransmissionCompleteFlag to ensure the TX is
62 * finished.
63 *
64 * @param base LPUART peripheral base address.
65 * @param data Start addresss of the data to write.
66 * @param length Size of the buffer to be sent.
67 */
68 static void LPUART_WriteNonBlocking(LPUART_Type *base, const uint8_t *data, size_t length);
69
70 /*!
71 * @brief Read RX register using non-blocking method.
72 *
73 * This function reads data from the TX register directly, upper layer must make
74 * sure the RX register is full or TX FIFO has data before calling this function.
75 *
76 * @param base LPUART peripheral base address.
77 * @param data Start addresss of the buffer to store the received data.
78 * @param length Size of the buffer.
79 */
80 static void LPUART_ReadNonBlocking(LPUART_Type *base, uint8_t *data, size_t length);
81
82 /*******************************************************************************
83 * Variables
84 ******************************************************************************/
85 /* Array of LPUART handle. */
86 static lpuart_handle_t *s_lpuartHandle[FSL_FEATURE_SOC_LPUART_COUNT];
87 /* Array of LPUART peripheral base address. */
88 static LPUART_Type *const s_lpuartBases[] = LPUART_BASE_PTRS;
89 /* Array of LPUART IRQ number. */
90 #if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ
91 static const IRQn_Type s_lpuartRxIRQ[] = LPUART_RX_IRQS;
92 static const IRQn_Type s_lpuartTxIRQ[] = LPUART_TX_IRQS;
93 #else
94 static const IRQn_Type s_lpuartIRQ[] = LPUART_RX_TX_IRQS;
95 #endif
96 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
97 /* Array of LPUART clock name. */
98 static const clock_ip_name_t s_lpuartClock[] = LPUART_CLOCKS;
99
100 #if defined(LPUART_PERIPH_CLOCKS)
101 /* Array of LPUART functional clock name. */
102 static const clock_ip_name_t s_lpuartPeriphClocks[] = LPUART_PERIPH_CLOCKS;
103 #endif
104
105 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
106
107 /* LPUART ISR for transactional APIs. */
108 static lpuart_isr_t s_lpuartIsr;
109
110 /*******************************************************************************
111 * Code
112 ******************************************************************************/
LPUART_GetInstance(LPUART_Type * base)113 uint32_t LPUART_GetInstance(LPUART_Type *base)
114 {
115 uint32_t instance;
116
117 /* Find the instance index from base address mappings. */
118 for (instance = 0; instance < ARRAY_SIZE(s_lpuartBases); instance++)
119 {
120 if (s_lpuartBases[instance] == base)
121 {
122 break;
123 }
124 }
125
126 assert(instance < ARRAY_SIZE(s_lpuartBases));
127
128 return instance;
129 }
130
LPUART_TransferGetRxRingBufferLength(LPUART_Type * base,lpuart_handle_t * handle)131 static size_t LPUART_TransferGetRxRingBufferLength(LPUART_Type *base, lpuart_handle_t *handle)
132 {
133 assert(handle);
134
135 size_t size;
136
137 if (handle->rxRingBufferTail > handle->rxRingBufferHead)
138 {
139 size = (size_t)(handle->rxRingBufferHead + handle->rxRingBufferSize - handle->rxRingBufferTail);
140 }
141 else
142 {
143 size = (size_t)(handle->rxRingBufferHead - handle->rxRingBufferTail);
144 }
145
146 return size;
147 }
148
LPUART_TransferIsRxRingBufferFull(LPUART_Type * base,lpuart_handle_t * handle)149 static bool LPUART_TransferIsRxRingBufferFull(LPUART_Type *base, lpuart_handle_t *handle)
150 {
151 assert(handle);
152
153 bool full;
154
155 if (LPUART_TransferGetRxRingBufferLength(base, handle) == (handle->rxRingBufferSize - 1U))
156 {
157 full = true;
158 }
159 else
160 {
161 full = false;
162 }
163 return full;
164 }
165
LPUART_WriteNonBlocking(LPUART_Type * base,const uint8_t * data,size_t length)166 static void LPUART_WriteNonBlocking(LPUART_Type *base, const uint8_t *data, size_t length)
167 {
168 assert(data);
169
170 size_t i;
171
172 /* The Non Blocking write data API assume user have ensured there is enough space in
173 peripheral to write. */
174 for (i = 0; i < length; i++)
175 {
176 base->DATA = data[i];
177 }
178 }
179
LPUART_ReadNonBlocking(LPUART_Type * base,uint8_t * data,size_t length)180 static void LPUART_ReadNonBlocking(LPUART_Type *base, uint8_t *data, size_t length)
181 {
182 assert(data);
183
184 size_t i;
185 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
186 uint32_t ctrl = base->CTRL;
187 bool isSevenDataBits =
188 ((ctrl & LPUART_CTRL_M7_MASK) ||
189 ((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK)));
190 #endif
191
192 /* The Non Blocking read data API assume user have ensured there is enough space in
193 peripheral to write. */
194 for (i = 0; i < length; i++)
195 {
196 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
197 if (isSevenDataBits)
198 {
199 data[i] = (base->DATA & 0x7F);
200 }
201 else
202 {
203 data[i] = base->DATA;
204 }
205 #else
206 data[i] = base->DATA;
207 #endif
208 }
209 }
210
LPUART_Init(LPUART_Type * base,const lpuart_config_t * config,uint32_t srcClock_Hz)211 status_t LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz)
212 {
213 assert(config);
214 assert(config->baudRate_Bps);
215 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
216 assert(FSL_FEATURE_LPUART_FIFO_SIZEn(base) >= config->txFifoWatermark);
217 assert(FSL_FEATURE_LPUART_FIFO_SIZEn(base) >= config->rxFifoWatermark);
218 #endif
219
220 uint32_t temp;
221 uint16_t sbr, sbrTemp;
222 uint32_t osr, osrTemp, tempDiff, calculatedBaud, baudDiff;
223
224 /* This LPUART instantiation uses a slightly different baud rate calculation
225 * The idea is to use the best OSR (over-sampling rate) possible
226 * Note, OSR is typically hard-set to 16 in other LPUART instantiations
227 * loop to find the best OSR value possible, one that generates minimum baudDiff
228 * iterate through the rest of the supported values of OSR */
229
230 baudDiff = config->baudRate_Bps;
231 osr = 0;
232 sbr = 0;
233 for (osrTemp = 4; osrTemp <= 32; osrTemp++)
234 {
235 /* calculate the temporary sbr value */
236 sbrTemp = (srcClock_Hz / (config->baudRate_Bps * osrTemp));
237 /*set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate*/
238 if (sbrTemp == 0)
239 {
240 sbrTemp = 1;
241 }
242 /* Calculate the baud rate based on the temporary OSR and SBR values */
243 calculatedBaud = (srcClock_Hz / (osrTemp * sbrTemp));
244
245 tempDiff = calculatedBaud - config->baudRate_Bps;
246
247 /* Select the better value between srb and (sbr + 1) */
248 if (tempDiff > (config->baudRate_Bps - (srcClock_Hz / (osrTemp * (sbrTemp + 1)))))
249 {
250 tempDiff = config->baudRate_Bps - (srcClock_Hz / (osrTemp * (sbrTemp + 1)));
251 sbrTemp++;
252 }
253
254 if (tempDiff <= baudDiff)
255 {
256 baudDiff = tempDiff;
257 osr = osrTemp; /* update and store the best OSR value calculated */
258 sbr = sbrTemp; /* update store the best SBR value calculated */
259 }
260 }
261
262 /* Check to see if actual baud rate is within 3% of desired baud rate
263 * based on the best calculate OSR value */
264 if (baudDiff > ((config->baudRate_Bps / 100) * 3))
265 {
266 /* Unacceptable baud rate difference of more than 3%*/
267 return kStatus_LPUART_BaudrateNotSupport;
268 }
269
270 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
271
272 uint32_t instance = LPUART_GetInstance(base);
273
274 /* Enable lpuart clock */
275 CLOCK_EnableClock(s_lpuartClock[instance]);
276 #if defined(LPUART_PERIPH_CLOCKS)
277 CLOCK_EnableClock(s_lpuartPeriphClocks[instance]);
278 #endif
279
280 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
281
282 #if defined(FSL_FEATURE_LPUART_HAS_GLOBAL) && FSL_FEATURE_LPUART_HAS_GLOBAL
283 /*Reset all internal logic and registers, except the Global Register */
284 LPUART_SoftwareReset(base);
285 #else
286 /* Disable LPUART TX RX before setting. */
287 base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK);
288 #endif
289
290 temp = base->BAUD;
291
292 /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling.
293 * If so, then "BOTHEDGE" sampling must be turned on */
294 if ((osr > 3) && (osr < 8))
295 {
296 temp |= LPUART_BAUD_BOTHEDGE_MASK;
297 }
298
299 /* program the osr value (bit value is one less than actual value) */
300 temp &= ~LPUART_BAUD_OSR_MASK;
301 temp |= LPUART_BAUD_OSR(osr - 1);
302
303 /* write the sbr value to the BAUD registers */
304 temp &= ~LPUART_BAUD_SBR_MASK;
305 base->BAUD = temp | LPUART_BAUD_SBR(sbr);
306
307 /* Set bit count and parity mode. */
308 base->BAUD &= ~LPUART_BAUD_M10_MASK;
309
310 temp = base->CTRL &
311 ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK | LPUART_CTRL_ILT_MASK |
312 LPUART_CTRL_IDLECFG_MASK);
313
314 temp |=
315 (uint8_t)config->parityMode | LPUART_CTRL_IDLECFG(config->rxIdleConfig) | LPUART_CTRL_ILT(config->rxIdleType);
316
317 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
318 if (kLPUART_SevenDataBits == config->dataBitsCount)
319 {
320 if (kLPUART_ParityDisabled != config->parityMode)
321 {
322 temp &= ~LPUART_CTRL_M7_MASK; /* Seven data bits and one parity bit */
323 }
324 else
325 {
326 temp |= LPUART_CTRL_M7_MASK;
327 }
328 }
329 else
330 #endif
331 {
332 if (kLPUART_ParityDisabled != config->parityMode)
333 {
334 temp |= LPUART_CTRL_M_MASK; /* Eight data bits and one parity bit */
335 }
336 }
337
338 base->CTRL = temp;
339
340 #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT
341 /* set stop bit per char */
342 temp = base->BAUD & ~LPUART_BAUD_SBNS_MASK;
343 base->BAUD = temp | LPUART_BAUD_SBNS((uint8_t)config->stopBitCount);
344 #endif
345
346 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
347 /* Set tx/rx WATER watermark
348 Note:
349 Take care of the RX FIFO, RX interrupt request only assert when received bytes
350 equal or more than RX water mark, there is potential issue if RX water
351 mark larger than 1.
352 For example, if RX FIFO water mark is 2, upper layer needs 5 bytes and
353 5 bytes are received. the last byte will be saved in FIFO but not trigger
354 RX interrupt because the water mark is 2.
355 */
356 base->WATER = (((uint32_t)(config->rxFifoWatermark) << 16) | config->txFifoWatermark);
357
358 /* Enable tx/rx FIFO */
359 base->FIFO |= (LPUART_FIFO_TXFE_MASK | LPUART_FIFO_RXFE_MASK);
360
361 /* Flush FIFO */
362 base->FIFO |= (LPUART_FIFO_TXFLUSH_MASK | LPUART_FIFO_RXFLUSH_MASK);
363 #endif
364
365 /* Clear all status flags */
366 temp = (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK |
367 LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK);
368
369 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
370 temp |= LPUART_STAT_LBKDIF_MASK;
371 #endif
372
373 #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING
374 temp |= (LPUART_STAT_MA1F_MASK | LPUART_STAT_MA2F_MASK);
375 #endif
376
377 #if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT
378 /* Set the CTS configuration/TX CTS source. */
379 base->MODIR |= LPUART_MODIR_TXCTSC(config->txCtsConfig) | LPUART_MODIR_TXCTSSRC(config->txCtsSource);
380 if (config->enableRxRTS)
381 {
382 /* Enable the receiver RTS(request-to-send) function. */
383 base->MODIR |= LPUART_MODIR_RXRTSE_MASK;
384 }
385 if (config->enableTxCTS)
386 {
387 /* Enable the CTS(clear-to-send) function. */
388 base->MODIR |= LPUART_MODIR_TXCTSE_MASK;
389 }
390 #endif
391
392 /* Set data bits order. */
393 if (config->isMsb)
394 {
395 temp |= LPUART_STAT_MSBF_MASK;
396 }
397 else
398 {
399 temp &= ~LPUART_STAT_MSBF_MASK;
400 }
401
402 base->STAT |= temp;
403
404 /* Enable TX/RX base on configure structure. */
405 temp = base->CTRL;
406 if (config->enableTx)
407 {
408 temp |= LPUART_CTRL_TE_MASK;
409 }
410
411 if (config->enableRx)
412 {
413 temp |= LPUART_CTRL_RE_MASK;
414 }
415
416 base->CTRL = temp;
417
418 return kStatus_Success;
419 }
LPUART_Deinit(LPUART_Type * base)420 void LPUART_Deinit(LPUART_Type *base)
421 {
422 uint32_t temp;
423
424 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
425 /* Wait tx FIFO send out*/
426 while (0 != ((base->WATER & LPUART_WATER_TXCOUNT_MASK) >> LPUART_WATER_TXWATER_SHIFT))
427 {
428 }
429 #endif
430 /* Wait last char shoft out */
431 while (0 == (base->STAT & LPUART_STAT_TC_MASK))
432 {
433 }
434
435 /* Clear all status flags */
436 temp = (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK |
437 LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK);
438
439 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
440 temp |= LPUART_STAT_LBKDIF_MASK;
441 #endif
442
443 #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING
444 temp |= (LPUART_STAT_MA1F_MASK | LPUART_STAT_MA2F_MASK);
445 #endif
446
447 base->STAT |= temp;
448
449 /* Disable the module. */
450 base->CTRL = 0;
451
452 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
453 uint32_t instance = LPUART_GetInstance(base);
454
455 /* Disable lpuart clock */
456 CLOCK_DisableClock(s_lpuartClock[instance]);
457
458 #if defined(LPUART_PERIPH_CLOCKS)
459 CLOCK_DisableClock(s_lpuartPeriphClocks[instance]);
460 #endif
461
462 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
463 }
464
LPUART_GetDefaultConfig(lpuart_config_t * config)465 void LPUART_GetDefaultConfig(lpuart_config_t *config)
466 {
467 assert(config);
468
469 config->baudRate_Bps = 115200U;
470 config->parityMode = kLPUART_ParityDisabled;
471 config->dataBitsCount = kLPUART_EightDataBits;
472 config->isMsb = false;
473 #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT
474 config->stopBitCount = kLPUART_OneStopBit;
475 #endif
476 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
477 config->txFifoWatermark = 0;
478 config->rxFifoWatermark = 0;
479 #endif
480 #if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT
481 config->enableRxRTS = false;
482 config->enableTxCTS = false;
483 config->txCtsConfig = kLPUART_CtsSampleAtStart;
484 config->txCtsSource = kLPUART_CtsSourcePin;
485 #endif
486 config->rxIdleType = kLPUART_IdleTypeStartBit;
487 config->rxIdleConfig = kLPUART_IdleCharacter1;
488 config->enableTx = false;
489 config->enableRx = false;
490 }
491
LPUART_SetBaudRate(LPUART_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz)492 status_t LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
493 {
494 assert(baudRate_Bps);
495
496 uint32_t temp, oldCtrl;
497 uint16_t sbr, sbrTemp;
498 uint32_t osr, osrTemp, tempDiff, calculatedBaud, baudDiff;
499
500 /* This LPUART instantiation uses a slightly different baud rate calculation
501 * The idea is to use the best OSR (over-sampling rate) possible
502 * Note, OSR is typically hard-set to 16 in other LPUART instantiations
503 * loop to find the best OSR value possible, one that generates minimum baudDiff
504 * iterate through the rest of the supported values of OSR */
505
506 baudDiff = baudRate_Bps;
507 osr = 0;
508 sbr = 0;
509 for (osrTemp = 4; osrTemp <= 32; osrTemp++)
510 {
511 /* calculate the temporary sbr value */
512 sbrTemp = (srcClock_Hz / (baudRate_Bps * osrTemp));
513 /*set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate*/
514 if (sbrTemp == 0)
515 {
516 sbrTemp = 1;
517 }
518 /* Calculate the baud rate based on the temporary OSR and SBR values */
519 calculatedBaud = (srcClock_Hz / (osrTemp * sbrTemp));
520
521 tempDiff = calculatedBaud - baudRate_Bps;
522
523 /* Select the better value between srb and (sbr + 1) */
524 if (tempDiff > (baudRate_Bps - (srcClock_Hz / (osrTemp * (sbrTemp + 1)))))
525 {
526 tempDiff = baudRate_Bps - (srcClock_Hz / (osrTemp * (sbrTemp + 1)));
527 sbrTemp++;
528 }
529
530 if (tempDiff <= baudDiff)
531 {
532 baudDiff = tempDiff;
533 osr = osrTemp; /* update and store the best OSR value calculated */
534 sbr = sbrTemp; /* update store the best SBR value calculated */
535 }
536 }
537
538 /* Check to see if actual baud rate is within 3% of desired baud rate
539 * based on the best calculate OSR value */
540 if (baudDiff < ((baudRate_Bps / 100) * 3))
541 {
542 /* Store CTRL before disable Tx and Rx */
543 oldCtrl = base->CTRL;
544
545 /* Disable LPUART TX RX before setting. */
546 base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK);
547
548 temp = base->BAUD;
549
550 /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling.
551 * If so, then "BOTHEDGE" sampling must be turned on */
552 if ((osr > 3) && (osr < 8))
553 {
554 temp |= LPUART_BAUD_BOTHEDGE_MASK;
555 }
556
557 /* program the osr value (bit value is one less than actual value) */
558 temp &= ~LPUART_BAUD_OSR_MASK;
559 temp |= LPUART_BAUD_OSR(osr - 1);
560
561 /* write the sbr value to the BAUD registers */
562 temp &= ~LPUART_BAUD_SBR_MASK;
563 base->BAUD = temp | LPUART_BAUD_SBR(sbr);
564
565 /* Restore CTRL. */
566 base->CTRL = oldCtrl;
567
568 return kStatus_Success;
569 }
570 else
571 {
572 /* Unacceptable baud rate difference of more than 3%*/
573 return kStatus_LPUART_BaudrateNotSupport;
574 }
575 }
576
LPUART_EnableInterrupts(LPUART_Type * base,uint32_t mask)577 void LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask)
578 {
579 base->BAUD |= ((mask << 8) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK));
580 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
581 base->FIFO = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) |
582 ((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK));
583 #endif
584 mask &= 0xFFFFFF00U;
585 base->CTRL |= mask;
586 }
587
LPUART_DisableInterrupts(LPUART_Type * base,uint32_t mask)588 void LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask)
589 {
590 base->BAUD &= ~((mask << 8) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK));
591 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
592 base->FIFO = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) &
593 ~((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK));
594 #endif
595 mask &= 0xFFFFFF00U;
596 base->CTRL &= ~mask;
597 }
598
LPUART_GetEnabledInterrupts(LPUART_Type * base)599 uint32_t LPUART_GetEnabledInterrupts(LPUART_Type *base)
600 {
601 uint32_t temp;
602 temp = (base->BAUD & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK)) >> 8;
603 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
604 temp |= (base->FIFO & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)) >> 8;
605 #endif
606 temp |= (base->CTRL & 0xFF0C000);
607
608 return temp;
609 }
610
LPUART_GetStatusFlags(LPUART_Type * base)611 uint32_t LPUART_GetStatusFlags(LPUART_Type *base)
612 {
613 uint32_t temp;
614 temp = base->STAT;
615 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
616 temp |= (base->FIFO &
617 (LPUART_FIFO_TXEMPT_MASK | LPUART_FIFO_RXEMPT_MASK | LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) >>
618 16;
619 #endif
620 return temp;
621 }
622
LPUART_ClearStatusFlags(LPUART_Type * base,uint32_t mask)623 status_t LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask)
624 {
625 uint32_t temp;
626 status_t status;
627 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
628 temp = (uint32_t)base->FIFO;
629 temp &= (uint32_t)(~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK));
630 temp |= (mask << 16) & (LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK);
631 base->FIFO = temp;
632 #endif
633 temp = (uint32_t)base->STAT;
634 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
635 temp &= (uint32_t)(~(LPUART_STAT_LBKDIF_MASK));
636 temp |= mask & LPUART_STAT_LBKDIF_MASK;
637 #endif
638 temp &= (uint32_t)(~(LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK |
639 LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK));
640 temp |= mask & (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK |
641 LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK);
642 #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING
643 temp &= (uint32_t)(~(LPUART_STAT_MA2F_MASK | LPUART_STAT_MA1F_MASK));
644 temp |= mask & (LPUART_STAT_MA2F_MASK | LPUART_STAT_MA1F_MASK);
645 #endif
646 base->STAT = temp;
647 /* If some flags still pending. */
648 if (mask & LPUART_GetStatusFlags(base))
649 {
650 /* Some flags can only clear or set by the hardware itself, these flags are: kLPUART_TxDataRegEmptyFlag,
651 kLPUART_TransmissionCompleteFlag, kLPUART_RxDataRegFullFlag, kLPUART_RxActiveFlag,
652 kLPUART_NoiseErrorInRxDataRegFlag, kLPUART_ParityErrorInRxDataRegFlag,
653 kLPUART_TxFifoEmptyFlag, kLPUART_RxFifoEmptyFlag. */
654 status = kStatus_LPUART_FlagCannotClearManually; /* flags can not clear manually */
655 }
656 else
657 {
658 status = kStatus_Success;
659 }
660
661 return status;
662 }
663
LPUART_WriteBlocking(LPUART_Type * base,const uint8_t * data,size_t length)664 void LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length)
665 {
666 assert(data);
667
668 /* This API can only ensure that the data is written into the data buffer but can't
669 ensure all data in the data buffer are sent into the transmit shift buffer. */
670 while (length--)
671 {
672 while (!(base->STAT & LPUART_STAT_TDRE_MASK))
673 {
674 }
675 base->DATA = *(data++);
676 }
677 }
678
LPUART_ReadBlocking(LPUART_Type * base,uint8_t * data,size_t length)679 status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length)
680 {
681 assert(data);
682
683 uint32_t statusFlag;
684 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
685 uint32_t ctrl = base->CTRL;
686 bool isSevenDataBits =
687 ((ctrl & LPUART_CTRL_M7_MASK) ||
688 ((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK)));
689 #endif
690
691 while (length--)
692 {
693 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
694 while (0 == ((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT))
695 #else
696 while (!(base->STAT & LPUART_STAT_RDRF_MASK))
697 #endif
698 {
699 statusFlag = LPUART_GetStatusFlags(base);
700
701 if (statusFlag & kLPUART_RxOverrunFlag)
702 {
703 LPUART_ClearStatusFlags(base, kLPUART_RxOverrunFlag);
704 return kStatus_LPUART_RxHardwareOverrun;
705 }
706
707 if (statusFlag & kLPUART_NoiseErrorFlag)
708 {
709 LPUART_ClearStatusFlags(base, kLPUART_NoiseErrorFlag);
710 return kStatus_LPUART_NoiseError;
711 }
712
713 if (statusFlag & kLPUART_FramingErrorFlag)
714 {
715 LPUART_ClearStatusFlags(base, kLPUART_FramingErrorFlag);
716 return kStatus_LPUART_FramingError;
717 }
718
719 if (statusFlag & kLPUART_ParityErrorFlag)
720 {
721 LPUART_ClearStatusFlags(base, kLPUART_ParityErrorFlag);
722 return kStatus_LPUART_ParityError;
723 }
724 }
725 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
726 if (isSevenDataBits)
727 {
728 *(data++) = (base->DATA & 0x7F);
729 }
730 else
731 {
732 *(data++) = base->DATA;
733 }
734 #else
735 *(data++) = base->DATA;
736 #endif
737 }
738
739 return kStatus_Success;
740 }
741
LPUART_TransferCreateHandle(LPUART_Type * base,lpuart_handle_t * handle,lpuart_transfer_callback_t callback,void * userData)742 void LPUART_TransferCreateHandle(LPUART_Type *base,
743 lpuart_handle_t *handle,
744 lpuart_transfer_callback_t callback,
745 void *userData)
746 {
747 assert(handle);
748
749 uint32_t instance;
750 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
751 uint32_t ctrl = base->CTRL;
752 bool isSevenDataBits =
753 ((ctrl & LPUART_CTRL_M7_MASK) ||
754 ((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK)));
755 #endif
756
757 /* Zero the handle. */
758 memset(handle, 0, sizeof(lpuart_handle_t));
759
760 /* Set the TX/RX state. */
761 handle->rxState = kLPUART_RxIdle;
762 handle->txState = kLPUART_TxIdle;
763
764 /* Set the callback and user data. */
765 handle->callback = callback;
766 handle->userData = userData;
767
768 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
769 /* Initial seven data bits flag */
770 handle->isSevenDataBits = isSevenDataBits;
771 #endif
772
773 /* Get instance from peripheral base address. */
774 instance = LPUART_GetInstance(base);
775
776 /* Save the handle in global variables to support the double weak mechanism. */
777 s_lpuartHandle[instance] = handle;
778
779 s_lpuartIsr = LPUART_TransferHandleIRQ;
780
781 /* Enable interrupt in NVIC. */
782 #if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ
783 EnableIRQ(s_lpuartRxIRQ[instance]);
784 EnableIRQ(s_lpuartTxIRQ[instance]);
785 #else
786 EnableIRQ(s_lpuartIRQ[instance]);
787 #endif
788 }
789
LPUART_TransferStartRingBuffer(LPUART_Type * base,lpuart_handle_t * handle,uint8_t * ringBuffer,size_t ringBufferSize)790 void LPUART_TransferStartRingBuffer(LPUART_Type *base,
791 lpuart_handle_t *handle,
792 uint8_t *ringBuffer,
793 size_t ringBufferSize)
794 {
795 assert(handle);
796 assert(ringBuffer);
797
798 /* Setup the ring buffer address */
799 handle->rxRingBuffer = ringBuffer;
800 handle->rxRingBufferSize = ringBufferSize;
801 handle->rxRingBufferHead = 0U;
802 handle->rxRingBufferTail = 0U;
803
804 /* Enable the interrupt to accept the data when user need the ring buffer. */
805 LPUART_EnableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable);
806 }
807
LPUART_TransferStopRingBuffer(LPUART_Type * base,lpuart_handle_t * handle)808 void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle)
809 {
810 assert(handle);
811
812 if (handle->rxState == kLPUART_RxIdle)
813 {
814 LPUART_DisableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable);
815 }
816
817 handle->rxRingBuffer = NULL;
818 handle->rxRingBufferSize = 0U;
819 handle->rxRingBufferHead = 0U;
820 handle->rxRingBufferTail = 0U;
821 }
822
LPUART_TransferSendNonBlocking(LPUART_Type * base,lpuart_handle_t * handle,lpuart_transfer_t * xfer)823 status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_t *xfer)
824 {
825 assert(handle);
826 assert(xfer);
827 assert(xfer->data);
828 assert(xfer->dataSize);
829
830 status_t status;
831
832 /* Return error if current TX busy. */
833 if (kLPUART_TxBusy == handle->txState)
834 {
835 status = kStatus_LPUART_TxBusy;
836 }
837 else
838 {
839 handle->txData = xfer->data;
840 handle->txDataSize = xfer->dataSize;
841 handle->txDataSizeAll = xfer->dataSize;
842 handle->txState = kLPUART_TxBusy;
843
844 /* Enable transmiter interrupt. */
845 LPUART_EnableInterrupts(base, kLPUART_TxDataRegEmptyInterruptEnable);
846
847 status = kStatus_Success;
848 }
849
850 return status;
851 }
852
LPUART_TransferAbortSend(LPUART_Type * base,lpuart_handle_t * handle)853 void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle)
854 {
855 assert(handle);
856
857 LPUART_DisableInterrupts(base, kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_TransmissionCompleteInterruptEnable);
858
859 handle->txDataSize = 0;
860 handle->txState = kLPUART_TxIdle;
861 }
862
LPUART_TransferGetSendCount(LPUART_Type * base,lpuart_handle_t * handle,uint32_t * count)863 status_t LPUART_TransferGetSendCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count)
864 {
865 assert(handle);
866 assert(count);
867
868 if (kLPUART_TxIdle == handle->txState)
869 {
870 return kStatus_NoTransferInProgress;
871 }
872
873 *count = handle->txDataSizeAll - handle->txDataSize;
874
875 return kStatus_Success;
876 }
877
LPUART_TransferReceiveNonBlocking(LPUART_Type * base,lpuart_handle_t * handle,lpuart_transfer_t * xfer,size_t * receivedBytes)878 status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base,
879 lpuart_handle_t *handle,
880 lpuart_transfer_t *xfer,
881 size_t *receivedBytes)
882 {
883 assert(handle);
884 assert(xfer);
885 assert(xfer->data);
886 assert(xfer->dataSize);
887
888 uint32_t i;
889 status_t status;
890 /* How many bytes to copy from ring buffer to user memory. */
891 size_t bytesToCopy = 0U;
892 /* How many bytes to receive. */
893 size_t bytesToReceive;
894 /* How many bytes currently have received. */
895 size_t bytesCurrentReceived;
896
897 /* How to get data:
898 1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize
899 to lpuart handle, enable interrupt to store received data to xfer->data. When
900 all data received, trigger callback.
901 2. If RX ring buffer is enabled and not empty, get data from ring buffer first.
902 If there are enough data in ring buffer, copy them to xfer->data and return.
903 If there are not enough data in ring buffer, copy all of them to xfer->data,
904 save the xfer->data remained empty space to lpuart handle, receive data
905 to this empty space and trigger callback when finished. */
906
907 if (kLPUART_RxBusy == handle->rxState)
908 {
909 status = kStatus_LPUART_RxBusy;
910 }
911 else
912 {
913 bytesToReceive = xfer->dataSize;
914 bytesCurrentReceived = 0;
915
916 /* If RX ring buffer is used. */
917 if (handle->rxRingBuffer)
918 {
919 /* Disable LPUART RX IRQ, protect ring buffer. */
920 LPUART_DisableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable);
921
922 /* How many bytes in RX ring buffer currently. */
923 bytesToCopy = LPUART_TransferGetRxRingBufferLength(base, handle);
924
925 if (bytesToCopy)
926 {
927 bytesToCopy = MIN(bytesToReceive, bytesToCopy);
928
929 bytesToReceive -= bytesToCopy;
930
931 /* Copy data from ring buffer to user memory. */
932 for (i = 0U; i < bytesToCopy; i++)
933 {
934 xfer->data[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];
935
936 /* Wrap to 0. Not use modulo (%) because it might be large and slow. */
937 if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
938 {
939 handle->rxRingBufferTail = 0U;
940 }
941 else
942 {
943 handle->rxRingBufferTail++;
944 }
945 }
946 }
947
948 /* If ring buffer does not have enough data, still need to read more data. */
949 if (bytesToReceive)
950 {
951 /* No data in ring buffer, save the request to LPUART handle. */
952 handle->rxData = xfer->data + bytesCurrentReceived;
953 handle->rxDataSize = bytesToReceive;
954 handle->rxDataSizeAll = bytesToReceive;
955 handle->rxState = kLPUART_RxBusy;
956 }
957 /* Enable LPUART RX IRQ if previously enabled. */
958 LPUART_EnableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable);
959
960 /* Call user callback since all data are received. */
961 if (0 == bytesToReceive)
962 {
963 if (handle->callback)
964 {
965 handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData);
966 }
967 }
968 }
969 /* Ring buffer not used. */
970 else
971 {
972 handle->rxData = xfer->data + bytesCurrentReceived;
973 handle->rxDataSize = bytesToReceive;
974 handle->rxDataSizeAll = bytesToReceive;
975 handle->rxState = kLPUART_RxBusy;
976
977 /* Enable RX interrupt. */
978 LPUART_EnableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable |
979 kLPUART_IdleLineInterruptEnable);
980 }
981
982 /* Return the how many bytes have read. */
983 if (receivedBytes)
984 {
985 *receivedBytes = bytesCurrentReceived;
986 }
987
988 status = kStatus_Success;
989 }
990
991 return status;
992 }
993
LPUART_TransferAbortReceive(LPUART_Type * base,lpuart_handle_t * handle)994 void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle)
995 {
996 assert(handle);
997
998 /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
999 if (!handle->rxRingBuffer)
1000 {
1001 /* Disable RX interrupt. */
1002 LPUART_DisableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable |
1003 kLPUART_IdleLineInterruptEnable);
1004 }
1005
1006 handle->rxDataSize = 0U;
1007 handle->rxState = kLPUART_RxIdle;
1008 }
1009
LPUART_TransferGetReceiveCount(LPUART_Type * base,lpuart_handle_t * handle,uint32_t * count)1010 status_t LPUART_TransferGetReceiveCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count)
1011 {
1012 assert(handle);
1013 assert(count);
1014
1015 if (kLPUART_RxIdle == handle->rxState)
1016 {
1017 return kStatus_NoTransferInProgress;
1018 }
1019
1020 *count = handle->rxDataSizeAll - handle->rxDataSize;
1021
1022 return kStatus_Success;
1023 }
1024
LPUART_TransferHandleIRQ(LPUART_Type * base,lpuart_handle_t * handle)1025 void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle)
1026 {
1027 assert(handle);
1028
1029 uint8_t count;
1030 uint8_t tempCount;
1031
1032 /* If RX overrun. */
1033 if (LPUART_STAT_OR_MASK & base->STAT)
1034 {
1035 /* Clear overrun flag, otherwise the RX does not work. */
1036 base->STAT = ((base->STAT & 0x3FE00000U) | LPUART_STAT_OR_MASK);
1037
1038 /* Trigger callback. */
1039 if (handle->callback)
1040 {
1041 handle->callback(base, handle, kStatus_LPUART_RxHardwareOverrun, handle->userData);
1042 }
1043 }
1044
1045 /* If IDLE flag is set and the IDLE interrupt is enabled. */
1046 if ((LPUART_STAT_IDLE_MASK & base->STAT) && (LPUART_CTRL_ILIE_MASK & base->CTRL))
1047 {
1048 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
1049 count = ((uint8_t)((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT));
1050
1051 while ((count) && (handle->rxDataSize))
1052 {
1053 tempCount = MIN(handle->rxDataSize, count);
1054
1055 /* Using non block API to read the data from the registers. */
1056 LPUART_ReadNonBlocking(base, handle->rxData, tempCount);
1057 handle->rxData += tempCount;
1058 handle->rxDataSize -= tempCount;
1059 count -= tempCount;
1060
1061 /* If rxDataSize is 0, disable idle line interrupt.*/
1062 if (!(handle->rxDataSize))
1063 {
1064 handle->rxState = kLPUART_RxIdle;
1065
1066 LPUART_DisableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable);
1067 if (handle->callback)
1068 {
1069 handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData);
1070 }
1071 }
1072 }
1073 #endif
1074 /* Clear IDLE flag.*/
1075 base->STAT |= LPUART_STAT_IDLE_MASK;
1076
1077 /* If rxDataSize is 0, disable idle line interrupt.*/
1078 if (!(handle->rxDataSize))
1079 {
1080 LPUART_DisableInterrupts(base, kLPUART_IdleLineInterruptEnable);
1081 }
1082 /* If callback is not NULL and rxDataSize is not 0. */
1083 if ((handle->callback) && (handle->rxDataSize))
1084 {
1085 handle->callback(base, handle, kStatus_LPUART_IdleLineDetected, handle->userData);
1086 }
1087 }
1088 /* Receive data register full */
1089 if ((LPUART_STAT_RDRF_MASK & base->STAT) && (LPUART_CTRL_RIE_MASK & base->CTRL))
1090 {
1091 /* Get the size that can be stored into buffer for this interrupt. */
1092 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
1093 count = ((uint8_t)((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT));
1094 #else
1095 count = 1;
1096 #endif
1097
1098 /* If handle->rxDataSize is not 0, first save data to handle->rxData. */
1099 while ((count) && (handle->rxDataSize))
1100 {
1101 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
1102 tempCount = MIN(handle->rxDataSize, count);
1103 #else
1104 tempCount = 1;
1105 #endif
1106
1107 /* Using non block API to read the data from the registers. */
1108 LPUART_ReadNonBlocking(base, handle->rxData, tempCount);
1109 handle->rxData += tempCount;
1110 handle->rxDataSize -= tempCount;
1111 count -= tempCount;
1112
1113 /* If all the data required for upper layer is ready, trigger callback. */
1114 if (!handle->rxDataSize)
1115 {
1116 handle->rxState = kLPUART_RxIdle;
1117
1118 if (handle->callback)
1119 {
1120 handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData);
1121 }
1122 }
1123 }
1124
1125 /* If use RX ring buffer, receive data to ring buffer. */
1126 if (handle->rxRingBuffer)
1127 {
1128 while (count--)
1129 {
1130 /* If RX ring buffer is full, trigger callback to notify over run. */
1131 if (LPUART_TransferIsRxRingBufferFull(base, handle))
1132 {
1133 if (handle->callback)
1134 {
1135 handle->callback(base, handle, kStatus_LPUART_RxRingBufferOverrun, handle->userData);
1136 }
1137 }
1138
1139 /* If ring buffer is still full after callback function, the oldest data is overrided. */
1140 if (LPUART_TransferIsRxRingBufferFull(base, handle))
1141 {
1142 /* Increase handle->rxRingBufferTail to make room for new data. */
1143 if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
1144 {
1145 handle->rxRingBufferTail = 0U;
1146 }
1147 else
1148 {
1149 handle->rxRingBufferTail++;
1150 }
1151 }
1152
1153 /* Read data. */
1154 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
1155 if (handle->isSevenDataBits)
1156 {
1157 handle->rxRingBuffer[handle->rxRingBufferHead] = (base->DATA & 0x7F);
1158 }
1159 else
1160 {
1161 handle->rxRingBuffer[handle->rxRingBufferHead] = base->DATA;
1162 }
1163 #else
1164 handle->rxRingBuffer[handle->rxRingBufferHead] = base->DATA;
1165 #endif
1166
1167 /* Increase handle->rxRingBufferHead. */
1168 if (handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
1169 {
1170 handle->rxRingBufferHead = 0U;
1171 }
1172 else
1173 {
1174 handle->rxRingBufferHead++;
1175 }
1176 }
1177 }
1178 /* If no receive requst pending, stop RX interrupt. */
1179 else if (!handle->rxDataSize)
1180 {
1181 LPUART_DisableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable);
1182 }
1183 else
1184 {
1185 }
1186 }
1187
1188 /* Send data register empty and the interrupt is enabled. */
1189 if ((base->STAT & LPUART_STAT_TDRE_MASK) && (base->CTRL & LPUART_CTRL_TIE_MASK))
1190 {
1191 /* Get the bytes that available at this moment. */
1192 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
1193 count = FSL_FEATURE_LPUART_FIFO_SIZEn(base) -
1194 ((base->WATER & LPUART_WATER_TXCOUNT_MASK) >> LPUART_WATER_TXCOUNT_SHIFT);
1195 #else
1196 count = 1;
1197 #endif
1198
1199 while ((count) && (handle->txDataSize))
1200 {
1201 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
1202 tempCount = MIN(handle->txDataSize, count);
1203 #else
1204 tempCount = 1;
1205 #endif
1206
1207 /* Using non block API to write the data to the registers. */
1208 LPUART_WriteNonBlocking(base, handle->txData, tempCount);
1209 handle->txData += tempCount;
1210 handle->txDataSize -= tempCount;
1211 count -= tempCount;
1212
1213 /* If all the data are written to data register, notify user with the callback, then TX finished. */
1214 if (!handle->txDataSize)
1215 {
1216 handle->txState = kLPUART_TxIdle;
1217
1218 /* Disable TX register empty interrupt. */
1219 base->CTRL = (base->CTRL & ~LPUART_CTRL_TIE_MASK);
1220
1221 /* Trigger callback. */
1222 if (handle->callback)
1223 {
1224 handle->callback(base, handle, kStatus_LPUART_TxIdle, handle->userData);
1225 }
1226 }
1227 }
1228 }
1229 }
1230
LPUART_TransferHandleErrorIRQ(LPUART_Type * base,lpuart_handle_t * handle)1231 void LPUART_TransferHandleErrorIRQ(LPUART_Type *base, lpuart_handle_t *handle)
1232 {
1233 /* To be implemented by User. */
1234 }
1235 #if defined(FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1) && FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1
1236 #if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ
LPUART0_LPUART1_RX_DriverIRQHandler(void)1237 void LPUART0_LPUART1_RX_DriverIRQHandler(void)
1238 {
1239 if (CLOCK_isEnabledClock(s_lpuartClock[0]))
1240 {
1241 if ((LPUART_STAT_OR_MASK & LPUART0->STAT) ||
1242 ((LPUART_STAT_RDRF_MASK & LPUART0->STAT) && (LPUART_CTRL_RIE_MASK & LPUART0->CTRL)))
1243 {
1244 s_lpuartIsr(LPUART0, s_lpuartHandle[0]);
1245 }
1246 }
1247 if (CLOCK_isEnabledClock(s_lpuartClock[1]))
1248 {
1249 if ((LPUART_STAT_OR_MASK & LPUART1->STAT) ||
1250 ((LPUART_STAT_RDRF_MASK & LPUART1->STAT) && (LPUART_CTRL_RIE_MASK & LPUART1->CTRL)))
1251 {
1252 s_lpuartIsr(LPUART1, s_lpuartHandle[1]);
1253 }
1254 }
1255 }
LPUART0_LPUART1_TX_DriverIRQHandler(void)1256 void LPUART0_LPUART1_TX_DriverIRQHandler(void)
1257 {
1258 if (CLOCK_isEnabledClock(s_lpuartClock[0]))
1259 {
1260 if ((LPUART_STAT_OR_MASK & LPUART0->STAT) ||
1261 ((LPUART0->STAT & LPUART_STAT_TDRE_MASK) && (LPUART0->CTRL & LPUART_CTRL_TIE_MASK)))
1262 {
1263 s_lpuartIsr(LPUART0, s_lpuartHandle[0]);
1264 }
1265 }
1266 if (CLOCK_isEnabledClock(s_lpuartClock[1]))
1267 {
1268 if ((LPUART_STAT_OR_MASK & LPUART1->STAT) ||
1269 ((LPUART1->STAT & LPUART_STAT_TDRE_MASK) && (LPUART1->CTRL & LPUART_CTRL_TIE_MASK)))
1270 {
1271 s_lpuartIsr(LPUART1, s_lpuartHandle[1]);
1272 }
1273 }
1274 }
1275 #else
LPUART0_LPUART1_DriverIRQHandler(void)1276 void LPUART0_LPUART1_DriverIRQHandler(void)
1277 {
1278 if (CLOCK_isEnabledClock(s_lpuartClock[0]))
1279 {
1280 if ((LPUART_STAT_OR_MASK & LPUART0->STAT) ||
1281 ((LPUART_STAT_RDRF_MASK & LPUART0->STAT) && (LPUART_CTRL_RIE_MASK & LPUART0->CTRL)) ||
1282 ((LPUART0->STAT & LPUART_STAT_TDRE_MASK) && (LPUART0->CTRL & LPUART_CTRL_TIE_MASK)))
1283 {
1284 s_lpuartIsr(LPUART0, s_lpuartHandle[0]);
1285 }
1286 }
1287 if (CLOCK_isEnabledClock(s_lpuartClock[1]))
1288 {
1289 if ((LPUART_STAT_OR_MASK & LPUART1->STAT) ||
1290 ((LPUART_STAT_RDRF_MASK & LPUART1->STAT) && (LPUART_CTRL_RIE_MASK & LPUART1->CTRL)) ||
1291 ((LPUART1->STAT & LPUART_STAT_TDRE_MASK) && (LPUART1->CTRL & LPUART_CTRL_TIE_MASK)))
1292 {
1293 s_lpuartIsr(LPUART1, s_lpuartHandle[1]);
1294 }
1295 }
1296 }
1297 #endif
1298 #endif
1299
1300 #if defined(LPUART0)
1301 #if !(defined(FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1) && FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1)
1302 #if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ
LPUART0_TX_DriverIRQHandler(void)1303 void LPUART0_TX_DriverIRQHandler(void)
1304 {
1305 s_lpuartIsr(LPUART0, s_lpuartHandle[0]);
1306 }
LPUART0_RX_DriverIRQHandler(void)1307 void LPUART0_RX_DriverIRQHandler(void)
1308 {
1309 s_lpuartIsr(LPUART0, s_lpuartHandle[0]);
1310 }
1311 #else
LPUART0_DriverIRQHandler(void)1312 void LPUART0_DriverIRQHandler(void)
1313 {
1314 s_lpuartIsr(LPUART0, s_lpuartHandle[0]);
1315 }
1316 #endif
1317 #endif
1318 #endif
1319
1320 #if defined(LPUART1)
1321 #if !(defined(FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1) && FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1)
1322 #if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ
LPUART1_TX_DriverIRQHandler(void)1323 void LPUART1_TX_DriverIRQHandler(void)
1324 {
1325 s_lpuartIsr(LPUART1, s_lpuartHandle[1]);
1326 }
LPUART1_RX_DriverIRQHandler(void)1327 void LPUART1_RX_DriverIRQHandler(void)
1328 {
1329 s_lpuartIsr(LPUART1, s_lpuartHandle[1]);
1330 }
1331 #else
LPUART1_DriverIRQHandler(void)1332 void LPUART1_DriverIRQHandler(void)
1333 {
1334 s_lpuartIsr(LPUART1, s_lpuartHandle[1]);
1335 }
1336 #endif
1337 #endif
1338 #endif
1339
1340 #if defined(LPUART2)
1341 #if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ
LPUART2_TX_DriverIRQHandler(void)1342 void LPUART2_TX_DriverIRQHandler(void)
1343 {
1344 s_lpuartIsr(LPUART2, s_lpuartHandle[2]);
1345 }
LPUART2_RX_DriverIRQHandler(void)1346 void LPUART2_RX_DriverIRQHandler(void)
1347 {
1348 s_lpuartIsr(LPUART2, s_lpuartHandle[2]);
1349 }
1350 #else
LPUART2_DriverIRQHandler(void)1351 void LPUART2_DriverIRQHandler(void)
1352 {
1353 s_lpuartIsr(LPUART2, s_lpuartHandle[2]);
1354 }
1355 #endif
1356 #endif
1357
1358 #if defined(LPUART3)
1359 #if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ
LPUART3_TX_DriverIRQHandler(void)1360 void LPUART3_TX_DriverIRQHandler(void)
1361 {
1362 s_lpuartIsr(LPUART3, s_lpuartHandle[3]);
1363 }
LPUART3_RX_DriverIRQHandler(void)1364 void LPUART3_RX_DriverIRQHandler(void)
1365 {
1366 s_lpuartIsr(LPUART3, s_lpuartHandle[3]);
1367 }
1368 #else
LPUART3_DriverIRQHandler(void)1369 void LPUART3_DriverIRQHandler(void)
1370 {
1371 s_lpuartIsr(LPUART3, s_lpuartHandle[3]);
1372 }
1373 #endif
1374 #endif
1375
1376 #if defined(LPUART4)
1377 #if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ
LPUART4_TX_DriverIRQHandler(void)1378 void LPUART4_TX_DriverIRQHandler(void)
1379 {
1380 s_lpuartIsr(LPUART4, s_lpuartHandle[4]);
1381 }
LPUART4_RX_DriverIRQHandler(void)1382 void LPUART4_RX_DriverIRQHandler(void)
1383 {
1384 s_lpuartIsr(LPUART4, s_lpuartHandle[4]);
1385 }
1386 #else
LPUART4_DriverIRQHandler(void)1387 void LPUART4_DriverIRQHandler(void)
1388 {
1389 s_lpuartIsr(LPUART4, s_lpuartHandle[4]);
1390 }
1391 #endif
1392 #endif
1393
1394 #if defined(LPUART5)
1395 #if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ
LPUART5_TX_DriverIRQHandler(void)1396 void LPUART5_TX_DriverIRQHandler(void)
1397 {
1398 s_lpuartIsr(LPUART5, s_lpuartHandle[5]);
1399 }
LPUART5_RX_DriverIRQHandler(void)1400 void LPUART5_RX_DriverIRQHandler(void)
1401 {
1402 s_lpuartIsr(LPUART5, s_lpuartHandle[5]);
1403 }
1404 #else
LPUART5_DriverIRQHandler(void)1405 void LPUART5_DriverIRQHandler(void)
1406 {
1407 s_lpuartIsr(LPUART5, s_lpuartHandle[5]);
1408 }
1409 #endif
1410 #endif
1411
1412 #if defined(CM4_0_LPUART)
M4_0_LPUART_DriverIRQHandler(void)1413 void M4_0_LPUART_DriverIRQHandler(void)
1414 {
1415 s_lpuartIsr(CM4_0_LPUART, s_lpuartHandle[LPUART_GetInstance(CM4_0_LPUART)]);
1416 }
1417 #endif
1418
1419 #if defined(CM4_1_LPUART)
M4_1_LPUART_DriverIRQHandler(void)1420 void M4_1_LPUART_DriverIRQHandler(void)
1421 {
1422 s_lpuartIsr(CM4_1_LPUART, s_lpuartHandle[LPUART_GetInstance(CM4_1_LPUART)]);
1423 }
1424 #endif
1425
1426 #if defined(DMA_LPUART0)
DMA_UART0_INT_IRQHandler(void)1427 void DMA_UART0_INT_IRQHandler(void)
1428 {
1429 s_lpuartIsr(DMA_LPUART0, s_lpuartHandle[LPUART_GetInstance(DMA_LPUART0)]);
1430 }
1431 #endif
1432
1433 #if defined(DMA_LPUART1)
DMA_UART1_INT_IRQHandler(void)1434 void DMA_UART1_INT_IRQHandler(void)
1435 {
1436 s_lpuartIsr(DMA_LPUART1, s_lpuartHandle[LPUART_GetInstance(DMA_LPUART1)]);
1437 }
1438 #endif
1439
1440 #if defined(DMA_LPUART2)
DMA_UART2_INT_IRQHandler(void)1441 void DMA_UART2_INT_IRQHandler(void)
1442 {
1443 s_lpuartIsr(DMA_LPUART2, s_lpuartHandle[LPUART_GetInstance(DMA_LPUART2)]);
1444 }
1445 #endif
1446
1447 #if defined(DMA_LPUART3)
DMA_UART3_INT_IRQHandler(void)1448 void DMA_UART3_INT_IRQHandler(void)
1449 {
1450 s_lpuartIsr(DMA_LPUART3, s_lpuartHandle[LPUART_GetInstance(DMA_LPUART3)]);
1451 }
1452 #endif
1453
1454 #if defined(DMA_LPUART4)
DMA_UART4_INT_IRQHandler(void)1455 void DMA_UART4_INT_IRQHandler(void)
1456 {
1457 s_lpuartIsr(DMA_LPUART4, s_lpuartHandle[LPUART_GetInstance(DMA_LPUART4)]);
1458 }
1459 #endif
1460