Back to home page

LXR

 
 

    


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

0001 /*
0002  * Copyright (c) 2015, Freescale Semiconductor, Inc.
0003  * Copyright 2016-2019 NXP
0004  * All rights reserved.
0005  *
0006  * SPDX-License-Identifier: BSD-3-Clause
0007  */
0008 
0009 #include "fsl_flexio_i2s.h"
0010 
0011 /* Component ID definition, used by tools. */
0012 #ifndef FSL_COMPONENT_ID
0013 #define FSL_COMPONENT_ID "platform.drivers.flexio_i2s"
0014 #endif
0015 
0016 /*******************************************************************************
0017  * Definitations
0018  ******************************************************************************/
0019 /*!@brief _sai_transfer_state*/
0020 enum
0021 {
0022     kFLEXIO_I2S_Busy = 0x0U, /*!< FLEXIO_I2S is busy */
0023     kFLEXIO_I2S_Idle,        /*!< Transfer is done. */
0024 };
0025 
0026 /*******************************************************************************
0027  * Prototypes
0028  ******************************************************************************/
0029 
0030 /*!
0031  * @brief Receive a piece of data in non-blocking way.
0032  *
0033  * @param base FLEXIO I2S base pointer
0034  * @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
0035  * @param buffer Pointer to the data to be read.
0036  * @param size Bytes to be read.
0037  */
0038 static void FLEXIO_I2S_ReadNonBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *rxData, size_t size);
0039 
0040 /*!
0041  * @brief sends a piece of data in non-blocking way.
0042  *
0043  * @param base FLEXIO I2S base pointer
0044  * @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
0045  * @param buffer Pointer to the data to be written.
0046  * @param size Bytes to be written.
0047  */
0048 static void FLEXIO_I2S_WriteNonBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *txData, size_t size);
0049 /*******************************************************************************
0050  * Variables
0051  ******************************************************************************/
0052 
0053 /*******************************************************************************
0054  * Code
0055  ******************************************************************************/
0056 
0057 static uint32_t FLEXIO_I2S_GetInstance(FLEXIO_I2S_Type *base)
0058 {
0059     return FLEXIO_GetInstance(base->flexioBase);
0060 }
0061 
0062 static void FLEXIO_I2S_WriteNonBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *txData, size_t size)
0063 {
0064     uint32_t i           = 0;
0065     uint8_t j            = 0;
0066     uint8_t bytesPerWord = bitWidth / 8U;
0067     uint32_t data        = 0;
0068     uint32_t temp        = 0;
0069 
0070     for (i = 0; i < size / bytesPerWord; i++)
0071     {
0072         for (j = 0; j < bytesPerWord; j++)
0073         {
0074             temp = (uint32_t)(*txData);
0075             data |= (temp << (8U * j));
0076             txData++;
0077         }
0078         base->flexioBase->SHIFTBUFBIS[base->txShifterIndex] = data << (32U - bitWidth);
0079         data                                                = 0;
0080     }
0081 }
0082 
0083 static void FLEXIO_I2S_ReadNonBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *rxData, size_t size)
0084 {
0085     uint32_t i           = 0;
0086     uint8_t j            = 0;
0087     uint8_t bytesPerWord = bitWidth / 8U;
0088     uint32_t data        = 0;
0089 
0090     for (i = 0; i < size / bytesPerWord; i++)
0091     {
0092         data = (base->flexioBase->SHIFTBUFBIS[base->rxShifterIndex]);
0093         for (j = 0; j < bytesPerWord; j++)
0094         {
0095             *rxData = (uint8_t)((data >> (8U * j)) & 0xFFU);
0096             rxData++;
0097         }
0098     }
0099 }
0100 
0101 /*!
0102  * brief Initializes the FlexIO I2S.
0103  *
0104  * This API configures FlexIO pins and shifter to I2S and configures the FlexIO I2S with a configuration structure.
0105  * The configuration structure can be filled by the user, or be set with default values by
0106  * FLEXIO_I2S_GetDefaultConfig().
0107  *
0108  * note  This API should be called at the beginning of the application to use
0109  * the FlexIO I2S driver. Otherwise, any access to the FlexIO I2S module can cause hard fault
0110  * because the clock is not enabled.
0111  *
0112  * param base FlexIO I2S base pointer
0113  * param config FlexIO I2S configure structure.
0114  */
0115 void FLEXIO_I2S_Init(FLEXIO_I2S_Type *base, const flexio_i2s_config_t *config)
0116 {
0117     assert((base != NULL) && (config != NULL));
0118 
0119     flexio_shifter_config_t shifterConfig = {0};
0120     flexio_timer_config_t timerConfig     = {0};
0121 
0122 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0123     /* Ungate flexio clock. */
0124     CLOCK_EnableClock(s_flexioClocks[FLEXIO_I2S_GetInstance(base)]);
0125 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0126 
0127     /* reset Flexio */
0128     FLEXIO_Reset(base->flexioBase);
0129 
0130     /* Set shifter for I2S Tx data */
0131     shifterConfig.timerSelect   = base->bclkTimerIndex;
0132     shifterConfig.pinSelect     = base->txPinIndex;
0133     shifterConfig.timerPolarity = config->txTimerPolarity;
0134     shifterConfig.pinConfig     = kFLEXIO_PinConfigOutput;
0135     shifterConfig.pinPolarity   = config->txPinPolarity;
0136     shifterConfig.shifterMode   = kFLEXIO_ShifterModeTransmit;
0137     shifterConfig.inputSource   = kFLEXIO_ShifterInputFromPin;
0138     shifterConfig.shifterStop   = kFLEXIO_ShifterStopBitDisable;
0139     if (config->masterSlave == kFLEXIO_I2S_Master)
0140     {
0141         shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
0142     }
0143     else
0144     {
0145         shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
0146     }
0147 
0148     FLEXIO_SetShifterConfig(base->flexioBase, base->txShifterIndex, &shifterConfig);
0149 
0150     /* Set shifter for I2S Rx Data */
0151     shifterConfig.timerSelect   = base->bclkTimerIndex;
0152     shifterConfig.pinSelect     = base->rxPinIndex;
0153     shifterConfig.timerPolarity = config->rxTimerPolarity;
0154     shifterConfig.pinConfig     = kFLEXIO_PinConfigOutputDisabled;
0155     shifterConfig.pinPolarity   = config->rxPinPolarity;
0156     shifterConfig.shifterMode   = kFLEXIO_ShifterModeReceive;
0157     shifterConfig.inputSource   = kFLEXIO_ShifterInputFromPin;
0158     shifterConfig.shifterStop   = kFLEXIO_ShifterStopBitDisable;
0159     shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
0160 
0161     FLEXIO_SetShifterConfig(base->flexioBase, base->rxShifterIndex, &shifterConfig);
0162 
0163     /* Set Timer to I2S frame sync */
0164     if (config->masterSlave == kFLEXIO_I2S_Master)
0165     {
0166         timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->txPinIndex);
0167         timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
0168         timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceExternal;
0169         timerConfig.pinConfig       = kFLEXIO_PinConfigOutput;
0170         timerConfig.pinSelect       = base->fsPinIndex;
0171         timerConfig.pinPolarity     = config->fsPinPolarity;
0172         timerConfig.timerMode       = kFLEXIO_TimerModeSingle16Bit;
0173         timerConfig.timerOutput     = kFLEXIO_TimerOutputOneNotAffectedByReset;
0174         timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
0175         timerConfig.timerReset      = kFLEXIO_TimerResetNever;
0176         timerConfig.timerDisable    = kFLEXIO_TimerDisableNever;
0177         timerConfig.timerEnable     = kFLEXIO_TimerEnableOnPrevTimerEnable;
0178         timerConfig.timerStart      = kFLEXIO_TimerStartBitDisabled;
0179         timerConfig.timerStop       = kFLEXIO_TimerStopBitDisabled;
0180     }
0181     else
0182     {
0183         timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->bclkPinIndex);
0184         timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
0185         timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
0186         timerConfig.pinConfig       = kFLEXIO_PinConfigOutputDisabled;
0187         timerConfig.pinSelect       = base->fsPinIndex;
0188         timerConfig.pinPolarity     = config->fsPinPolarity;
0189         timerConfig.timerMode       = kFLEXIO_TimerModeSingle16Bit;
0190         timerConfig.timerOutput     = kFLEXIO_TimerOutputOneNotAffectedByReset;
0191         timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnTriggerInputShiftTriggerInput;
0192         timerConfig.timerReset      = kFLEXIO_TimerResetNever;
0193         timerConfig.timerDisable    = kFLEXIO_TimerDisableOnTimerCompare;
0194         timerConfig.timerEnable     = kFLEXIO_TimerEnableOnPinRisingEdge;
0195         timerConfig.timerStart      = kFLEXIO_TimerStartBitDisabled;
0196         timerConfig.timerStop       = kFLEXIO_TimerStopBitDisabled;
0197     }
0198     FLEXIO_SetTimerConfig(base->flexioBase, base->fsTimerIndex, &timerConfig);
0199 
0200     /* Set Timer to I2S bit clock */
0201     if (config->masterSlave == kFLEXIO_I2S_Master)
0202     {
0203         timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->txShifterIndex);
0204         timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
0205         timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
0206         timerConfig.pinSelect       = base->bclkPinIndex;
0207         timerConfig.pinConfig       = kFLEXIO_PinConfigOutput;
0208         timerConfig.pinPolarity     = config->bclkPinPolarity;
0209         timerConfig.timerMode       = kFLEXIO_TimerModeDual8BitBaudBit;
0210         timerConfig.timerOutput     = kFLEXIO_TimerOutputOneNotAffectedByReset;
0211         timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
0212         timerConfig.timerReset      = kFLEXIO_TimerResetNever;
0213         timerConfig.timerDisable    = kFLEXIO_TimerDisableNever;
0214         timerConfig.timerEnable     = kFLEXIO_TimerEnableOnTriggerHigh;
0215         timerConfig.timerStart      = kFLEXIO_TimerStartBitEnabled;
0216         timerConfig.timerStop       = kFLEXIO_TimerStopBitDisabled;
0217     }
0218     else
0219     {
0220         timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_TIMn(base->fsTimerIndex);
0221         timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
0222         timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
0223         timerConfig.pinSelect       = base->bclkPinIndex;
0224         timerConfig.pinConfig       = kFLEXIO_PinConfigOutputDisabled;
0225         timerConfig.pinPolarity     = config->bclkPinPolarity;
0226         timerConfig.timerMode       = kFLEXIO_TimerModeSingle16Bit;
0227         timerConfig.timerOutput     = kFLEXIO_TimerOutputOneNotAffectedByReset;
0228         timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
0229         timerConfig.timerReset      = kFLEXIO_TimerResetNever;
0230         timerConfig.timerDisable    = kFLEXIO_TimerDisableOnTimerCompareTriggerLow;
0231         timerConfig.timerEnable     = kFLEXIO_TimerEnableOnPinRisingEdgeTriggerHigh;
0232         timerConfig.timerStart      = kFLEXIO_TimerStartBitDisabled;
0233         timerConfig.timerStop       = kFLEXIO_TimerStopBitDisabled;
0234     }
0235     FLEXIO_SetTimerConfig(base->flexioBase, base->bclkTimerIndex, &timerConfig);
0236 
0237     /* If enable flexio I2S */
0238     if (config->enableI2S)
0239     {
0240         base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
0241     }
0242     else
0243     {
0244         base->flexioBase->CTRL &= ~FLEXIO_CTRL_FLEXEN_MASK;
0245     }
0246 }
0247 
0248 /*!
0249  * brief  Sets the FlexIO I2S configuration structure to default values.
0250  *
0251  * The purpose of this API is to get the configuration structure initialized for use in FLEXIO_I2S_Init().
0252  * Users may use the initialized structure unchanged in FLEXIO_I2S_Init() or modify
0253  * some fields of the structure before calling FLEXIO_I2S_Init().
0254  *
0255  * param config pointer to master configuration structure
0256  */
0257 void FLEXIO_I2S_GetDefaultConfig(flexio_i2s_config_t *config)
0258 {
0259     /* Initializes the configure structure to zero. */
0260     (void)memset(config, 0, sizeof(*config));
0261 
0262     config->masterSlave     = kFLEXIO_I2S_Master;
0263     config->enableI2S       = true;
0264     config->txPinPolarity   = kFLEXIO_PinActiveHigh;
0265     config->rxPinPolarity   = kFLEXIO_PinActiveHigh;
0266     config->bclkPinPolarity = kFLEXIO_PinActiveHigh;
0267     config->fsPinPolarity   = kFLEXIO_PinActiveLow;
0268     config->txTimerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
0269     config->rxTimerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
0270 }
0271 
0272 /*!
0273  * brief De-initializes the FlexIO I2S.
0274  *
0275  * Calling this API resets the FlexIO I2S shifter and timer config. After calling this API,
0276  * call the FLEXO_I2S_Init to use the FlexIO I2S module.
0277  *
0278  * param base FlexIO I2S base pointer
0279  */
0280 void FLEXIO_I2S_Deinit(FLEXIO_I2S_Type *base)
0281 {
0282     base->flexioBase->SHIFTCFG[base->txShifterIndex] = 0;
0283     base->flexioBase->SHIFTCTL[base->txShifterIndex] = 0;
0284     base->flexioBase->SHIFTCFG[base->rxShifterIndex] = 0;
0285     base->flexioBase->SHIFTCTL[base->rxShifterIndex] = 0;
0286     base->flexioBase->TIMCFG[base->fsTimerIndex]     = 0;
0287     base->flexioBase->TIMCMP[base->fsTimerIndex]     = 0;
0288     base->flexioBase->TIMCTL[base->fsTimerIndex]     = 0;
0289     base->flexioBase->TIMCFG[base->bclkTimerIndex]   = 0;
0290     base->flexioBase->TIMCMP[base->bclkTimerIndex]   = 0;
0291     base->flexioBase->TIMCTL[base->bclkTimerIndex]   = 0;
0292 }
0293 
0294 /*!
0295  * brief Enables the FlexIO I2S interrupt.
0296  *
0297  * This function enables the FlexIO UART interrupt.
0298  *
0299  * param base Pointer to FLEXIO_I2S_Type structure
0300  * param mask interrupt source
0301  */
0302 void FLEXIO_I2S_EnableInterrupts(FLEXIO_I2S_Type *base, uint32_t mask)
0303 {
0304     if ((mask & (uint32_t)kFLEXIO_I2S_TxDataRegEmptyInterruptEnable) != 0UL)
0305     {
0306         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1UL << base->txShifterIndex);
0307     }
0308     if ((mask & (uint32_t)kFLEXIO_I2S_RxDataRegFullInterruptEnable) != 0UL)
0309     {
0310         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1UL << base->rxShifterIndex);
0311     }
0312 }
0313 
0314 /*!
0315  * brief Gets the FlexIO I2S status flags.
0316  *
0317  * param base Pointer to FLEXIO_I2S_Type structure
0318  * return Status flag, which are ORed by the enumerators in the _flexio_i2s_status_flags.
0319  */
0320 uint32_t FLEXIO_I2S_GetStatusFlags(FLEXIO_I2S_Type *base)
0321 {
0322     uint32_t status = 0;
0323     status = ((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->txShifterIndex)) >> base->txShifterIndex);
0324     status |=
0325         (((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->rxShifterIndex)) >> (base->rxShifterIndex))
0326          << 1U);
0327     return status;
0328 }
0329 
0330 /*!
0331  * brief Disables the FlexIO I2S interrupt.
0332  *
0333  * This function enables the FlexIO UART interrupt.
0334  *
0335  * param base pointer to FLEXIO_I2S_Type structure
0336  * param mask interrupt source
0337  */
0338 void FLEXIO_I2S_DisableInterrupts(FLEXIO_I2S_Type *base, uint32_t mask)
0339 {
0340     if ((mask & (uint32_t)kFLEXIO_I2S_TxDataRegEmptyInterruptEnable) != 0UL)
0341     {
0342         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1UL << base->txShifterIndex);
0343     }
0344     if ((mask & (uint32_t)kFLEXIO_I2S_RxDataRegFullInterruptEnable) != 0UL)
0345     {
0346         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1UL << base->rxShifterIndex);
0347     }
0348 }
0349 
0350 /*!
0351  * brief Configures the FlexIO I2S audio format in master mode.
0352  *
0353  * Audio format can be changed in run-time of FlexIO I2S. This function configures the sample rate and audio data
0354  * format to be transferred.
0355  *
0356  * param base Pointer to FLEXIO_I2S_Type structure
0357  * param format Pointer to FlexIO I2S audio data format structure.
0358  * param srcClock_Hz I2S master clock source frequency in Hz.
0359  */
0360 void FLEXIO_I2S_MasterSetFormat(FLEXIO_I2S_Type *base, flexio_i2s_format_t *format, uint32_t srcClock_Hz)
0361 {
0362     uint32_t timDiv  = srcClock_Hz / (format->sampleRate_Hz * format->bitWidth * 2U);
0363     uint32_t bclkDiv = 0;
0364 
0365     /* Shall keep bclk and fs div an integer */
0366     if ((timDiv % 2UL) != 0UL)
0367     {
0368         timDiv += 1U;
0369     }
0370     /* Set Frame sync timer cmp */
0371     base->flexioBase->TIMCMP[base->fsTimerIndex] = FLEXIO_TIMCMP_CMP(format->bitWidth * timDiv - 1U);
0372 
0373     /* Set bit clock timer cmp */
0374     bclkDiv                                        = ((timDiv / 2U - 1U) | ((format->bitWidth * 2UL - 1UL) << 8U));
0375     base->flexioBase->TIMCMP[base->bclkTimerIndex] = FLEXIO_TIMCMP_CMP(bclkDiv);
0376 }
0377 
0378 /*!
0379  * brief Configures the FlexIO I2S audio format in slave mode.
0380  *
0381  * Audio format can be changed in run-time of FlexIO I2S. This function configures the sample rate and audio data
0382  * format to be transferred.
0383  *
0384  * param base Pointer to FLEXIO_I2S_Type structure
0385  * param format Pointer to FlexIO I2S audio data format structure.
0386  */
0387 void FLEXIO_I2S_SlaveSetFormat(FLEXIO_I2S_Type *base, flexio_i2s_format_t *format)
0388 {
0389     /* Set Frame sync timer cmp */
0390     base->flexioBase->TIMCMP[base->fsTimerIndex] = FLEXIO_TIMCMP_CMP(format->bitWidth * 4UL - 3UL);
0391 
0392     /* Set bit clock timer cmp */
0393     base->flexioBase->TIMCMP[base->bclkTimerIndex] = FLEXIO_TIMCMP_CMP(format->bitWidth * 2UL - 1UL);
0394 }
0395 
0396 /*!
0397  * brief Sends data using a blocking method.
0398  *
0399  * note This function blocks via polling until data is ready to be sent.
0400  *
0401  * param base FlexIO I2S base pointer.
0402  * param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
0403  * param txData Pointer to the data to be written.
0404  * param size Bytes to be written.
0405  * retval kStatus_Success Successfully write data.
0406  * retval kStatus_FLEXIO_I2C_Timeout Timeout polling status flags.
0407  */
0408 status_t FLEXIO_I2S_WriteBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *txData, size_t size)
0409 {
0410     uint32_t i           = 0;
0411     uint8_t bytesPerWord = bitWidth / 8U;
0412 #if I2S_RETRY_TIMES
0413     uint32_t waitTimes = I2S_RETRY_TIMES;
0414 #endif
0415 
0416     for (i = 0; i < size / bytesPerWord; i++)
0417     {
0418         /* Wait until it can write data */
0419 #if I2S_RETRY_TIMES
0420         waitTimes = I2S_RETRY_TIMES;
0421         while (((FLEXIO_I2S_GetStatusFlags(base) & (uint32_t)kFLEXIO_I2S_TxDataRegEmptyFlag) == 0UL) &&
0422                (--waitTimes != 0U))
0423         {
0424         }
0425         if (waitTimes == 0U)
0426         {
0427             return kStatus_FLEXIO_I2S_Timeout;
0428         }
0429 #else
0430         while ((FLEXIO_I2S_GetStatusFlags(base) & (uint32_t)kFLEXIO_I2S_TxDataRegEmptyFlag) == 0UL)
0431         {
0432         }
0433 #endif
0434 
0435         FLEXIO_I2S_WriteNonBlocking(base, bitWidth, txData, bytesPerWord);
0436         txData = (uint8_t *)((uint32_t)txData + bytesPerWord);
0437     }
0438 
0439     /* Wait until the last data is sent */
0440 #if I2S_RETRY_TIMES
0441     waitTimes = I2S_RETRY_TIMES;
0442     while (((FLEXIO_I2S_GetStatusFlags(base) & (uint32_t)kFLEXIO_I2S_TxDataRegEmptyFlag) == 0UL) && (--waitTimes != 0U))
0443     {
0444     }
0445     if (waitTimes == 0U)
0446     {
0447         return kStatus_FLEXIO_I2S_Timeout;
0448     }
0449 #else
0450     while ((FLEXIO_I2S_GetStatusFlags(base) & (uint32_t)kFLEXIO_I2S_TxDataRegEmptyFlag) == 0UL)
0451     {
0452     }
0453 #endif
0454 
0455     return kStatus_Success;
0456 }
0457 
0458 /*!
0459  * brief Receives a piece of data using a blocking method.
0460  *
0461  * note This function blocks via polling until data is ready to be sent.
0462  *
0463  * param base FlexIO I2S base pointer
0464  * param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
0465  * param rxData Pointer to the data to be read.
0466  * param size Bytes to be read.
0467  * retval kStatus_Success Successfully read data.
0468  * retval kStatus_FLEXIO_I2C_Timeout Timeout polling status flags.
0469  */
0470 status_t FLEXIO_I2S_ReadBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *rxData, size_t size)
0471 {
0472     uint32_t i           = 0;
0473     uint8_t bytesPerWord = bitWidth / 8U;
0474 #if I2S_RETRY_TIMES
0475     uint32_t waitTimes = I2S_RETRY_TIMES;
0476 #endif
0477 
0478     for (i = 0; i < size / bytesPerWord; i++)
0479     {
0480         /* Wait until data is received */
0481 #if I2S_RETRY_TIMES
0482         waitTimes = I2S_RETRY_TIMES;
0483         while ((!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->rxShifterIndex)) != 0UL)) &&
0484                (--waitTimes != 0U))
0485         {
0486         }
0487         if (waitTimes == 0U)
0488         {
0489             return kStatus_FLEXIO_I2S_Timeout;
0490         }
0491 #else
0492         while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->rxShifterIndex)) != 0UL))
0493         {
0494         }
0495 #endif
0496 
0497         FLEXIO_I2S_ReadNonBlocking(base, bitWidth, rxData, bytesPerWord);
0498         rxData = (uint8_t *)((uint32_t)rxData + bytesPerWord);
0499     }
0500     return kStatus_Success;
0501 }
0502 
0503 /*!
0504  * brief Initializes the FlexIO I2S handle.
0505  *
0506  * This function initializes the FlexIO I2S handle which can be used for other
0507  * FlexIO I2S transactional APIs. Call this API once to get the
0508  * initialized handle.
0509  *
0510  * param base Pointer to FLEXIO_I2S_Type structure
0511  * param handle Pointer to flexio_i2s_handle_t structure to store the transfer state.
0512  * param callback FlexIO I2S callback function, which is called while finished a block.
0513  * param userData User parameter for the FlexIO I2S callback.
0514  */
0515 void FLEXIO_I2S_TransferTxCreateHandle(FLEXIO_I2S_Type *base,
0516                                        flexio_i2s_handle_t *handle,
0517                                        flexio_i2s_callback_t callback,
0518                                        void *userData)
0519 {
0520     assert(handle != NULL);
0521 
0522     IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
0523 
0524     /* Zero the handle. */
0525     (void)memset(handle, 0, sizeof(*handle));
0526 
0527     /* Store callback and user data. */
0528     handle->callback = callback;
0529     handle->userData = userData;
0530 
0531     /* Save the context in global variables to support the double weak mechanism. */
0532     (void)FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_I2S_TransferTxHandleIRQ);
0533 
0534     /* Set the TX/RX state. */
0535     handle->state = (uint32_t)kFLEXIO_I2S_Idle;
0536 
0537     /* Enable interrupt in NVIC. */
0538     (void)EnableIRQ(flexio_irqs[FLEXIO_I2S_GetInstance(base)]);
0539 }
0540 
0541 /*!
0542  * brief Initializes the FlexIO I2S receive handle.
0543  *
0544  * This function initializes the FlexIO I2S handle which can be used for other
0545  * FlexIO I2S transactional APIs. Call this API once to get the
0546  * initialized handle.
0547  *
0548  * param base Pointer to FLEXIO_I2S_Type structure.
0549  * param handle Pointer to flexio_i2s_handle_t structure to store the transfer state.
0550  * param callback FlexIO I2S callback function, which is called while finished a block.
0551  * param userData User parameter for the FlexIO I2S callback.
0552  */
0553 void FLEXIO_I2S_TransferRxCreateHandle(FLEXIO_I2S_Type *base,
0554                                        flexio_i2s_handle_t *handle,
0555                                        flexio_i2s_callback_t callback,
0556                                        void *userData)
0557 {
0558     assert(handle != NULL);
0559 
0560     IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
0561 
0562     /* Zero the handle. */
0563     (void)memset(handle, 0, sizeof(*handle));
0564 
0565     /* Store callback and user data. */
0566     handle->callback = callback;
0567     handle->userData = userData;
0568 
0569     /* Save the context in global variables to support the double weak mechanism. */
0570     (void)FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_I2S_TransferRxHandleIRQ);
0571 
0572     /* Set the TX/RX state. */
0573     handle->state = (uint32_t)kFLEXIO_I2S_Idle;
0574 
0575     /* Enable interrupt in NVIC. */
0576     (void)EnableIRQ(flexio_irqs[FLEXIO_I2S_GetInstance(base)]);
0577 }
0578 
0579 /*!
0580  * brief Configures the FlexIO I2S audio format.
0581  *
0582  * Audio format can be changed at run-time of FlexIO I2S. This function configures the sample rate and audio data
0583  * format to be transferred.
0584  *
0585  * param base Pointer to FLEXIO_I2S_Type structure.
0586  * param handle FlexIO I2S handle pointer.
0587  * param format Pointer to audio data format structure.
0588  * param srcClock_Hz FlexIO I2S bit clock source frequency in Hz. This parameter should be 0 while in slave mode.
0589  */
0590 void FLEXIO_I2S_TransferSetFormat(FLEXIO_I2S_Type *base,
0591                                   flexio_i2s_handle_t *handle,
0592                                   flexio_i2s_format_t *format,
0593                                   uint32_t srcClock_Hz)
0594 {
0595     assert((handle != NULL) && (format != NULL));
0596 
0597     /* Set the bitWidth to handle */
0598     handle->bitWidth = format->bitWidth;
0599 
0600     /* Set sample rate */
0601     if (srcClock_Hz != 0UL)
0602     {
0603         /* It is master */
0604         FLEXIO_I2S_MasterSetFormat(base, format, srcClock_Hz);
0605     }
0606     else
0607     {
0608         FLEXIO_I2S_SlaveSetFormat(base, format);
0609     }
0610 }
0611 
0612 /*!
0613  * brief Performs an interrupt non-blocking send transfer on FlexIO I2S.
0614  *
0615  * note The API returns immediately after transfer initiates.
0616  * Call FLEXIO_I2S_GetRemainingBytes to poll the transfer status and check whether
0617  * the transfer is finished. If the return status is 0, the transfer is finished.
0618  *
0619  * param base Pointer to FLEXIO_I2S_Type structure.
0620  * param handle Pointer to flexio_i2s_handle_t structure which stores the transfer state
0621  * param xfer Pointer to flexio_i2s_transfer_t structure
0622  * retval kStatus_Success Successfully start the data transmission.
0623  * retval kStatus_FLEXIO_I2S_TxBusy Previous transmission still not finished, data not all written to TX register yet.
0624  * retval kStatus_InvalidArgument The input parameter is invalid.
0625  */
0626 status_t FLEXIO_I2S_TransferSendNonBlocking(FLEXIO_I2S_Type *base,
0627                                             flexio_i2s_handle_t *handle,
0628                                             flexio_i2s_transfer_t *xfer)
0629 {
0630     assert(handle != NULL);
0631 
0632     /* Check if the queue is full */
0633     if (handle->queue[handle->queueUser].data != NULL)
0634     {
0635         return kStatus_FLEXIO_I2S_QueueFull;
0636     }
0637     if ((xfer->dataSize == 0U) || (xfer->data == NULL))
0638     {
0639         return kStatus_InvalidArgument;
0640     }
0641 
0642     /* Add into queue */
0643     handle->queue[handle->queueUser].data     = xfer->data;
0644     handle->queue[handle->queueUser].dataSize = xfer->dataSize;
0645     handle->transferSize[handle->queueUser]   = xfer->dataSize;
0646     handle->queueUser                         = (handle->queueUser + 1U) % FLEXIO_I2S_XFER_QUEUE_SIZE;
0647 
0648     /* Set the state to busy */
0649     handle->state = (uint32_t)kFLEXIO_I2S_Busy;
0650 
0651     FLEXIO_I2S_EnableInterrupts(base, kFLEXIO_I2S_TxDataRegEmptyInterruptEnable);
0652 
0653     /* Enable Tx transfer */
0654     FLEXIO_I2S_Enable(base, true);
0655 
0656     return kStatus_Success;
0657 }
0658 
0659 /*!
0660  * brief Performs an interrupt non-blocking receive transfer on FlexIO I2S.
0661  *
0662  * note The API returns immediately after transfer initiates.
0663  * Call FLEXIO_I2S_GetRemainingBytes to poll the transfer status to check whether
0664  * the transfer is finished. If the return status is 0, the transfer is finished.
0665  *
0666  * param base Pointer to FLEXIO_I2S_Type structure.
0667  * param handle Pointer to flexio_i2s_handle_t structure which stores the transfer state
0668  * param xfer Pointer to flexio_i2s_transfer_t structure
0669  * retval kStatus_Success Successfully start the data receive.
0670  * retval kStatus_FLEXIO_I2S_RxBusy Previous receive still not finished.
0671  * retval kStatus_InvalidArgument The input parameter is invalid.
0672  */
0673 status_t FLEXIO_I2S_TransferReceiveNonBlocking(FLEXIO_I2S_Type *base,
0674                                                flexio_i2s_handle_t *handle,
0675                                                flexio_i2s_transfer_t *xfer)
0676 {
0677     assert(handle != NULL);
0678 
0679     /* Check if the queue is full */
0680     if (handle->queue[handle->queueUser].data != NULL)
0681     {
0682         return kStatus_FLEXIO_I2S_QueueFull;
0683     }
0684 
0685     if ((xfer->dataSize == 0U) || (xfer->data == NULL))
0686     {
0687         return kStatus_InvalidArgument;
0688     }
0689 
0690     /* Add into queue */
0691     handle->queue[handle->queueUser].data     = xfer->data;
0692     handle->queue[handle->queueUser].dataSize = xfer->dataSize;
0693     handle->transferSize[handle->queueUser]   = xfer->dataSize;
0694     handle->queueUser                         = (handle->queueUser + 1U) % FLEXIO_I2S_XFER_QUEUE_SIZE;
0695 
0696     /* Set state to busy */
0697     handle->state = (uint32_t)kFLEXIO_I2S_Busy;
0698 
0699     /* Enable interrupt */
0700     FLEXIO_I2S_EnableInterrupts(base, kFLEXIO_I2S_RxDataRegFullInterruptEnable);
0701 
0702     /* Enable Rx transfer */
0703     FLEXIO_I2S_Enable(base, true);
0704 
0705     return kStatus_Success;
0706 }
0707 
0708 /*!
0709  * brief Aborts the current send.
0710  *
0711  * note This API can be called at any time when interrupt non-blocking transfer initiates
0712  * to abort the transfer in a early time.
0713  *
0714  * param base Pointer to FLEXIO_I2S_Type structure.
0715  * param handle Pointer to flexio_i2s_handle_t structure which stores the transfer state
0716  */
0717 void FLEXIO_I2S_TransferAbortSend(FLEXIO_I2S_Type *base, flexio_i2s_handle_t *handle)
0718 {
0719     assert(handle != NULL);
0720 
0721     /* Stop Tx transfer and disable interrupt */
0722     FLEXIO_I2S_DisableInterrupts(base, kFLEXIO_I2S_TxDataRegEmptyInterruptEnable);
0723     handle->state = (uint32_t)kFLEXIO_I2S_Idle;
0724 
0725     /* Clear the queue */
0726     (void)memset(handle->queue, 0, sizeof(flexio_i2s_transfer_t) * FLEXIO_I2S_XFER_QUEUE_SIZE);
0727     handle->queueDriver = 0;
0728     handle->queueUser   = 0;
0729 }
0730 
0731 /*!
0732  * brief Aborts the current receive.
0733  *
0734  * note This API can be called at any time when interrupt non-blocking transfer initiates
0735  * to abort the transfer in a early time.
0736  *
0737  * param base Pointer to FLEXIO_I2S_Type structure.
0738  * param handle Pointer to flexio_i2s_handle_t structure which stores the transfer state
0739  */
0740 void FLEXIO_I2S_TransferAbortReceive(FLEXIO_I2S_Type *base, flexio_i2s_handle_t *handle)
0741 {
0742     assert(handle != NULL);
0743 
0744     /* Stop rx transfer and disable interrupt */
0745     FLEXIO_I2S_DisableInterrupts(base, kFLEXIO_I2S_RxDataRegFullInterruptEnable);
0746     handle->state = (uint32_t)kFLEXIO_I2S_Idle;
0747 
0748     /* Clear the queue */
0749     (void)memset(handle->queue, 0, sizeof(flexio_i2s_transfer_t) * FLEXIO_I2S_XFER_QUEUE_SIZE);
0750     handle->queueDriver = 0;
0751     handle->queueUser   = 0;
0752 }
0753 
0754 /*!
0755  * brief Gets the remaining bytes to be sent.
0756  *
0757  * param base Pointer to FLEXIO_I2S_Type structure.
0758  * param handle Pointer to flexio_i2s_handle_t structure which stores the transfer state
0759  * param count Bytes sent.
0760  * retval kStatus_Success Succeed get the transfer count.
0761  * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
0762  */
0763 status_t FLEXIO_I2S_TransferGetSendCount(FLEXIO_I2S_Type *base, flexio_i2s_handle_t *handle, size_t *count)
0764 {
0765     assert(handle != NULL);
0766 
0767     status_t status     = kStatus_Success;
0768     uint8_t queueDriver = handle->queueDriver;
0769 
0770     if (handle->state != (uint32_t)kFLEXIO_I2S_Busy)
0771     {
0772         status = kStatus_NoTransferInProgress;
0773     }
0774     else
0775     {
0776         *count = (handle->transferSize[queueDriver] - handle->queue[queueDriver].dataSize);
0777     }
0778 
0779     return status;
0780 }
0781 
0782 /*!
0783  * brief Gets the remaining bytes to be received.
0784  *
0785  * param base Pointer to FLEXIO_I2S_Type structure.
0786  * param handle Pointer to flexio_i2s_handle_t structure which stores the transfer state
0787  * return count Bytes received.
0788  * retval kStatus_Success Succeed get the transfer count.
0789  * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
0790  */
0791 status_t FLEXIO_I2S_TransferGetReceiveCount(FLEXIO_I2S_Type *base, flexio_i2s_handle_t *handle, size_t *count)
0792 {
0793     assert(handle != NULL);
0794 
0795     status_t status     = kStatus_Success;
0796     uint8_t queueDriver = handle->queueDriver;
0797 
0798     if (handle->state != (uint32_t)kFLEXIO_I2S_Busy)
0799     {
0800         status = kStatus_NoTransferInProgress;
0801     }
0802     else
0803     {
0804         *count = (handle->transferSize[queueDriver] - handle->queue[queueDriver].dataSize);
0805     }
0806 
0807     return status;
0808 }
0809 
0810 /*!
0811  * brief Tx interrupt handler.
0812  *
0813  * param i2sBase Pointer to FLEXIO_I2S_Type structure.
0814  * param i2sHandle Pointer to flexio_i2s_handle_t structure
0815  */
0816 void FLEXIO_I2S_TransferTxHandleIRQ(void *i2sBase, void *i2sHandle)
0817 {
0818     assert(i2sHandle != NULL);
0819 
0820     flexio_i2s_handle_t *handle = (flexio_i2s_handle_t *)i2sHandle;
0821     FLEXIO_I2S_Type *base       = (FLEXIO_I2S_Type *)i2sBase;
0822     uint8_t *buffer             = handle->queue[handle->queueDriver].data;
0823     uint8_t dataSize            = handle->bitWidth / 8U;
0824 
0825     /* Handle error */
0826     if ((FLEXIO_GetShifterErrorFlags(base->flexioBase) & (1UL << base->txShifterIndex)) != 0UL)
0827     {
0828         FLEXIO_ClearShifterErrorFlags(base->flexioBase, (1UL << base->txShifterIndex));
0829     }
0830     /* Handle transfer */
0831     if (((FLEXIO_I2S_GetStatusFlags(base) & (uint32_t)kFLEXIO_I2S_TxDataRegEmptyFlag) != 0UL) &&
0832         (handle->queue[handle->queueDriver].data != NULL))
0833     {
0834         FLEXIO_I2S_WriteNonBlocking(base, handle->bitWidth, buffer, dataSize);
0835 
0836         /* Update internal counter */
0837         handle->queue[handle->queueDriver].dataSize -= dataSize;
0838         handle->queue[handle->queueDriver].data =
0839             (uint8_t *)((uint32_t)handle->queue[handle->queueDriver].data + dataSize);
0840     }
0841 
0842     /* If finished a block, call the callback function */
0843     if ((handle->queue[handle->queueDriver].dataSize == 0U) && (handle->queue[handle->queueDriver].data != NULL))
0844     {
0845         (void)memset(&handle->queue[handle->queueDriver], 0, sizeof(flexio_i2s_transfer_t));
0846         handle->queueDriver = (handle->queueDriver + 1U) % FLEXIO_I2S_XFER_QUEUE_SIZE;
0847         if (handle->callback != NULL)
0848         {
0849             (handle->callback)(base, handle, kStatus_Success, handle->userData);
0850         }
0851     }
0852 
0853     /* If all data finished, just stop the transfer */
0854     if (handle->queue[handle->queueDriver].data == NULL)
0855     {
0856         FLEXIO_I2S_TransferAbortSend(base, handle);
0857     }
0858 }
0859 
0860 /*!
0861  * brief Rx interrupt handler.
0862  *
0863  * param i2sBase Pointer to FLEXIO_I2S_Type structure.
0864  * param i2sHandle Pointer to flexio_i2s_handle_t structure.
0865  */
0866 void FLEXIO_I2S_TransferRxHandleIRQ(void *i2sBase, void *i2sHandle)
0867 {
0868     assert(i2sHandle != NULL);
0869 
0870     flexio_i2s_handle_t *handle = (flexio_i2s_handle_t *)i2sHandle;
0871     FLEXIO_I2S_Type *base       = (FLEXIO_I2S_Type *)i2sBase;
0872     uint8_t *buffer             = handle->queue[handle->queueDriver].data;
0873     uint8_t dataSize            = handle->bitWidth / 8U;
0874 
0875     /* Handle transfer */
0876     if (((FLEXIO_I2S_GetStatusFlags(base) & (uint32_t)kFLEXIO_I2S_RxDataRegFullFlag) != 0UL) &&
0877         (handle->queue[handle->queueDriver].data != NULL))
0878     {
0879         FLEXIO_I2S_ReadNonBlocking(base, handle->bitWidth, buffer, dataSize);
0880 
0881         /* Update internal state */
0882         handle->queue[handle->queueDriver].dataSize -= dataSize;
0883         handle->queue[handle->queueDriver].data =
0884             (uint8_t *)((uint32_t)handle->queue[handle->queueDriver].data + dataSize);
0885     }
0886 
0887     /* If finished a block, call the callback function */
0888     if ((handle->queue[handle->queueDriver].dataSize == 0U) && (handle->queue[handle->queueDriver].data != NULL))
0889     {
0890         (void)memset(&handle->queue[handle->queueDriver], 0, sizeof(flexio_i2s_transfer_t));
0891         handle->queueDriver = (handle->queueDriver + 1U) % FLEXIO_I2S_XFER_QUEUE_SIZE;
0892         if (handle->callback != NULL)
0893         {
0894             (handle->callback)(base, handle, kStatus_Success, handle->userData);
0895         }
0896     }
0897 
0898     /* If all data finished, just stop the transfer */
0899     if (handle->queue[handle->queueDriver].data == NULL)
0900     {
0901         FLEXIO_I2S_TransferAbortReceive(base, handle);
0902     }
0903 }