summaryrefslogtreecommitdiffstats
path: root/bsps/arm/imxrt/mcux-sdk/drivers/asrc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc.c1031
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc.h761
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc_edma.c470
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc_edma.h245
4 files changed, 2507 insertions, 0 deletions
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc.c b/bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc.c
new file mode 100644
index 0000000000..be4f6c1b4d
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc.c
@@ -0,0 +1,1031 @@
+/*
+ * Copyright 2019-2021 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_asrc.h"
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.asrc"
+#endif
+
+/*******************************************************************************
+ * Definitations
+ ******************************************************************************/
+/*! @brief Typedef for asrc tx interrupt handler. */
+typedef void (*asrc_isr_t)(ASRC_Type *base, asrc_handle_t *asrcHandle);
+/*! @brief ASRC support maximum channel number */
+#define ASRC_SUPPORT_MAXIMUM_CHANNEL_NUMER (10U)
+#define ASRC_SAMPLE_RATIO_DECIMAL_DEPTH (26U)
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+/*!
+ * @brief ASRC read non blocking.
+ *
+ * @param base ASRC base pointer.
+ * @param channelPair ASRC channel pair.
+ * @param destAddress dest buffer address.
+ * @param samples number of samples to read.
+ * @param sampleWidth the width that one sample takes.
+ */
+static void ASRC_ReadNonBlocking(
+ ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *destAddress, uint32_t samples, uint32_t sampleWidth);
+
+/*!
+ * @brief ASRC write non blocking.
+ *
+ * @param base ASRC base pointer.
+ * @param channelPair ASRC channel pair.
+ * @param srcAddress source buffer address.
+ * @param samples number of samples to read.
+ * @param sampleMask the mask of sample data.
+ * @param sampleWidth the width that one sample takes.
+ */
+static void ASRC_WriteNonBlocking(ASRC_Type *base,
+ asrc_channel_pair_t channelPair,
+ const uint32_t *srcAddress,
+ uint32_t samples,
+ uint32_t sampleMask,
+ uint32_t sampleWidth);
+
+/*!
+ * @brief ASRC calculate divider and prescaler.
+ *
+ * @param sampleRate_Hz sample rate.
+ * @param sourceClock_Hz source clock.
+ */
+static uint32_t ASRC_CalculateClockDivider(uint32_t sampleRate_Hz, uint32_t sourceClock_Hz);
+
+/*!
+ * @brief ASRC pre/post processing selection.
+ *
+ * @param inSampleRate in audio data sample rate.
+ * @param outSampleRate out audio data sample rate.
+ * @param preProc pre processing selection.
+ * @param postProc post precessing selection.
+ */
+static status_t ASRC_ProcessSelection(uint32_t inSampleRate,
+ uint32_t outSampleRate,
+ uint32_t *preProc,
+ uint32_t *postProc);
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+/* Base pointer array */
+static ASRC_Type *const s_asrcBases[] = ASRC_BASE_PTRS;
+/*!@brief asrc handle pointer */
+static asrc_handle_t *s_asrcHandle[ARRAY_SIZE(s_asrcBases)][FSL_ASRC_CHANNEL_PAIR_COUNT];
+/* IRQ number array */
+static const IRQn_Type s_asrcIRQ[] = ASRC_IRQS;
+
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+/* Clock name array */
+static const clock_ip_name_t s_asrcClock[] = ASRC_CLOCKS;
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+/*! @brief Pointer to IRQ handler for each instance. */
+static asrc_isr_t s_asrcIsr;
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+uint32_t ASRC_GetInstance(ASRC_Type *base)
+{
+ uint32_t instance;
+
+ /* Find the instance index from base address mappings. */
+ for (instance = 0; instance < ARRAY_SIZE(s_asrcBases); instance++)
+ {
+ if (s_asrcBases[instance] == base)
+ {
+ break;
+ }
+ }
+
+ assert(instance < ARRAY_SIZE(s_asrcBases));
+
+ return instance;
+}
+
+static void ASRC_ReadNonBlocking(
+ ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *destAddress, uint32_t samples, uint32_t sampleWidth)
+{
+ uint32_t i = 0U;
+ uint32_t *destAddr = destAddress;
+ volatile uint32_t *srcAddr = ASRC_ASRDO_ADDR(base, channelPair);
+
+ for (i = 0U; i < samples; i++)
+ {
+ *destAddr = *srcAddr;
+ destAddr = (uint32_t *)((uint32_t)destAddr + sampleWidth);
+ }
+}
+
+static void ASRC_WriteNonBlocking(ASRC_Type *base,
+ asrc_channel_pair_t channelPair,
+ const uint32_t *srcAddress,
+ uint32_t samples,
+ uint32_t sampleMask,
+ uint32_t sampleWidth)
+{
+ uint32_t i = 0U;
+ const uint32_t *srcAddr = srcAddress;
+ volatile uint32_t *destAddr = ASRC_ASRDI_ADDR(base, channelPair);
+
+ for (i = 0U; i < samples; i++)
+ {
+ *destAddr = *srcAddr & sampleMask;
+ srcAddr = (uint32_t *)((uint32_t)srcAddr + sampleWidth);
+ }
+}
+
+static uint32_t ASRC_CalculateClockDivider(uint32_t sampleRate_Hz, uint32_t sourceClock_Hz)
+{
+ assert(sourceClock_Hz >= sampleRate_Hz);
+
+ uint32_t divider = sourceClock_Hz / sampleRate_Hz;
+ uint32_t prescaler = 0U;
+
+ /* sourceClock_Hz = sampleRate_Hz * divider * (2 ^ prescaler) */
+ while (divider > 8U)
+ {
+ divider >>= 1U;
+ prescaler++;
+ }
+ /* Hardware limitation:
+ * If the prescaler is set to 1, the clock divider can only be set to 1 and the clock source must have a 50% duty
+ * cycle
+ */
+ if ((prescaler == 1U) && (divider != 1U))
+ {
+ divider >>= 1U;
+ prescaler++;
+ }
+ /* fine tuning */
+ if (sourceClock_Hz / ((1UL << prescaler) * divider) > sampleRate_Hz)
+ {
+ divider++;
+ }
+
+ return ((divider - 1U) << 3U) | (prescaler & 0x7U);
+}
+
+static status_t ASRC_ProcessSelection(uint32_t inSampleRate,
+ uint32_t outSampleRate,
+ uint32_t *preProc,
+ uint32_t *postProc)
+{
+ bool op2Cond = false;
+ bool op0Cond = false;
+
+ op2Cond = (((inSampleRate * 15U > outSampleRate * 16U) && (outSampleRate < 56000U)) ||
+ ((inSampleRate > 56000U) && (outSampleRate < 56000U)));
+ op0Cond = (inSampleRate * 23U < outSampleRate * 8U);
+
+ /* preProc == 4 or preProc == 5 is not support now */
+ if ((inSampleRate * 8U > 129U * outSampleRate) || ((inSampleRate * 8U > 65U * outSampleRate)))
+ {
+ return kStatus_ASRCNotSupport;
+ }
+
+ if (inSampleRate * 8U > 33U * outSampleRate)
+ {
+ *preProc = 2U;
+ }
+ else if (inSampleRate * 8U > 15U * outSampleRate)
+ {
+ if (inSampleRate > 152000U)
+ {
+ *preProc = 2U;
+ }
+ else
+ {
+ *preProc = 1U;
+ }
+ }
+ else if (inSampleRate < 76000U)
+ {
+ *preProc = 0;
+ }
+ else if (inSampleRate > 152000U)
+ {
+ *preProc = 2;
+ }
+ else
+ {
+ *preProc = 1;
+ }
+
+ if (op2Cond)
+ {
+ *postProc = 2;
+ }
+ else if (op0Cond)
+ {
+ *postProc = 0;
+ }
+ else
+ {
+ *postProc = 1;
+ }
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Map register sample width to real sample width.
+ *
+ * note This API is depends on the ASRC configuration, should be called after the ASRC_SetChannelPairConfig.
+ * param base asrc base pointer.
+ * param channelPair asrc channel pair index.
+ * param inWidth ASRC channel pair number.
+ * param outWidth input sample rate.
+ * retval input sample mask value.
+ */
+uint32_t ASRC_MapSamplesWidth(ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *inWidth, uint32_t *outWidth)
+{
+ uint32_t sampleMask = 0U,
+ inRegWidth = (ASRC_ASRMCR1(base, channelPair) & ASRC_ASRMCR1_IWD_MASK) >> ASRC_ASRMCR1_IWD_SHIFT,
+ outRegWidth = ASRC_ASRMCR1(base, channelPair) & ASRC_ASRMCR1_OW16_MASK,
+ inDataAlign = (ASRC_ASRMCR1(base, channelPair) & ASRC_ASRMCR1_IMSB_MASK) >> ASRC_ASRMCR1_IMSB_SHIFT,
+ outDataAlign = (ASRC_ASRMCR1(base, channelPair) & ASRC_ASRMCR1_OMSB_MASK) >> ASRC_ASRMCR1_OMSB_SHIFT;
+ /* get in sample width */
+ if (inRegWidth == (uint32_t)kASRC_DataWidth8Bit)
+ {
+ *inWidth = 1U;
+ sampleMask = 0xFFU;
+ if (inDataAlign == (uint32_t)kASRC_DataAlignMSB)
+ {
+ *inWidth = 2U;
+ sampleMask = 0xFF00U;
+ }
+ }
+ else if (inRegWidth == (uint32_t)kASRC_DataWidth16Bit)
+ {
+ *inWidth = 2U;
+ sampleMask = 0xFFFFU;
+ if (inDataAlign == (uint32_t)kASRC_DataAlignMSB)
+ {
+ *inWidth = 4U;
+ sampleMask = 0xFFFF0000U;
+ }
+ }
+ else
+ {
+ *inWidth = 3U;
+ sampleMask = 0xFFFFFFU;
+
+ if (inDataAlign == (uint32_t)kASRC_DataAlignMSB)
+ {
+ sampleMask = 0xFFFFFF00U;
+ *inWidth = 4U;
+ }
+ }
+ /* get out sample width */
+ if (outRegWidth == (uint32_t)kASRC_DataWidth16Bit)
+ {
+ *outWidth = 2U;
+ if (outDataAlign == (uint32_t)kASRC_DataAlignMSB)
+ {
+ *outWidth = 4U;
+ }
+ }
+ else
+ {
+ *outWidth = 4U;
+ }
+
+ return sampleMask;
+}
+
+/*!
+ * brief ASRC configure ideal ratio.
+ * The ideal ratio should be used when input clock source is not avalible.
+ *
+ * param base ASRC base pointer.
+ * param channelPair ASRC channel pair.
+ * param inputSampleRate input audio data sample rate.
+ * param outputSampleRate output audio data sample rate.
+ */
+status_t ASRC_SetIdealRatioConfig(ASRC_Type *base,
+ asrc_channel_pair_t channelPair,
+ uint32_t inputSampleRate,
+ uint32_t outputSampleRate)
+{
+ uint32_t ratio = 0U, i = 0U;
+ uint32_t preProc = 0U, postProc = 0U;
+ uint32_t asrcfg = base->ASRCFG;
+ /* caculate integer part */
+ ratio = (inputSampleRate / outputSampleRate) << ASRC_SAMPLE_RATIO_DECIMAL_DEPTH;
+
+ inputSampleRate %= outputSampleRate;
+ /* get decimal part */
+ for (i = 1U; i <= ASRC_SAMPLE_RATIO_DECIMAL_DEPTH; i++)
+ {
+ inputSampleRate <<= 1;
+
+ if (inputSampleRate < outputSampleRate)
+ {
+ continue;
+ }
+
+ ratio |= 1UL << (ASRC_SAMPLE_RATIO_DECIMAL_DEPTH - i);
+ inputSampleRate -= outputSampleRate;
+
+ if (0U == inputSampleRate)
+ {
+ break;
+ }
+ }
+ /* select pre/post precessing option */
+ if (ASRC_ProcessSelection(inputSampleRate, outputSampleRate, &preProc, &postProc) != kStatus_Success)
+ {
+ return kStatus_ASRCNotSupport;
+ }
+
+ ASRC_IDEAL_RATIO_HIGH(base, channelPair) = ASRC_ASRIDRHA_IDRATIOA_H(ratio >> 24U);
+ ASRC_IDEAL_RATIO_LOW(base, channelPair) = ASRC_ASRIDRLA_IDRATIOA_L(ratio);
+ base->ASRCTR &= ~ASRC_ASRCTR_AT_MASK(channelPair);
+ asrcfg &= ~(ASRC_ASRCFG_PRE_MODE_MASK(channelPair) | ASRC_ASRCFG_POST_MODE_MASK(channelPair));
+ asrcfg |= ASRC_ASRCFG_PRE_MODE(preProc, channelPair) | ASRC_ASRCFG_POST_MODE(postProc, channelPair);
+ base->ASRCFG = asrcfg;
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Initializes the asrc peripheral.
+ *
+ * This API gates the asrc clock. The asrc module can't operate unless ASRC_Init is called to enable the clock.
+ *
+ * param base asrc base pointer.
+ * param asrcPeripheralClock_Hz peripheral clock of ASRC.
+ */
+void ASRC_Init(ASRC_Type *base, uint32_t asrcPeripheralClock_Hz)
+{
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+ /* Enable the asrc clock */
+ CLOCK_EnableClock(s_asrcClock[ASRC_GetInstance(base)]);
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+
+ /* disable ASRC channel pair, enable ASRC */
+ base->ASRCTR = 1U;
+
+ /* disable all the interrupt */
+ base->ASRIER = 0U;
+
+#if (defined FSL_FEATURE_ASRC_PARAMETER_REGISTER_NAME_ASRPM) && FSL_FEATURE_ASRC_PARAMETER_REGISTER_NAME_ASRPM
+ /* set paramter register to default configurations per recommand value in reference manual */
+ base->ASRPM[0] = 0x7fffffU;
+ base->ASRPM[1] = 0x255555U;
+ base->ASRPM[2] = 0xff7280U;
+ base->ASRPM[3] = 0xff7280U;
+ base->ASRPM[4] = 0xff7280U;
+#else
+ /* set paramter register to default configurations per recommand value in reference manual */
+ base->ASRPMn[0] = 0x7fffffU;
+ base->ASRPMn[1] = 0x255555U;
+ base->ASRPMn[2] = 0xff7280U;
+ base->ASRPMn[3] = 0xff7280U;
+ base->ASRPMn[4] = 0xff7280U;
+#endif /*FSL_FEATURE_ASRC_PARAMETER_REGISTER_NAME_ASRPM*/
+ /* set task queue fifo */
+ base->ASRTFR1 = ASRC_ASRTFR1_TF_BASE(0x7C);
+ /* 76K/56K divider */
+ base->ASR76K = ASRC_ASR76K_ASR76K(asrcPeripheralClock_Hz / 76000U);
+ base->ASR56K = ASRC_ASR56K_ASR56K(asrcPeripheralClock_Hz / 56000U);
+}
+
+/*!
+ * brief De-initializes the ASRC peripheral.
+ *
+ * This API gates the ASRC clock and disable ASRC module. The ASRC module can't operate unless ASRC_Init
+ *
+ * param base ASRC base pointer.
+ */
+void ASRC_Deinit(ASRC_Type *base)
+{
+ /* disable ASRC module */
+ ASRC_ModuleEnable(base, false);
+
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+ CLOCK_DisableClock(s_asrcClock[ASRC_GetInstance(base)]);
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+}
+
+/*!
+ * brief Do software reset .
+ *
+ * This software reset bit is self-clear bit, it will generate a software reset signal inside ASRC.
+ * After 9 cycles of the ASRC processing clock, this reset process will stop and this bit will cleared
+ * automatically.
+ *
+ * param base ASRC base pointer
+ */
+void ASRC_SoftwareReset(ASRC_Type *base)
+{
+ base->ASRCTR |= ASRC_ASRCTR_SRST_MASK;
+ /* polling reset clear automatically */
+ while ((base->ASRCTR & ASRC_ASRCTR_SRST_MASK) != 0U)
+ {
+ }
+}
+
+/*!
+ * brief ASRC configure channel pair.
+ *
+ * param base ASRC base pointer.
+ * param channelPair index of channel pair, reference _asrc_channel_pair.
+ * param config ASRC channel pair configuration pointer.
+ * param inputSampleRate in audio data sample rate.
+ * param outSampleRate out audio data sample rate.
+ */
+status_t ASRC_SetChannelPairConfig(ASRC_Type *base,
+ asrc_channel_pair_t channelPair,
+ asrc_channel_pair_config_t *config,
+ uint32_t inputSampleRate,
+ uint32_t outputSampleRate)
+{
+ assert(config != NULL);
+
+ if (config->outDataWidth == kASRC_DataWidth8Bit)
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ if (((inputSampleRate < (uint32_t)kASRC_SampleRate_8000HZ) ||
+ (inputSampleRate > (uint32_t)kASRC_SampleRate_192000HZ)) ||
+ ((outputSampleRate < (uint32_t)kASRC_SampleRate_8000HZ) ||
+ (outputSampleRate > (uint32_t)kASRC_SampleRate_192000HZ)) ||
+ (((outputSampleRate > (uint32_t)kASRC_SampleRate_8000HZ) &&
+ (outputSampleRate < (uint32_t)kASRC_SampleRate_30000HZ)) &&
+ (inputSampleRate / outputSampleRate > 8U || outputSampleRate / inputSampleRate > 24U)))
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ uint32_t i = 0U;
+ /* channel pair processing selection and ratio configuration */
+ uint32_t asrctr = base->ASRCTR & (~(ASRC_ASRCTR_AT_MASK(channelPair) | ASRC_ASRCTR_RATIO_MASK(channelPair)));
+ /* use automatic selection for processing option by default */
+ asrctr |= ASRC_ASRCTR_AT_MASK(channelPair);
+ /* ratio configuration */
+ asrctr |= ASRC_ASRCTR_RATIO(config->sampleRateRatio, channelPair);
+ base->ASRCTR = asrctr;
+
+ /* audio data channel counter configurations */
+ uint32_t asrcncr = base->ASRCNCR & (~ASRC_ASRCNCR_CHANNEL_COUNTER_MASK(channelPair));
+ base->ASRCNCR = asrcncr | ASRC_ASRCNCR_CHANNEL_COUNTER(config->audioDataChannels, channelPair);
+
+ /* in clock source and out clock source configurations */
+ uint32_t asrcsr =
+ base->ASRCSR &
+ (~(ASRC_ASRCSR_INPUT_CLOCK_SOURCE_MASK(channelPair) | ASRC_ASRCSR_OUTPUT_CLOCK_SOURCE_MASK(channelPair)));
+ asrcsr |= ASRC_ASRCSR_OUTPUT_CLOCK_SOURCE(config->outClockSource, channelPair);
+ if (config->inClockSource != kASRC_ClockSourceNotAvalible)
+ {
+ asrcsr |= ASRC_ASRCSR_INPUT_CLOCK_SOURCE(config->inClockSource, channelPair);
+ }
+ base->ASRCSR = asrcsr;
+
+ /* clock divider configuration */
+ uint32_t asrcdr =
+ base->ASRCDR1 &
+ (~(ASRC_ASRCDR_INPUT_PRESCALER_MASK(channelPair) | ASRC_ASRCDR_INPUT_DIVIDER_MASK(channelPair) |
+ ASRC_ASRCDR_OUTPUT_PRESCALER_MASK(channelPair) | ASRC_ASRCDR_OUTPUT_DIVIDER_MASK(channelPair)));
+
+ asrcdr |= ASCR_ASRCDR_OUTPUT_CLOCK_DIVIDER_PRESCALER(
+ ASRC_CalculateClockDivider(outputSampleRate, config->outSourceClock_Hz), channelPair);
+ if (config->inClockSource != kASRC_ClockSourceNotAvalible)
+ {
+ asrcdr |= ASCR_ASRCDR_INPUT_CLOCK_DIVIDER_PRESCALER(
+ ASRC_CalculateClockDivider(inputSampleRate, config->inSourceClock_Hz), channelPair);
+ }
+
+ if (channelPair == kASRC_ChannelPairC)
+ {
+ base->ASRCDR2 = asrcdr;
+ }
+ else
+ {
+ base->ASRCDR1 = asrcdr;
+ }
+
+ /* data width/sign extension/data align configuration */
+ ASRC_ASRMCR1(base, channelPair) = ASRC_ASRMCR1_OW16(config->outDataWidth) | ASRC_ASRMCR1_IWD(config->inDataWidth) |
+ ASRC_ASRMCR1_OSGN(config->outSignExtension) |
+ ASRC_ASRMCR1_OMSB(config->outDataAlign) | ASRC_ASRMCR1_IMSB(config->inDataAlign);
+ /* data configurations, MISC */
+ uint32_t asrmcra = ASRC_ASRMCR(base, channelPair) &
+ (~(ASRC_ASRMCRA_BUFSTALLA_MASK | ASRC_ASRMCRA_EXTTHRSHA_MASK |
+ ASRC_ASRMCRA_INFIFO_THRESHOLDA_MASK | ASRC_ASRMCRA_OUTFIFO_THRESHOLDA_MASK));
+ /* buffer stall */
+ asrmcra |= ASRC_ASRMCRA_BUFSTALLA(config->bufStallWhenFifoEmptyFull);
+ /* in fifo and out fifo threshold */
+ asrmcra |= ASRC_ASRMCRA_EXTTHRSHA_MASK | ASRC_ASRMCRA_INFIFO_THRESHOLDA(config->inFifoThreshold - 1UL) |
+ ASRC_ASRMCRA_OUTFIFO_THRESHOLDA(config->outFifoThreshold - 1UL);
+ ASRC_ASRMCR(base, channelPair) = asrmcra;
+
+ if (config->sampleRateRatio == kASRC_RatioUseIdealRatio)
+ {
+ if (ASRC_SetIdealRatioConfig(base, channelPair, inputSampleRate, outputSampleRate) != kStatus_Success)
+ {
+ return kStatus_ASRCChannelPairConfigureFailed;
+ }
+ }
+
+ /* channel pair enable */
+ ASRC_ChannelPairEnable(base, channelPair, true);
+
+ /* wait channel initial served */
+ while (!ASRC_GetChannelPairInitialStatus(base, channelPair))
+ {
+ }
+
+ for (i = 0U; i < (uint32_t)config->audioDataChannels * 4U; i++)
+ {
+ ASRC_ChannelPairWriteData(base, channelPair, 0U);
+ }
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Get output sample buffer size.
+ *
+ * note This API is depends on the ASRC output configuration, should be called after the ASRC_SetChannelPairConfig.
+ *
+ * param base asrc base pointer.
+ * param channelPair ASRC channel pair number.
+ * param inSampleRate input sample rate.
+ * param outSampleRate output sample rate.
+ * param inSamples input sampleS size.
+ * retval output buffer size in byte.
+ */
+uint32_t ASRC_GetOutSamplesSize(ASRC_Type *base,
+ asrc_channel_pair_t channelPair,
+ uint32_t inSampleRate,
+ uint32_t outSampleRate,
+ uint32_t inSamplesize)
+{
+ uint32_t inSamples = 0U;
+ uint32_t outSamples = 0U;
+ uint32_t outSamplesBufSize = 0U, audioChannels = ASRC_GET_CHANNEL_COUNTER(base, channelPair);
+ ;
+ asrc_data_width_t outWdith = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_OW16_MASK) == ASRC_ASRMCR1_OW16_MASK ?
+ kASRC_DataWidth16Bit :
+ kASRC_DataWidth24Bit;
+ asrc_data_align_t outAlign = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_OMSB_MASK) == ASRC_ASRMCR1_OMSB_MASK ?
+ kASRC_DataAlignMSB :
+ kASRC_DataAlignLSB;
+ uint32_t inWdith = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_IWD_MASK) >> ASRC_ASRMCR1_IWD_SHIFT;
+ asrc_data_align_t inAlign = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_IMSB_MASK) == ASRC_ASRMCR1_IMSB_MASK ?
+ kASRC_DataAlignMSB :
+ kASRC_DataAlignLSB;
+
+ bool signExtend = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_OSGN_MASK) == ASRC_ASRMCR1_OSGN_MASK ? true : false;
+
+ /* 24bit input data */
+ if (inWdith == 0U)
+ {
+ inSamples = inSamplesize / (inAlign == kASRC_DataAlignMSB ? 4U : 3U);
+ }
+ /* 16bit input data */
+ else if (inWdith == 1U)
+ {
+ inSamples = inSamplesize / (inAlign == kASRC_DataAlignMSB ? 4U : 2U);
+ }
+ /* 8bit input data */
+ else
+ {
+ inSamples = inSamplesize / (inAlign == kASRC_DataAlignMSB ? 2U : 1U);
+ }
+
+ outSamples = (uint32_t)((uint64_t)inSamples * outSampleRate / inSampleRate);
+ /* make sure output samples is in group */
+ outSamples = outSamples - outSamples % audioChannels;
+
+ if (outWdith == kASRC_DataWidth16Bit)
+ {
+ if ((outAlign == kASRC_DataAlignMSB) || signExtend)
+ {
+ outSamplesBufSize = outSamples * 4U;
+ }
+ else
+ {
+ outSamplesBufSize = outSamples * 2U;
+ }
+ }
+
+ if (outWdith == kASRC_DataWidth24Bit)
+ {
+ outSamplesBufSize = outSamples * 4U;
+ }
+
+ return outSamplesBufSize;
+}
+
+/*!
+ * brief Performs an blocking convert on asrc.
+ *
+ * note This API returns immediately after the convert finished.
+ *
+ * param base asrc base pointer.
+ * param channelPair channel pair index.
+ * param xfer Pointer to the ASRC_transfer_t structure.
+ * retval kStatus_Success Successfully started the data receive.
+ */
+status_t ASRC_TransferBlocking(ASRC_Type *base, asrc_channel_pair_t channelPair, asrc_transfer_t *xfer)
+{
+ assert(xfer != NULL);
+
+ uint32_t inWaterMark = ASRC_ASRMCR(base, channelPair) & ASRC_ASRMCRA_INFIFO_THRESHOLDA_MASK,
+ outWaterMark = (ASRC_ASRMCR(base, channelPair) & ASRC_ASRMCRA_OUTFIFO_THRESHOLDA_MASK) >>
+ ASRC_ASRMCRA_OUTFIFO_THRESHOLDA_SHIFT,
+ audioChannels = ASRC_GET_CHANNEL_COUNTER(base, channelPair);
+ uint8_t *inAddr = (uint8_t *)xfer->inData, *outAddr = (uint8_t *)xfer->outData;
+ uint32_t onceWriteSamples = 0U;
+ uint32_t status = 0U, inSampleMask = 0U, inSamples = 0U, outSamples = 0U, inWidth = 0U, outWidth = 0U;
+
+ inSampleMask = ASRC_MapSamplesWidth(base, channelPair, &inWidth, &outWidth);
+ inSamples = xfer->inDataSize / inWidth;
+ outSamples = xfer->outDataSize / outWidth;
+ inWaterMark *= audioChannels;
+ outWaterMark *= audioChannels;
+
+ while (outSamples != 0U)
+ {
+ status = ASRC_GetStatus(base);
+
+ if ((status & ((uint32_t)kASRC_StatusPairCInputReady | (uint32_t)kASRC_StatusPairBInputReady |
+ (uint32_t)kASRC_StatusPairAInputReady)) != 0U)
+ {
+ onceWriteSamples =
+ MIN(inSamples, (size_t)((FSL_ASRC_CHANNEL_PAIR_FIFO_DEPTH * audioChannels - inWaterMark)));
+ ASRC_WriteNonBlocking(base, channelPair, (uint32_t *)(uint32_t)inAddr, onceWriteSamples, inSampleMask,
+ inWidth);
+ inAddr = (uint8_t *)((uint32_t)inAddr + onceWriteSamples * inWidth);
+ inSamples -= onceWriteSamples;
+ }
+
+ if (outSamples > outWaterMark)
+ {
+ if ((status & ((uint32_t)kASRC_StatusPairCOutputReady | (uint32_t)kASRC_StatusPairAOutputReady |
+ (uint32_t)kASRC_StatusPairBOutputReady)) != 0U)
+ {
+ ASRC_ReadNonBlocking(base, channelPair, (uint32_t *)(uint32_t)outAddr, outWaterMark, outWidth);
+ outAddr = (uint8_t *)((uint32_t)outAddr + outWaterMark * outWidth);
+ outSamples -= outWaterMark;
+ }
+ }
+ else
+ {
+ outSamples -=
+ ASRC_GetRemainFifoSamples(base, channelPair, (uint32_t *)(uint32_t)outAddr, outWidth, outSamples);
+ continue;
+ }
+ }
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief ASRC configure channel pair.
+ *
+ * param base ASRC base pointer.
+ * param handle ASRC transactional handle pointer.
+ * param config ASRC channel pair configuration pointer.
+ * param inputSampleRate in audio data sample rate.
+ * param outputSampleRate out audio data sample rate.
+ */
+status_t ASRC_TransferSetChannelPairConfig(ASRC_Type *base,
+ asrc_handle_t *handle,
+ asrc_channel_pair_config_t *config,
+ uint32_t inputSampleRate,
+ uint32_t outputSampleRate)
+{
+ assert(handle != NULL);
+
+ handle->in.fifoThreshold = config->inFifoThreshold * (uint32_t)config->audioDataChannels;
+ handle->out.fifoThreshold = config->outFifoThreshold * (uint32_t)config->audioDataChannels;
+ handle->audioDataChannels = config->audioDataChannels;
+
+ if (ASRC_SetChannelPairConfig(base, handle->channelPair, config, inputSampleRate, outputSampleRate) !=
+ kStatus_Success)
+ {
+ return kStatus_ASRCChannelPairConfigureFailed;
+ }
+
+ handle->in.sampleMask =
+ ASRC_MapSamplesWidth(base, handle->channelPair, &handle->in.sampleWidth, &handle->out.sampleWidth);
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Get left samples in fifo.
+ *
+ * param base asrc base pointer.
+ * param channelPair ASRC channel pair number.
+ * param buffer input sample numbers.
+ * param outSampleWidth output sample width.
+ * param remainSamples output sample rate.
+ * retval remain samples number.
+ */
+uint32_t ASRC_GetRemainFifoSamples(
+ ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *buffer, uint32_t outSampleWidth, uint32_t remainSamples)
+{
+ uint32_t remainSamplesInFifo = 0U;
+ uint32_t audioChannels = ASRC_GET_CHANNEL_COUNTER(base, channelPair);
+ remainSamplesInFifo =
+ ((ASRC_ASRFST_ADDR(base, channelPair) & ASRC_ASRFSTA_OUTFIFO_FILLA_MASK) >> ASRC_ASRFSTA_OUTFIFO_FILLA_SHIFT) *
+ audioChannels;
+
+ if (remainSamples < remainSamplesInFifo)
+ {
+ remainSamplesInFifo = remainSamples;
+ }
+
+ ASRC_ReadNonBlocking(base, channelPair, (uint32_t *)buffer, remainSamplesInFifo, outSampleWidth);
+
+ return remainSamplesInFifo;
+}
+
+/*!
+ * brief Initializes the ASRC handle.
+ *
+ * This function initializes the handle for the ASRC transactional APIs. Call
+ * this function once to get the handle initialized.
+ *
+ * param base ASRC base pointer
+ * param handle ASRC handle pointer.
+ * param inCallback Pointer to the user callback function.
+ * param outCallback Pointer to the user callback function.
+ * param userData User parameter passed to the callback function
+ */
+void ASRC_TransferCreateHandle(ASRC_Type *base,
+ asrc_handle_t *handle,
+ asrc_channel_pair_t channelPair,
+ asrc_transfer_callback_t inCallback,
+ asrc_transfer_callback_t outCallback,
+ void *userData)
+{
+ assert(handle != NULL);
+
+ uint32_t instance = ASRC_GetInstance(base);
+
+ (void)memset(handle, 0, sizeof(*handle));
+
+ s_asrcHandle[instance][channelPair] = handle;
+
+ handle->in.callback = inCallback;
+ handle->out.callback = outCallback;
+ handle->userData = userData;
+ handle->channelPair = channelPair;
+ /* Set the isr pointer */
+ s_asrcIsr = ASRC_TransferHandleIRQ;
+
+ (void)EnableIRQ(s_asrcIRQ[instance]);
+}
+
+/*!
+ * brief Performs an interrupt non-blocking convert on asrc.
+ *
+ * note This API returns immediately after the transfer initiates, application should check the wait and check the
+ * callback status.
+ *
+ * param base asrc base pointer.
+ * param handle Pointer to the asrc_handle_t structure which stores the transfer state.
+ * param xfer Pointer to the ASRC_transfer_t structure.
+ * retval kStatus_Success Successfully started the data receive.
+ * retval kStatus_ASRCBusy Previous receive still not finished.
+ */
+status_t ASRC_TransferNonBlocking(ASRC_Type *base, asrc_handle_t *handle, asrc_transfer_t *xfer)
+{
+ assert(handle != NULL);
+ assert(xfer != NULL);
+
+ /* Check if the queue is full */
+ if ((handle->in.asrcQueue[handle->in.queueUser] != NULL) || (handle->out.asrcQueue[handle->out.queueUser] != NULL))
+ {
+ return kStatus_ASRCBusy;
+ }
+
+ /* Add into queue */
+ handle->in.transferSamples[handle->in.queueUser] = xfer->inDataSize / handle->in.sampleWidth;
+ handle->in.asrcQueue[handle->in.queueUser] = xfer->inData;
+ handle->in.queueUser = (handle->in.queueUser + 1U) % ASRC_XFER_QUEUE_SIZE;
+
+ handle->out.asrcQueue[handle->out.queueUser] = xfer->outData;
+ handle->out.transferSamples[handle->out.queueUser] = xfer->outDataSize / handle->out.sampleWidth;
+ handle->out.queueUser = (handle->out.queueUser + 1U) % ASRC_XFER_QUEUE_SIZE;
+
+ if (handle->state != (uint32_t)kStatus_ASRCBusy)
+ {
+ /* enable channel pair interrupt */
+ ASRC_EnableInterrupt(base, ASRC_ASRIER_INPUT_INTERRUPT_MASK(handle->channelPair) |
+ (uint32_t)kASRC_OverLoadInterruptMask |
+ ASRC_ASRIER_OUTPUTPUT_INTERRUPT_MASK(handle->channelPair));
+ }
+
+ /* Set the state to busy */
+ handle->state = kStatus_ASRCBusy;
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Gets a set byte count.
+ *
+ * param base asrc base pointer.
+ * param handle Pointer to the ASRC_handle_t structure which stores the transfer state.
+ * param count Bytes count sent.
+ * retval kStatus_Success Succeed get the transfer count.
+ * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
+ */
+status_t ASRC_TransferGetConvertedCount(ASRC_Type *base, asrc_handle_t *handle, size_t *count)
+{
+ assert(handle != NULL);
+
+ status_t status = kStatus_Success;
+
+ if (handle->state != (uint32_t)kStatus_ASRCBusy)
+ {
+ status = kStatus_ASRCIdle;
+ }
+ else
+ {
+ *count = handle->out.transferSamples[handle->out.queueDriver];
+ }
+
+ return status;
+}
+
+/*!
+ * brief Aborts the current convert.
+ *
+ * note This API can be called any time when an interrupt non-blocking transfer initiates
+ * to abort the transfer early.
+ *
+ * param base asrc base pointer.
+ * param handle Pointer to the ASRC_handle_t structure which stores the transfer state.
+ */
+void ASRC_TransferAbortConvert(ASRC_Type *base, asrc_handle_t *handle)
+{
+ assert(handle != NULL);
+
+ /* enable ASRC module */
+ ASRC_ModuleEnable(base, false);
+
+ handle->state = kStatus_ASRCIdle;
+
+ handle->in.queueDriver = 0;
+ handle->in.queueUser = 0;
+ handle->out.queueDriver = 0;
+ handle->out.queueUser = 0;
+}
+
+/*!
+ * brief Terminate all asrc convert.
+ *
+ * This function will clear all transfer slots buffered in the asrc queue. If users only want to abort the
+ * current transfer slot, please call ASRC_TransferAbortSend.
+ *
+ * param base asrc base pointer.
+ * param handle asrc eDMA handle pointer.
+ */
+void ASRC_TransferTerminateConvert(ASRC_Type *base, asrc_handle_t *handle)
+{
+ assert(handle != NULL);
+
+ /* Abort the current transfer */
+ ASRC_TransferAbortConvert(base, handle);
+
+ /* Clear all the internal information */
+ (void)memset(handle->in.asrcQueue, 0, sizeof(handle->in.asrcQueue));
+ (void)memset(handle->in.transferSamples, 0, sizeof(handle->in.transferSamples));
+ (void)memset(handle->out.asrcQueue, 0, sizeof(handle->out.asrcQueue));
+ (void)memset(handle->out.transferSamples, 0, sizeof(handle->out.transferSamples));
+}
+
+/*!
+ * brief ASRC convert interrupt handler.
+ *
+ * param base asrc base pointer.
+ * param handle Pointer to the asrc_handle_t structure.
+ */
+void ASRC_TransferHandleIRQ(ASRC_Type *base, asrc_handle_t *handle)
+{
+ assert(handle != NULL);
+
+ uint32_t status = base->ASRSTR;
+
+ /* Handle Error */
+ if ((status & (uint32_t)kASRC_StatusInputError) != 0U)
+ {
+ /* Call the callback */
+ if (handle->in.callback != NULL)
+ {
+ (handle->in.callback)(base, handle, kStatus_ASRCConvertError, handle->userData);
+ }
+ }
+
+ if ((status & (uint32_t)kASRC_StatusOutputError) != 0U)
+ {
+ /* Call the callback */
+ if (handle->out.callback != NULL)
+ {
+ (handle->out.callback)(base, handle, kStatus_ASRCConvertError, handle->userData);
+ }
+ }
+
+ /* Handle transfer */
+ if ((status & ((uint32_t)kASRC_StatusPairCOutputReady | (uint32_t)kASRC_StatusPairAOutputReady |
+ (uint32_t)kASRC_StatusPairBOutputReady)) != 0U)
+ {
+ if (handle->out.transferSamples[handle->out.queueDriver] != 0U)
+ {
+ ASRC_ReadNonBlocking(base, handle->channelPair,
+ (uint32_t *)(uint32_t)handle->out.asrcQueue[handle->out.queueDriver],
+ handle->out.fifoThreshold, handle->out.sampleWidth);
+ handle->out.transferSamples[handle->out.queueDriver] -= handle->out.fifoThreshold;
+ handle->out.asrcQueue[handle->out.queueDriver] =
+ (uint8_t *)((uint32_t)handle->out.asrcQueue[handle->out.queueDriver] +
+ handle->out.fifoThreshold * handle->out.sampleWidth);
+ }
+ }
+
+ if ((status & ((uint32_t)kASRC_StatusPairCInputReady | (uint32_t)kASRC_StatusPairBInputReady |
+ (uint32_t)kASRC_StatusPairAInputReady)) != 0U)
+ {
+ /* Judge if the data need to transmit is less than space */
+ uint32_t size = MIN((handle->in.transferSamples[handle->in.queueDriver]),
+ (size_t)((FSL_ASRC_CHANNEL_PAIR_FIFO_DEPTH * (uint32_t)handle->audioDataChannels -
+ handle->in.fifoThreshold)));
+ ASRC_WriteNonBlocking(base, handle->channelPair,
+ (uint32_t *)(uint32_t)handle->in.asrcQueue[handle->in.queueDriver], size,
+ handle->in.sampleMask, handle->in.sampleWidth);
+ handle->in.transferSamples[handle->in.queueDriver] -= size;
+ handle->in.asrcQueue[handle->in.queueDriver] =
+ (uint8_t *)((uint32_t)handle->in.asrcQueue[handle->in.queueDriver] + size * handle->in.sampleWidth);
+ }
+
+ /* If finished a block, call the callback function */
+ if (handle->in.transferSamples[handle->in.queueDriver] == 0U)
+ {
+ handle->in.asrcQueue[handle->in.queueDriver] = NULL;
+ handle->in.queueDriver = (handle->in.queueDriver + 1U) % ASRC_XFER_QUEUE_SIZE;
+ if (handle->in.callback != NULL)
+ {
+ (handle->in.callback)(base, handle, kStatus_ASRCIdle, handle->userData);
+ }
+ }
+
+ if (handle->out.transferSamples[handle->out.queueDriver] < (handle->out.fifoThreshold + 1U))
+ {
+ handle->out.transferSamples[handle->out.queueDriver] -= ASRC_GetRemainFifoSamples(
+ base, handle->channelPair, (uint32_t *)(uint32_t)handle->out.asrcQueue[handle->out.queueDriver],
+ handle->out.sampleWidth, handle->out.transferSamples[handle->out.queueDriver]);
+ }
+
+ if (handle->out.transferSamples[handle->out.queueDriver] == 0U)
+ {
+ handle->out.asrcQueue[handle->out.queueDriver] = NULL;
+ handle->out.queueDriver = (handle->out.queueDriver + 1U) % ASRC_XFER_QUEUE_SIZE;
+ if (handle->out.callback != NULL)
+ {
+ (handle->out.callback)(base, handle, kStatus_ASRCIdle, handle->userData);
+ }
+ }
+
+ /* If all data finished, just stop the transfer */
+ if (handle->out.asrcQueue[handle->out.queueDriver] == NULL)
+ {
+ ASRC_TransferAbortConvert(base, handle);
+ }
+}
+
+#if defined ASRC
+void ASRC_DriverIRQHandler(void);
+void ASRC_DriverIRQHandler(void)
+{
+ /* channel PAIR A interrupt handling*/
+ if ((ASRC->ASRSTR & (uint32_t)kASRC_StatusPairAInterrupt) != 0U)
+ {
+ s_asrcIsr(ASRC, s_asrcHandle[0][0U]);
+ }
+ /* channel PAIR B interrupt handling*/
+ if ((ASRC->ASRSTR & (uint32_t)kASRC_StatusPairBInterrupt) != 0U)
+ {
+ s_asrcIsr(ASRC, s_asrcHandle[0][1U]);
+ }
+ /* channel PAIR C interrupt handling*/
+ if ((ASRC->ASRSTR & (uint32_t)kASRC_StatusPairCInterrupt) != 0U)
+ {
+ s_asrcIsr(ASRC, s_asrcHandle[0][2U]);
+ }
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif /* ASRC */
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc.h b/bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc.h
new file mode 100644
index 0000000000..e4f8ce384a
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc.h
@@ -0,0 +1,761 @@
+/*
+ * Copyright 2019-2021 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_ASRC_H_
+#define _FSL_ASRC_H_
+
+#include "fsl_common.h"
+
+/*!
+ * @addtogroup asrc_driver
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @name Driver version */
+/*@{*/
+#define FSL_ASRC_DRIVER_VERSION (MAKE_VERSION(2, 1, 2)) /*!< Version 2.1.2 */
+/*@}*/
+
+#ifndef ASRC_XFER_QUEUE_SIZE
+/*!@brief ASRC transfer queue size, user can refine it according to use case. */
+#define ASRC_XFER_QUEUE_SIZE (4U)
+#endif
+/*!@brief ASRC channel pair count */
+#define FSL_ASRC_CHANNEL_PAIR_COUNT (4U)
+/*! @brief ASRC FIFO depth */
+#define FSL_ASRC_CHANNEL_PAIR_FIFO_DEPTH (64U)
+
+/*! @brief ASRC register access macro */
+#define ASRC_ASRCTR_AT_MASK(index) ((uint32_t)1U << (ASRC_ASRCTR_ATSA_SHIFT + (uint32_t)(index)))
+#define ASRC_ASRCTR_RATIO_MASK(index) ((uint32_t)3U << (ASRC_ASRCTR_IDRA_SHIFT + (uint32_t)(index)*2U))
+#define ASRC_ASRCTR_RATIO(ratio, index) \
+ (((uint32_t)((uint32_t)(ratio) << (ASRC_ASRCTR_IDRA_SHIFT + (uint32_t)(index)*2U))) & ASRC_ASRCTR_RATIO_MASK(index))
+#define ASRC_ASRIER_INPUT_INTERRUPT_MASK(index) ((uint32_t)1U << (ASRC_ASRIER_ADIEA_SHIFT + (uint32_t)(index)))
+#define ASRC_ASRIER_OUTPUTPUT_INTERRUPT_MASK(index) ((uint32_t)1U << (ASRC_ASRIER_ADOEA_SHIFT + (uint32_t)(index)))
+#define ASRC_ASRCNCR_CHANNEL_COUNTER_MASK(index) ((uint32_t)0xFU << (ASRC_ASRCNCR_ANCA_SHIFT + (uint32_t)(index)*4U))
+#define ASRC_ASRCNCR_CHANNEL_COUNTER(counter, index) \
+ ((uint32_t)((uint32_t)(counter) << (ASRC_ASRCNCR_ANCA_SHIFT + (uint32_t)(index)*4U)) & \
+ ASRC_ASRCNCR_CHANNEL_COUNTER_MASK(index))
+#define ASRC_ASRCFG_PRE_MODE_MASK(index) ((uint32_t)3U << (ASRC_ASRCFG_PREMODA_SHIFT + (uint32_t)(index)*4U))
+#define ASRC_ASRCFG_PRE_MODE(mode, index) \
+ ((uint32_t)((uint32_t)(mode) << (ASRC_ASRCFG_PREMODA_SHIFT + (uint32_t)(index)*4U)) & \
+ ASRC_ASRCFG_PRE_MODE_MASK(index))
+#define ASRC_ASRCFG_POST_MODE_MASK(index) ((uint32_t)3U << (ASRC_ASRCFG_POSTMODA_SHIFT + (uint32_t)(index)*4U))
+#define ASRC_ASRCFG_POST_MODE(mode, index) \
+ ((uint32_t)((uint32_t)(mode) << (ASRC_ASRCFG_POSTMODA_SHIFT + (uint32_t)(index)*4U)) & \
+ ASRC_ASRCFG_POST_MODE_MASK(index))
+#define ASRC_ASRCFG_INIT_DONE_MASK(index) ((uint32_t)1U << (ASRC_ASRCFG_INIRQA_SHIFT + (uint32_t)(index)))
+#define ASRC_ASRCSR_INPUT_CLOCK_SOURCE_MASK(index) ((uint32_t)0xFU << (ASRC_ASRCSR_AICSA_SHIFT + (uint32_t)(index)*4U))
+#define ASRC_ASRCSR_INPUT_CLOCK_SOURCE(source, index) \
+ ((uint32_t)((uint32_t)(source) << (ASRC_ASRCSR_AICSA_SHIFT + (uint32_t)(index)*4U)) & \
+ ASRC_ASRCSR_INPUT_CLOCK_SOURCE_MASK(index))
+#define ASRC_ASRCSR_OUTPUT_CLOCK_SOURCE_MASK(index) ((uint32_t)0xFU << (ASRC_ASRCSR_AOCSA_SHIFT + (uint32_t)(index)*4U))
+#define ASRC_ASRCSR_OUTPUT_CLOCK_SOURCE(source, index) \
+ ((uint32_t)((uint32_t)(source) << (ASRC_ASRCSR_AOCSA_SHIFT + (uint32_t)(index)*4U)) & \
+ ASRC_ASRCSR_OUTPUT_CLOCK_SOURCE_MASK(index))
+
+#define ASRC_ASRCDR_INPUT_PRESCALER_MASK(index) \
+ ((uint32_t)(index) < 2U ? ((uint32_t)7U << (ASRC_ASRCDR1_AICPA_SHIFT + (uint32_t)(index)*6U)) : 7U)
+#define ASRC_ASRCDR_INPUT_PRESCALER(prescaler, index) \
+ (((index) < 2U ? ((uint32_t)(prescaler) << (ASRC_ASRCDR1_AICPA_SHIFT + (uint32_t)(index)*6U)) : (prescaler)) & \
+ ASRC_ASRCDR1_INPUT_PRESCALER_MASK(index))
+#define ASRC_ASRCDR_INPUT_DIVIDER_MASK(index) \
+ ((uint32_t)(index) < 2U ? ((uint32_t)7U << (ASRC_ASRCDR1_AICDA_SHIFT + (uint32_t)(index)*6U)) : \
+ (7U << ASRC_ASRCDR1_AICDA_SHIFT))
+#define ASRC_ASRCDR_INPUT_DIVIDER(divider, index) \
+ (((uint32_t)(index) < 2U ? ((uint32_t)(divider) << (ASRC_ASRCDR1_AICDA_SHIFT + (uint32_t)(index)*6U)) : \
+ ((uint32_t)(divider) << ASRC_ASRCDR1_AICDA_SHIFT)) & \
+ ASRC_ASRCDR_INPUT_DIVIDER_MASK(index))
+#define ASRC_ASRCDR_OUTPUT_PRESCALER_MASK(index) \
+ ((uint32_t)(index) < 2U ? ((uint32_t)7U << (ASRC_ASRCDR1_AOCPA_SHIFT + (uint32_t)(index)*6U)) : (7U << 6U))
+#define ASRC_ASRCDR_OUTPUT_PRESCALER(prescaler, index) \
+ (((uint32_t)(index) < 2U ? ((uint32_t)(prescaler) << (ASRC_ASRCDR1_AOCPA_SHIFT + (uint32_t)(index)*6U)) : \
+ ((uint32_t)(prescaler) << 6U)) & \
+ ASRC_ASRCDR_OUTPUT_PRESCALER_MASK(index))
+#define ASRC_ASRCDR_OUTPUT_DIVIDER_MASK(index) \
+ ((uint32_t)(index) < 2U ? ((uint32_t)7U << (ASRC_ASRCDR1_AOCDA_SHIFT + (uint32_t)(index)*6U)) : (7UL << 9U))
+#define ASRC_ASRCDR_OUTPUT_DIVIDER(divider, index) \
+ (((uint32_t)(index) < 2U ? ((uint32_t)(divider) << (ASRC_ASRCDR1_AOCDA_SHIFT + (uint32_t)(index)*6U)) : \
+ ((uint32_t)(divider) << 9U)) & \
+ ASRC_ASRCDR_OUTPUT_DIVIDER_MASK(index))
+
+#define ASCR_ASRCDR_OUTPUT_CLOCK_DIVIDER_PRESCALER(value, index) \
+ (((uint32_t)(index) < 2U ? ((uint32_t)(value) << (ASRC_ASRCDR1_AOCPA_SHIFT + (uint32_t)(index)*6U)) : \
+ ((uint32_t)(value) << 6U)))
+#define ASCR_ASRCDR_INPUT_CLOCK_DIVIDER_PRESCALER(value, index) \
+ (((uint32_t)(index) < 2U ? ((uint32_t)(value) << ((uint32_t)(index)*6U)) : ((uint32_t)(value))))
+
+#define ASRC_IDEAL_RATIO_HIGH(base, index) *(volatile uint32_t *)((uint32_t)(&(base)->ASRIDRHA) + (uint32_t)(index)*8U)
+#define ASRC_IDEAL_RATIO_LOW(base, index) *(volatile uint32_t *)((uint32_t)(&(base)->ASRIDRLA) + (uint32_t)(index)*8U)
+#define ASRC_ASRMCR(base, index) *(volatile uint32_t *)((uint32_t)(&(base)->ASRMCRA) + (uint32_t)(index)*8U)
+#define ASRC_ASRMCR1(base, index) *(volatile uint32_t *)((uint32_t)(&((base)->ASRMCR1[(index)])))
+#define ASRC_ASRDI(base, index) *(volatile uint32_t *)((uint32_t)(&(base)->ASRDIA) + (uint32_t)(index)*8U)
+#define ASRC_ASRDO(base, index) *(volatile uint32_t *)((uint32_t)(&(base)->ASRDOA) + (uint32_t)(index)*8U)
+#define ASRC_ASRDI_ADDR(base, index) (volatile uint32_t *)((uint32_t)(&(base)->ASRDIA) + (uint32_t)(index)*8U)
+#define ASRC_ASRDO_ADDR(base, index) (volatile uint32_t *)((uint32_t)(&(base)->ASRDOA) + (uint32_t)(index)*8U)
+#define ASRC_ASRFST_ADDR(base, index) (*(volatile uint32_t *)((uint32_t)(&(base)->ASRFSTA) + (uint32_t)(index)*8U))
+#define ASRC_GET_CHANNEL_COUNTER(base, index) (((base)->ASRCNCR >> ((uint32_t)(index)*4U)) & 0xFU)
+
+/*! @brief ASRC return status
+ * @anchor _asrc_status_t
+ */
+enum
+{
+ kStatus_ASRCIdle = MAKE_STATUS(kStatusGroup_ASRC, 0), /*!< ASRC is idle. */
+ kStatus_ASRCInIdle = MAKE_STATUS(kStatusGroup_ASRC, 1), /*!< ASRC in is idle. */
+ kStatus_ASRCOutIdle = MAKE_STATUS(kStatusGroup_ASRC, 2), /*!< ASRC out is idle. */
+ kStatus_ASRCBusy = MAKE_STATUS(kStatusGroup_ASRC, 3), /*!< ASRC is busy. */
+ kStatus_ASRCInvalidArgument = MAKE_STATUS(kStatusGroup_ASRC, 4), /*!< ASRC invalid argument. */
+ kStatus_ASRCClockConfigureFailed = MAKE_STATUS(kStatusGroup_ASRC, 5), /*!< ASRC clock configure failed */
+ kStatus_ASRCChannelPairConfigureFailed = MAKE_STATUS(kStatusGroup_ASRC, 6), /*!< ASRC clock configure failed */
+ kStatus_ASRCConvertError = MAKE_STATUS(kStatusGroup_ASRC, 7), /*!< ASRC clock configure failed */
+ kStatus_ASRCNotSupport = MAKE_STATUS(kStatusGroup_ASRC, 8), /*!< ASRC not support */
+ kStatus_ASRCQueueFull = MAKE_STATUS(kStatusGroup_ASRC, 9), /*!< ASRC queue is full */
+ kStatus_ASRCOutQueueIdle = MAKE_STATUS(kStatusGroup_ASRC, 10), /*!< ASRC out queue is idle */
+ kStatus_ASRCInQueueIdle = MAKE_STATUS(kStatusGroup_ASRC, 11), /*!< ASRC in queue is idle */
+};
+
+/*! @brief ASRC channel pair mask */
+typedef enum _asrc_channel_pair
+{
+ kASRC_ChannelPairA = 0, /*!< channel pair A value */
+ kASRC_ChannelPairB = 1, /*!< channel pair B value */
+ kASRC_ChannelPairC = 2, /*!< channel pair C value */
+} asrc_channel_pair_t;
+
+/*! @brief ASRC support sample rate
+ * @anchor _asrc_sample_rate
+ */
+enum
+{
+ kASRC_SampleRate_8000HZ = 8000U, /*!< asrc sample rate 8KHZ */
+ kASRC_SampleRate_11025HZ = 11025U, /*!< asrc sample rate 11.025KHZ */
+ kASRC_SampleRate_12000HZ = 12000U, /*!< asrc sample rate 12KHZ */
+ kASRC_SampleRate_16000HZ = 16000U, /*!< asrc sample rate 16KHZ */
+ kASRC_SampleRate_22050HZ = 22050U, /*!< asrc sample rate 22.05KHZ */
+ kASRC_SampleRate_24000HZ = 24000U, /*!< asrc sample rate 24KHZ */
+ kASRC_SampleRate_30000HZ = 30000U, /*!< asrc sample rate 30KHZ */
+ kASRC_SampleRate_32000HZ = 32000U, /*!< asrc sample rate 32KHZ */
+ kASRC_SampleRate_44100HZ = 44100U, /*!< asrc sample rate 44.1KHZ */
+ kASRC_SampleRate_48000HZ = 48000U, /*!< asrc sample rate 48KHZ */
+ kASRC_SampleRate_64000HZ = 64000U, /*!< asrc sample rate 64KHZ */
+ kASRC_SampleRate_88200HZ = 88200U, /*!< asrc sample rate 88.2KHZ */
+ kASRC_SampleRate_96000HZ = 96000U, /*!< asrc sample rate 96KHZ */
+ kASRC_SampleRate_128000HZ = 128000U, /*!< asrc sample rate 128KHZ */
+ kASRC_SampleRate_176400HZ = 176400U, /*!< asrc sample rate 176.4KHZ */
+ kASRC_SampleRate_192000HZ = 192000U, /*!< asrc sample rate 192KHZ */
+};
+
+/*! @brief The ASRC interrupt enable flag
+ * @anchor _asrc_interrupt_mask
+ */
+enum
+{
+ kASRC_FPInWaitStateInterruptEnable = ASRC_ASRIER_AFPWE_MASK, /*!< FP in wait state mask */
+ kASRC_OverLoadInterruptMask = ASRC_ASRIER_AOLIE_MASK, /*!< overload interrupt mask */
+ kASRC_DataOutputCInterruptMask = ASRC_ASRIER_ADOEC_MASK, /*!< data output c interrupt mask */
+ kASRC_DataOutputBInterruptMask = ASRC_ASRIER_ADOEB_MASK, /*!< data output b interrupt mask */
+ kASRC_DataOutputAInterruptMask = ASRC_ASRIER_ADOEA_MASK, /*!< data output a interrupt mask */
+ kASRC_DataInputCInterruptMask = ASRC_ASRIER_ADIEC_MASK, /*!< data input c interrupt mask */
+ kASRC_DataInputBInterruptMask = ASRC_ASRIER_ADIEB_MASK, /*!< data input b interrupt mask */
+ kASRC_DataInputAInterruptMask = ASRC_ASRIER_ADIEA_MASK, /*!< data input a interrupt mask */
+};
+
+/*! @brief The ASRC interrupt status
+ * @anchor _asrc_interrupt_status
+ */
+enum
+{
+ kASRC_StatusDSLCounterReady = ASRC_ASRSTR_DSLCNT_MASK, /*!< DSL counter */
+ kASRC_StatusTaskQueueOverLoad = ASRC_ASRSTR_ATQOL_MASK, /*!< task queue overload */
+ kASRC_StatusPairCOutputOverLoad = ASRC_ASRSTR_AOOLC_MASK, /*!< pair c output overload */
+ kASRC_StatusPairBOutputOverLoad = ASRC_ASRSTR_AOOLB_MASK, /*!< pair b output overload */
+ kASRC_StatusPairAOutputOverLoad = ASRC_ASRSTR_AOOLA_MASK, /*!< pair a output overload */
+ kASRC_StatusPairCInputOverLoad = ASRC_ASRSTR_AIOLC_MASK, /*!< pair c input overload */
+ kASRC_StatusPairBInputOverLoad = ASRC_ASRSTR_AIOLB_MASK, /*!<pair b input overload */
+ kASRC_StatusPairAInputOverLoad = ASRC_ASRSTR_AIOLA_MASK, /*!< pair a input overload */
+ kASRC_StatusPairCOutputOverflow = ASRC_ASRSTR_AODOC_MASK, /*!< pair c output overflow */
+ kASRC_StatusPairBOutputOverflow = ASRC_ASRSTR_AODOB_MASK, /*!< pair b output overflow */
+ kASRC_StatusPairAOutputOverflow = ASRC_ASRSTR_AODOA_MASK, /*!< pair a output overflow */
+ kASRC_StatusPairCInputUnderflow = ASRC_ASRSTR_AIDUC_MASK, /*!< pair c input underflow*/
+ kASRC_StatusPairBInputUnderflow = ASRC_ASRSTR_AIDUB_MASK, /*!< pair b input under flow */
+ kASRC_StatusPairAInputUnderflow = ASRC_ASRSTR_AIDUA_MASK, /*!< pair a input underflow*/
+ kASRC_StatusFPInWaitState = ASRC_ASRSTR_FPWT_MASK, /*!< FP in wait state */
+ kASRC_StatusOverloadError = ASRC_ASRSTR_AOLE_MASK, /*!< overload error */
+
+ kASRC_StatusInputError = kASRC_StatusPairCInputOverLoad | kASRC_StatusPairBInputOverLoad |
+ kASRC_StatusPairAInputOverLoad | kASRC_StatusPairCInputUnderflow |
+ kASRC_StatusPairBInputUnderflow |
+ kASRC_StatusPairAInputUnderflow, /*!< input error status */
+
+ kASRC_StatusOutputError = kASRC_StatusPairCOutputOverLoad | kASRC_StatusPairBOutputOverLoad |
+ kASRC_StatusPairAOutputOverLoad | kASRC_StatusPairCOutputOverflow |
+ kASRC_StatusPairBOutputOverflow |
+ kASRC_StatusPairAOutputOverflow, /*!< output error status */
+
+ kASRC_StatusPairCOutputReady = ASRC_ASRSTR_AODFC_MASK, /*!< pair c output ready */
+ kASRC_StatusPairBOutputReady = ASRC_ASRSTR_AODFB_MASK, /*!< pair b output ready */
+ kASRC_StatusPairAOutputReady = ASRC_ASRSTR_AODFA_MASK, /*!< pair a output ready */
+ kASRC_StatusPairCInputReady = ASRC_ASRSTR_AIDEC_MASK, /*!< pair c input ready */
+ kASRC_StatusPairBInputReady = ASRC_ASRSTR_AIDEB_MASK, /*!< pair b input ready */
+ kASRC_StatusPairAInputReady = ASRC_ASRSTR_AIDEA_MASK, /*!< pair a input ready */
+ kASRC_StatusPairAInterrupt = kASRC_StatusPairAInputReady | kASRC_StatusPairAOutputReady, /*!< pair A interrupt */
+ kASRC_StatusPairBInterrupt = kASRC_StatusPairBInputReady | kASRC_StatusPairBOutputReady, /*!< pair B interrupt */
+ kASRC_StatusPairCInterrupt = kASRC_StatusPairCInputReady | kASRC_StatusPairCOutputReady, /*!< pair C interrupt */
+
+};
+
+/*! @brief ASRC channel pair status
+ * @anchor _asrc_channel_pair_status
+ */
+enum
+{
+ kASRC_OutputFifoNearFull = ASRC_ASRFSTA_OAFA_MASK, /*!< channel pair output fifo near full */
+ kASRC_InputFifoNearEmpty = ASRC_ASRFSTA_IAEA_MASK, /*!< channel pair input fifo near empty */
+};
+
+/*! @brief ASRC ideal ratio */
+typedef enum _asrc_ratio
+{
+ kASRC_RatioNotUsed = 0U, /*!< ideal ratio not used */
+ kASRC_RatioUseInternalMeasured =
+ 2U, /*!< ideal ratio use internal measure ratio, can be used for real time streaming audio */
+ kASRC_RatioUseIdealRatio =
+ 3U, /*!< ideal ratio use manual configure ratio, can be used for the non-real time streaming audio */
+} asrc_ratio_t;
+
+/*! @brief Number of channels in audio data */
+typedef enum _asrc_audio_channel
+{
+ kASRC_ChannelsNumber1 = 1U, /*!< channel number is 1 */
+ kASRC_ChannelsNumber2 = 2U, /*!< channel number is 2 */
+ kASRC_ChannelsNumber3 = 3U, /*!< channel number is 3 */
+ kASRC_ChannelsNumber4 = 4U, /*!< channel number is 4 */
+ kASRC_ChannelsNumber5 = 5U, /*!< channel number is 5 */
+ kASRC_ChannelsNumber6 = 6U, /*!< channel number is 6 */
+ kASRC_ChannelsNumber7 = 7U, /*!< channel number is 7 */
+ kASRC_ChannelsNumber8 = 8U, /*!< channel number is 8 */
+ kASRC_ChannelsNumber9 = 9U, /*!< channel number is 9 */
+ kASRC_ChannelsNumber10 = 10U, /*!< channel number is 10 */
+} asrc_audio_channel_t;
+
+/*! @brief data width */
+typedef enum _asrc_data_width
+{
+ kASRC_DataWidth24Bit = 0U, /*!< data width 24bit */
+ kASRC_DataWidth16Bit = 1U, /*!< data width 16bit */
+ kASRC_DataWidth8Bit = 2U, /*!< data width 8bit */
+} asrc_data_width_t;
+
+/*! @brief data alignment */
+typedef enum _asrc_data_align
+{
+ kASRC_DataAlignMSB = 1U, /*!< data alignment MSB */
+ kASRC_DataAlignLSB = 0U, /*!< data alignment LSB */
+} asrc_data_align_t;
+
+/*! @brief sign extension */
+typedef enum _asrc_sign_extension
+{
+ kASRC_NoSignExtension = 0U, /*!< no sign extension */
+ kASRC_SignExtension = 1U, /*!< sign extension */
+} asrc_sign_extension_t;
+
+/*! @brief asrc channel pair configuation */
+typedef struct _asrc_channel_pair_config
+{
+ asrc_audio_channel_t audioDataChannels; /*!< audio data channel numbers */
+ asrc_clock_source_t
+ inClockSource; /*!< input clock source, reference the clock source definition in SOC header file */
+ uint32_t inSourceClock_Hz; /*!< input source clock frequency */
+
+ asrc_clock_source_t
+ outClockSource; /*!< output clock source, reference the clock source definition in SOC header file */
+ uint32_t outSourceClock_Hz; /*!< output source clock frequency */
+
+ asrc_ratio_t sampleRateRatio; /*!< sample rate ratio type */
+
+ asrc_data_width_t inDataWidth; /*!< input data width */
+ asrc_data_align_t inDataAlign; /*!< input data alignment */
+
+ asrc_data_width_t outDataWidth; /*!< output data width */
+ asrc_data_align_t outDataAlign; /*!< output data alignment */
+ asrc_sign_extension_t outSignExtension; /*!< output extension */
+
+ uint8_t outFifoThreshold; /*!< output fifo threshold */
+ uint8_t inFifoThreshold; /*!< input fifo threshold */
+
+ bool bufStallWhenFifoEmptyFull; /*!< stall Pair A conversion in case of Buffer near empty full condition */
+
+} asrc_channel_pair_config_t;
+
+/*! @brief SAI transfer structure */
+typedef struct _asrc_transfer
+{
+ void *inData; /*!< Data address to convert.*/
+ size_t inDataSize; /*!< input data size. */
+ void *outData; /*!< Data address to store converted data */
+ size_t outDataSize; /*!< output data size. */
+} asrc_transfer_t;
+
+/*! @brief asrc handler */
+typedef struct _asrc_handle asrc_handle_t;
+
+/*! @brief ASRC transfer callback prototype */
+typedef void (*asrc_transfer_callback_t)(ASRC_Type *base, asrc_handle_t *handle, status_t status, void *userData);
+
+/*! @brief asrc in handler */
+typedef struct _asrc_in_handle
+{
+ asrc_transfer_callback_t callback; /*!< Callback function called at convert complete */
+ uint32_t sampleWidth; /*!< data width */
+ uint32_t sampleMask; /*!< data mask */
+ uint32_t fifoThreshold; /*!< fifo threshold */
+ uint8_t *asrcQueue[ASRC_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer */
+ size_t transferSamples[ASRC_XFER_QUEUE_SIZE]; /*!< Data bytes need to convert */
+ volatile uint8_t queueUser; /*!< Index for user to queue transfer */
+ volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */
+} asrc_in_handle_t;
+
+/*! @brief output handler */
+typedef struct _asrc_out_handle
+{
+ asrc_transfer_callback_t callback; /*!< Callback function called at convert complete */
+ uint32_t sampleWidth; /*!< data width */
+ uint32_t fifoThreshold; /*!< fifo threshold */
+ uint8_t *asrcQueue[ASRC_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer */
+ size_t transferSamples[ASRC_XFER_QUEUE_SIZE]; /*!< Data bytes need to convert */
+ volatile uint8_t queueUser; /*!< Index for user to queue transfer */
+ volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */
+} asrc_out_handle_t;
+
+/*! @brief ASRC handle structure */
+struct _asrc_handle
+{
+ ASRC_Type *base; /*!< base address */
+
+ uint32_t state; /*!< Transfer status */
+ void *userData; /*!< Callback parameter passed to callback function*/
+
+ asrc_audio_channel_t audioDataChannels; /*!< audio channel number */
+ asrc_channel_pair_t channelPair; /*!< channel pair mask */
+
+ asrc_in_handle_t in; /*!< asrc input handler */
+ asrc_out_handle_t out; /*!< asrc output handler */
+};
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /*_cplusplus*/
+
+/*!
+ * @name Initialization and deinitialization
+ * @{
+ */
+
+/*!
+ * @brief Get instance number of the ASRC peripheral.
+ *
+ * @param base ASRC base pointer.
+ */
+uint32_t ASRC_GetInstance(ASRC_Type *base);
+
+/*!
+ * brief Initializes the asrc peripheral.
+ *
+ * This API gates the asrc clock. The asrc module can't operate unless ASRC_Init is called to enable the clock.
+ *
+ * param base asrc base pointer.
+ * param asrcPeripheralClock_Hz peripheral clock of ASRC.
+ */
+void ASRC_Init(ASRC_Type *base, uint32_t asrcPeripheralClock_Hz);
+
+/*!
+ * @brief De-initializes the ASRC peripheral.
+ *
+ * This API gates the ASRC clock and disable ASRC module. The ASRC module can't operate unless ASRC_Init
+ *
+ * @param base ASRC base pointer.
+ */
+void ASRC_Deinit(ASRC_Type *base);
+
+/*!
+ * @brief Do software reset .
+ *
+ * This software reset bit is self-clear bit, it will generate a software reset signal inside ASRC.
+ * After 9 cycles of the ASRC processing clock, this reset process will stop and this bit will cleared
+ * automatically.
+ *
+ * @param base ASRC base pointer
+ */
+void ASRC_SoftwareReset(ASRC_Type *base);
+
+/*!
+ * @brief ASRC configure channel pair.
+ *
+ * @param base ASRC base pointer.
+ * @param channelPair index of channel pair, reference _asrc_channel_pair.
+ * @param config ASRC channel pair configuration pointer.
+ * @param inputSampleRate input audio data sample rate.
+ * @param outputSampleRate output audio data sample rate.
+ */
+status_t ASRC_SetChannelPairConfig(ASRC_Type *base,
+ asrc_channel_pair_t channelPair,
+ asrc_channel_pair_config_t *config,
+ uint32_t inputSampleRate,
+ uint32_t outputSampleRate);
+
+/*!
+ * @brief Get output sample buffer size.
+ *
+ * @note This API is depends on the ASRC output configuration, should be called after the ASRC_SetChannelPairConfig.
+ *
+ * @param base asrc base pointer.
+ * @param channelPair ASRC channel pair number.
+ * @param inSampleRate input sample rate.
+ * @param outSampleRate output sample rate.
+ * @param inSamplesize input sampleS size.
+ * @retval output buffer size in byte.
+ */
+uint32_t ASRC_GetOutSamplesSize(ASRC_Type *base,
+ asrc_channel_pair_t channelPair,
+ uint32_t inSampleRate,
+ uint32_t outSampleRate,
+ uint32_t inSamplesize);
+
+/*!
+ * @brief Map register sample width to real sample width.
+ *
+ * @note This API is depends on the ASRC configuration, should be called after the ASRC_SetChannelPairConfig.
+ * @param base asrc base pointer.
+ * @param channelPair asrc channel pair index.
+ * @param inWidth ASRC channel pair number.
+ * @param outWidth input sample rate.
+ * @retval input sample mask value.
+ */
+uint32_t ASRC_MapSamplesWidth(ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *inWidth, uint32_t *outWidth);
+
+/*!
+ * @brief Get left samples in fifo.
+ *
+ * @param base asrc base pointer.
+ * @param channelPair ASRC channel pair number.
+ * @param buffer input sample numbers.
+ * @param outSampleWidth output sample width.
+ * @param remainSamples output sample rate.
+ * @retval remain samples number.
+ */
+uint32_t ASRC_GetRemainFifoSamples(ASRC_Type *base,
+ asrc_channel_pair_t channelPair,
+ uint32_t *buffer,
+ uint32_t outSampleWidth,
+ uint32_t remainSamples);
+
+/*!
+ * @brief ASRC module enable.
+ *
+ * @param base ASRC base pointer.
+ * @param enable true is enable, false is disable
+ */
+static inline void ASRC_ModuleEnable(ASRC_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->ASRCTR |= ASRC_ASRCTR_ASRCEN_MASK;
+ }
+ else
+ {
+ base->ASRCTR &= ~ASRC_ASRCTR_ASRCEN_MASK;
+ }
+}
+
+/*!
+ * @brief ASRC enable channel pair.
+ *
+ * @param base ASRC base pointer.
+ * @param channelPair channel pair mask value, reference _asrc_channel_pair_mask.
+ * @param enable true is enable, false is disable.
+ */
+static inline void ASRC_ChannelPairEnable(ASRC_Type *base, asrc_channel_pair_t channelPair, bool enable)
+{
+ if (enable)
+ {
+ base->ASRCTR |= 1UL << ((uint32_t)channelPair + 1U);
+ }
+ else
+ {
+ base->ASRCTR &= ~(1UL << ((uint32_t)channelPair + 1U));
+ }
+}
+/*! @} */
+
+/*!
+ * @name Interrupts
+ * @{
+ */
+
+/*!
+ * @brief ASRC interrupt enable
+ * This function enable the ASRC interrupt with the provided mask.
+ *
+ * @param base ASRC peripheral base address.
+ * @param mask The interrupts to enable. Logical OR of @ref _asrc_interrupt_mask.
+ */
+static inline void ASRC_EnableInterrupt(ASRC_Type *base, uint32_t mask)
+{
+ base->ASRIER |= mask;
+}
+
+/*!
+ * @brief ASRC interrupt disable
+ * This function disable the ASRC interrupt with the provided mask.
+ *
+ * @param base ASRC peripheral base address.
+ * @param mask The interrupts to disable. Logical OR of @ref _asrc_interrupt_mask.
+ */
+static inline void ASRC_DisableInterrupt(ASRC_Type *base, uint32_t mask)
+{
+ base->ASRIER &= ~mask;
+}
+
+/*! @} */
+
+/*!
+ * @name Status
+ * @{
+ */
+
+/*!
+ * @brief Gets the ASRC status flag state.
+ *
+ * @param base ASRC base pointer
+ * @return ASRC Tx status flag value. Use the Status Mask to get the status value needed.
+ */
+static inline uint32_t ASRC_GetStatus(ASRC_Type *base)
+{
+ return base->ASRSTR;
+}
+
+/*!
+ * @brief Gets the ASRC channel pair initialization state.
+ *
+ * @param base ASRC base pointer
+ * @param channel ASRC channel pair.
+ * @return ASRC Tx status flag value. Use the Status Mask to get the status value needed.
+ */
+static inline bool ASRC_GetChannelPairInitialStatus(ASRC_Type *base, asrc_channel_pair_t channel)
+{
+ return ((base->ASRCFG >> ASRC_ASRCFG_INIRQA_SHIFT) & (1U << (uint32_t)channel)) == 0U ? false : true;
+}
+
+/*!
+ * @brief Gets the ASRC channel A fifo a status flag state.
+ *
+ * @param base ASRC base pointer
+ * @param channelPair ASRC channel pair.
+ * @return ASRC channel pair a fifo status flag value. Use the Status Mask to get the status value needed.
+ */
+static inline uint32_t ASRC_GetChannelPairFifoStatus(ASRC_Type *base, asrc_channel_pair_t channelPair)
+{
+ return ASRC_ASRMCR(base, channelPair) & ((uint32_t)kASRC_OutputFifoNearFull | (uint32_t)kASRC_InputFifoNearEmpty);
+}
+
+/*! @} */
+
+/*!
+ * @name Bus Operations
+ * @{
+ */
+
+/*!
+ * @brief Writes data into ASRC channel pair FIFO.
+ * Note: ASRC fifo width is 24bit.
+ * @param base ASRC base pointer.
+ * @param channelPair ASRC channel pair.
+ * @param data Data needs to be written.
+ */
+static inline void ASRC_ChannelPairWriteData(ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t data)
+{
+ ASRC_ASRDI(base, channelPair) = data;
+}
+
+/*!
+ * @brief Read data from ASRC channel pair FIFO.
+ * Note: ASRC fifo width is 24bit.
+ *
+ * @param base ASRC base pointer.
+ * @param channelPair ASRC channel pair.
+ * @retval value read from fifo.
+ */
+static inline uint32_t ASRC_ChannelPairReadData(ASRC_Type *base, asrc_channel_pair_t channelPair)
+{
+ return ASRC_ASRDO(base, channelPair);
+}
+
+/*!
+ * @brief Get input data fifo address.
+ * Note: ASRC fifo width is 24bit.
+ *
+ * @param base ASRC base pointer.
+ * @param channelPair ASRC channel pair.
+ */
+static inline uint32_t ASRC_GetInputDataRegisterAddress(ASRC_Type *base, asrc_channel_pair_t channelPair)
+{
+ return (uint32_t)ASRC_ASRDI_ADDR(base, channelPair);
+}
+
+/*!
+ * @brief Get output data fifo address.
+ * Note: ASRC fifo width is 24bit.
+ *
+ * @param base ASRC base pointer.
+ * @param channelPair ASRC channel pair.
+ */
+static inline uint32_t ASRC_GetOutputDataRegisterAddress(ASRC_Type *base, asrc_channel_pair_t channelPair)
+{
+ return (uint32_t)ASRC_ASRDO_ADDR(base, channelPair);
+}
+
+/*!
+ * @brief ASRC configure ideal ratio.
+ * The ideal ratio should be used when input clock source is not avalible.
+ *
+ * @param base ASRC base pointer.
+ * @param channelPair ASRC channel pair.
+ * @param inputSampleRate input audio data sample rate.
+ * @param outputSampleRate output audio data sample rate.
+ */
+status_t ASRC_SetIdealRatioConfig(ASRC_Type *base,
+ asrc_channel_pair_t channelPair,
+ uint32_t inputSampleRate,
+ uint32_t outputSampleRate);
+
+/*! @} */
+
+/*!
+ * @name Transactional
+ * @{
+ */
+
+/*!
+ * @brief ASRC configure channel pair.
+ *
+ * @param base ASRC base pointer.
+ * @param handle ASRC transactional handle pointer.
+ * @param config ASRC channel pair configuration pointer.
+ * @param inputSampleRate input audio data sample rate.
+ * @param outputSampleRate output audio data sample rate.
+ */
+status_t ASRC_TransferSetChannelPairConfig(ASRC_Type *base,
+ asrc_handle_t *handle,
+ asrc_channel_pair_config_t *config,
+ uint32_t inputSampleRate,
+ uint32_t outputSampleRate);
+
+/*!
+ * @brief Initializes the ASRC handle.
+ *
+ * This function initializes the handle for the ASRC transactional APIs. Call
+ * this function once to get the handle initialized.
+ *
+ * @param base ASRC base pointer
+ * @param handle ASRC handle pointer.
+ * @param channelPair ASRC channel pair.
+ * @param inCallback Pointer to the user callback function.
+ * @param outCallback Pointer to the user callback function.
+ * @param userData User parameter passed to the callback function
+ */
+void ASRC_TransferCreateHandle(ASRC_Type *base,
+ asrc_handle_t *handle,
+ asrc_channel_pair_t channelPair,
+ asrc_transfer_callback_t inCallback,
+ asrc_transfer_callback_t outCallback,
+ void *userData);
+
+/*!
+ * @brief Performs an interrupt non-blocking convert on asrc.
+ *
+ * @note This API returns immediately after the transfer initiates, application should check the wait and check the
+ * callback status.
+ *
+ * @param base asrc base pointer.
+ * @param handle Pointer to the asrc_handle_t structure which stores the transfer state.
+ * @param xfer Pointer to the ASRC_transfer_t structure.
+ * @retval kStatus_Success Successfully started the data receive.
+ * @retval kStatus_ASRCBusy Previous receive still not finished.
+ */
+status_t ASRC_TransferNonBlocking(ASRC_Type *base, asrc_handle_t *handle, asrc_transfer_t *xfer);
+
+/*!
+ * @brief Performs an blocking convert on asrc.
+ *
+ * @note This API returns immediately after the convert finished.
+ *
+ * @param base asrc base pointer.
+ * @param channelPair channel pair index.
+ * @param xfer Pointer to the ASRC_transfer_t structure.
+ * @retval kStatus_Success Successfully started the data receive.
+ */
+status_t ASRC_TransferBlocking(ASRC_Type *base, asrc_channel_pair_t channelPair, asrc_transfer_t *xfer);
+
+/*!
+ * @brief Get converted byte count.
+ *
+ * @param base ASRC base pointer.
+ * @param handle Pointer to the asrc_handle_t structure which stores the transfer state.
+ * @param count Bytes count sent.
+ * @retval kStatus_Success Succeed get the transfer count.
+ * @retval kStatus_ASRCIdle There is not a non-blocking transaction currently in progress.
+ */
+status_t ASRC_TransferGetConvertedCount(ASRC_Type *base, asrc_handle_t *handle, size_t *count);
+
+/*!
+ * @brief Aborts the current convert.
+ *
+ * @note This API can be called any time when an interrupt non-blocking transfer initiates
+ * to abort the transfer early.
+ *
+ * @param base ASRC base pointer.
+ * @param handle Pointer to the asrc_handle_t structure which stores the transfer state.
+ */
+void ASRC_TransferAbortConvert(ASRC_Type *base, asrc_handle_t *handle);
+
+/*!
+ * @brief Terminate all ASRC convert.
+ *
+ * This function will clear all transfer slots buffered in the asrc queue. If users only want to abort the
+ * current transfer slot, please call ASRC_TransferAbortConvert.
+ *
+ * @param base ASRC base pointer.
+ * @param handle ASRC eDMA handle pointer.
+ */
+void ASRC_TransferTerminateConvert(ASRC_Type *base, asrc_handle_t *handle);
+
+/*!
+ * @brief ASRC convert interrupt handler.
+ *
+ * @param base ASRC base pointer.
+ * @param handle Pointer to the asrc_handle_t structure.
+ */
+void ASRC_TransferHandleIRQ(ASRC_Type *base, asrc_handle_t *handle);
+
+/*! @} */
+
+#if defined(__cplusplus)
+}
+#endif /*_cplusplus*/
+
+/*! @} */
+
+#endif /* _FSL_ASRC_H_ */
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc_edma.c b/bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc_edma.c
new file mode 100644
index 0000000000..8731a8e8fe
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc_edma.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright 2019-2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_asrc_edma.h"
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.asrc_edma"
+#endif
+
+/*******************************************************************************
+ * Definitations
+ ******************************************************************************/
+/* Used for 32byte aligned */
+#define STCD_ADDR(address) (edma_tcd_t *)(((uint32_t)(address) + 32U) & ~0x1FU)
+
+/*<! Structure definition for uart_edma_private_handle_t. The structure is private. */
+typedef struct _asrc_edma_private_handle
+{
+ ASRC_Type *base;
+ asrc_edma_handle_t *handle;
+} asrc_edma_private_handle_t;
+
+/*<! Private handle only used for internally. */
+static asrc_edma_private_handle_t s_edmaPrivateHandle[FSL_FEATURE_SOC_ASRC_COUNT][FSL_ASRC_CHANNEL_PAIR_COUNT];
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+/*!
+ * @brief ASRC EDMA callback for input.
+ *
+ * @param handle pointer to asrc_edma_handle_t structure which stores the transfer state.
+ * @param userData Parameter for user callback.
+ * @param done If the DMA transfer finished.
+ * @param tcds The TCD index.
+ */
+static void ASRC_InEDMACallback(edma_handle_t *handle, void *userData, bool done, uint32_t tcds);
+
+/*!
+ * @brief ASRC EDMA callback for output.
+ *
+ * @param handle pointer to asrc_edma_handle_t structure which stores the transfer state.
+ * @param userData Parameter for user callback.
+ * @param done If the DMA transfer finished.
+ * @param tcds The TCD index.
+ */
+static void ASRC_OutEDMACallback(edma_handle_t *handle, void *userData, bool done, uint32_t tcds);
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+static void ASRC_InEDMACallback(edma_handle_t *handle, void *userData, bool done, uint32_t tcds)
+{
+ asrc_edma_private_handle_t *privHandle = (asrc_edma_private_handle_t *)userData;
+ asrc_edma_handle_t *asrcHandle = privHandle->handle;
+ asrc_in_edma_handle_t *asrcInHandle = &(privHandle->handle->in);
+ status_t inStatus = kStatus_ASRCInIdle;
+ /* If finished a block, call the callback function */
+ asrcInHandle->asrcQueue[asrcInHandle->queueDriver] = NULL;
+ asrcInHandle->queueDriver = (asrcInHandle->queueDriver + 1U) % ASRC_XFER_QUEUE_SIZE;
+
+ /* If all data finished, just stop the transfer */
+ if (asrcInHandle->asrcQueue[asrcInHandle->queueDriver] == NULL)
+ {
+ EDMA_AbortTransfer(asrcInHandle->inDmaHandle);
+ inStatus = kStatus_ASRCInQueueIdle;
+ }
+
+ if (asrcHandle->callback != NULL)
+ {
+ (asrcHandle->callback)(privHandle->base, asrcHandle, inStatus, asrcHandle->userData);
+ }
+}
+
+static void ASRC_OutEDMACallback(edma_handle_t *handle, void *userData, bool done, uint32_t tcds)
+{
+ asrc_edma_private_handle_t *privHandle = (asrc_edma_private_handle_t *)userData;
+ asrc_edma_handle_t *asrcHandle = privHandle->handle;
+ asrc_out_edma_handle_t *asrcOutHandle = &(privHandle->handle->out);
+ uint32_t queueDriverIndex = asrcOutHandle->queueDriver;
+ status_t callbackStatus = kStatus_ASRCOutIdle;
+
+ /* If finished a block, call the callback function */
+ asrcOutHandle->asrcQueue[queueDriverIndex] = NULL;
+ asrcOutHandle->queueDriver = (uint8_t)((queueDriverIndex + 1U) % ASRC_XFER_OUT_QUEUE_SIZE);
+
+ /* If all data finished, just stop the transfer */
+ if (asrcOutHandle->asrcQueue[asrcOutHandle->queueDriver] == NULL)
+ {
+ EDMA_AbortTransfer(asrcOutHandle->outDmaHandle);
+ callbackStatus = kStatus_ASRCOutQueueIdle;
+ }
+
+ if (asrcHandle->callback != NULL)
+ {
+ (asrcHandle->callback)(privHandle->base, asrcHandle, callbackStatus, asrcHandle->userData);
+ }
+}
+/*!
+ * brief Initializes the ASRC IN eDMA handle.
+ *
+ * This function initializes the ASRC DMA handle, which can be used for other ASRC transactional APIs.
+ * Usually, for a specified ASRC channel pair, call this API once to get the initialized handle.
+ *
+ * param base ASRC base pointer.
+ * param channelPair ASRC channel pair
+ * param handle ASRC eDMA handle pointer.
+ * param callback Pointer to user callback function.
+ * param txDmaHandle ASRC send edma handle pointer.
+ * param periphConfig peripheral configuration.
+ * param userData User parameter passed to the callback function.
+ */
+void ASRC_TransferInCreateHandleEDMA(ASRC_Type *base,
+ asrc_edma_handle_t *handle,
+ asrc_channel_pair_t channelPair,
+ asrc_edma_callback_t callback,
+ edma_handle_t *inDmaHandle,
+ const asrc_p2p_edma_config_t *periphConfig,
+ void *userData)
+{
+ assert((handle != NULL) && (inDmaHandle != NULL));
+
+ uint32_t instance = ASRC_GetInstance(base);
+
+ /* Zero the handle */
+ (void)memset(&handle->in, 0, sizeof(asrc_in_edma_handle_t));
+
+ handle->in.inDmaHandle = inDmaHandle;
+ handle->callback = callback;
+ handle->userData = userData;
+
+ /* Set ASRC state to idle */
+ handle->in.state = kStatus_ASRCIdle;
+ handle->channelPair = channelPair;
+ handle->in.peripheralConfig = periphConfig;
+
+ s_edmaPrivateHandle[instance][channelPair].base = base;
+ s_edmaPrivateHandle[instance][channelPair].handle = handle;
+
+ /* Need to use scatter gather */
+ EDMA_InstallTCDMemory(inDmaHandle, (edma_tcd_t *)(STCD_ADDR(handle->in.tcd)), ASRC_XFER_OUT_QUEUE_SIZE);
+ /* Install callback for Tx dma channel */
+ EDMA_SetCallback(inDmaHandle, ASRC_InEDMACallback, &s_edmaPrivateHandle[instance][channelPair]);
+}
+
+/*!
+ * brief Initializes the ASRC OUT eDMA handle.
+ *
+ * This function initializes the ASRC DMA handle, which can be used for other ASRC transactional APIs.
+ * Usually, for a specified ASRC channel pair, call this API once to get the initialized handle.
+ *
+ * param base ASRC base pointer.
+ * param channelPair ASRC channel pair
+ * param handle ASRC eDMA handle pointer.
+ * param callback Pointer to user callback function.
+ * param txDmaHandle ASRC send edma handle pointer.
+ * param periphConfig peripheral configuration.
+ * param userData User parameter passed to the callback function.
+ */
+void ASRC_TransferOutCreateHandleEDMA(ASRC_Type *base,
+ asrc_edma_handle_t *handle,
+ asrc_channel_pair_t channelPair,
+ asrc_edma_callback_t callback,
+ edma_handle_t *outDmaHandle,
+ const asrc_p2p_edma_config_t *periphConfig,
+ void *userData)
+{
+ assert((handle != NULL) && (NULL != outDmaHandle));
+
+ uint32_t instance = ASRC_GetInstance(base);
+
+ /* Zero the handle */
+ (void)memset(&handle->out, 0, sizeof(asrc_out_edma_handle_t));
+
+ handle->out.outDmaHandle = outDmaHandle;
+ handle->callback = callback;
+ handle->userData = userData;
+
+ /* Set ASRC state to idle */
+ handle->out.state = kStatus_ASRCIdle;
+ handle->channelPair = channelPair;
+ handle->out.peripheralConfig = periphConfig;
+
+ s_edmaPrivateHandle[instance][channelPair].base = base;
+ s_edmaPrivateHandle[instance][channelPair].handle = handle;
+
+ /* Need to use scatter gather */
+ EDMA_InstallTCDMemory(outDmaHandle, (edma_tcd_t *)(STCD_ADDR(handle->out.tcd)), ASRC_XFER_OUT_QUEUE_SIZE);
+ /* Install callback for Tx dma channel */
+ EDMA_SetCallback(outDmaHandle, ASRC_OutEDMACallback, &s_edmaPrivateHandle[instance][channelPair]);
+}
+
+/*!
+ * brief Configures the ASRC channel pair.
+ *
+ * param base ASRC base pointer.
+ * param handle ASRC eDMA handle pointer.
+ * param asrcConfig asrc configurations.
+ * param periphConfig peripheral configuration.
+ * param inputSampleRate ASRC input sample rate.
+ * param outputSampleRate ASRC output sample rate.
+ */
+status_t ASRC_TransferSetChannelPairConfigEDMA(ASRC_Type *base,
+ asrc_edma_handle_t *handle,
+ asrc_channel_pair_config_t *asrcConfig,
+ uint32_t inSampleRate,
+ uint32_t outSampleRate)
+{
+ assert((handle != NULL) && (NULL != asrcConfig));
+
+ /* Configure the audio format to ASRC registers */
+ if (ASRC_SetChannelPairConfig(base, handle->channelPair, asrcConfig, inSampleRate, outSampleRate) !=
+ kStatus_Success)
+ {
+ return kStatus_ASRCChannelPairConfigureFailed;
+ }
+ handle->in.fifoThreshold = (asrcConfig->inFifoThreshold) * (uint32_t)asrcConfig->audioDataChannels;
+ handle->out.fifoThreshold = (asrcConfig->outFifoThreshold) * (uint32_t)asrcConfig->audioDataChannels;
+ (void)ASRC_MapSamplesWidth(base, handle->channelPair, &handle->in.sampleWidth, &handle->out.sampleWidth);
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Get output sample buffer size can be transferred by edma.
+ *
+ * note This API is depends on the ASRC output configuration, should be called after the
+ * ASRC_TransferSetChannelPairConfigEDMA.
+ *
+ * param base asrc base pointer.
+ * param handle ASRC channel pair edma handle.
+ * param inSampleRate input sample rate.
+ * param outSampleRate output sample rate.
+ * param inSamples input sampleS size.
+ * retval output buffer size in byte.
+ */
+uint32_t ASRC_GetOutSamplesSizeEDMA(
+ ASRC_Type *base, asrc_edma_handle_t *handle, uint32_t inSampleRate, uint32_t outSampleRate, uint32_t inSamplesize)
+{
+ uint32_t outputSize = ASRC_GetOutSamplesSize(base, handle->channelPair, inSampleRate, outSampleRate, inSamplesize);
+
+ return outputSize - outputSize % handle->out.fifoThreshold;
+}
+
+static status_t ASRC_TransferOutSubmitEDMA(ASRC_Type *base,
+ asrc_edma_handle_t *handle,
+ uint32_t *outDataAddr,
+ uint32_t outDataSize)
+{
+ assert(outDataAddr != NULL);
+ assert(outDataSize != 0U);
+
+ uint32_t outAddr = ASRC_GetOutputDataRegisterAddress(base, handle->channelPair);
+ edma_transfer_config_t config = {0};
+ edma_transfer_type_t type = kEDMA_PeripheralToMemory;
+
+ if (handle->out.asrcQueue[handle->out.queueUser] != NULL)
+ {
+ return kStatus_ASRCQueueFull;
+ }
+
+ if (handle->out.peripheralConfig != NULL)
+ {
+ type = kEDMA_PeripheralToPeripheral;
+ }
+
+ if (handle->out.asrcQueue[handle->out.queueUser] != NULL)
+ {
+ return kStatus_ASRCQueueFull;
+ }
+
+ handle->out.asrcQueue[handle->out.queueUser] = outDataAddr;
+ handle->out.transferSize[handle->out.queueUser] = outDataSize;
+ handle->out.queueUser = (handle->out.queueUser + 1U) % ASRC_XFER_OUT_QUEUE_SIZE;
+ /* Prepare ASRC output edma configuration */
+ EDMA_PrepareTransfer(&config, (uint32_t *)outAddr, handle->out.sampleWidth, outDataAddr, handle->out.sampleWidth,
+ handle->out.fifoThreshold * handle->out.sampleWidth, outDataSize, type);
+
+ if (handle->out.state != (uint32_t)kStatus_ASRCBusy)
+ {
+ (void)EDMA_SubmitTransfer(handle->out.outDmaHandle, &config);
+
+ EDMA_StartTransfer(handle->out.outDmaHandle);
+
+ if ((handle->out.peripheralConfig != NULL) && (handle->out.peripheralConfig->startPeripheral != NULL))
+ {
+ handle->out.peripheralConfig->startPeripheral(true);
+ }
+ }
+
+ return kStatus_Success;
+}
+
+static status_t ASRC_TransferInSubmitEDMA(ASRC_Type *base,
+ asrc_edma_handle_t *handle,
+ uint32_t *inDataAddr,
+ uint32_t inDataSize)
+{
+ assert(inDataAddr != NULL);
+ assert(inDataSize != 0U);
+
+ uint32_t inAddr = ASRC_GetInputDataRegisterAddress(base, handle->channelPair);
+ edma_transfer_config_t config = {0};
+
+ if (handle->in.asrcQueue[handle->in.queueUser] != NULL)
+ {
+ return kStatus_ASRCQueueFull;
+ }
+
+ /* Add into queue */
+ handle->in.asrcQueue[handle->in.queueUser] = inDataAddr;
+ handle->in.transferSize[handle->in.queueUser] = inDataSize;
+ handle->in.queueUser = (handle->in.queueUser + 1U) % ASRC_XFER_IN_QUEUE_SIZE;
+
+ /* Prepare ASRC input edma configuration */
+ EDMA_PrepareTransfer(&config, (uint32_t *)inDataAddr, handle->in.sampleWidth, (uint32_t *)inAddr,
+ handle->in.sampleWidth, handle->in.fifoThreshold * handle->in.sampleWidth, inDataSize,
+ handle->in.peripheralConfig == NULL ? kEDMA_MemoryToPeripheral : kEDMA_PeripheralToPeripheral);
+
+ if (handle->in.state != (uint32_t)kStatus_ASRCBusy)
+ {
+ (void)EDMA_SubmitTransfer(handle->in.inDmaHandle, &config);
+ EDMA_StartTransfer(handle->in.inDmaHandle);
+ /* start peripheral */
+ if ((handle->in.peripheralConfig != NULL) && (handle->in.peripheralConfig->startPeripheral != NULL))
+ {
+ handle->in.peripheralConfig->startPeripheral(true);
+ }
+ }
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Performs a non-blocking ASRC convert using EDMA.
+ *
+ * note This interface returns immediately after the transfer initiates.
+
+ * param base ASRC base pointer.
+ * param handle ASRC eDMA handle pointer.
+ * param xfer Pointer to the DMA transfer structure.
+ * retval kStatus_Success Start a ASRC eDMA send successfully.
+ * retval kStatus_InvalidArgument The input argument is invalid.
+ * retval kStatus_ASRCQueueFull ASRC EDMA driver queue is full.
+ */
+status_t ASRC_TransferEDMA(ASRC_Type *base, asrc_edma_handle_t *handle, asrc_transfer_t *xfer)
+{
+ assert(handle != NULL);
+
+ if (ASRC_TransferOutSubmitEDMA(base, handle, xfer->outData, xfer->outDataSize) != kStatus_Success)
+ {
+ return kStatus_ASRCQueueFull;
+ }
+
+ if (ASRC_TransferInSubmitEDMA(base, handle, xfer->inData, xfer->inDataSize) != kStatus_Success)
+ {
+ return kStatus_ASRCQueueFull;
+ }
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Aborts a ASRC IN transfer using eDMA.
+ *
+ * This function only aborts the current transfer slots, the other transfer slots' information still kept
+ * in the handler. If users want to terminate all transfer slots, just call ASRC_TransferTerminalP2PEDMA.
+ *
+ * param base ASRC base pointer.
+ * param handle ASRC eDMA handle pointer.
+ */
+void ASRC_TransferInAbortEDMA(ASRC_Type *base, asrc_edma_handle_t *handle)
+{
+ assert(handle != NULL);
+
+ /* Disable dma */
+ EDMA_AbortTransfer(handle->in.inDmaHandle);
+
+ /* Handle the queue index */
+ handle->in.asrcQueue[handle->in.queueDriver] = NULL;
+ handle->in.queueDriver = (handle->in.queueDriver + 1U) % ASRC_XFER_QUEUE_SIZE;
+
+ /* Set the handle state */
+ handle->in.state = kStatus_ASRCIdle;
+}
+
+/*!
+ * brief Aborts a ASRC OUT transfer using eDMA.
+ *
+ * This function only aborts the current transfer slots, the other transfer slots' information still kept
+ * in the handler. If users want to terminate all transfer slots, just call ASRC_TransferTerminalP2PEDMA.
+ *
+ * param base ASRC base pointer.
+ * param handle ASRC eDMA handle pointer.
+ */
+void ASRC_TransferOutAbortEDMA(ASRC_Type *base, asrc_edma_handle_t *handle)
+{
+ assert(handle != NULL);
+
+ /* Disable dma */
+ EDMA_AbortTransfer(handle->out.outDmaHandle);
+
+ /* Handle the queue index */
+ handle->out.asrcQueue[handle->out.queueDriver] = NULL;
+ handle->out.queueDriver = (handle->out.queueDriver + 1U) % ASRC_XFER_QUEUE_SIZE;
+
+ /* Set the handle state */
+ handle->out.state = kStatus_ASRCIdle;
+}
+
+/*!
+ * brief Terminate In ASRC Convert.
+ *
+ * This function will clear all transfer slots buffered in the asrc queue. If users only want to abort the
+ * current transfer slot, please call ASRC_TransferAbortPP2PEDMA.
+ *
+ * param base ASRC base pointer.
+ * param handle ASRC eDMA handle pointer.
+ */
+void ASRC_TransferInTerminalEDMA(ASRC_Type *base, asrc_edma_handle_t *handle)
+{
+ assert(handle != NULL);
+
+ /* Abort the current transfer */
+ ASRC_TransferInAbortEDMA(base, handle);
+ /* stop peripheral */
+ if ((handle->in.peripheralConfig != NULL) && (handle->in.peripheralConfig->startPeripheral != NULL))
+ {
+ handle->in.peripheralConfig->startPeripheral(false);
+ }
+
+ /* Clear all the internal information */
+ (void)memset(handle->in.tcd, 0, sizeof(handle->in.tcd));
+ (void)memset(handle->in.asrcQueue, 0, sizeof(handle->in.asrcQueue));
+ (void)memset(handle->in.transferSize, 0, sizeof(handle->in.transferSize));
+ handle->in.queueUser = 0U;
+ handle->in.queueDriver = 0U;
+}
+
+/*!
+ * brief Terminate Out ASRC Convert.
+ *
+ * This function will clear all transfer slots buffered in the asrc queue. If users only want to abort the
+ * current transfer slot, please call ASRC_TransferAbortPP2PEDMA.
+ *
+ * param base ASRC base pointer.
+ * param handle ASRC eDMA handle pointer.
+ */
+void ASRC_TransferOutTerminalEDMA(ASRC_Type *base, asrc_edma_handle_t *handle)
+{
+ assert(handle != NULL);
+
+ /* Abort the current transfer */
+ ASRC_TransferOutAbortEDMA(base, handle);
+
+ if ((handle->out.peripheralConfig != NULL) && (handle->out.peripheralConfig->startPeripheral != NULL))
+ {
+ handle->out.peripheralConfig->startPeripheral(false);
+ }
+
+ (void)memset(handle->out.tcd, 0, sizeof(handle->out.tcd));
+ (void)memset(handle->out.asrcQueue, 0, sizeof(handle->out.asrcQueue));
+ (void)memset(handle->out.transferSize, 0, sizeof(handle->out.transferSize));
+ handle->out.queueUser = 0U;
+ handle->out.queueDriver = 0U;
+}
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc_edma.h b/bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc_edma.h
new file mode 100644
index 0000000000..89053232c8
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/asrc/fsl_asrc_edma.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2019-2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef _FSL_ASRC_P2P_EDMA_H_
+#define _FSL_ASRC_P2P_EDMA_H_
+
+#include "fsl_edma.h"
+#include "fsl_asrc.h"
+
+/*!
+ * @addtogroup asrc_edma_driver
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @name Driver version */
+/*@{*/
+#define FSL_ASRC_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0 */
+/*@}*/
+/*!< @brief ASRC IN edma QUEUE size */
+#define ASRC_XFER_IN_QUEUE_SIZE 4U
+#define ASRC_XFER_OUT_QUEUE_SIZE (ASRC_XFER_QUEUE_SIZE * 2U)
+
+typedef struct _asrc_edma_handle asrc_edma_handle_t;
+
+/*! @brief ASRC eDMA transfer callback function for finish and error */
+typedef void (*asrc_edma_callback_t)(ASRC_Type *base, asrc_edma_handle_t *handle, status_t status, void *userData);
+
+/*! @brief ASRC trigger peripheral function pointer */
+typedef void (*asrc_start_peripheral_t)(bool start);
+/*! @brief destination peripheral configuration */
+typedef struct _asrc_p2p_edma_config
+{
+ uint8_t watermark; /*!< peripheral watermark */
+ uint8_t channel; /*!< peripheral channel number */
+ asrc_start_peripheral_t startPeripheral; /*!< trigger peripheral start */
+} asrc_p2p_edma_config_t;
+
+/*!@ brief asrc in edma handler */
+typedef struct _asrc_in_edma_handle
+{
+ edma_handle_t *inDmaHandle; /*!< DMA handler for ASRC in */
+
+ uint8_t tcd[(ASRC_XFER_IN_QUEUE_SIZE + 1U) * sizeof(edma_tcd_t)]; /*!< TCD pool for eDMA send. */
+
+ uint32_t sampleWidth; /*!< input data width */
+ uint32_t fifoThreshold; /*!< ASRC input fifo threshold */
+ uint32_t *asrcQueue[ASRC_XFER_IN_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer. */
+ size_t transferSize[ASRC_XFER_IN_QUEUE_SIZE]; /*!< Data bytes need to transfer */
+ volatile uint8_t queueUser; /*!< Index for user to queue transfer. */
+ volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */
+ uint32_t state; /*!< Internal state for ASRC eDMA transfer */
+
+ const asrc_p2p_edma_config_t *peripheralConfig; /*!< peripheral configuration pointer */
+} asrc_in_edma_handle_t;
+
+/*!@ brief asrc out edma handler */
+typedef struct _asrc_out_edma_handle
+{
+ edma_handle_t *outDmaHandle; /*!< DMA handler for ASRC out */
+
+ uint8_t tcd[(ASRC_XFER_OUT_QUEUE_SIZE + 1U) * sizeof(edma_tcd_t)]; /*!< TCD pool for eDMA send. */
+
+ uint32_t sampleWidth; /*!< output data width */
+ uint32_t fifoThreshold; /*!< ASRC output fifo threshold */
+ uint32_t *asrcQueue[ASRC_XFER_OUT_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer. */
+ size_t transferSize[ASRC_XFER_OUT_QUEUE_SIZE]; /*!< Data bytes need to transfer */
+ volatile uint8_t queueUser; /*!< Index for user to queue transfer. */
+ volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */
+ uint32_t state; /*!< Internal state for ASRC eDMA transfer */
+ const asrc_p2p_edma_config_t *peripheralConfig; /*!< peripheral configuration pointer */
+} asrc_out_edma_handle_t;
+
+/*! @brief ASRC DMA transfer handle.*/
+struct _asrc_edma_handle
+{
+ asrc_in_edma_handle_t in; /*!< asrc in handler */
+ asrc_out_edma_handle_t out; /*!< asrc out handler */
+ asrc_channel_pair_t channelPair; /*!< channel pair */
+ void *userData; /*!< User callback parameter */
+ asrc_edma_callback_t callback; /*!< Callback for users while transfer finish or error occurs */
+};
+
+/*******************************************************************************
+ * APIs
+ ******************************************************************************/
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @name eDMA Transactional
+ * @{
+ */
+
+/*!
+ * @brief Initializes the ASRC IN eDMA handle.
+ *
+ * This function initializes the ASRC DMA handle, which can be used for other ASRC transactional APIs.
+ * Usually, for a specified ASRC channel pair, call this API once to get the initialized handle.
+ *
+ * @param base ASRC base pointer.
+ * @param channelPair ASRC channel pair
+ * @param handle ASRC eDMA handle pointer.
+ * @param callback Pointer to user callback function.
+ * @param inDmaHandle DMA handler for ASRC in.
+ * @param periphConfig peripheral configuration.
+ * @param userData User parameter passed to the callback function.
+ */
+void ASRC_TransferInCreateHandleEDMA(ASRC_Type *base,
+ asrc_edma_handle_t *handle,
+ asrc_channel_pair_t channelPair,
+ asrc_edma_callback_t callback,
+ edma_handle_t *inDmaHandle,
+ const asrc_p2p_edma_config_t *periphConfig,
+ void *userData);
+
+/*!
+ * @brief Initializes the ASRC OUT eDMA handle.
+ *
+ * This function initializes the ASRC DMA handle, which can be used for other ASRC transactional APIs.
+ * Usually, for a specified ASRC channel pair, call this API once to get the initialized handle.
+ *
+ * @param base ASRC base pointer.
+ * @param channelPair ASRC channel pair
+ * @param handle ASRC eDMA handle pointer.
+ * @param callback Pointer to user callback function.
+ * @param outDmaHandle DMA handler for ASRC out.
+ * @param periphConfig peripheral configuration.
+ * @param userData User parameter passed to the callback function.
+ */
+void ASRC_TransferOutCreateHandleEDMA(ASRC_Type *base,
+ asrc_edma_handle_t *handle,
+ asrc_channel_pair_t channelPair,
+ asrc_edma_callback_t callback,
+ edma_handle_t *outDmaHandle,
+ const asrc_p2p_edma_config_t *periphConfig,
+ void *userData);
+
+/*!
+ * @brief Configures the ASRC P2P channel pair.
+ *
+ *
+ * @param base ASRC base pointer.
+ * @param handle ASRC eDMA handle pointer.
+ * @param asrcConfig asrc configurations.
+ * @param inSampleRate ASRC input sample rate.
+ * @param outSampleRate ASRC output sample rate.
+ */
+status_t ASRC_TransferSetChannelPairConfigEDMA(ASRC_Type *base,
+ asrc_edma_handle_t *handle,
+ asrc_channel_pair_config_t *asrcConfig,
+ uint32_t inSampleRate,
+ uint32_t outSampleRate);
+
+/*!
+ * @brief Get output sample buffer size can be transferred by edma.
+ *
+ * @note This API is depends on the ASRC output configuration, should be called after the
+ * ASRC_TransferSetChannelPairConfigEDMA.
+ *
+ * @param base asrc base pointer.
+ * @param handle ASRC channel pair edma handle.
+ * @param inSampleRate input sample rate.
+ * @param outSampleRate output sample rate.
+ * @param inSamplesize input sampleS size.
+ * @retval output buffer size in byte.
+ */
+uint32_t ASRC_GetOutSamplesSizeEDMA(
+ ASRC_Type *base, asrc_edma_handle_t *handle, uint32_t inSampleRate, uint32_t outSampleRate, uint32_t inSamplesize);
+
+/*!
+ * @brief Performs a non-blocking ASRC m2m convert using EDMA.
+ *
+ * @note This interface returns immediately after the transfer initiates.
+
+ * @param base ASRC base pointer.
+ * @param handle ASRC eDMA handle pointer.
+ * @param xfer Pointer to the DMA transfer structure.
+ * @retval kStatus_Success Start a ASRC eDMA send successfully.
+ * @retval kStatus_InvalidArgument The input argument is invalid.
+ * @retval kStatus_ASRCQueueFull ASRC EDMA driver queue is full.
+ */
+status_t ASRC_TransferEDMA(ASRC_Type *base, asrc_edma_handle_t *handle, asrc_transfer_t *xfer);
+
+/*!
+ * @brief Aborts a ASRC IN transfer using eDMA.
+ *
+ * This function only aborts the current transfer slots, the other transfer slots' information still kept
+ * in the handler. If users want to terminate all transfer slots, just call ASRC_TransferTerminalP2PEDMA.
+ *
+ * @param base ASRC base pointer.
+ * @param handle ASRC eDMA handle pointer.
+ */
+void ASRC_TransferInAbortEDMA(ASRC_Type *base, asrc_edma_handle_t *handle);
+
+/*!
+ * @brief Aborts a ASRC OUT transfer using eDMA.
+ *
+ * This function only aborts the current transfer slots, the other transfer slots' information still kept
+ * in the handler. If users want to terminate all transfer slots, just call ASRC_TransferTerminalP2PEDMA.
+ *
+ * @param base ASRC base pointer.
+ * @param handle ASRC eDMA handle pointer.
+ */
+void ASRC_TransferOutAbortEDMA(ASRC_Type *base, asrc_edma_handle_t *handle);
+
+/*!
+ * @brief Terminate In ASRC Convert.
+ *
+ * This function will clear all transfer slots buffered in the asrc queue. If users only want to abort the
+ * current transfer slot, please call ASRC_TransferAbortPP2PEDMA.
+ *
+ * @param base ASRC base pointer.
+ * @param handle ASRC eDMA handle pointer.
+ */
+void ASRC_TransferInTerminalEDMA(ASRC_Type *base, asrc_edma_handle_t *handle);
+
+/*!
+ * @brief Terminate Out ASRC Convert.
+ *
+ * This function will clear all transfer slots buffered in the asrc queue. If users only want to abort the
+ * current transfer slot, please call ASRC_TransferAbortPP2PEDMA.
+ *
+ * @param base ASRC base pointer.
+ * @param handle ASRC eDMA handle pointer.
+ */
+void ASRC_TransferOutTerminalEDMA(ASRC_Type *base, asrc_edma_handle_t *handle);
+
+/*! @} */
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*!
+ * @}
+ */
+#endif