Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:59

0001 /*
0002  * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
0003  * Copyright 2016-2021 NXP
0004  * All rights reserved.
0005  *
0006  * SPDX-License-Identifier: BSD-3-Clause
0007  */
0008 
0009 #include "fsl_flexio_uart.h"
0010 
0011 /*******************************************************************************
0012  * Definitions
0013  ******************************************************************************/
0014 
0015 /* Component ID definition, used by tools. */
0016 #ifndef FSL_COMPONENT_ID
0017 #define FSL_COMPONENT_ID "platform.drivers.flexio_uart"
0018 #endif
0019 
0020 /*<! @brief uart transfer state. */
0021 enum _flexio_uart_transfer_states
0022 {
0023     kFLEXIO_UART_TxIdle, /* TX idle. */
0024     kFLEXIO_UART_TxBusy, /* TX busy. */
0025     kFLEXIO_UART_RxIdle, /* RX idle. */
0026     kFLEXIO_UART_RxBusy  /* RX busy. */
0027 };
0028 
0029 /*******************************************************************************
0030  * Prototypes
0031  ******************************************************************************/
0032 
0033 /*!
0034  * @brief Get the length of received data in RX ring buffer.
0035  *
0036  * @param handle FLEXIO UART handle pointer.
0037  * @return Length of received data in RX ring buffer.
0038  */
0039 static size_t FLEXIO_UART_TransferGetRxRingBufferLength(flexio_uart_handle_t *handle);
0040 
0041 /*!
0042  * @brief Check whether the RX ring buffer is full.
0043  *
0044  * @param handle FLEXIO UART handle pointer.
0045  * @retval true  RX ring buffer is full.
0046  * @retval false RX ring buffer is not full.
0047  */
0048 static bool FLEXIO_UART_TransferIsRxRingBufferFull(flexio_uart_handle_t *handle);
0049 
0050 /*******************************************************************************
0051  * Codes
0052  ******************************************************************************/
0053 
0054 static uint32_t FLEXIO_UART_GetInstance(FLEXIO_UART_Type *base)
0055 {
0056     return FLEXIO_GetInstance(base->flexioBase);
0057 }
0058 
0059 static size_t FLEXIO_UART_TransferGetRxRingBufferLength(flexio_uart_handle_t *handle)
0060 {
0061     size_t size;
0062     uint16_t rxRingBufferHead = handle->rxRingBufferHead;
0063     uint16_t rxRingBufferTail = handle->rxRingBufferTail;
0064 
0065     if (rxRingBufferTail > rxRingBufferHead)
0066     {
0067         size = (size_t)rxRingBufferHead + handle->rxRingBufferSize - (size_t)rxRingBufferTail;
0068     }
0069     else
0070     {
0071         size = (size_t)rxRingBufferHead - (size_t)rxRingBufferTail;
0072     }
0073 
0074     return size;
0075 }
0076 
0077 static bool FLEXIO_UART_TransferIsRxRingBufferFull(flexio_uart_handle_t *handle)
0078 {
0079     bool full;
0080 
0081     if (FLEXIO_UART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U))
0082     {
0083         full = true;
0084     }
0085     else
0086     {
0087         full = false;
0088     }
0089 
0090     return full;
0091 }
0092 
0093 /*!
0094  * brief Ungates the FlexIO clock, resets the FlexIO module, configures FlexIO UART
0095  * hardware, and configures the FlexIO UART with FlexIO UART configuration.
0096  * The configuration structure can be filled by the user or be set with
0097  * default values by FLEXIO_UART_GetDefaultConfig().
0098  *
0099  * Example
0100    code
0101    FLEXIO_UART_Type base = {
0102    .flexioBase = FLEXIO,
0103    .TxPinIndex = 0,
0104    .RxPinIndex = 1,
0105    .shifterIndex = {0,1},
0106    .timerIndex = {0,1}
0107    };
0108    flexio_uart_config_t config = {
0109    .enableInDoze = false,
0110    .enableInDebug = true,
0111    .enableFastAccess = false,
0112    .baudRate_Bps = 115200U,
0113    .bitCountPerChar = 8
0114    };
0115    FLEXIO_UART_Init(base, &config, srcClock_Hz);
0116    endcode
0117  *
0118  * param base Pointer to the FLEXIO_UART_Type structure.
0119  * param userConfig Pointer to the flexio_uart_config_t structure.
0120  * param srcClock_Hz FlexIO source clock in Hz.
0121  * retval kStatus_Success Configuration success.
0122  * retval kStatus_FLEXIO_UART_BaudrateNotSupport Baudrate is not supported for current clock source frequency.
0123 */
0124 status_t FLEXIO_UART_Init(FLEXIO_UART_Type *base, const flexio_uart_config_t *userConfig, uint32_t srcClock_Hz)
0125 {
0126     assert((base != NULL) && (userConfig != NULL));
0127 
0128     flexio_shifter_config_t shifterConfig;
0129     flexio_timer_config_t timerConfig;
0130     uint32_t ctrlReg  = 0;
0131     uint16_t timerDiv = 0;
0132     uint16_t timerCmp = 0;
0133     uint32_t calculatedBaud;
0134     uint32_t diff;
0135     status_t result = kStatus_Success;
0136 
0137     /* Clear the shifterConfig & timerConfig struct. */
0138     (void)memset(&shifterConfig, 0, sizeof(shifterConfig));
0139     (void)memset(&timerConfig, 0, sizeof(timerConfig));
0140 
0141 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0142     /* Ungate flexio clock. */
0143     CLOCK_EnableClock(s_flexioClocks[FLEXIO_UART_GetInstance(base)]);
0144 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0145 
0146     /* Configure FLEXIO UART */
0147     ctrlReg = base->flexioBase->CTRL;
0148     ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
0149     ctrlReg |= (FLEXIO_CTRL_DBGE(userConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(userConfig->enableFastAccess) |
0150                 FLEXIO_CTRL_FLEXEN(userConfig->enableUart));
0151     if (!userConfig->enableInDoze)
0152     {
0153         ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
0154     }
0155 
0156     base->flexioBase->CTRL = ctrlReg;
0157 
0158     /* Do hardware configuration. */
0159     /* 1. Configure the shifter 0 for tx. */
0160     shifterConfig.timerSelect   = base->timerIndex[0];
0161     shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
0162     shifterConfig.pinConfig     = kFLEXIO_PinConfigOutput;
0163     shifterConfig.pinSelect     = base->TxPinIndex;
0164     shifterConfig.pinPolarity   = kFLEXIO_PinActiveHigh;
0165     shifterConfig.shifterMode   = kFLEXIO_ShifterModeTransmit;
0166     shifterConfig.inputSource   = kFLEXIO_ShifterInputFromPin;
0167     shifterConfig.shifterStop   = kFLEXIO_ShifterStopBitHigh;
0168     shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitLow;
0169 
0170     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
0171 
0172     /*2. Configure the timer 0 for tx. */
0173     timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
0174     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
0175     timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
0176     timerConfig.pinConfig       = kFLEXIO_PinConfigOutputDisabled;
0177     timerConfig.pinSelect       = base->TxPinIndex;
0178     timerConfig.pinPolarity     = kFLEXIO_PinActiveHigh;
0179     timerConfig.timerMode       = kFLEXIO_TimerModeDual8BitBaudBit;
0180     timerConfig.timerOutput     = kFLEXIO_TimerOutputOneNotAffectedByReset;
0181     timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
0182     timerConfig.timerReset      = kFLEXIO_TimerResetNever;
0183     timerConfig.timerDisable    = kFLEXIO_TimerDisableOnTimerCompare;
0184     timerConfig.timerEnable     = kFLEXIO_TimerEnableOnTriggerHigh;
0185     timerConfig.timerStop       = kFLEXIO_TimerStopBitEnableOnTimerDisable;
0186     timerConfig.timerStart      = kFLEXIO_TimerStartBitEnabled;
0187 
0188     timerDiv = (uint16_t)(srcClock_Hz / userConfig->baudRate_Bps);
0189     timerDiv = timerDiv / 2U - 1U;
0190 
0191     if (timerDiv > 0xFFU)
0192     {
0193         /* Check whether the calculated timerDiv is within allowed range. */
0194         return kStatus_FLEXIO_UART_BaudrateNotSupport;
0195     }
0196     else
0197     {
0198         /* Check to see if actual baud rate is within 3% of desired baud rate
0199          * based on the best calculated timerDiv value */
0200         calculatedBaud = srcClock_Hz / (((uint32_t)timerDiv + 1U) * 2U);
0201         /* timerDiv cannot be larger than the ideal divider, so calculatedBaud is definitely larger
0202            than configured baud */
0203         diff = calculatedBaud - userConfig->baudRate_Bps;
0204         if (diff > ((userConfig->baudRate_Bps / 100U) * 3U))
0205         {
0206             return kStatus_FLEXIO_UART_BaudrateNotSupport;
0207         }
0208     }
0209 
0210     timerCmp = ((uint16_t)userConfig->bitCountPerChar * 2U - 1U) << 8U;
0211     timerCmp |= timerDiv;
0212 
0213     timerConfig.timerCompare = timerCmp;
0214 
0215     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
0216 
0217     /* 3. Configure the shifter 1 for rx. */
0218     shifterConfig.timerSelect   = base->timerIndex[1];
0219     shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
0220     shifterConfig.pinConfig     = kFLEXIO_PinConfigOutputDisabled;
0221     shifterConfig.pinSelect     = base->RxPinIndex;
0222     shifterConfig.pinPolarity   = kFLEXIO_PinActiveHigh;
0223     shifterConfig.shifterMode   = kFLEXIO_ShifterModeReceive;
0224     shifterConfig.inputSource   = kFLEXIO_ShifterInputFromPin;
0225     shifterConfig.shifterStop   = kFLEXIO_ShifterStopBitHigh;
0226     shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitLow;
0227 
0228     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
0229 
0230     /* 4. Configure the timer 1 for rx. */
0231     timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->RxPinIndex);
0232     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
0233     timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceExternal;
0234     timerConfig.pinConfig       = kFLEXIO_PinConfigOutputDisabled;
0235     timerConfig.pinSelect       = base->RxPinIndex;
0236     timerConfig.pinPolarity     = kFLEXIO_PinActiveLow;
0237     timerConfig.timerMode       = kFLEXIO_TimerModeDual8BitBaudBit;
0238     timerConfig.timerOutput     = kFLEXIO_TimerOutputOneAffectedByReset;
0239     timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
0240     timerConfig.timerReset      = kFLEXIO_TimerResetOnTimerPinRisingEdge;
0241     timerConfig.timerDisable    = kFLEXIO_TimerDisableOnTimerCompare;
0242     timerConfig.timerEnable     = kFLEXIO_TimerEnableOnPinRisingEdge;
0243     timerConfig.timerStop       = kFLEXIO_TimerStopBitEnableOnTimerDisable;
0244     timerConfig.timerStart      = kFLEXIO_TimerStartBitEnabled;
0245 
0246     timerConfig.timerCompare = timerCmp;
0247 
0248     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
0249 
0250     return result;
0251 }
0252 
0253 /*!
0254  * brief Resets the FlexIO UART shifter and timer config.
0255  *
0256  * note After calling this API, call the FLEXO_UART_Init to use the FlexIO UART module.
0257  *
0258  * param base Pointer to FLEXIO_UART_Type structure
0259  */
0260 void FLEXIO_UART_Deinit(FLEXIO_UART_Type *base)
0261 {
0262     base->flexioBase->SHIFTCFG[base->shifterIndex[0]] = 0;
0263     base->flexioBase->SHIFTCTL[base->shifterIndex[0]] = 0;
0264     base->flexioBase->SHIFTCFG[base->shifterIndex[1]] = 0;
0265     base->flexioBase->SHIFTCTL[base->shifterIndex[1]] = 0;
0266     base->flexioBase->TIMCFG[base->timerIndex[0]]     = 0;
0267     base->flexioBase->TIMCMP[base->timerIndex[0]]     = 0;
0268     base->flexioBase->TIMCTL[base->timerIndex[0]]     = 0;
0269     base->flexioBase->TIMCFG[base->timerIndex[1]]     = 0;
0270     base->flexioBase->TIMCMP[base->timerIndex[1]]     = 0;
0271     base->flexioBase->TIMCTL[base->timerIndex[1]]     = 0;
0272     /* Clear the shifter flag. */
0273     base->flexioBase->SHIFTSTAT = (1UL << base->shifterIndex[0]);
0274     base->flexioBase->SHIFTSTAT = (1UL << base->shifterIndex[1]);
0275     /* Clear the timer flag. */
0276     base->flexioBase->TIMSTAT = (1UL << base->timerIndex[0]);
0277     base->flexioBase->TIMSTAT = (1UL << base->timerIndex[1]);
0278 }
0279 
0280 /*!
0281  * brief Gets the default configuration to configure the FlexIO UART. The configuration
0282  * can be used directly for calling the FLEXIO_UART_Init().
0283  * Example:
0284    code
0285    flexio_uart_config_t config;
0286    FLEXIO_UART_GetDefaultConfig(&userConfig);
0287    endcode
0288  * param userConfig Pointer to the flexio_uart_config_t structure.
0289 */
0290 void FLEXIO_UART_GetDefaultConfig(flexio_uart_config_t *userConfig)
0291 {
0292     assert(userConfig != NULL);
0293 
0294     /* Initializes the configure structure to zero. */
0295     (void)memset(userConfig, 0, sizeof(*userConfig));
0296 
0297     userConfig->enableUart       = true;
0298     userConfig->enableInDoze     = false;
0299     userConfig->enableInDebug    = true;
0300     userConfig->enableFastAccess = false;
0301     /* Default baud rate 115200. */
0302     userConfig->baudRate_Bps = 115200U;
0303     /* Default bit count at 8. */
0304     userConfig->bitCountPerChar = kFLEXIO_UART_8BitsPerChar;
0305 }
0306 
0307 /*!
0308  * brief Enables the FlexIO UART interrupt.
0309  *
0310  * This function enables the FlexIO UART interrupt.
0311  *
0312  * param base Pointer to the FLEXIO_UART_Type structure.
0313  * param mask Interrupt source.
0314  */
0315 void FLEXIO_UART_EnableInterrupts(FLEXIO_UART_Type *base, uint32_t mask)
0316 {
0317     if ((mask & (uint32_t)kFLEXIO_UART_TxDataRegEmptyInterruptEnable) != 0U)
0318     {
0319         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[0]);
0320     }
0321     if ((mask & (uint32_t)kFLEXIO_UART_RxDataRegFullInterruptEnable) != 0U)
0322     {
0323         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[1]);
0324     }
0325 }
0326 
0327 /*!
0328  * brief Disables the FlexIO UART interrupt.
0329  *
0330  * This function disables the FlexIO UART interrupt.
0331  *
0332  * param base Pointer to the FLEXIO_UART_Type structure.
0333  * param mask Interrupt source.
0334  */
0335 void FLEXIO_UART_DisableInterrupts(FLEXIO_UART_Type *base, uint32_t mask)
0336 {
0337     if ((mask & (uint32_t)kFLEXIO_UART_TxDataRegEmptyInterruptEnable) != 0U)
0338     {
0339         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[0]);
0340     }
0341     if ((mask & (uint32_t)kFLEXIO_UART_RxDataRegFullInterruptEnable) != 0U)
0342     {
0343         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[1]);
0344     }
0345 }
0346 
0347 /*!
0348  * brief Gets the FlexIO UART status flags.
0349  *
0350  * param base Pointer to the FLEXIO_UART_Type structure.
0351  * return FlexIO UART status flags.
0352  */
0353 
0354 uint32_t FLEXIO_UART_GetStatusFlags(FLEXIO_UART_Type *base)
0355 {
0356     uint32_t status = 0U;
0357     status =
0358         ((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])) >> base->shifterIndex[0]);
0359     status |=
0360         (((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[1])) >> (base->shifterIndex[1]))
0361          << 1U);
0362     status |=
0363         (((FLEXIO_GetShifterErrorFlags(base->flexioBase) & (1UL << base->shifterIndex[1])) >> (base->shifterIndex[1]))
0364          << 2U);
0365     return status;
0366 }
0367 
0368 /*!
0369  * brief Gets the FlexIO UART status flags.
0370  *
0371  * param base Pointer to the FLEXIO_UART_Type structure.
0372  * param mask Status flag.
0373  *      The parameter can be any combination of the following values:
0374  *          arg kFLEXIO_UART_TxDataRegEmptyFlag
0375  *          arg kFLEXIO_UART_RxEmptyFlag
0376  *          arg kFLEXIO_UART_RxOverRunFlag
0377  */
0378 
0379 void FLEXIO_UART_ClearStatusFlags(FLEXIO_UART_Type *base, uint32_t mask)
0380 {
0381     if ((mask & (uint32_t)kFLEXIO_UART_TxDataRegEmptyFlag) != 0U)
0382     {
0383         FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1UL << base->shifterIndex[0]);
0384     }
0385     if ((mask & (uint32_t)kFLEXIO_UART_RxDataRegFullFlag) != 0U)
0386     {
0387         FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
0388     }
0389     if ((mask & (uint32_t)kFLEXIO_UART_RxOverRunFlag) != 0U)
0390     {
0391         FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
0392     }
0393 }
0394 
0395 /*!
0396  * brief Sends a buffer of data bytes.
0397  *
0398  * note This function blocks using the polling method until all bytes have been sent.
0399  *
0400  * param base Pointer to the FLEXIO_UART_Type structure.
0401  * param txData The data bytes to send.
0402  * param txSize The number of data bytes to send.
0403  * retval kStatus_FLEXIO_UART_Timeout Transmission timed out and was aborted.
0404  * retval kStatus_Success Successfully wrote all data.
0405  */
0406 status_t FLEXIO_UART_WriteBlocking(FLEXIO_UART_Type *base, const uint8_t *txData, size_t txSize)
0407 {
0408     assert(txData != NULL);
0409     assert(txSize != 0U);
0410 #if UART_RETRY_TIMES
0411     uint32_t waitTimes;
0412 #endif
0413 
0414     while (0U != txSize--)
0415     {
0416         /* Wait until data transfer complete. */
0417 #if UART_RETRY_TIMES
0418         waitTimes = UART_RETRY_TIMES;
0419         while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
0420                (0U != --waitTimes))
0421 #else
0422         while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
0423 #endif
0424         {
0425         }
0426 #if UART_RETRY_TIMES
0427         if (0U == waitTimes)
0428         {
0429             return kStatus_FLEXIO_UART_Timeout;
0430         }
0431 #endif
0432 
0433         base->flexioBase->SHIFTBUF[base->shifterIndex[0]] = *txData++;
0434     }
0435     return kStatus_Success;
0436 }
0437 
0438 /*!
0439  * brief Receives a buffer of bytes.
0440  *
0441  * note This function blocks using the polling method until all bytes have been received.
0442  *
0443  * param base Pointer to the FLEXIO_UART_Type structure.
0444  * param rxData The buffer to store the received bytes.
0445  * param rxSize The number of data bytes to be received.
0446  * retval kStatus_FLEXIO_UART_Timeout Transmission timed out and was aborted.
0447  * retval kStatus_Success Successfully received all data.
0448  */
0449 status_t FLEXIO_UART_ReadBlocking(FLEXIO_UART_Type *base, uint8_t *rxData, size_t rxSize)
0450 {
0451     assert(rxData != NULL);
0452     assert(rxSize != 0U);
0453 #if UART_RETRY_TIMES
0454     uint32_t waitTimes;
0455 #endif
0456 
0457     while (0U != rxSize--)
0458     {
0459         /* Wait until data transfer complete. */
0460 #if UART_RETRY_TIMES
0461         waitTimes = UART_RETRY_TIMES;
0462         while ((0U == (FLEXIO_UART_GetStatusFlags(base) & (uint32_t)kFLEXIO_UART_RxDataRegFullFlag)) &&
0463                (0U != --waitTimes))
0464 #else
0465         while (0U == (FLEXIO_UART_GetStatusFlags(base) & (uint32_t)kFLEXIO_UART_RxDataRegFullFlag))
0466 #endif
0467         {
0468         }
0469 #if UART_RETRY_TIMES
0470         if (0U == waitTimes)
0471         {
0472             return kStatus_FLEXIO_UART_Timeout;
0473         }
0474 #endif
0475 
0476         *rxData++ = (uint8_t)(base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]]);
0477     }
0478     return kStatus_Success;
0479 }
0480 
0481 /*!
0482  * brief Initializes the UART handle.
0483  *
0484  * This function initializes the FlexIO UART handle, which can be used for other FlexIO
0485  * UART transactional APIs. Call this API once to get the
0486  * initialized handle.
0487  *
0488  * The UART driver supports the "background" receiving, which means that users can set up
0489  * a RX ring buffer optionally. Data received is stored into the ring buffer even when
0490  * the user doesn't call the FLEXIO_UART_TransferReceiveNonBlocking() API. If there is already data
0491  * received in the ring buffer, users can get the received data from the ring buffer
0492  * directly. The ring buffer is disabled if passing NULL as p ringBuffer.
0493  *
0494  * param base to FLEXIO_UART_Type structure.
0495  * param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
0496  * param callback The callback function.
0497  * param userData The parameter of the callback function.
0498  * retval kStatus_Success Successfully create the handle.
0499  * retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
0500  */
0501 status_t FLEXIO_UART_TransferCreateHandle(FLEXIO_UART_Type *base,
0502                                           flexio_uart_handle_t *handle,
0503                                           flexio_uart_transfer_callback_t callback,
0504                                           void *userData)
0505 {
0506     assert(handle != NULL);
0507 
0508     IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
0509 
0510     /* Zero the handle. */
0511     (void)memset(handle, 0, sizeof(*handle));
0512 
0513     /* Set the TX/RX state. */
0514     handle->rxState = (uint8_t)kFLEXIO_UART_RxIdle;
0515     handle->txState = (uint8_t)kFLEXIO_UART_TxIdle;
0516 
0517     /* Set the callback and user data. */
0518     handle->callback = callback;
0519     handle->userData = userData;
0520 
0521     /* Clear pending NVIC IRQ before enable NVIC IRQ. */
0522     NVIC_ClearPendingIRQ(flexio_irqs[FLEXIO_UART_GetInstance(base)]);
0523     /* Enable interrupt in NVIC. */
0524     (void)EnableIRQ(flexio_irqs[FLEXIO_UART_GetInstance(base)]);
0525 
0526     /* Save the context in global variables to support the double weak mechanism. */
0527     return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_UART_TransferHandleIRQ);
0528 }
0529 
0530 /*!
0531  * brief Sets up the RX ring buffer.
0532  *
0533  * This function sets up the RX ring buffer to a specific UART handle.
0534  *
0535  * When the RX ring buffer is used, data received is stored into the ring buffer even when
0536  * the user doesn't call the UART_ReceiveNonBlocking() API. If there is already data received
0537  * in the ring buffer, users can get the received data from the ring buffer directly.
0538  *
0539  * note When using the RX ring buffer, one byte is reserved for internal use. In other
0540  * words, if p ringBufferSize is 32, only 31 bytes are used for saving data.
0541  *
0542  * param base Pointer to the FLEXIO_UART_Type structure.
0543  * param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
0544  * param ringBuffer Start address of ring buffer for background receiving. Pass NULL to disable the ring buffer.
0545  * param ringBufferSize Size of the ring buffer.
0546  */
0547 void FLEXIO_UART_TransferStartRingBuffer(FLEXIO_UART_Type *base,
0548                                          flexio_uart_handle_t *handle,
0549                                          uint8_t *ringBuffer,
0550                                          size_t ringBufferSize)
0551 {
0552     assert(handle != NULL);
0553 
0554     /* Setup the ringbuffer address */
0555     if (ringBuffer != NULL)
0556     {
0557         handle->rxRingBuffer     = ringBuffer;
0558         handle->rxRingBufferSize = ringBufferSize;
0559         handle->rxRingBufferHead = 0U;
0560         handle->rxRingBufferTail = 0U;
0561 
0562         /* Enable the interrupt to accept the data when user need the ring buffer. */
0563         FLEXIO_UART_EnableInterrupts(base, (uint32_t)kFLEXIO_UART_RxDataRegFullInterruptEnable);
0564     }
0565 }
0566 
0567 /*!
0568  * brief Aborts the background transfer and uninstalls the ring buffer.
0569  *
0570  * This function aborts the background transfer and uninstalls the ring buffer.
0571  *
0572  * param base Pointer to the FLEXIO_UART_Type structure.
0573  * param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
0574  */
0575 void FLEXIO_UART_TransferStopRingBuffer(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle)
0576 {
0577     assert(handle != NULL);
0578 
0579     if (handle->rxState == (uint8_t)kFLEXIO_UART_RxIdle)
0580     {
0581         FLEXIO_UART_DisableInterrupts(base, (uint32_t)kFLEXIO_UART_RxDataRegFullInterruptEnable);
0582     }
0583 
0584     handle->rxRingBuffer     = NULL;
0585     handle->rxRingBufferSize = 0U;
0586     handle->rxRingBufferHead = 0U;
0587     handle->rxRingBufferTail = 0U;
0588 }
0589 
0590 /*!
0591  * brief Transmits a buffer of data using the interrupt method.
0592  *
0593  * This function sends data using an interrupt method. This is a non-blocking function,
0594  * which returns directly without waiting for all data to be written to the TX register. When
0595  * all data is written to the TX register in ISR, the FlexIO UART driver calls the callback
0596  * function and passes the ref kStatus_FLEXIO_UART_TxIdle as status parameter.
0597  *
0598  * note The kStatus_FLEXIO_UART_TxIdle is passed to the upper layer when all data is written
0599  * to the TX register. However, it does not ensure that all data is sent out.
0600  *
0601  * param base Pointer to the FLEXIO_UART_Type structure.
0602  * param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
0603  * param xfer FlexIO UART transfer structure. See #flexio_uart_transfer_t.
0604  * retval kStatus_Success Successfully starts the data transmission.
0605  * retval kStatus_UART_TxBusy Previous transmission still not finished, data not written to the TX register.
0606  */
0607 status_t FLEXIO_UART_TransferSendNonBlocking(FLEXIO_UART_Type *base,
0608                                              flexio_uart_handle_t *handle,
0609                                              flexio_uart_transfer_t *xfer)
0610 {
0611     status_t status;
0612 
0613     /* Return error if xfer invalid. */
0614     if ((0U == xfer->dataSize) || (NULL == xfer->txData))
0615     {
0616         return kStatus_InvalidArgument;
0617     }
0618 
0619     /* Return error if current TX busy. */
0620     if ((uint8_t)kFLEXIO_UART_TxBusy == handle->txState)
0621     {
0622         status = kStatus_FLEXIO_UART_TxBusy;
0623     }
0624     else
0625     {
0626         handle->txData        = xfer->txData;
0627         handle->txDataSize    = xfer->dataSize;
0628         handle->txDataSizeAll = xfer->dataSize;
0629         handle->txState       = (uint8_t)kFLEXIO_UART_TxBusy;
0630 
0631         /* Enable transmiter interrupt. */
0632         FLEXIO_UART_EnableInterrupts(base, (uint32_t)kFLEXIO_UART_TxDataRegEmptyInterruptEnable);
0633 
0634         status = kStatus_Success;
0635     }
0636 
0637     return status;
0638 }
0639 
0640 /*!
0641  * brief Aborts the interrupt-driven data transmit.
0642  *
0643  * This function aborts the interrupt-driven data sending. Get the remainBytes to find out
0644  * how many bytes are still not sent out.
0645  *
0646  * param base Pointer to the FLEXIO_UART_Type structure.
0647  * param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
0648  */
0649 void FLEXIO_UART_TransferAbortSend(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle)
0650 {
0651     /* Disable the transmitter and disable the interrupt. */
0652     FLEXIO_UART_DisableInterrupts(base, (uint32_t)kFLEXIO_UART_TxDataRegEmptyInterruptEnable);
0653 
0654     handle->txDataSize = 0U;
0655     handle->txState    = (uint8_t)kFLEXIO_UART_TxIdle;
0656 }
0657 
0658 /*!
0659  * brief Gets the number of bytes sent.
0660  *
0661  * This function gets the number of bytes sent driven by interrupt.
0662  *
0663  * param base Pointer to the FLEXIO_UART_Type structure.
0664  * param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
0665  * param count Number of bytes sent so far by the non-blocking transaction.
0666  * retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
0667  * retval kStatus_Success Successfully return the count.
0668  */
0669 status_t FLEXIO_UART_TransferGetSendCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count)
0670 {
0671     assert(handle != NULL);
0672     assert(count != NULL);
0673 
0674     if ((uint8_t)kFLEXIO_UART_TxIdle == handle->txState)
0675     {
0676         return kStatus_NoTransferInProgress;
0677     }
0678 
0679     *count = handle->txDataSizeAll - handle->txDataSize;
0680 
0681     return kStatus_Success;
0682 }
0683 
0684 /*!
0685  * brief Receives a buffer of data using the interrupt method.
0686  *
0687  * This function receives data using the interrupt method. This is a non-blocking function,
0688  * which returns without waiting for all data to be received.
0689  * If the RX ring buffer is used and not empty, the data in ring buffer is copied and
0690  * the parameter p receivedBytes shows how many bytes are copied from the ring buffer.
0691  * After copying, if the data in ring buffer is not enough to read, the receive
0692  * request is saved by the UART driver. When new data arrives, the receive request
0693  * is serviced first. When all data is received, the UART driver notifies the upper layer
0694  * through a callback function and passes the status parameter ref kStatus_UART_RxIdle.
0695  * For example, if the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer,
0696  * the 5 bytes are copied to xfer->data. This function returns with the
0697  * parameter p receivedBytes set to 5. For the last 5 bytes, newly arrived data is
0698  * saved from the xfer->data[5]. When 5 bytes are received, the UART driver notifies upper layer.
0699  * If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
0700  * to receive data to xfer->data. When all data is received, the upper layer is notified.
0701  *
0702  * param base Pointer to the FLEXIO_UART_Type structure.
0703  * param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
0704  * param xfer UART transfer structure. See #flexio_uart_transfer_t.
0705  * param receivedBytes Bytes received from the ring buffer directly.
0706  * retval kStatus_Success Successfully queue the transfer into the transmit queue.
0707  * retval kStatus_FLEXIO_UART_RxBusy Previous receive request is not finished.
0708  */
0709 status_t FLEXIO_UART_TransferReceiveNonBlocking(FLEXIO_UART_Type *base,
0710                                                 flexio_uart_handle_t *handle,
0711                                                 flexio_uart_transfer_t *xfer,
0712                                                 size_t *receivedBytes)
0713 {
0714     uint32_t i;
0715     status_t status;
0716     /* How many bytes to copy from ring buffer to user memory. */
0717     size_t bytesToCopy = 0U;
0718     /* How many bytes to receive. */
0719     size_t bytesToReceive;
0720     /* How many bytes currently have received. */
0721     size_t bytesCurrentReceived;
0722 
0723     /* Return error if xfer invalid. */
0724     if ((0U == xfer->dataSize) || (NULL == xfer->rxData))
0725     {
0726         return kStatus_InvalidArgument;
0727     }
0728 
0729     /* How to get data:
0730        1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize
0731           to uart handle, enable interrupt to store received data to xfer->data. When
0732           all data received, trigger callback.
0733        2. If RX ring buffer is enabled and not empty, get data from ring buffer first.
0734           If there are enough data in ring buffer, copy them to xfer->data and return.
0735           If there are not enough data in ring buffer, copy all of them to xfer->data,
0736           save the xfer->data remained empty space to uart handle, receive data
0737           to this empty space and trigger callback when finished. */
0738 
0739     if ((uint8_t)kFLEXIO_UART_RxBusy == handle->rxState)
0740     {
0741         status = kStatus_FLEXIO_UART_RxBusy;
0742     }
0743     else
0744     {
0745         bytesToReceive       = xfer->dataSize;
0746         bytesCurrentReceived = 0U;
0747 
0748         /* If RX ring buffer is used. */
0749         if (handle->rxRingBuffer != NULL)
0750         {
0751             /* Disable FLEXIO_UART RX IRQ, protect ring buffer. */
0752             FLEXIO_UART_DisableInterrupts(base, (uint32_t)kFLEXIO_UART_RxDataRegFullInterruptEnable);
0753 
0754             /* How many bytes in RX ring buffer currently. */
0755             bytesToCopy = FLEXIO_UART_TransferGetRxRingBufferLength(handle);
0756 
0757             if (bytesToCopy != 0U)
0758             {
0759                 bytesToCopy = MIN(bytesToReceive, bytesToCopy);
0760 
0761                 bytesToReceive -= bytesToCopy;
0762 
0763                 /* Copy data from ring buffer to user memory. */
0764                 for (i = 0U; i < bytesToCopy; i++)
0765                 {
0766                     xfer->rxData[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];
0767 
0768                     /* Wrap to 0. Not use modulo (%) because it might be large and slow. */
0769                     if ((uint32_t)handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
0770                     {
0771                         handle->rxRingBufferTail = 0U;
0772                     }
0773                     else
0774                     {
0775                         handle->rxRingBufferTail++;
0776                     }
0777                 }
0778             }
0779 
0780             /* If ring buffer does not have enough data, still need to read more data. */
0781             if (bytesToReceive != 0U)
0782             {
0783                 /* No data in ring buffer, save the request to UART handle. */
0784                 handle->rxData        = xfer->rxData + bytesCurrentReceived;
0785                 handle->rxDataSize    = bytesToReceive;
0786                 handle->rxDataSizeAll = xfer->dataSize;
0787                 handle->rxState       = (uint8_t)kFLEXIO_UART_RxBusy;
0788             }
0789 
0790             /* Enable FLEXIO_UART RX IRQ if previously enabled. */
0791             FLEXIO_UART_EnableInterrupts(base, (uint32_t)kFLEXIO_UART_RxDataRegFullInterruptEnable);
0792 
0793             /* Call user callback since all data are received. */
0794             if (0U == bytesToReceive)
0795             {
0796                 if (handle->callback != NULL)
0797                 {
0798                     handle->callback(base, handle, kStatus_FLEXIO_UART_RxIdle, handle->userData);
0799                 }
0800             }
0801         }
0802         /* Ring buffer not used. */
0803         else
0804         {
0805             handle->rxData        = xfer->rxData + bytesCurrentReceived;
0806             handle->rxDataSize    = bytesToReceive;
0807             handle->rxDataSizeAll = bytesToReceive;
0808             handle->rxState       = (uint8_t)kFLEXIO_UART_RxBusy;
0809 
0810             /* Enable RX interrupt. */
0811             FLEXIO_UART_EnableInterrupts(base, (uint32_t)kFLEXIO_UART_RxDataRegFullInterruptEnable);
0812         }
0813 
0814         /* Return the how many bytes have read. */
0815         if (receivedBytes != NULL)
0816         {
0817             *receivedBytes = bytesCurrentReceived;
0818         }
0819 
0820         status = kStatus_Success;
0821     }
0822 
0823     return status;
0824 }
0825 
0826 /*!
0827  * brief Aborts the receive data which was using IRQ.
0828  *
0829  * This function aborts the receive data which was using IRQ.
0830  *
0831  * param base Pointer to the FLEXIO_UART_Type structure.
0832  * param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
0833  */
0834 void FLEXIO_UART_TransferAbortReceive(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle)
0835 {
0836     /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
0837     if (NULL == handle->rxRingBuffer)
0838     {
0839         /* Disable RX interrupt. */
0840         FLEXIO_UART_DisableInterrupts(base, (uint32_t)kFLEXIO_UART_RxDataRegFullInterruptEnable);
0841     }
0842 
0843     handle->rxDataSize = 0U;
0844     handle->rxState    = (uint8_t)kFLEXIO_UART_RxIdle;
0845 }
0846 
0847 /*!
0848  * brief Gets the number of bytes received.
0849  *
0850  * This function gets the number of bytes received driven by interrupt.
0851  *
0852  * param base Pointer to the FLEXIO_UART_Type structure.
0853  * param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
0854  * param count Number of bytes received so far by the non-blocking transaction.
0855  * retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
0856  * retval kStatus_Success Successfully return the count.
0857  */
0858 status_t FLEXIO_UART_TransferGetReceiveCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count)
0859 {
0860     assert(handle != NULL);
0861     assert(count != NULL);
0862 
0863     if ((uint8_t)kFLEXIO_UART_RxIdle == handle->rxState)
0864     {
0865         return kStatus_NoTransferInProgress;
0866     }
0867 
0868     *count = handle->rxDataSizeAll - handle->rxDataSize;
0869 
0870     return kStatus_Success;
0871 }
0872 
0873 /*!
0874  * brief FlexIO UART IRQ handler function.
0875  *
0876  * This function processes the FlexIO UART transmit and receives the IRQ request.
0877  *
0878  * param uartType Pointer to the FLEXIO_UART_Type structure.
0879  * param uartHandle Pointer to the flexio_uart_handle_t structure to store the transfer state.
0880  */
0881 void FLEXIO_UART_TransferHandleIRQ(void *uartType, void *uartHandle)
0882 {
0883     uint8_t count                = 1;
0884     FLEXIO_UART_Type *base       = (FLEXIO_UART_Type *)uartType;
0885     flexio_uart_handle_t *handle = (flexio_uart_handle_t *)uartHandle;
0886     uint16_t rxRingBufferHead;
0887 
0888     /* Read the status back. */
0889     uint32_t status = FLEXIO_UART_GetStatusFlags(base);
0890 
0891     /* If RX overrun. */
0892     if (((uint32_t)kFLEXIO_UART_RxOverRunFlag & status) != 0U)
0893     {
0894         /* Clear Overrun flag. */
0895         FLEXIO_UART_ClearStatusFlags(base, (uint32_t)kFLEXIO_UART_RxOverRunFlag);
0896 
0897         /* Trigger callback. */
0898         if (handle->callback != NULL)
0899         {
0900             handle->callback(base, handle, kStatus_FLEXIO_UART_RxHardwareOverrun, handle->userData);
0901         }
0902     }
0903 
0904     /* Receive data register full */
0905     if ((((uint32_t)kFLEXIO_UART_RxDataRegFullFlag & status) != 0U) &&
0906         ((base->flexioBase->SHIFTSIEN & (1UL << base->shifterIndex[1])) != 0U))
0907     {
0908         /* If handle->rxDataSize is not 0, first save data to handle->rxData. */
0909         if (handle->rxDataSize != 0U)
0910         {
0911             /* Using non block API to read the data from the registers. */
0912             FLEXIO_UART_ReadByte(base, handle->rxData);
0913             handle->rxDataSize--;
0914             handle->rxData++;
0915             count--;
0916 
0917             /* If all the data required for upper layer is ready, trigger callback. */
0918             if (0U == handle->rxDataSize)
0919             {
0920                 handle->rxState = (uint8_t)kFLEXIO_UART_RxIdle;
0921 
0922                 if (handle->callback != NULL)
0923                 {
0924                     handle->callback(base, handle, kStatus_FLEXIO_UART_RxIdle, handle->userData);
0925                 }
0926             }
0927         }
0928 
0929         if (handle->rxRingBuffer != NULL)
0930         {
0931             if (count != 0U)
0932             {
0933                 /* If RX ring buffer is full, trigger callback to notify over run. */
0934                 if (FLEXIO_UART_TransferIsRxRingBufferFull(handle))
0935                 {
0936                     if (handle->callback != NULL)
0937                     {
0938                         handle->callback(base, handle, kStatus_FLEXIO_UART_RxRingBufferOverrun, handle->userData);
0939                     }
0940                 }
0941 
0942                 /* If ring buffer is still full after callback function, the oldest data is overridden. */
0943                 if (FLEXIO_UART_TransferIsRxRingBufferFull(handle))
0944                 {
0945                     /* Increase handle->rxRingBufferTail to make room for new data. */
0946                     if ((uint32_t)handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
0947                     {
0948                         handle->rxRingBufferTail = 0U;
0949                     }
0950                     else
0951                     {
0952                         handle->rxRingBufferTail++;
0953                     }
0954                 }
0955 
0956                 /* Read data. */
0957                 rxRingBufferHead = handle->rxRingBufferHead;
0958                 handle->rxRingBuffer[rxRingBufferHead] =
0959                     (uint8_t)(base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]]);
0960 
0961                 /* Increase handle->rxRingBufferHead. */
0962                 if ((uint32_t)handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
0963                 {
0964                     handle->rxRingBufferHead = 0U;
0965                 }
0966                 else
0967                 {
0968                     handle->rxRingBufferHead++;
0969                 }
0970             }
0971         }
0972         /* If no receive requst pending, stop RX interrupt. */
0973         else if (0U == handle->rxDataSize)
0974         {
0975             FLEXIO_UART_DisableInterrupts(base, (uint32_t)kFLEXIO_UART_RxDataRegFullInterruptEnable);
0976         }
0977         else
0978         {
0979         }
0980     }
0981 
0982     /* Send data register empty and the interrupt is enabled. */
0983     if ((((uint32_t)kFLEXIO_UART_TxDataRegEmptyFlag & status) != 0U) &&
0984         ((base->flexioBase->SHIFTSIEN & (1UL << base->shifterIndex[0])) != 0U))
0985     {
0986         if (handle->txDataSize != 0U)
0987         {
0988             /* Using non block API to write the data to the registers. */
0989             FLEXIO_UART_WriteByte(base, handle->txData);
0990             handle->txData++;
0991             handle->txDataSize--;
0992 
0993             /* If all the data are written to data register, TX finished. */
0994             if (0U == handle->txDataSize)
0995             {
0996                 handle->txState = (uint8_t)kFLEXIO_UART_TxIdle;
0997 
0998                 /* Disable TX register empty interrupt. */
0999                 FLEXIO_UART_DisableInterrupts(base, (uint32_t)kFLEXIO_UART_TxDataRegEmptyInterruptEnable);
1000 
1001                 /* Trigger callback. */
1002                 if (handle->callback != NULL)
1003                 {
1004                     handle->callback(base, handle, kStatus_FLEXIO_UART_TxIdle, handle->userData);
1005                 }
1006             }
1007         }
1008     }
1009 }