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_flexio_uart.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /*<! @brief uart transfer state. */
16 enum _flexio_uart_transfer_states
17 {
18     kFLEXIO_UART_TxIdle, /* TX idle. */
19     kFLEXIO_UART_TxBusy, /* TX busy. */
20     kFLEXIO_UART_RxIdle, /* RX idle. */
21     kFLEXIO_UART_RxBusy  /* RX busy. */
22 };
23 
24 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
25 extern const clock_ip_name_t s_flexioClocks[];
26 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
27 
28 extern FLEXIO_Type *const s_flexioBases[];
29 
30 /*******************************************************************************
31  * Prototypes
32  ******************************************************************************/
33 
34 extern uint32_t FLEXIO_GetInstance(FLEXIO_Type *base);
35 
36 /*!
37  * @brief Get the length of received data in RX ring buffer.
38  *
39  * @param handle FLEXIO UART handle pointer.
40  * @return Length of received data in RX ring buffer.
41  */
42 static size_t FLEXIO_UART_TransferGetRxRingBufferLength(flexio_uart_handle_t *handle);
43 
44 /*!
45  * @brief Check whether the RX ring buffer is full.
46  *
47  * @param handle FLEXIO UART handle pointer.
48  * @retval true  RX ring buffer is full.
49  * @retval false RX ring buffer is not full.
50  */
51 static bool FLEXIO_UART_TransferIsRxRingBufferFull(flexio_uart_handle_t *handle);
52 
53 /*******************************************************************************
54  * Codes
55  ******************************************************************************/
56 
FLEXIO_UART_GetInstance(FLEXIO_UART_Type * base)57 uint32_t FLEXIO_UART_GetInstance(FLEXIO_UART_Type *base)
58 {
59     return FLEXIO_GetInstance(base->flexioBase);
60 }
61 
FLEXIO_UART_TransferGetRxRingBufferLength(flexio_uart_handle_t * handle)62 static size_t FLEXIO_UART_TransferGetRxRingBufferLength(flexio_uart_handle_t *handle)
63 {
64     size_t size;
65 
66     if (handle->rxRingBufferTail > handle->rxRingBufferHead)
67     {
68         size = (size_t)(handle->rxRingBufferHead + handle->rxRingBufferSize - handle->rxRingBufferTail);
69     }
70     else
71     {
72         size = (size_t)(handle->rxRingBufferHead - handle->rxRingBufferTail);
73     }
74 
75     return size;
76 }
77 
FLEXIO_UART_TransferIsRxRingBufferFull(flexio_uart_handle_t * handle)78 static bool FLEXIO_UART_TransferIsRxRingBufferFull(flexio_uart_handle_t *handle)
79 {
80     bool full;
81 
82     if (FLEXIO_UART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U))
83     {
84         full = true;
85     }
86     else
87     {
88         full = false;
89     }
90 
91     return full;
92 }
93 
FLEXIO_UART_Init(FLEXIO_UART_Type * base,const flexio_uart_config_t * userConfig,uint32_t srcClock_Hz)94 status_t FLEXIO_UART_Init(FLEXIO_UART_Type *base, const flexio_uart_config_t *userConfig, uint32_t srcClock_Hz)
95 {
96     assert(base && userConfig);
97 
98     flexio_shifter_config_t shifterConfig;
99     flexio_timer_config_t timerConfig;
100     uint32_t ctrlReg = 0;
101     uint16_t timerDiv = 0;
102     uint16_t timerCmp = 0;
103     status_t result = kStatus_Success;
104 
105     /* Clear the shifterConfig & timerConfig struct. */
106     memset(&shifterConfig, 0, sizeof(shifterConfig));
107     memset(&timerConfig, 0, sizeof(timerConfig));
108 
109 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
110     /* Ungate flexio clock. */
111     CLOCK_EnableClock(s_flexioClocks[FLEXIO_UART_GetInstance(base)]);
112 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
113 
114     /* Reset FLEXIO before configuration. */
115     FLEXIO_Reset(base->flexioBase);
116 
117     /* Configure FLEXIO UART */
118     ctrlReg = base->flexioBase->CTRL;
119     ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
120     ctrlReg |= (FLEXIO_CTRL_DBGE(userConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(userConfig->enableFastAccess) |
121                 FLEXIO_CTRL_FLEXEN(userConfig->enableUart));
122     if (!userConfig->enableInDoze)
123     {
124         ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
125     }
126 
127     base->flexioBase->CTRL = ctrlReg;
128 
129     /* Do hardware configuration. */
130     /* 1. Configure the shifter 0 for tx. */
131     shifterConfig.timerSelect = base->timerIndex[0];
132     shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
133     shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
134     shifterConfig.pinSelect = base->TxPinIndex;
135     shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
136     shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
137     shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
138     shifterConfig.shifterStop = kFLEXIO_ShifterStopBitHigh;
139     shifterConfig.shifterStart = kFLEXIO_ShifterStartBitLow;
140 
141     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
142 
143     /*2. Configure the timer 0 for tx. */
144     timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
145     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
146     timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
147     timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
148     timerConfig.pinSelect = base->TxPinIndex;
149     timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
150     timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
151     timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
152     timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
153     timerConfig.timerReset = kFLEXIO_TimerResetNever;
154     timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
155     timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh;
156     timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable;
157     timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
158 
159     timerDiv = srcClock_Hz / userConfig->baudRate_Bps;
160     timerDiv = timerDiv / 2 - 1;
161 
162     if (timerDiv > 0xFFU)
163     {
164         result = kStatus_InvalidArgument;
165     }
166 
167     timerCmp = ((uint32_t)(userConfig->bitCountPerChar * 2 - 1)) << 8U;
168     timerCmp |= timerDiv;
169 
170     timerConfig.timerCompare = timerCmp;
171 
172     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
173 
174     /* 3. Configure the shifter 1 for rx. */
175     shifterConfig.timerSelect = base->timerIndex[1];
176     shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
177     shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
178     shifterConfig.pinSelect = base->RxPinIndex;
179     shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
180     shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
181     shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
182     shifterConfig.shifterStop = kFLEXIO_ShifterStopBitHigh;
183     shifterConfig.shifterStart = kFLEXIO_ShifterStartBitLow;
184 
185     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
186 
187     /* 4. Configure the timer 1 for rx. */
188     timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->RxPinIndex);
189     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
190     timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceExternal;
191     timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
192     timerConfig.pinSelect = base->RxPinIndex;
193     timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
194     timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
195     timerConfig.timerOutput = kFLEXIO_TimerOutputOneAffectedByReset;
196     timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
197     timerConfig.timerReset = kFLEXIO_TimerResetOnTimerPinRisingEdge;
198     timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
199     timerConfig.timerEnable = kFLEXIO_TimerEnableOnPinRisingEdge;
200     timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable;
201     timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
202 
203     timerConfig.timerCompare = timerCmp;
204 
205     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
206 
207     return result;
208 }
209 
FLEXIO_UART_Deinit(FLEXIO_UART_Type * base)210 void FLEXIO_UART_Deinit(FLEXIO_UART_Type *base)
211 {
212     /* Disable FLEXIO UART module. */
213     FLEXIO_UART_Enable(base, false);
214 
215 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
216     /* Gate flexio clock. */
217     CLOCK_DisableClock(kCLOCK_Flexio0);
218 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
219 }
220 
FLEXIO_UART_GetDefaultConfig(flexio_uart_config_t * userConfig)221 void FLEXIO_UART_GetDefaultConfig(flexio_uart_config_t *userConfig)
222 {
223     assert(userConfig);
224 
225     userConfig->enableUart = true;
226     userConfig->enableInDoze = false;
227     userConfig->enableInDebug = true;
228     userConfig->enableFastAccess = false;
229     /* Default baud rate 115200. */
230     userConfig->baudRate_Bps = 115200U;
231     /* Default bit count at 8. */
232     userConfig->bitCountPerChar = kFLEXIO_UART_8BitsPerChar;
233 }
234 
FLEXIO_UART_EnableInterrupts(FLEXIO_UART_Type * base,uint32_t mask)235 void FLEXIO_UART_EnableInterrupts(FLEXIO_UART_Type *base, uint32_t mask)
236 {
237     if (mask & kFLEXIO_UART_TxDataRegEmptyInterruptEnable)
238     {
239         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[0]);
240     }
241     if (mask & kFLEXIO_UART_RxDataRegFullInterruptEnable)
242     {
243         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[1]);
244     }
245 }
246 
FLEXIO_UART_DisableInterrupts(FLEXIO_UART_Type * base,uint32_t mask)247 void FLEXIO_UART_DisableInterrupts(FLEXIO_UART_Type *base, uint32_t mask)
248 {
249     if (mask & kFLEXIO_UART_TxDataRegEmptyInterruptEnable)
250     {
251         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[0]);
252     }
253     if (mask & kFLEXIO_UART_RxDataRegFullInterruptEnable)
254     {
255         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[1]);
256     }
257 }
258 
FLEXIO_UART_GetStatusFlags(FLEXIO_UART_Type * base)259 uint32_t FLEXIO_UART_GetStatusFlags(FLEXIO_UART_Type *base)
260 {
261     uint32_t status = 0;
262     status =
263         ((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])) >> base->shifterIndex[0]);
264     status |=
265         (((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1]))
266          << 1U);
267     status |=
268         (((FLEXIO_GetShifterErrorFlags(base->flexioBase) & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1]))
269          << 2U);
270     return status;
271 }
272 
FLEXIO_UART_ClearStatusFlags(FLEXIO_UART_Type * base,uint32_t mask)273 void FLEXIO_UART_ClearStatusFlags(FLEXIO_UART_Type *base, uint32_t mask)
274 {
275     if (mask & kFLEXIO_UART_TxDataRegEmptyFlag)
276     {
277         FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[0]);
278     }
279     if (mask & kFLEXIO_UART_RxDataRegFullFlag)
280     {
281         FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[1]);
282     }
283     if (mask & kFLEXIO_UART_RxOverRunFlag)
284     {
285         FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1U << base->shifterIndex[1]);
286     }
287 }
288 
FLEXIO_UART_WriteBlocking(FLEXIO_UART_Type * base,const uint8_t * txData,size_t txSize)289 void FLEXIO_UART_WriteBlocking(FLEXIO_UART_Type *base, const uint8_t *txData, size_t txSize)
290 {
291     assert(txData);
292     assert(txSize);
293 
294     while (txSize--)
295     {
296         /* Wait until data transfer complete. */
297         while (!(FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])))
298         {
299         }
300 
301         base->flexioBase->SHIFTBUF[base->shifterIndex[0]] = *txData++;
302     }
303 }
304 
FLEXIO_UART_ReadBlocking(FLEXIO_UART_Type * base,uint8_t * rxData,size_t rxSize)305 void FLEXIO_UART_ReadBlocking(FLEXIO_UART_Type *base, uint8_t *rxData, size_t rxSize)
306 {
307     assert(rxData);
308     assert(rxSize);
309 
310     while (rxSize--)
311     {
312         /* Wait until data transfer complete. */
313         while (!(FLEXIO_UART_GetStatusFlags(base) & kFLEXIO_UART_RxDataRegFullFlag))
314         {
315         }
316 
317         *rxData++ = base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]];
318     }
319 }
320 
FLEXIO_UART_TransferCreateHandle(FLEXIO_UART_Type * base,flexio_uart_handle_t * handle,flexio_uart_transfer_callback_t callback,void * userData)321 status_t FLEXIO_UART_TransferCreateHandle(FLEXIO_UART_Type *base,
322                                           flexio_uart_handle_t *handle,
323                                           flexio_uart_transfer_callback_t callback,
324                                           void *userData)
325 {
326     assert(handle);
327 
328     IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
329 
330     /* Zero the handle. */
331     memset(handle, 0, sizeof(*handle));
332 
333     /* Set the TX/RX state. */
334     handle->rxState = kFLEXIO_UART_RxIdle;
335     handle->txState = kFLEXIO_UART_TxIdle;
336 
337     /* Set the callback and user data. */
338     handle->callback = callback;
339     handle->userData = userData;
340 
341     /* Enable interrupt in NVIC. */
342     EnableIRQ(flexio_irqs[FLEXIO_UART_GetInstance(base)]);
343 
344     /* Save the context in global variables to support the double weak mechanism. */
345     return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_UART_TransferHandleIRQ);
346 }
347 
FLEXIO_UART_TransferStartRingBuffer(FLEXIO_UART_Type * base,flexio_uart_handle_t * handle,uint8_t * ringBuffer,size_t ringBufferSize)348 void FLEXIO_UART_TransferStartRingBuffer(FLEXIO_UART_Type *base,
349                                          flexio_uart_handle_t *handle,
350                                          uint8_t *ringBuffer,
351                                          size_t ringBufferSize)
352 {
353     assert(handle);
354 
355     /* Setup the ringbuffer address */
356     if (ringBuffer)
357     {
358         handle->rxRingBuffer = ringBuffer;
359         handle->rxRingBufferSize = ringBufferSize;
360         handle->rxRingBufferHead = 0U;
361         handle->rxRingBufferTail = 0U;
362 
363         /* Enable the interrupt to accept the data when user need the ring buffer. */
364         FLEXIO_UART_EnableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
365     }
366 }
367 
FLEXIO_UART_TransferStopRingBuffer(FLEXIO_UART_Type * base,flexio_uart_handle_t * handle)368 void FLEXIO_UART_TransferStopRingBuffer(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle)
369 {
370     assert(handle);
371 
372     if (handle->rxState == kFLEXIO_UART_RxIdle)
373     {
374         FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
375     }
376 
377     handle->rxRingBuffer = NULL;
378     handle->rxRingBufferSize = 0U;
379     handle->rxRingBufferHead = 0U;
380     handle->rxRingBufferTail = 0U;
381 }
382 
FLEXIO_UART_TransferSendNonBlocking(FLEXIO_UART_Type * base,flexio_uart_handle_t * handle,flexio_uart_transfer_t * xfer)383 status_t FLEXIO_UART_TransferSendNonBlocking(FLEXIO_UART_Type *base,
384                                              flexio_uart_handle_t *handle,
385                                              flexio_uart_transfer_t *xfer)
386 {
387     status_t status;
388 
389     /* Return error if xfer invalid. */
390     if ((0U == xfer->dataSize) || (NULL == xfer->data))
391     {
392         return kStatus_InvalidArgument;
393     }
394 
395     /* Return error if current TX busy. */
396     if (kFLEXIO_UART_TxBusy == handle->txState)
397     {
398         status = kStatus_FLEXIO_UART_TxBusy;
399     }
400     else
401     {
402         handle->txData = xfer->data;
403         handle->txDataSize = xfer->dataSize;
404         handle->txDataSizeAll = xfer->dataSize;
405         handle->txState = kFLEXIO_UART_TxBusy;
406 
407         /* Enable transmiter interrupt. */
408         FLEXIO_UART_EnableInterrupts(base, kFLEXIO_UART_TxDataRegEmptyInterruptEnable);
409 
410         status = kStatus_Success;
411     }
412 
413     return status;
414 }
415 
FLEXIO_UART_TransferAbortSend(FLEXIO_UART_Type * base,flexio_uart_handle_t * handle)416 void FLEXIO_UART_TransferAbortSend(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle)
417 {
418     /* Disable the transmitter and disable the interrupt. */
419     FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_TxDataRegEmptyInterruptEnable);
420 
421     handle->txDataSize = 0;
422     handle->txState = kFLEXIO_UART_TxIdle;
423 }
424 
FLEXIO_UART_TransferGetSendCount(FLEXIO_UART_Type * base,flexio_uart_handle_t * handle,size_t * count)425 status_t FLEXIO_UART_TransferGetSendCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count)
426 {
427     assert(handle);
428     assert(count);
429 
430     if (kFLEXIO_UART_TxIdle == handle->txState)
431     {
432         return kStatus_NoTransferInProgress;
433     }
434 
435     *count = handle->txDataSizeAll - handle->txDataSize;
436 
437     return kStatus_Success;
438 }
439 
FLEXIO_UART_TransferReceiveNonBlocking(FLEXIO_UART_Type * base,flexio_uart_handle_t * handle,flexio_uart_transfer_t * xfer,size_t * receivedBytes)440 status_t FLEXIO_UART_TransferReceiveNonBlocking(FLEXIO_UART_Type *base,
441                                                 flexio_uart_handle_t *handle,
442                                                 flexio_uart_transfer_t *xfer,
443                                                 size_t *receivedBytes)
444 {
445     uint32_t i;
446     status_t status;
447     /* How many bytes to copy from ring buffer to user memory. */
448     size_t bytesToCopy = 0U;
449     /* How many bytes to receive. */
450     size_t bytesToReceive;
451     /* How many bytes currently have received. */
452     size_t bytesCurrentReceived;
453 
454     /* Return error if xfer invalid. */
455     if ((0U == xfer->dataSize) || (NULL == xfer->data))
456     {
457         return kStatus_InvalidArgument;
458     }
459 
460     /* How to get data:
461        1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize
462           to uart handle, enable interrupt to store received data to xfer->data. When
463           all data received, trigger callback.
464        2. If RX ring buffer is enabled and not empty, get data from ring buffer first.
465           If there are enough data in ring buffer, copy them to xfer->data and return.
466           If there are not enough data in ring buffer, copy all of them to xfer->data,
467           save the xfer->data remained empty space to uart handle, receive data
468           to this empty space and trigger callback when finished. */
469 
470     if (kFLEXIO_UART_RxBusy == handle->rxState)
471     {
472         status = kStatus_FLEXIO_UART_RxBusy;
473     }
474     else
475     {
476         bytesToReceive = xfer->dataSize;
477         bytesCurrentReceived = 0U;
478 
479         /* If RX ring buffer is used. */
480         if (handle->rxRingBuffer)
481         {
482             /* Disable FLEXIO_UART RX IRQ, protect ring buffer. */
483             FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
484 
485             /* How many bytes in RX ring buffer currently. */
486             bytesToCopy = FLEXIO_UART_TransferGetRxRingBufferLength(handle);
487 
488             if (bytesToCopy)
489             {
490                 bytesToCopy = MIN(bytesToReceive, bytesToCopy);
491 
492                 bytesToReceive -= bytesToCopy;
493 
494                 /* Copy data from ring buffer to user memory. */
495                 for (i = 0U; i < bytesToCopy; i++)
496                 {
497                     xfer->data[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];
498 
499                     /* Wrap to 0. Not use modulo (%) because it might be large and slow. */
500                     if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
501                     {
502                         handle->rxRingBufferTail = 0U;
503                     }
504                     else
505                     {
506                         handle->rxRingBufferTail++;
507                     }
508                 }
509             }
510 
511             /* If ring buffer does not have enough data, still need to read more data. */
512             if (bytesToReceive)
513             {
514                 /* No data in ring buffer, save the request to UART handle. */
515                 handle->rxData = xfer->data + bytesCurrentReceived;
516                 handle->rxDataSize = bytesToReceive;
517                 handle->rxDataSizeAll = bytesToReceive;
518                 handle->rxState = kFLEXIO_UART_RxBusy;
519             }
520 
521             /* Enable FLEXIO_UART RX IRQ if previously enabled. */
522             FLEXIO_UART_EnableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
523         }
524         /* Ring buffer not used. */
525         else
526         {
527             handle->rxData = xfer->data + bytesCurrentReceived;
528             handle->rxDataSize = bytesToReceive;
529             handle->rxDataSizeAll = bytesToReceive;
530             handle->rxState = kFLEXIO_UART_RxBusy;
531 
532             /* Enable RX interrupt. */
533             FLEXIO_UART_EnableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
534         }
535 
536         /* Return the how many bytes have read. */
537         if (receivedBytes)
538         {
539             *receivedBytes = bytesCurrentReceived;
540         }
541 
542         status = kStatus_Success;
543     }
544 
545     return status;
546 }
547 
FLEXIO_UART_TransferAbortReceive(FLEXIO_UART_Type * base,flexio_uart_handle_t * handle)548 void FLEXIO_UART_TransferAbortReceive(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle)
549 {
550     /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
551     if (!handle->rxRingBuffer)
552     {
553         /* Disable RX interrupt. */
554         FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
555     }
556 
557     handle->rxDataSize = 0U;
558     handle->rxState = kFLEXIO_UART_RxIdle;
559 }
560 
FLEXIO_UART_TransferGetReceiveCount(FLEXIO_UART_Type * base,flexio_uart_handle_t * handle,size_t * count)561 status_t FLEXIO_UART_TransferGetReceiveCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count)
562 {
563     assert(handle);
564     assert(count);
565 
566     if (kFLEXIO_UART_RxIdle == handle->rxState)
567     {
568         return kStatus_NoTransferInProgress;
569     }
570 
571     *count = handle->rxDataSizeAll - handle->rxDataSize;
572 
573     return kStatus_Success;
574 }
575 
FLEXIO_UART_TransferHandleIRQ(void * uartType,void * uartHandle)576 void FLEXIO_UART_TransferHandleIRQ(void *uartType, void *uartHandle)
577 {
578     uint8_t count = 1;
579     FLEXIO_UART_Type *base = (FLEXIO_UART_Type *)uartType;
580     flexio_uart_handle_t *handle = (flexio_uart_handle_t *)uartHandle;
581 
582     /* Read the status back. */
583     uint8_t status = FLEXIO_UART_GetStatusFlags(base);
584 
585     /* If RX overrun. */
586     if (kFLEXIO_UART_RxOverRunFlag & status)
587     {
588         /* Clear Overrun flag. */
589         FLEXIO_UART_ClearStatusFlags(base, kFLEXIO_UART_RxOverRunFlag);
590 
591         /* Trigger callback. */
592         if (handle->callback)
593         {
594             handle->callback(base, handle, kStatus_FLEXIO_UART_RxHardwareOverrun, handle->userData);
595         }
596     }
597 
598     /* Receive data register full */
599     if ((kFLEXIO_UART_RxDataRegFullFlag & status) && (base->flexioBase->SHIFTSIEN & (1U << base->shifterIndex[1])))
600     {
601         /* If handle->rxDataSize is not 0, first save data to handle->rxData. */
602         if (handle->rxDataSize)
603         {
604             /* Using non block API to read the data from the registers. */
605             FLEXIO_UART_ReadByte(base, handle->rxData);
606             handle->rxDataSize--;
607             handle->rxData++;
608             count--;
609 
610             /* If all the data required for upper layer is ready, trigger callback. */
611             if (!handle->rxDataSize)
612             {
613                 handle->rxState = kFLEXIO_UART_RxIdle;
614 
615                 if (handle->callback)
616                 {
617                     handle->callback(base, handle, kStatus_FLEXIO_UART_RxIdle, handle->userData);
618                 }
619             }
620         }
621 
622         if (handle->rxRingBuffer)
623         {
624             if (count)
625             {
626                 /* If RX ring buffer is full, trigger callback to notify over run. */
627                 if (FLEXIO_UART_TransferIsRxRingBufferFull(handle))
628                 {
629                     if (handle->callback)
630                     {
631                         handle->callback(base, handle, kStatus_FLEXIO_UART_RxRingBufferOverrun, handle->userData);
632                     }
633                 }
634 
635                 /* If ring buffer is still full after callback function, the oldest data is overrided. */
636                 if (FLEXIO_UART_TransferIsRxRingBufferFull(handle))
637                 {
638                     /* Increase handle->rxRingBufferTail to make room for new data. */
639                     if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
640                     {
641                         handle->rxRingBufferTail = 0U;
642                     }
643                     else
644                     {
645                         handle->rxRingBufferTail++;
646                     }
647                 }
648 
649                 /* Read data. */
650                 handle->rxRingBuffer[handle->rxRingBufferHead] = base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]];
651 
652                 /* Increase handle->rxRingBufferHead. */
653                 if (handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
654                 {
655                     handle->rxRingBufferHead = 0U;
656                 }
657                 else
658                 {
659                     handle->rxRingBufferHead++;
660                 }
661             }
662         }
663         /* If no receive requst pending, stop RX interrupt. */
664         else if (!handle->rxDataSize)
665         {
666             FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
667         }
668         else
669         {
670         }
671     }
672 
673     /* Send data register empty and the interrupt is enabled. */
674     if ((kFLEXIO_UART_TxDataRegEmptyFlag & status) && (base->flexioBase->SHIFTSIEN & (1U << base->shifterIndex[0])))
675     {
676         if (handle->txDataSize)
677         {
678             /* Using non block API to write the data to the registers. */
679             FLEXIO_UART_WriteByte(base, handle->txData);
680             handle->txData++;
681             handle->txDataSize--;
682             count--;
683 
684             /* If all the data are written to data register, TX finished. */
685             if (!handle->txDataSize)
686             {
687                 handle->txState = kFLEXIO_UART_TxIdle;
688 
689                 /* Disable TX register empty interrupt. */
690                 FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_TxDataRegEmptyInterruptEnable);
691 
692                 /* Trigger callback. */
693                 if (handle->callback)
694                 {
695                     handle->callback(base, handle, kStatus_FLEXIO_UART_TxIdle, handle->userData);
696                 }
697             }
698         }
699     }
700 }
701