2018-09-20 23:18:14 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2016, Freescale Semiconductor, Inc.
|
|
|
|
* Copyright 2016-2017 NXP
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
2019-06-12 15:01:12 +08:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2018-09-20 23:18:14 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "fsl_sai.h"
|
|
|
|
|
|
|
|
/* Component ID definition, used by tools. */
|
|
|
|
#ifndef FSL_COMPONENT_ID
|
|
|
|
#define FSL_COMPONENT_ID "platform.drivers.sai"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Definitations
|
|
|
|
******************************************************************************/
|
|
|
|
enum _sai_transfer_state
|
|
|
|
{
|
|
|
|
kSAI_Busy = 0x0U, /*!< SAI is busy */
|
|
|
|
kSAI_Idle, /*!< Transfer is done. */
|
|
|
|
kSAI_Error /*!< Transfer error occured. */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*! @brief Typedef for sai tx interrupt handler. */
|
|
|
|
typedef void (*sai_tx_isr_t)(I2S_Type *base, sai_handle_t *saiHandle);
|
|
|
|
|
|
|
|
/*! @brief Typedef for sai rx interrupt handler. */
|
|
|
|
typedef void (*sai_rx_isr_t)(I2S_Type *base, sai_handle_t *saiHandle);
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Prototypes
|
|
|
|
******************************************************************************/
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Set the master clock divider.
|
|
|
|
*
|
|
|
|
* This API will compute the master clock divider according to master clock frequency and master
|
|
|
|
* clock source clock source frequency.
|
|
|
|
*
|
|
|
|
* @param base SAI base pointer.
|
|
|
|
* @param mclk_Hz Mater clock frequency in Hz.
|
|
|
|
* @param mclkSrcClock_Hz Master clock source frequency in Hz.
|
|
|
|
*/
|
|
|
|
static void SAI_SetMasterClockDivider(I2S_Type *base, uint32_t mclk_Hz, uint32_t mclkSrcClock_Hz);
|
|
|
|
#endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Get the instance number for SAI.
|
|
|
|
*
|
|
|
|
* @param base SAI base pointer.
|
|
|
|
*/
|
|
|
|
static uint32_t SAI_GetInstance(I2S_Type *base);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief sends a piece of data in non-blocking way.
|
|
|
|
*
|
|
|
|
* @param base SAI base pointer
|
2019-06-12 15:01:12 +08:00
|
|
|
* @param channel start channel number.
|
|
|
|
* @param channelMask enabled channels mask.
|
|
|
|
* @param endChannel end channel numbers.
|
2018-09-20 23:18:14 +08:00
|
|
|
* @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
|
|
|
|
* @param buffer Pointer to the data to be written.
|
|
|
|
* @param size Bytes to be written.
|
|
|
|
*/
|
2019-06-12 15:01:12 +08:00
|
|
|
static void SAI_WriteNonBlocking(I2S_Type *base,
|
|
|
|
uint32_t channel,
|
|
|
|
uint32_t channelMask,
|
|
|
|
uint32_t endChannel,
|
|
|
|
uint32_t bitWidth,
|
|
|
|
uint8_t *buffer,
|
|
|
|
uint32_t size);
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Receive a piece of data in non-blocking way.
|
|
|
|
*
|
|
|
|
* @param base SAI base pointer
|
2019-06-12 15:01:12 +08:00
|
|
|
* @param channel start channel number.
|
|
|
|
* @param channelMask enabled channels mask.
|
|
|
|
* @param endChannel end channel numbers.
|
2018-09-20 23:18:14 +08:00
|
|
|
* @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
|
|
|
|
* @param buffer Pointer to the data to be read.
|
|
|
|
* @param size Bytes to be read.
|
|
|
|
*/
|
2019-06-12 15:01:12 +08:00
|
|
|
static void SAI_ReadNonBlocking(I2S_Type *base,
|
|
|
|
uint32_t channel,
|
|
|
|
uint32_t channelMask,
|
|
|
|
uint32_t endChannel,
|
|
|
|
uint32_t bitWidth,
|
|
|
|
uint8_t *buffer,
|
|
|
|
uint32_t size);
|
2018-09-20 23:18:14 +08:00
|
|
|
/*******************************************************************************
|
|
|
|
* Variables
|
|
|
|
******************************************************************************/
|
|
|
|
/* Base pointer array */
|
|
|
|
static I2S_Type *const s_saiBases[] = I2S_BASE_PTRS;
|
|
|
|
/*!@brief SAI handle pointer */
|
|
|
|
static sai_handle_t *s_saiHandle[ARRAY_SIZE(s_saiBases)][2];
|
|
|
|
/* IRQ number array */
|
|
|
|
static const IRQn_Type s_saiTxIRQ[] = I2S_TX_IRQS;
|
|
|
|
static const IRQn_Type s_saiRxIRQ[] = I2S_RX_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_saiClock[] = SAI_CLOCKS;
|
|
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
|
|
/*! @brief Pointer to tx IRQ handler for each instance. */
|
|
|
|
static sai_tx_isr_t s_saiTxIsr;
|
|
|
|
/*! @brief Pointer to tx IRQ handler for each instance. */
|
|
|
|
static sai_rx_isr_t s_saiRxIsr;
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Code
|
|
|
|
******************************************************************************/
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
|
|
|
|
static void SAI_SetMasterClockDivider(I2S_Type *base, uint32_t mclk_Hz, uint32_t mclkSrcClock_Hz)
|
|
|
|
{
|
|
|
|
uint32_t freq = mclkSrcClock_Hz;
|
|
|
|
uint16_t fract, divide;
|
|
|
|
uint32_t remaind = 0;
|
|
|
|
uint32_t current_remainder = 0xFFFFFFFFU;
|
|
|
|
uint16_t current_fract = 0;
|
|
|
|
uint16_t current_divide = 0;
|
|
|
|
uint32_t mul_freq = 0;
|
|
|
|
uint32_t max_fract = 256;
|
|
|
|
|
|
|
|
/*In order to prevent overflow */
|
|
|
|
freq /= 100;
|
|
|
|
mclk_Hz /= 100;
|
|
|
|
|
|
|
|
/* Compute the max fract number */
|
|
|
|
max_fract = mclk_Hz * 4096 / freq + 1;
|
|
|
|
if (max_fract > 256)
|
|
|
|
{
|
|
|
|
max_fract = 256;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Looking for the closet frequency */
|
|
|
|
for (fract = 1; fract < max_fract; fract++)
|
|
|
|
{
|
|
|
|
mul_freq = freq * fract;
|
|
|
|
remaind = mul_freq % mclk_Hz;
|
|
|
|
divide = mul_freq / mclk_Hz;
|
|
|
|
|
|
|
|
/* Find the exactly frequency */
|
|
|
|
if (remaind == 0)
|
|
|
|
{
|
|
|
|
current_fract = fract;
|
|
|
|
current_divide = mul_freq / mclk_Hz;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Closer to next one, set the closest to next data */
|
|
|
|
if (remaind > mclk_Hz / 2)
|
|
|
|
{
|
|
|
|
remaind = mclk_Hz - remaind;
|
|
|
|
divide += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update the closest div and fract */
|
|
|
|
if (remaind < current_remainder)
|
|
|
|
{
|
|
|
|
current_fract = fract;
|
|
|
|
current_divide = divide;
|
|
|
|
current_remainder = remaind;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill the computed fract and divider to registers */
|
|
|
|
base->MDR = I2S_MDR_DIVIDE(current_divide - 1) | I2S_MDR_FRACT(current_fract - 1);
|
|
|
|
|
|
|
|
/* Waiting for the divider updated */
|
|
|
|
while (base->MCR & I2S_MCR_DUF_MASK)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */
|
|
|
|
|
|
|
|
static uint32_t SAI_GetInstance(I2S_Type *base)
|
|
|
|
{
|
|
|
|
uint32_t instance;
|
|
|
|
|
|
|
|
/* Find the instance index from base address mappings. */
|
|
|
|
for (instance = 0; instance < ARRAY_SIZE(s_saiBases); instance++)
|
|
|
|
{
|
|
|
|
if (s_saiBases[instance] == base)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(instance < ARRAY_SIZE(s_saiBases));
|
|
|
|
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
static void SAI_WriteNonBlocking(I2S_Type *base,
|
|
|
|
uint32_t channel,
|
|
|
|
uint32_t channelMask,
|
|
|
|
uint32_t endChannel,
|
|
|
|
uint32_t bitWidth,
|
|
|
|
uint8_t *buffer,
|
|
|
|
uint32_t size)
|
2018-09-20 23:18:14 +08:00
|
|
|
{
|
|
|
|
uint32_t i = 0;
|
2019-06-12 15:01:12 +08:00
|
|
|
uint8_t j = 0, m = 0;
|
2018-09-20 23:18:14 +08:00
|
|
|
uint8_t bytesPerWord = bitWidth / 8U;
|
|
|
|
uint32_t data = 0;
|
|
|
|
uint32_t temp = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < size / bytesPerWord; i++)
|
|
|
|
{
|
2019-06-12 15:01:12 +08:00
|
|
|
for (j = channel; j <= endChannel; j++)
|
2018-09-20 23:18:14 +08:00
|
|
|
{
|
2019-06-12 15:01:12 +08:00
|
|
|
if ((1U << j) & channelMask)
|
|
|
|
{
|
|
|
|
for (m = 0; m < bytesPerWord; m++)
|
|
|
|
{
|
|
|
|
temp = (uint32_t)(*buffer);
|
|
|
|
data |= (temp << (8U * m));
|
|
|
|
buffer++;
|
|
|
|
}
|
|
|
|
base->TDR[j] = data;
|
|
|
|
data = 0;
|
|
|
|
}
|
2018-09-20 23:18:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
static void SAI_ReadNonBlocking(I2S_Type *base,
|
|
|
|
uint32_t channel,
|
|
|
|
uint32_t channelMask,
|
|
|
|
uint32_t endChannel,
|
|
|
|
uint32_t bitWidth,
|
|
|
|
uint8_t *buffer,
|
|
|
|
uint32_t size)
|
2018-09-20 23:18:14 +08:00
|
|
|
{
|
|
|
|
uint32_t i = 0;
|
2019-06-12 15:01:12 +08:00
|
|
|
uint8_t j = 0, m = 0;
|
2018-09-20 23:18:14 +08:00
|
|
|
uint8_t bytesPerWord = bitWidth / 8U;
|
|
|
|
uint32_t data = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < size / bytesPerWord; i++)
|
|
|
|
{
|
2019-06-12 15:01:12 +08:00
|
|
|
for (j = channel; j <= endChannel; j++)
|
2018-09-20 23:18:14 +08:00
|
|
|
{
|
2019-06-12 15:01:12 +08:00
|
|
|
if ((1U << j) & channelMask)
|
|
|
|
{
|
|
|
|
data = base->RDR[j];
|
|
|
|
for (m = 0; m < bytesPerWord; m++)
|
|
|
|
{
|
|
|
|
*buffer = (data >> (8U * m)) & 0xFF;
|
|
|
|
buffer++;
|
|
|
|
}
|
|
|
|
}
|
2018-09-20 23:18:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Initializes the SAI Tx peripheral.
|
|
|
|
*
|
|
|
|
* Ungates the SAI clock, resets the module, and configures SAI Tx with a configuration structure.
|
|
|
|
* The configuration structure can be custom filled or set with default values by
|
|
|
|
* SAI_TxGetDefaultConfig().
|
|
|
|
*
|
|
|
|
* note This API should be called at the beginning of the application to use
|
|
|
|
* the SAI driver. Otherwise, accessing the SAIM module can cause a hard fault
|
|
|
|
* because the clock is not enabled.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param config SAI configuration structure.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TxInit(I2S_Type *base, const sai_config_t *config)
|
|
|
|
{
|
|
|
|
uint32_t val = 0;
|
|
|
|
|
|
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
|
|
/* Enable the SAI clock */
|
|
|
|
CLOCK_EnableClock(s_saiClock[SAI_GetInstance(base)]);
|
|
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)
|
2019-06-12 15:01:12 +08:00
|
|
|
#if !(defined(FSL_FEATURE_SAI_HAS_NO_MCR_MICS) && (FSL_FEATURE_SAI_HAS_NO_MCR_MICS))
|
2018-09-20 23:18:14 +08:00
|
|
|
/* Master clock source setting */
|
|
|
|
val = (base->MCR & ~I2S_MCR_MICS_MASK);
|
|
|
|
base->MCR = (val | I2S_MCR_MICS(config->mclkSource));
|
2019-06-12 15:01:12 +08:00
|
|
|
#endif
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
/* Configure Master clock output enable */
|
|
|
|
val = (base->MCR & ~I2S_MCR_MOE_MASK);
|
|
|
|
base->MCR = (val | I2S_MCR_MOE(config->mclkOutputEnable));
|
|
|
|
#endif /* FSL_FEATURE_SAI_HAS_MCR */
|
|
|
|
|
|
|
|
SAI_TxReset(base);
|
|
|
|
|
|
|
|
/* Configure audio protocol */
|
|
|
|
switch (config->protocol)
|
|
|
|
{
|
|
|
|
case kSAI_BusLeftJustified:
|
|
|
|
base->TCR2 |= I2S_TCR2_BCP_MASK;
|
|
|
|
base->TCR3 &= ~I2S_TCR3_WDFL_MASK;
|
|
|
|
base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(31U) | I2S_TCR4_FSE(0U) | I2S_TCR4_FSP(0U) | I2S_TCR4_FRSZ(1U);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kSAI_BusRightJustified:
|
|
|
|
base->TCR2 |= I2S_TCR2_BCP_MASK;
|
|
|
|
base->TCR3 &= ~I2S_TCR3_WDFL_MASK;
|
|
|
|
base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(31U) | I2S_TCR4_FSE(0U) | I2S_TCR4_FSP(0U) | I2S_TCR4_FRSZ(1U);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kSAI_BusI2S:
|
|
|
|
base->TCR2 |= I2S_TCR2_BCP_MASK;
|
|
|
|
base->TCR3 &= ~I2S_TCR3_WDFL_MASK;
|
|
|
|
base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(31U) | I2S_TCR4_FSE(1U) | I2S_TCR4_FSP(1U) | I2S_TCR4_FRSZ(1U);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kSAI_BusPCMA:
|
|
|
|
base->TCR2 &= ~I2S_TCR2_BCP_MASK;
|
|
|
|
base->TCR3 &= ~I2S_TCR3_WDFL_MASK;
|
|
|
|
base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(0U) | I2S_TCR4_FSE(1U) | I2S_TCR4_FSP(0U) | I2S_TCR4_FRSZ(1U);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kSAI_BusPCMB:
|
|
|
|
base->TCR2 &= ~I2S_TCR2_BCP_MASK;
|
|
|
|
base->TCR3 &= ~I2S_TCR3_WDFL_MASK;
|
|
|
|
base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(0U) | I2S_TCR4_FSE(0U) | I2S_TCR4_FSP(0U) | I2S_TCR4_FRSZ(1U);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set master or slave */
|
|
|
|
if (config->masterSlave == kSAI_Master)
|
|
|
|
{
|
|
|
|
base->TCR2 |= I2S_TCR2_BCD_MASK;
|
|
|
|
base->TCR4 |= I2S_TCR4_FSD_MASK;
|
|
|
|
|
|
|
|
/* Bit clock source setting */
|
|
|
|
val = base->TCR2 & (~I2S_TCR2_MSEL_MASK);
|
|
|
|
base->TCR2 = (val | I2S_TCR2_MSEL(config->bclkSource));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->TCR2 &= ~I2S_TCR2_BCD_MASK;
|
|
|
|
base->TCR4 &= ~I2S_TCR4_FSD_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set Sync mode */
|
|
|
|
switch (config->syncMode)
|
|
|
|
{
|
|
|
|
case kSAI_ModeAsync:
|
|
|
|
val = base->TCR2;
|
|
|
|
val &= ~I2S_TCR2_SYNC_MASK;
|
|
|
|
base->TCR2 = (val | I2S_TCR2_SYNC(0U));
|
|
|
|
break;
|
|
|
|
case kSAI_ModeSync:
|
|
|
|
val = base->TCR2;
|
|
|
|
val &= ~I2S_TCR2_SYNC_MASK;
|
|
|
|
base->TCR2 = (val | I2S_TCR2_SYNC(1U));
|
|
|
|
/* If sync with Rx, should set Rx to async mode */
|
|
|
|
val = base->RCR2;
|
|
|
|
val &= ~I2S_RCR2_SYNC_MASK;
|
|
|
|
base->RCR2 = (val | I2S_RCR2_SYNC(0U));
|
|
|
|
break;
|
|
|
|
case kSAI_ModeSyncWithOtherTx:
|
|
|
|
val = base->TCR2;
|
|
|
|
val &= ~I2S_TCR2_SYNC_MASK;
|
|
|
|
base->TCR2 = (val | I2S_TCR2_SYNC(2U));
|
|
|
|
break;
|
|
|
|
case kSAI_ModeSyncWithOtherRx:
|
|
|
|
val = base->TCR2;
|
|
|
|
val &= ~I2S_TCR2_SYNC_MASK;
|
|
|
|
base->TCR2 = (val | I2S_TCR2_SYNC(3U));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_FIFO_FUNCTION_AFTER_ERROR) && FSL_FEATURE_SAI_HAS_FIFO_FUNCTION_AFTER_ERROR
|
|
|
|
SAI_TxSetFIFOErrorContinue(base, true);
|
|
|
|
#endif /* FSL_FEATURE_SAI_HAS_FIFO_FUNCTION_AFTER_ERROR */
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Initializes the SAI Rx peripheral.
|
|
|
|
*
|
|
|
|
* Ungates the SAI clock, resets the module, and configures the SAI Rx with a configuration structure.
|
|
|
|
* The configuration structure can be custom filled or set with default values by
|
|
|
|
* SAI_RxGetDefaultConfig().
|
|
|
|
*
|
|
|
|
* note This API should be called at the beginning of the application to use
|
|
|
|
* the SAI driver. Otherwise, accessing the SAI module can cause a hard fault
|
|
|
|
* because the clock is not enabled.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param config SAI configuration structure.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_RxInit(I2S_Type *base, const sai_config_t *config)
|
|
|
|
{
|
|
|
|
uint32_t val = 0;
|
|
|
|
|
|
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
|
|
/* Enable SAI clock first. */
|
|
|
|
CLOCK_EnableClock(s_saiClock[SAI_GetInstance(base)]);
|
|
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)
|
2019-06-12 15:01:12 +08:00
|
|
|
#if !(defined(FSL_FEATURE_SAI_HAS_NO_MCR_MICS) && (FSL_FEATURE_SAI_HAS_NO_MCR_MICS))
|
2018-09-20 23:18:14 +08:00
|
|
|
/* Master clock source setting */
|
|
|
|
val = (base->MCR & ~I2S_MCR_MICS_MASK);
|
|
|
|
base->MCR = (val | I2S_MCR_MICS(config->mclkSource));
|
2019-06-12 15:01:12 +08:00
|
|
|
#endif
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
/* Configure Master clock output enable */
|
|
|
|
val = (base->MCR & ~I2S_MCR_MOE_MASK);
|
|
|
|
base->MCR = (val | I2S_MCR_MOE(config->mclkOutputEnable));
|
|
|
|
#endif /* FSL_FEATURE_SAI_HAS_MCR */
|
|
|
|
|
|
|
|
SAI_RxReset(base);
|
|
|
|
|
|
|
|
/* Configure audio protocol */
|
|
|
|
switch (config->protocol)
|
|
|
|
{
|
|
|
|
case kSAI_BusLeftJustified:
|
|
|
|
base->RCR2 |= I2S_RCR2_BCP_MASK;
|
|
|
|
base->RCR3 &= ~I2S_RCR3_WDFL_MASK;
|
|
|
|
base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(31U) | I2S_RCR4_FSE(0U) | I2S_RCR4_FSP(0U) | I2S_RCR4_FRSZ(1U);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kSAI_BusRightJustified:
|
|
|
|
base->RCR2 |= I2S_RCR2_BCP_MASK;
|
|
|
|
base->RCR3 &= ~I2S_RCR3_WDFL_MASK;
|
|
|
|
base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(31U) | I2S_RCR4_FSE(0U) | I2S_RCR4_FSP(0U) | I2S_RCR4_FRSZ(1U);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kSAI_BusI2S:
|
|
|
|
base->RCR2 |= I2S_RCR2_BCP_MASK;
|
|
|
|
base->RCR3 &= ~I2S_RCR3_WDFL_MASK;
|
|
|
|
base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(31U) | I2S_RCR4_FSE(1U) | I2S_RCR4_FSP(1U) | I2S_RCR4_FRSZ(1U);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kSAI_BusPCMA:
|
|
|
|
base->RCR2 &= ~I2S_RCR2_BCP_MASK;
|
|
|
|
base->RCR3 &= ~I2S_RCR3_WDFL_MASK;
|
|
|
|
base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(0U) | I2S_RCR4_FSE(1U) | I2S_RCR4_FSP(0U) | I2S_RCR4_FRSZ(1U);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kSAI_BusPCMB:
|
|
|
|
base->RCR2 &= ~I2S_RCR2_BCP_MASK;
|
|
|
|
base->RCR3 &= ~I2S_RCR3_WDFL_MASK;
|
|
|
|
base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(0U) | I2S_RCR4_FSE(0U) | I2S_RCR4_FSP(0U) | I2S_RCR4_FRSZ(1U);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set master or slave */
|
|
|
|
if (config->masterSlave == kSAI_Master)
|
|
|
|
{
|
|
|
|
base->RCR2 |= I2S_RCR2_BCD_MASK;
|
|
|
|
base->RCR4 |= I2S_RCR4_FSD_MASK;
|
|
|
|
|
|
|
|
/* Bit clock source setting */
|
|
|
|
val = base->RCR2 & (~I2S_RCR2_MSEL_MASK);
|
|
|
|
base->RCR2 = (val | I2S_RCR2_MSEL(config->bclkSource));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->RCR2 &= ~I2S_RCR2_BCD_MASK;
|
|
|
|
base->RCR4 &= ~I2S_RCR4_FSD_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set Sync mode */
|
|
|
|
switch (config->syncMode)
|
|
|
|
{
|
|
|
|
case kSAI_ModeAsync:
|
|
|
|
val = base->RCR2;
|
|
|
|
val &= ~I2S_RCR2_SYNC_MASK;
|
|
|
|
base->RCR2 = (val | I2S_RCR2_SYNC(0U));
|
|
|
|
break;
|
|
|
|
case kSAI_ModeSync:
|
|
|
|
val = base->RCR2;
|
|
|
|
val &= ~I2S_RCR2_SYNC_MASK;
|
|
|
|
base->RCR2 = (val | I2S_RCR2_SYNC(1U));
|
|
|
|
/* If sync with Tx, should set Tx to async mode */
|
|
|
|
val = base->TCR2;
|
|
|
|
val &= ~I2S_TCR2_SYNC_MASK;
|
|
|
|
base->TCR2 = (val | I2S_TCR2_SYNC(0U));
|
|
|
|
break;
|
|
|
|
case kSAI_ModeSyncWithOtherTx:
|
|
|
|
val = base->RCR2;
|
|
|
|
val &= ~I2S_RCR2_SYNC_MASK;
|
|
|
|
base->RCR2 = (val | I2S_RCR2_SYNC(2U));
|
|
|
|
break;
|
|
|
|
case kSAI_ModeSyncWithOtherRx:
|
|
|
|
val = base->RCR2;
|
|
|
|
val &= ~I2S_RCR2_SYNC_MASK;
|
|
|
|
base->RCR2 = (val | I2S_RCR2_SYNC(3U));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_FIFO_FUNCTION_AFTER_ERROR) && FSL_FEATURE_SAI_HAS_FIFO_FUNCTION_AFTER_ERROR
|
|
|
|
SAI_RxSetFIFOErrorContinue(base, true);
|
|
|
|
#endif /* FSL_FEATURE_SAI_HAS_FIFO_FUNCTION_AFTER_ERROR */
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief De-initializes the SAI peripheral.
|
|
|
|
*
|
|
|
|
* This API gates the SAI clock. The SAI module can't operate unless SAI_TxInit
|
|
|
|
* or SAI_RxInit is called to enable the clock.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_Deinit(I2S_Type *base)
|
|
|
|
{
|
|
|
|
SAI_TxEnable(base, false);
|
|
|
|
SAI_RxEnable(base, false);
|
|
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
|
|
CLOCK_DisableClock(s_saiClock[SAI_GetInstance(base)]);
|
|
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Sets the SAI Tx configuration structure to default values.
|
|
|
|
*
|
|
|
|
* This API initializes the configuration structure for use in SAI_TxConfig().
|
|
|
|
* The initialized structure can remain unchanged in SAI_TxConfig(), or it can be modified
|
|
|
|
* before calling SAI_TxConfig().
|
|
|
|
* This is an example.
|
|
|
|
code
|
|
|
|
sai_config_t config;
|
|
|
|
SAI_TxGetDefaultConfig(&config);
|
|
|
|
endcode
|
|
|
|
*
|
|
|
|
* param config pointer to master configuration structure
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TxGetDefaultConfig(sai_config_t *config)
|
|
|
|
{
|
2019-06-12 15:01:12 +08:00
|
|
|
/* Initializes the configure structure to zero. */
|
|
|
|
memset(config, 0, sizeof(*config));
|
|
|
|
|
2018-09-20 23:18:14 +08:00
|
|
|
config->bclkSource = kSAI_BclkSourceMclkDiv;
|
|
|
|
config->masterSlave = kSAI_Master;
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)
|
|
|
|
config->mclkOutputEnable = true;
|
2019-06-12 15:01:12 +08:00
|
|
|
#if !(defined(FSL_FEATURE_SAI_HAS_NO_MCR_MICS) && (FSL_FEATURE_SAI_HAS_NO_MCR_MICS))
|
|
|
|
config->mclkSource = kSAI_MclkSourceSysclk;
|
|
|
|
#endif
|
2018-09-20 23:18:14 +08:00
|
|
|
#endif /* FSL_FEATURE_SAI_HAS_MCR */
|
2019-06-12 15:01:12 +08:00
|
|
|
config->protocol = kSAI_BusI2S;
|
|
|
|
config->syncMode = kSAI_ModeAsync;
|
2018-09-20 23:18:14 +08:00
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Sets the SAI Rx configuration structure to default values.
|
|
|
|
*
|
|
|
|
* This API initializes the configuration structure for use in SAI_RxConfig().
|
|
|
|
* The initialized structure can remain unchanged in SAI_RxConfig() or it can be modified
|
|
|
|
* before calling SAI_RxConfig().
|
|
|
|
* This is an example.
|
|
|
|
code
|
|
|
|
sai_config_t config;
|
|
|
|
SAI_RxGetDefaultConfig(&config);
|
|
|
|
endcode
|
|
|
|
*
|
|
|
|
* param config pointer to master configuration structure
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_RxGetDefaultConfig(sai_config_t *config)
|
|
|
|
{
|
2019-06-12 15:01:12 +08:00
|
|
|
/* Initializes the configure structure to zero. */
|
|
|
|
memset(config, 0, sizeof(*config));
|
|
|
|
|
2018-09-20 23:18:14 +08:00
|
|
|
config->bclkSource = kSAI_BclkSourceMclkDiv;
|
|
|
|
config->masterSlave = kSAI_Master;
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)
|
|
|
|
config->mclkOutputEnable = true;
|
2019-06-12 15:01:12 +08:00
|
|
|
#if !(defined(FSL_FEATURE_SAI_HAS_NO_MCR_MICS) && (FSL_FEATURE_SAI_HAS_NO_MCR_MICS))
|
|
|
|
config->mclkSource = kSAI_MclkSourceSysclk;
|
|
|
|
#endif
|
2018-09-20 23:18:14 +08:00
|
|
|
#endif /* FSL_FEATURE_SAI_HAS_MCR */
|
2019-06-12 15:01:12 +08:00
|
|
|
config->protocol = kSAI_BusI2S;
|
|
|
|
config->syncMode = kSAI_ModeSync;
|
2018-09-20 23:18:14 +08:00
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Resets the SAI Tx.
|
|
|
|
*
|
|
|
|
* This function enables the software reset and FIFO reset of SAI Tx. After reset, clear the reset bit.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TxReset(I2S_Type *base)
|
|
|
|
{
|
|
|
|
/* Set the software reset and FIFO reset to clear internal state */
|
|
|
|
base->TCSR = I2S_TCSR_SR_MASK | I2S_TCSR_FR_MASK;
|
|
|
|
|
|
|
|
/* Clear software reset bit, this should be done by software */
|
|
|
|
base->TCSR &= ~I2S_TCSR_SR_MASK;
|
|
|
|
|
|
|
|
/* Reset all Tx register values */
|
|
|
|
base->TCR2 = 0;
|
|
|
|
base->TCR3 = 0;
|
|
|
|
base->TCR4 = 0;
|
|
|
|
base->TCR5 = 0;
|
|
|
|
base->TMR = 0;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Resets the SAI Rx.
|
|
|
|
*
|
|
|
|
* This function enables the software reset and FIFO reset of SAI Rx. After reset, clear the reset bit.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_RxReset(I2S_Type *base)
|
|
|
|
{
|
|
|
|
/* Set the software reset and FIFO reset to clear internal state */
|
|
|
|
base->RCSR = I2S_RCSR_SR_MASK | I2S_RCSR_FR_MASK;
|
|
|
|
|
|
|
|
/* Clear software reset bit, this should be done by software */
|
|
|
|
base->RCSR &= ~I2S_RCSR_SR_MASK;
|
|
|
|
|
|
|
|
/* Reset all Rx register values */
|
|
|
|
base->RCR2 = 0;
|
|
|
|
base->RCR3 = 0;
|
|
|
|
base->RCR4 = 0;
|
|
|
|
base->RCR5 = 0;
|
|
|
|
base->RMR = 0;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Enables/disables the SAI Tx.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param enable True means enable SAI Tx, false means disable.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TxEnable(I2S_Type *base, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
/* If clock is sync with Rx, should enable RE bit. */
|
|
|
|
if (((base->TCR2 & I2S_TCR2_SYNC_MASK) >> I2S_TCR2_SYNC_SHIFT) == 0x1U)
|
|
|
|
{
|
|
|
|
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | I2S_RCSR_RE_MASK);
|
|
|
|
}
|
|
|
|
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | I2S_TCSR_TE_MASK);
|
|
|
|
/* Also need to clear the FIFO error flag before start */
|
|
|
|
SAI_TxClearStatusFlags(base, kSAI_FIFOErrorFlag);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If RE not sync with TE, than disable TE, otherwise, shall not disable TE */
|
|
|
|
if (((base->RCR2 & I2S_RCR2_SYNC_MASK) >> I2S_RCR2_SYNC_SHIFT) != 0x1U)
|
|
|
|
{
|
|
|
|
/* Should not close RE even sync with Rx */
|
|
|
|
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) & (~I2S_TCSR_TE_MASK));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Enables/disables the SAI Rx.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param enable True means enable SAI Rx, false means disable.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_RxEnable(I2S_Type *base, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
/* If clock is sync with Tx, should enable TE bit. */
|
|
|
|
if (((base->RCR2 & I2S_RCR2_SYNC_MASK) >> I2S_RCR2_SYNC_SHIFT) == 0x1U)
|
|
|
|
{
|
|
|
|
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | I2S_TCSR_TE_MASK);
|
|
|
|
}
|
|
|
|
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | I2S_RCSR_RE_MASK);
|
|
|
|
/* Also need to clear the FIFO error flag before start */
|
|
|
|
SAI_RxClearStatusFlags(base, kSAI_FIFOErrorFlag);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* While TX is not sync with RX, close RX */
|
|
|
|
if (((base->TCR2 & I2S_TCR2_SYNC_MASK) >> I2S_TCR2_SYNC_SHIFT) != 0x1U)
|
|
|
|
{
|
|
|
|
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) & (~I2S_RCSR_RE_MASK));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Do software reset or FIFO reset .
|
|
|
|
*
|
|
|
|
* FIFO reset means clear all the data in the FIFO, and make the FIFO pointer both to 0.
|
|
|
|
* Software reset means claer the Tx internal logic, including the bit clock, frame count etc. But software
|
|
|
|
* reset will not clear any configuration registers like TCR1~TCR5.
|
|
|
|
* This function will also clear all the error flags such as FIFO error, sync error etc.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param type Reset type, FIFO reset or software reset
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TxSoftwareReset(I2S_Type *base, sai_reset_type_t type)
|
|
|
|
{
|
|
|
|
base->TCSR |= (uint32_t)type;
|
|
|
|
|
|
|
|
/* Clear the software reset */
|
|
|
|
base->TCSR &= ~I2S_TCSR_SR_MASK;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Do software reset or FIFO reset .
|
|
|
|
*
|
|
|
|
* FIFO reset means clear all the data in the FIFO, and make the FIFO pointer both to 0.
|
|
|
|
* Software reset means claer the Rx internal logic, including the bit clock, frame count etc. But software
|
|
|
|
* reset will not clear any configuration registers like RCR1~RCR5.
|
|
|
|
* This function will also clear all the error flags such as FIFO error, sync error etc.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param type Reset type, FIFO reset or software reset
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_RxSoftwareReset(I2S_Type *base, sai_reset_type_t type)
|
|
|
|
{
|
|
|
|
base->RCSR |= (uint32_t)type;
|
|
|
|
|
|
|
|
/* Clear the software reset */
|
|
|
|
base->RCSR &= ~I2S_RCSR_SR_MASK;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Set the Tx channel FIFO enable mask.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param mask Channel enable mask, 0 means all channel FIFO disabled, 1 means channel 0 enabled,
|
|
|
|
* 3 means both channel 0 and channel 1 enabled.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TxSetChannelFIFOMask(I2S_Type *base, uint8_t mask)
|
|
|
|
{
|
|
|
|
base->TCR3 &= ~I2S_TCR3_TCE_MASK;
|
|
|
|
base->TCR3 |= I2S_TCR3_TCE(mask);
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Set the Rx channel FIFO enable mask.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param mask Channel enable mask, 0 means all channel FIFO disabled, 1 means channel 0 enabled,
|
|
|
|
* 3 means both channel 0 and channel 1 enabled.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_RxSetChannelFIFOMask(I2S_Type *base, uint8_t mask)
|
|
|
|
{
|
|
|
|
base->RCR3 &= ~I2S_RCR3_RCE_MASK;
|
|
|
|
base->RCR3 |= I2S_RCR3_RCE(mask);
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Set the Tx data order.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param order Data order MSB or LSB
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TxSetDataOrder(I2S_Type *base, sai_data_order_t order)
|
|
|
|
{
|
|
|
|
uint32_t val = (base->TCR4) & (~I2S_TCR4_MF_MASK);
|
|
|
|
|
|
|
|
val |= I2S_TCR4_MF(order);
|
|
|
|
base->TCR4 = val;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Set the Rx data order.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param order Data order MSB or LSB
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_RxSetDataOrder(I2S_Type *base, sai_data_order_t order)
|
|
|
|
{
|
|
|
|
uint32_t val = (base->RCR4) & (~I2S_RCR4_MF_MASK);
|
|
|
|
|
|
|
|
val |= I2S_RCR4_MF(order);
|
|
|
|
base->RCR4 = val;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Set the Tx data order.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param order Data order MSB or LSB
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TxSetBitClockPolarity(I2S_Type *base, sai_clock_polarity_t polarity)
|
|
|
|
{
|
|
|
|
uint32_t val = (base->TCR2) & (~I2S_TCR2_BCP_MASK);
|
|
|
|
|
|
|
|
val |= I2S_TCR2_BCP(polarity);
|
|
|
|
base->TCR2 = val;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Set the Rx data order.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param order Data order MSB or LSB
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_RxSetBitClockPolarity(I2S_Type *base, sai_clock_polarity_t polarity)
|
|
|
|
{
|
|
|
|
uint32_t val = (base->RCR2) & (~I2S_RCR2_BCP_MASK);
|
|
|
|
|
|
|
|
val |= I2S_RCR2_BCP(polarity);
|
|
|
|
base->RCR2 = val;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Set the Tx data order.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param order Data order MSB or LSB
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TxSetFrameSyncPolarity(I2S_Type *base, sai_clock_polarity_t polarity)
|
|
|
|
{
|
|
|
|
uint32_t val = (base->TCR4) & (~I2S_TCR4_FSP_MASK);
|
|
|
|
|
|
|
|
val |= I2S_TCR4_FSP(polarity);
|
|
|
|
base->TCR4 = val;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Set the Rx data order.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param order Data order MSB or LSB
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_RxSetFrameSyncPolarity(I2S_Type *base, sai_clock_polarity_t polarity)
|
|
|
|
{
|
|
|
|
uint32_t val = (base->RCR4) & (~I2S_RCR4_FSP_MASK);
|
|
|
|
|
|
|
|
val |= I2S_RCR4_FSP(polarity);
|
|
|
|
base->RCR4 = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_FIFO_PACKING) && FSL_FEATURE_SAI_HAS_FIFO_PACKING
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Set Tx FIFO packing feature.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param pack FIFO pack type. It is element of sai_fifo_packing_t.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TxSetFIFOPacking(I2S_Type *base, sai_fifo_packing_t pack)
|
|
|
|
{
|
|
|
|
uint32_t val = base->TCR4;
|
|
|
|
|
|
|
|
val &= ~I2S_TCR4_FPACK_MASK;
|
|
|
|
val |= I2S_TCR4_FPACK(pack);
|
|
|
|
base->TCR4 = val;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Set Rx FIFO packing feature.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param pack FIFO pack type. It is element of sai_fifo_packing_t.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_RxSetFIFOPacking(I2S_Type *base, sai_fifo_packing_t pack)
|
|
|
|
{
|
|
|
|
uint32_t val = base->RCR4;
|
|
|
|
|
|
|
|
val &= ~I2S_RCR4_FPACK_MASK;
|
|
|
|
val |= I2S_RCR4_FPACK(pack);
|
|
|
|
base->RCR4 = val;
|
|
|
|
}
|
|
|
|
#endif /* FSL_FEATURE_SAI_HAS_FIFO_PACKING */
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Configures the SAI Tx audio format.
|
|
|
|
*
|
|
|
|
* The audio format can be changed at run-time. This function configures the sample rate and audio data
|
|
|
|
* format to be transferred.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param format Pointer to the SAI audio data format structure.
|
|
|
|
* param mclkSourceClockHz SAI master clock source frequency in Hz.
|
|
|
|
* param bclkSourceClockHz SAI bit clock source frequency in Hz. If the bit clock source is a master
|
|
|
|
* clock, this value should equal the masterClockHz.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TxSetFormat(I2S_Type *base,
|
|
|
|
sai_transfer_format_t *format,
|
|
|
|
uint32_t mclkSourceClockHz,
|
|
|
|
uint32_t bclkSourceClockHz)
|
|
|
|
{
|
|
|
|
uint32_t bclk = 0;
|
|
|
|
uint32_t val = 0;
|
2019-06-12 15:01:12 +08:00
|
|
|
uint32_t i = 0U;
|
|
|
|
uint32_t divider = 0U, channelNums = 0U;
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
if (format->isFrameSyncCompact)
|
|
|
|
{
|
2019-06-12 15:01:12 +08:00
|
|
|
bclk = format->sampleRate_Hz * format->bitWidth * (format->stereo == kSAI_Stereo ? 2U : 1U);
|
2018-09-20 23:18:14 +08:00
|
|
|
val = (base->TCR4 & (~I2S_TCR4_SYWD_MASK));
|
|
|
|
val |= I2S_TCR4_SYWD(format->bitWidth - 1U);
|
|
|
|
base->TCR4 = val;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bclk = format->sampleRate_Hz * 32U * 2U;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Compute the mclk */
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
|
|
|
|
/* Check if master clock divider enabled, then set master clock divider */
|
|
|
|
if (base->MCR & I2S_MCR_MOE_MASK)
|
|
|
|
{
|
|
|
|
SAI_SetMasterClockDivider(base, format->masterClockHz, mclkSourceClockHz);
|
|
|
|
}
|
|
|
|
#endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */
|
|
|
|
|
|
|
|
/* Set bclk if needed */
|
|
|
|
if (base->TCR2 & I2S_TCR2_BCD_MASK)
|
|
|
|
{
|
|
|
|
base->TCR2 &= ~I2S_TCR2_DIV_MASK;
|
2019-06-12 15:01:12 +08:00
|
|
|
/* need to check the divided bclk, if bigger than target, then divider need to re-calculate. */
|
|
|
|
divider = bclkSourceClockHz / bclk;
|
|
|
|
/* for the condition where the source clock is smaller than target bclk */
|
|
|
|
if (divider == 0U)
|
|
|
|
{
|
|
|
|
divider++;
|
|
|
|
}
|
|
|
|
/* recheck the divider if properly or not, to make sure output blck not bigger than target*/
|
|
|
|
if ((bclkSourceClockHz / divider) > bclk)
|
|
|
|
{
|
|
|
|
divider++;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_BCLK_BYPASS) && (FSL_FEATURE_SAI_HAS_BCLK_BYPASS)
|
|
|
|
/* if bclk same with MCLK, bypass the divider */
|
|
|
|
if (divider == 1U)
|
|
|
|
{
|
|
|
|
base->TCR2 |= I2S_TCR2_BYP_MASK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
base->TCR2 |= I2S_TCR2_DIV(divider / 2U - 1U);
|
|
|
|
}
|
2018-09-20 23:18:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set bitWidth */
|
|
|
|
val = (format->isFrameSyncCompact) ? (format->bitWidth - 1) : 31U;
|
|
|
|
if (format->protocol == kSAI_BusRightJustified)
|
|
|
|
{
|
|
|
|
base->TCR5 = I2S_TCR5_WNW(val) | I2S_TCR5_W0W(val) | I2S_TCR5_FBT(val);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (base->TCR4 & I2S_TCR4_MF_MASK)
|
|
|
|
{
|
|
|
|
base->TCR5 = I2S_TCR5_WNW(val) | I2S_TCR5_W0W(val) | I2S_TCR5_FBT(format->bitWidth - 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->TCR5 = I2S_TCR5_WNW(val) | I2S_TCR5_W0W(val) | I2S_TCR5_FBT(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set mono or stereo */
|
|
|
|
base->TMR = (uint32_t)format->stereo;
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/* if channel mask is not set, then format->channel must be set,
|
|
|
|
use it to get channel mask value */
|
|
|
|
if (format->channelMask == 0U)
|
|
|
|
{
|
|
|
|
format->channelMask = 1U << format->channel;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if channel nums is not set, calculate it here according to channelMask*/
|
|
|
|
for (i = 0U; i < FSL_FEATURE_SAI_CHANNEL_COUNT; i++)
|
|
|
|
{
|
|
|
|
if (((uint32_t)1 << i) & format->channelMask)
|
|
|
|
{
|
|
|
|
/* geet start channel number when channelNums = 0 only */
|
|
|
|
if (channelNums == 0U)
|
|
|
|
{
|
|
|
|
format->channel = i;
|
|
|
|
}
|
|
|
|
channelNums++;
|
|
|
|
format->endChannel = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
format->channelNums = channelNums;
|
|
|
|
assert(format->channelNums <= FSL_FEATURE_SAI_CHANNEL_COUNT);
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE) && (FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE)
|
|
|
|
/* make sure combine mode disabled while multipe channel is used */
|
|
|
|
if (format->channelNums > 1U)
|
|
|
|
{
|
|
|
|
base->TCR4 &= ~I2S_TCR4_FCOMB_MASK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-09-20 23:18:14 +08:00
|
|
|
/* Set data channel */
|
|
|
|
base->TCR3 &= ~I2S_TCR3_TCE_MASK;
|
2019-06-12 15:01:12 +08:00
|
|
|
base->TCR3 |= I2S_TCR3_TCE(format->channelMask);
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
/* Set watermark */
|
|
|
|
base->TCR1 = format->watermark;
|
|
|
|
#endif /* FSL_FEATURE_SAI_FIFO_COUNT */
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Configures the SAI Rx audio format.
|
|
|
|
*
|
|
|
|
* The audio format can be changed at run-time. This function configures the sample rate and audio data
|
|
|
|
* format to be transferred.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param format Pointer to the SAI audio data format structure.
|
|
|
|
* param mclkSourceClockHz SAI master clock source frequency in Hz.
|
|
|
|
* param bclkSourceClockHz SAI bit clock source frequency in Hz. If the bit clock source is a master
|
|
|
|
* clock, this value should equal the masterClockHz.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_RxSetFormat(I2S_Type *base,
|
|
|
|
sai_transfer_format_t *format,
|
|
|
|
uint32_t mclkSourceClockHz,
|
|
|
|
uint32_t bclkSourceClockHz)
|
|
|
|
{
|
|
|
|
uint32_t bclk = 0;
|
|
|
|
uint32_t val = 0;
|
2019-06-12 15:01:12 +08:00
|
|
|
uint32_t i = 0U;
|
|
|
|
uint32_t divider = 0U, channelNums = 0U;
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
if (format->isFrameSyncCompact)
|
|
|
|
{
|
2019-06-12 15:01:12 +08:00
|
|
|
bclk = format->sampleRate_Hz * format->bitWidth * (format->stereo == kSAI_Stereo ? 2U : 1U);
|
2018-09-20 23:18:14 +08:00
|
|
|
val = (base->RCR4 & (~I2S_RCR4_SYWD_MASK));
|
|
|
|
val |= I2S_RCR4_SYWD(format->bitWidth - 1U);
|
|
|
|
base->RCR4 = val;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bclk = format->sampleRate_Hz * 32U * 2U;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Compute the mclk */
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
|
|
|
|
/* Check if master clock divider enabled */
|
|
|
|
if (base->MCR & I2S_MCR_MOE_MASK)
|
|
|
|
{
|
|
|
|
SAI_SetMasterClockDivider(base, format->masterClockHz, mclkSourceClockHz);
|
|
|
|
}
|
|
|
|
#endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */
|
|
|
|
|
|
|
|
/* Set bclk if needed */
|
|
|
|
if (base->RCR2 & I2S_RCR2_BCD_MASK)
|
|
|
|
{
|
|
|
|
base->RCR2 &= ~I2S_RCR2_DIV_MASK;
|
2019-06-12 15:01:12 +08:00
|
|
|
/* need to check the divided bclk, if bigger than target, then divider need to re-calculate. */
|
|
|
|
divider = bclkSourceClockHz / bclk;
|
|
|
|
/* for the condition where the source clock is smaller than target bclk */
|
|
|
|
if (divider == 0U)
|
|
|
|
{
|
|
|
|
divider++;
|
|
|
|
}
|
|
|
|
/* recheck the divider if properly or not, to make sure output blck not bigger than target*/
|
|
|
|
if ((bclkSourceClockHz / divider) > bclk)
|
|
|
|
{
|
|
|
|
divider++;
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_BCLK_BYPASS) && (FSL_FEATURE_SAI_HAS_BCLK_BYPASS)
|
|
|
|
/* if bclk same with MCLK, bypass the divider */
|
|
|
|
if (divider == 1U)
|
|
|
|
{
|
|
|
|
base->RCR2 |= I2S_RCR2_BYP_MASK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
base->RCR2 |= I2S_RCR2_DIV(divider / 2U - 1U);
|
|
|
|
}
|
2018-09-20 23:18:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set bitWidth */
|
|
|
|
val = (format->isFrameSyncCompact) ? (format->bitWidth - 1) : 31U;
|
|
|
|
if (format->protocol == kSAI_BusRightJustified)
|
|
|
|
{
|
|
|
|
base->RCR5 = I2S_RCR5_WNW(val) | I2S_RCR5_W0W(val) | I2S_RCR5_FBT(val);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (base->RCR4 & I2S_RCR4_MF_MASK)
|
|
|
|
{
|
|
|
|
base->RCR5 = I2S_RCR5_WNW(val) | I2S_RCR5_W0W(val) | I2S_RCR5_FBT(format->bitWidth - 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->RCR5 = I2S_RCR5_WNW(val) | I2S_RCR5_W0W(val) | I2S_RCR5_FBT(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set mono or stereo */
|
|
|
|
base->RMR = (uint32_t)format->stereo;
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/* if channel mask is not set, then format->channel must be set,
|
|
|
|
use it to get channel mask value */
|
|
|
|
if (format->channelMask == 0U)
|
|
|
|
{
|
|
|
|
format->channelMask = 1U << format->channel;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if channel nums is not set, calculate it here according to channelMask*/
|
|
|
|
for (i = 0U; i < FSL_FEATURE_SAI_CHANNEL_COUNT; i++)
|
|
|
|
{
|
|
|
|
if (((uint32_t)1 << i) & format->channelMask)
|
|
|
|
{
|
|
|
|
/* geet start channel number when channelNums = 0 only */
|
|
|
|
if (channelNums == 0U)
|
|
|
|
{
|
|
|
|
format->channel = i;
|
|
|
|
}
|
|
|
|
channelNums++;
|
|
|
|
format->endChannel = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
format->channelNums = channelNums;
|
|
|
|
assert(format->channelNums <= FSL_FEATURE_SAI_CHANNEL_COUNT);
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE) && (FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE)
|
|
|
|
/* make sure combine mode disabled while multipe channel is used */
|
|
|
|
if (format->channelNums > 1U)
|
|
|
|
{
|
|
|
|
base->RCR4 &= ~I2S_RCR4_FCOMB_MASK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-09-20 23:18:14 +08:00
|
|
|
/* Set data channel */
|
|
|
|
base->RCR3 &= ~I2S_RCR3_RCE_MASK;
|
2019-06-12 15:01:12 +08:00
|
|
|
/* enable all the channel */
|
|
|
|
base->RCR3 |= I2S_RCR3_RCE(format->channelMask);
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
/* Set watermark */
|
|
|
|
base->RCR1 = format->watermark;
|
|
|
|
#endif /* FSL_FEATURE_SAI_FIFO_COUNT */
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Sends data using a blocking method.
|
|
|
|
*
|
|
|
|
* note This function blocks by polling until data is ready to be sent.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param channel Data channel used.
|
|
|
|
* param bitWidth How many bits in an audio word; usually 8/16/24/32 bits.
|
|
|
|
* param buffer Pointer to the data to be written.
|
|
|
|
* param size Bytes to be written.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_WriteBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size)
|
|
|
|
{
|
|
|
|
uint32_t i = 0;
|
|
|
|
uint8_t bytesPerWord = bitWidth / 8U;
|
2019-06-12 15:01:12 +08:00
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
bytesPerWord = (size_t)((FSL_FEATURE_SAI_FIFO_COUNT - base->TCR1) * bytesPerWord);
|
|
|
|
#endif
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
while (i < size)
|
|
|
|
{
|
|
|
|
/* Wait until it can write data */
|
|
|
|
while (!(base->TCSR & I2S_TCSR_FWF_MASK))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
SAI_WriteNonBlocking(base, channel, 1U << channel, channel, bitWidth, buffer, bytesPerWord);
|
2018-09-20 23:18:14 +08:00
|
|
|
buffer += bytesPerWord;
|
|
|
|
i += bytesPerWord;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Wait until the last data is sent */
|
|
|
|
while (!(base->TCSR & I2S_TCSR_FWF_MASK))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Sends data to multi channel using a blocking method.
|
|
|
|
*
|
|
|
|
* note This function blocks by polling until data is ready to be sent.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param channel Data channel used.
|
|
|
|
* param channelMask channel mask.
|
|
|
|
* param bitWidth How many bits in an audio word; usually 8/16/24/32 bits.
|
|
|
|
* param buffer Pointer to the data to be written.
|
|
|
|
* param size Bytes to be written.
|
|
|
|
*/
|
|
|
|
void SAI_WriteMultiChannelBlocking(
|
|
|
|
I2S_Type *base, uint32_t channel, uint32_t channelMask, uint32_t bitWidth, uint8_t *buffer, uint32_t size)
|
|
|
|
{
|
|
|
|
uint32_t i = 0, j = 0;
|
|
|
|
uint8_t bytesPerWord = bitWidth / 8U;
|
|
|
|
uint32_t channelNums = 0U, endChannel = 0U;
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
bytesPerWord = (size_t)((FSL_FEATURE_SAI_FIFO_COUNT - base->TCR1) * bytesPerWord);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
for (i = 0U; (i < FSL_FEATURE_SAI_CHANNEL_COUNT); i++)
|
|
|
|
{
|
|
|
|
if ((1U << i) & (channelMask))
|
|
|
|
{
|
|
|
|
channelNums++;
|
|
|
|
endChannel = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(channelNums <= FSL_FEATURE_SAI_CHANNEL_COUNT);
|
|
|
|
bytesPerWord *= channelNums;
|
|
|
|
|
|
|
|
while (j < size)
|
|
|
|
{
|
|
|
|
/* Wait until it can write data */
|
|
|
|
while (!(base->TCSR & I2S_TCSR_FWF_MASK))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SAI_WriteNonBlocking(base, channel, channelMask, endChannel, bitWidth, buffer, bytesPerWord);
|
|
|
|
buffer += bytesPerWord;
|
|
|
|
j += bytesPerWord;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Wait until the last data is sent */
|
|
|
|
while (!(base->TCSR & I2S_TCSR_FWF_MASK))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* brief Receives multi channel data using a blocking method.
|
|
|
|
*
|
|
|
|
* note This function blocks by polling until data is ready to be sent.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param channel Data channel used.
|
|
|
|
* param channelMask channel mask.
|
|
|
|
* param bitWidth How many bits in an audio word; usually 8/16/24/32 bits.
|
|
|
|
* param buffer Pointer to the data to be read.
|
|
|
|
* param size Bytes to be read.
|
|
|
|
*/
|
|
|
|
void SAI_ReadMultiChannelBlocking(
|
|
|
|
I2S_Type *base, uint32_t channel, uint32_t channelMask, uint32_t bitWidth, uint8_t *buffer, uint32_t size)
|
|
|
|
{
|
|
|
|
uint32_t i = 0, j = 0;
|
|
|
|
uint8_t bytesPerWord = bitWidth / 8U;
|
|
|
|
uint32_t channelNums = 0U, endChannel = 0U;
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
bytesPerWord = (size_t)(base->RCR1 * bytesPerWord);
|
|
|
|
#endif
|
|
|
|
for (i = 0U; (i < FSL_FEATURE_SAI_CHANNEL_COUNT); i++)
|
|
|
|
{
|
|
|
|
if ((1U << i) & (channelMask))
|
|
|
|
{
|
|
|
|
channelNums++;
|
|
|
|
endChannel = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(channelNums <= FSL_FEATURE_SAI_CHANNEL_COUNT);
|
|
|
|
bytesPerWord *= channelNums;
|
|
|
|
|
|
|
|
while (j < size)
|
|
|
|
{
|
|
|
|
/* Wait until data is received */
|
|
|
|
while (!(base->RCSR & I2S_RCSR_FWF_MASK))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SAI_ReadNonBlocking(base, channel, channelMask, endChannel, bitWidth, buffer, bytesPerWord);
|
|
|
|
buffer += bytesPerWord;
|
|
|
|
j += bytesPerWord;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* brief Receives data using a blocking method.
|
|
|
|
*
|
|
|
|
* note This function blocks by polling until data is ready to be sent.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param channel Data channel used.
|
|
|
|
* param bitWidth How many bits in an audio word; usually 8/16/24/32 bits.
|
|
|
|
* param buffer Pointer to the data to be read.
|
|
|
|
* param size Bytes to be read.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_ReadBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size)
|
|
|
|
{
|
|
|
|
uint32_t i = 0;
|
|
|
|
uint8_t bytesPerWord = bitWidth / 8U;
|
2019-06-12 15:01:12 +08:00
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
bytesPerWord = (size_t)(base->RCR1 * bytesPerWord);
|
|
|
|
#endif
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
while (i < size)
|
|
|
|
{
|
|
|
|
/* Wait until data is received */
|
|
|
|
while (!(base->RCSR & I2S_RCSR_FWF_MASK))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
SAI_ReadNonBlocking(base, channel, 1U << channel, channel, bitWidth, buffer, bytesPerWord);
|
2018-09-20 23:18:14 +08:00
|
|
|
buffer += bytesPerWord;
|
|
|
|
i += bytesPerWord;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Initializes the SAI Tx handle.
|
|
|
|
*
|
|
|
|
* This function initializes the Tx handle for the SAI Tx transactional APIs. Call
|
|
|
|
* this function once to get the handle initialized.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param handle SAI handle pointer.
|
|
|
|
* param callback Pointer to the user callback function.
|
|
|
|
* param userData User parameter passed to the callback function
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TransferTxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
/* Zero the handle */
|
|
|
|
memset(handle, 0, sizeof(*handle));
|
|
|
|
|
|
|
|
s_saiHandle[SAI_GetInstance(base)][0] = handle;
|
|
|
|
|
|
|
|
handle->callback = callback;
|
|
|
|
handle->userData = userData;
|
2019-06-12 15:01:12 +08:00
|
|
|
handle->base = base;
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
/* Set the isr pointer */
|
|
|
|
s_saiTxIsr = SAI_TransferTxHandleIRQ;
|
|
|
|
|
|
|
|
/* Enable Tx irq */
|
|
|
|
EnableIRQ(s_saiTxIRQ[SAI_GetInstance(base)]);
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Initializes the SAI Rx handle.
|
|
|
|
*
|
|
|
|
* This function initializes the Rx handle for the SAI Rx transactional APIs. Call
|
|
|
|
* this function once to get the handle initialized.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param handle SAI handle pointer.
|
|
|
|
* param callback Pointer to the user callback function.
|
|
|
|
* param userData User parameter passed to the callback function.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TransferRxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
/* Zero the handle */
|
|
|
|
memset(handle, 0, sizeof(*handle));
|
|
|
|
|
|
|
|
s_saiHandle[SAI_GetInstance(base)][1] = handle;
|
|
|
|
|
|
|
|
handle->callback = callback;
|
|
|
|
handle->userData = userData;
|
2019-06-12 15:01:12 +08:00
|
|
|
handle->base = base;
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
/* Set the isr pointer */
|
|
|
|
s_saiRxIsr = SAI_TransferRxHandleIRQ;
|
|
|
|
|
|
|
|
/* Enable Rx irq */
|
|
|
|
EnableIRQ(s_saiRxIRQ[SAI_GetInstance(base)]);
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Configures the SAI Tx audio format.
|
|
|
|
*
|
|
|
|
* The audio format can be changed at run-time. This function configures the sample rate and audio data
|
|
|
|
* format to be transferred.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param handle SAI handle pointer.
|
|
|
|
* param format Pointer to the SAI audio data format structure.
|
|
|
|
* param mclkSourceClockHz SAI master clock source frequency in Hz.
|
|
|
|
* param bclkSourceClockHz SAI bit clock source frequency in Hz. If a bit clock source is a master
|
|
|
|
* clock, this value should equal the masterClockHz in format.
|
|
|
|
* return Status of this function. Return value is the status_t.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
status_t SAI_TransferTxSetFormat(I2S_Type *base,
|
|
|
|
sai_handle_t *handle,
|
|
|
|
sai_transfer_format_t *format,
|
|
|
|
uint32_t mclkSourceClockHz,
|
|
|
|
uint32_t bclkSourceClockHz)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
if ((bclkSourceClockHz < format->sampleRate_Hz)
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
|
|
|
|
|| (mclkSourceClockHz < format->sampleRate_Hz)
|
|
|
|
#endif
|
|
|
|
)
|
2018-09-20 23:18:14 +08:00
|
|
|
{
|
|
|
|
return kStatus_InvalidArgument;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy format to handle */
|
|
|
|
handle->bitWidth = format->bitWidth;
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
handle->watermark = format->watermark;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
SAI_TxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz);
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
handle->channel = format->channel;
|
|
|
|
/* used for multi channel */
|
|
|
|
handle->channelMask = format->channelMask;
|
|
|
|
handle->channelNums = format->channelNums;
|
|
|
|
handle->endChannel = format->endChannel;
|
|
|
|
|
2018-09-20 23:18:14 +08:00
|
|
|
return kStatus_Success;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Configures the SAI Rx audio format.
|
|
|
|
*
|
|
|
|
* The audio format can be changed at run-time. This function configures the sample rate and audio data
|
|
|
|
* format to be transferred.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param handle SAI handle pointer.
|
|
|
|
* param format Pointer to the SAI audio data format structure.
|
|
|
|
* param mclkSourceClockHz SAI master clock source frequency in Hz.
|
|
|
|
* param bclkSourceClockHz SAI bit clock source frequency in Hz. If a bit clock source is a master
|
|
|
|
* clock, this value should equal the masterClockHz in format.
|
|
|
|
* return Status of this function. Return value is one of status_t.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
status_t SAI_TransferRxSetFormat(I2S_Type *base,
|
|
|
|
sai_handle_t *handle,
|
|
|
|
sai_transfer_format_t *format,
|
|
|
|
uint32_t mclkSourceClockHz,
|
|
|
|
uint32_t bclkSourceClockHz)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
if ((bclkSourceClockHz < format->sampleRate_Hz)
|
|
|
|
#if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
|
|
|
|
|| (mclkSourceClockHz < format->sampleRate_Hz)
|
|
|
|
#endif
|
|
|
|
)
|
2018-09-20 23:18:14 +08:00
|
|
|
{
|
|
|
|
return kStatus_InvalidArgument;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy format to handle */
|
|
|
|
handle->bitWidth = format->bitWidth;
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
handle->watermark = format->watermark;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
SAI_RxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz);
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
handle->channel = format->channel;
|
|
|
|
/* used for multi channel */
|
|
|
|
handle->channelMask = format->channelMask;
|
|
|
|
handle->channelNums = format->channelNums;
|
|
|
|
handle->endChannel = format->endChannel;
|
|
|
|
|
2018-09-20 23:18:14 +08:00
|
|
|
return kStatus_Success;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Performs an interrupt non-blocking send transfer on SAI.
|
|
|
|
*
|
|
|
|
* note This API returns immediately after the transfer initiates.
|
|
|
|
* Call the SAI_TxGetTransferStatusIRQ to poll the transfer status and check whether
|
|
|
|
* the transfer is finished. If the return status is not kStatus_SAI_Busy, the transfer
|
|
|
|
* is finished.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param handle Pointer to the sai_handle_t structure which stores the transfer state.
|
|
|
|
* param xfer Pointer to the sai_transfer_t structure.
|
|
|
|
* retval kStatus_Success Successfully started the data receive.
|
|
|
|
* retval kStatus_SAI_TxBusy Previous receive still not finished.
|
|
|
|
* retval kStatus_InvalidArgument The input parameter is invalid.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
status_t SAI_TransferSendNonBlocking(I2S_Type *base, sai_handle_t *handle, sai_transfer_t *xfer)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
/* Check if the queue is full */
|
|
|
|
if (handle->saiQueue[handle->queueUser].data)
|
|
|
|
{
|
|
|
|
return kStatus_SAI_QueueFull;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add into queue */
|
|
|
|
handle->transferSize[handle->queueUser] = xfer->dataSize;
|
|
|
|
handle->saiQueue[handle->queueUser].data = xfer->data;
|
|
|
|
handle->saiQueue[handle->queueUser].dataSize = xfer->dataSize;
|
|
|
|
handle->queueUser = (handle->queueUser + 1) % SAI_XFER_QUEUE_SIZE;
|
|
|
|
|
|
|
|
/* Set the state to busy */
|
|
|
|
handle->state = kSAI_Busy;
|
|
|
|
|
|
|
|
/* Enable interrupt */
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
/* Use FIFO request interrupt and fifo error*/
|
|
|
|
SAI_TxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFORequestInterruptEnable);
|
|
|
|
#else
|
|
|
|
SAI_TxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable);
|
|
|
|
#endif /* FSL_FEATURE_SAI_FIFO_COUNT */
|
|
|
|
|
|
|
|
/* Enable Tx transfer */
|
|
|
|
SAI_TxEnable(base, true);
|
|
|
|
|
|
|
|
return kStatus_Success;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Performs an interrupt non-blocking receive transfer on SAI.
|
|
|
|
*
|
|
|
|
* note This API returns immediately after the transfer initiates.
|
|
|
|
* Call the SAI_RxGetTransferStatusIRQ to poll the transfer status and check whether
|
|
|
|
* the transfer is finished. If the return status is not kStatus_SAI_Busy, the transfer
|
|
|
|
* is finished.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param handle Pointer to the sai_handle_t structure which stores the transfer state.
|
|
|
|
* param xfer Pointer to the sai_transfer_t structure.
|
|
|
|
* retval kStatus_Success Successfully started the data receive.
|
|
|
|
* retval kStatus_SAI_RxBusy Previous receive still not finished.
|
|
|
|
* retval kStatus_InvalidArgument The input parameter is invalid.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
status_t SAI_TransferReceiveNonBlocking(I2S_Type *base, sai_handle_t *handle, sai_transfer_t *xfer)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
/* Check if the queue is full */
|
|
|
|
if (handle->saiQueue[handle->queueUser].data)
|
|
|
|
{
|
|
|
|
return kStatus_SAI_QueueFull;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add into queue */
|
|
|
|
handle->transferSize[handle->queueUser] = xfer->dataSize;
|
|
|
|
handle->saiQueue[handle->queueUser].data = xfer->data;
|
|
|
|
handle->saiQueue[handle->queueUser].dataSize = xfer->dataSize;
|
|
|
|
handle->queueUser = (handle->queueUser + 1) % SAI_XFER_QUEUE_SIZE;
|
|
|
|
|
|
|
|
/* Set state to busy */
|
|
|
|
handle->state = kSAI_Busy;
|
|
|
|
|
|
|
|
/* Enable interrupt */
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
/* Use FIFO request interrupt and fifo error*/
|
|
|
|
SAI_RxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFORequestInterruptEnable);
|
|
|
|
#else
|
|
|
|
SAI_RxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable);
|
|
|
|
#endif /* FSL_FEATURE_SAI_FIFO_COUNT */
|
|
|
|
|
|
|
|
/* Enable Rx transfer */
|
|
|
|
SAI_RxEnable(base, true);
|
|
|
|
|
|
|
|
return kStatus_Success;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Gets a set byte count.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param handle Pointer to the sai_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.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
status_t SAI_TransferGetSendCount(I2S_Type *base, sai_handle_t *handle, size_t *count)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
status_t status = kStatus_Success;
|
|
|
|
|
|
|
|
if (handle->state != kSAI_Busy)
|
|
|
|
{
|
|
|
|
status = kStatus_NoTransferInProgress;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*count = (handle->transferSize[handle->queueDriver] - handle->saiQueue[handle->queueDriver].dataSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Gets a received byte count.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param handle Pointer to the sai_handle_t structure which stores the transfer state.
|
|
|
|
* param count Bytes count received.
|
|
|
|
* retval kStatus_Success Succeed get the transfer count.
|
|
|
|
* retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
status_t SAI_TransferGetReceiveCount(I2S_Type *base, sai_handle_t *handle, size_t *count)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
status_t status = kStatus_Success;
|
|
|
|
|
|
|
|
if (handle->state != kSAI_Busy)
|
|
|
|
{
|
|
|
|
status = kStatus_NoTransferInProgress;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*count = (handle->transferSize[handle->queueDriver] - handle->saiQueue[handle->queueDriver].dataSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Aborts the current send.
|
|
|
|
*
|
|
|
|
* note This API can be called any time when an interrupt non-blocking transfer initiates
|
|
|
|
* to abort the transfer early.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param handle Pointer to the sai_handle_t structure which stores the transfer state.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TransferAbortSend(I2S_Type *base, sai_handle_t *handle)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
/* Stop Tx transfer and disable interrupt */
|
|
|
|
SAI_TxEnable(base, false);
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
/* Use FIFO request interrupt and fifo error */
|
|
|
|
SAI_TxDisableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFORequestInterruptEnable);
|
|
|
|
#else
|
|
|
|
SAI_TxDisableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable);
|
|
|
|
#endif /* FSL_FEATURE_SAI_FIFO_COUNT */
|
|
|
|
|
|
|
|
handle->state = kSAI_Idle;
|
|
|
|
|
|
|
|
/* Clear the queue */
|
|
|
|
memset(handle->saiQueue, 0, sizeof(sai_transfer_t) * SAI_XFER_QUEUE_SIZE);
|
|
|
|
handle->queueDriver = 0;
|
|
|
|
handle->queueUser = 0;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Aborts the current IRQ receive.
|
|
|
|
*
|
|
|
|
* note This API can be called when an interrupt non-blocking transfer initiates
|
|
|
|
* to abort the transfer early.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer
|
|
|
|
* param handle Pointer to the sai_handle_t structure which stores the transfer state.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TransferAbortReceive(I2S_Type *base, sai_handle_t *handle)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
/* Stop Tx transfer and disable interrupt */
|
|
|
|
SAI_RxEnable(base, false);
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
/* Use FIFO request interrupt and fifo error */
|
|
|
|
SAI_RxDisableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFORequestInterruptEnable);
|
|
|
|
#else
|
|
|
|
SAI_RxDisableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable);
|
|
|
|
#endif /* FSL_FEATURE_SAI_FIFO_COUNT */
|
|
|
|
|
|
|
|
handle->state = kSAI_Idle;
|
|
|
|
|
|
|
|
/* Clear the queue */
|
|
|
|
memset(handle->saiQueue, 0, sizeof(sai_transfer_t) * SAI_XFER_QUEUE_SIZE);
|
|
|
|
handle->queueDriver = 0;
|
|
|
|
handle->queueUser = 0;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Terminate all SAI send.
|
|
|
|
*
|
|
|
|
* This function will clear all transfer slots buffered in the sai queue. If users only want to abort the
|
|
|
|
* current transfer slot, please call SAI_TransferAbortSend.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param handle SAI eDMA handle pointer.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TransferTerminateSend(I2S_Type *base, sai_handle_t *handle)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
/* Abort the current transfer */
|
|
|
|
SAI_TransferAbortSend(base, handle);
|
|
|
|
|
|
|
|
/* Clear all the internal information */
|
|
|
|
memset(handle->saiQueue, 0U, sizeof(handle->saiQueue));
|
|
|
|
memset(handle->transferSize, 0U, sizeof(handle->transferSize));
|
|
|
|
handle->queueUser = 0U;
|
|
|
|
handle->queueDriver = 0U;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Terminate all SAI receive.
|
|
|
|
*
|
|
|
|
* This function will clear all transfer slots buffered in the sai queue. If users only want to abort the
|
|
|
|
* current transfer slot, please call SAI_TransferAbortReceive.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param handle SAI eDMA handle pointer.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TransferTerminateReceive(I2S_Type *base, sai_handle_t *handle)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
/* Abort the current transfer */
|
|
|
|
SAI_TransferAbortReceive(base, handle);
|
|
|
|
|
|
|
|
/* Clear all the internal information */
|
|
|
|
memset(handle->saiQueue, 0U, sizeof(handle->saiQueue));
|
|
|
|
memset(handle->transferSize, 0U, sizeof(handle->transferSize));
|
|
|
|
handle->queueUser = 0U;
|
|
|
|
handle->queueDriver = 0U;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Tx interrupt handler.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param handle Pointer to the sai_handle_t structure.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TransferTxHandleIRQ(I2S_Type *base, sai_handle_t *handle)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
uint8_t *buffer = handle->saiQueue[handle->queueDriver].data;
|
2019-06-12 15:01:12 +08:00
|
|
|
uint8_t dataSize = (handle->bitWidth / 8U) * handle->channelNums;
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
/* Handle Error */
|
|
|
|
if (base->TCSR & I2S_TCSR_FEF_MASK)
|
|
|
|
{
|
|
|
|
/* Clear FIFO error flag to continue transfer */
|
|
|
|
SAI_TxClearStatusFlags(base, kSAI_FIFOErrorFlag);
|
|
|
|
|
|
|
|
/* Reset FIFO for safety */
|
|
|
|
SAI_TxSoftwareReset(base, kSAI_ResetTypeFIFO);
|
|
|
|
|
|
|
|
/* Call the callback */
|
|
|
|
if (handle->callback)
|
|
|
|
{
|
|
|
|
(handle->callback)(base, handle, kStatus_SAI_TxError, handle->userData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle transfer */
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if (base->TCSR & I2S_TCSR_FRF_MASK)
|
|
|
|
{
|
|
|
|
/* Judge if the data need to transmit is less than space */
|
|
|
|
uint8_t size = MIN((handle->saiQueue[handle->queueDriver].dataSize),
|
|
|
|
(size_t)((FSL_FEATURE_SAI_FIFO_COUNT - handle->watermark) * dataSize));
|
|
|
|
|
|
|
|
/* Copy the data from sai buffer to FIFO */
|
2019-06-12 15:01:12 +08:00
|
|
|
SAI_WriteNonBlocking(base, handle->channel, handle->channelMask, handle->endChannel, handle->bitWidth, buffer,
|
|
|
|
size);
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
/* Update the internal counter */
|
|
|
|
handle->saiQueue[handle->queueDriver].dataSize -= size;
|
|
|
|
handle->saiQueue[handle->queueDriver].data += size;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (base->TCSR & I2S_TCSR_FWF_MASK)
|
|
|
|
{
|
|
|
|
uint8_t size = MIN((handle->saiQueue[handle->queueDriver].dataSize), dataSize);
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
SAI_WriteNonBlocking(base, handle->channel, handle->channelMask, handle->endChannel, handle->bitWidth, buffer,
|
|
|
|
size);
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
/* Update internal counter */
|
|
|
|
handle->saiQueue[handle->queueDriver].dataSize -= size;
|
|
|
|
handle->saiQueue[handle->queueDriver].data += size;
|
|
|
|
}
|
|
|
|
#endif /* FSL_FEATURE_SAI_FIFO_COUNT */
|
|
|
|
|
|
|
|
/* If finished a blcok, call the callback function */
|
|
|
|
if (handle->saiQueue[handle->queueDriver].dataSize == 0U)
|
|
|
|
{
|
|
|
|
memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t));
|
|
|
|
handle->queueDriver = (handle->queueDriver + 1) % SAI_XFER_QUEUE_SIZE;
|
|
|
|
if (handle->callback)
|
|
|
|
{
|
|
|
|
(handle->callback)(base, handle, kStatus_SAI_TxIdle, handle->userData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If all data finished, just stop the transfer */
|
|
|
|
if (handle->saiQueue[handle->queueDriver].data == NULL)
|
|
|
|
{
|
|
|
|
SAI_TransferAbortSend(base, handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Tx interrupt handler.
|
|
|
|
*
|
|
|
|
* param base SAI base pointer.
|
|
|
|
* param handle Pointer to the sai_handle_t structure.
|
|
|
|
*/
|
2018-09-20 23:18:14 +08:00
|
|
|
void SAI_TransferRxHandleIRQ(I2S_Type *base, sai_handle_t *handle)
|
|
|
|
{
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
uint8_t *buffer = handle->saiQueue[handle->queueDriver].data;
|
2019-06-12 15:01:12 +08:00
|
|
|
uint8_t dataSize = (handle->bitWidth / 8U) * handle->channelNums;
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
/* Handle Error */
|
|
|
|
if (base->RCSR & I2S_RCSR_FEF_MASK)
|
|
|
|
{
|
|
|
|
/* Clear FIFO error flag to continue transfer */
|
|
|
|
SAI_RxClearStatusFlags(base, kSAI_FIFOErrorFlag);
|
|
|
|
|
|
|
|
/* Reset FIFO for safety */
|
|
|
|
SAI_RxSoftwareReset(base, kSAI_ResetTypeFIFO);
|
|
|
|
|
|
|
|
/* Call the callback */
|
|
|
|
if (handle->callback)
|
|
|
|
{
|
|
|
|
(handle->callback)(base, handle, kStatus_SAI_RxError, handle->userData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle transfer */
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if (base->RCSR & I2S_RCSR_FRF_MASK)
|
|
|
|
{
|
|
|
|
/* Judge if the data need to transmit is less than space */
|
|
|
|
uint8_t size = MIN((handle->saiQueue[handle->queueDriver].dataSize), (handle->watermark * dataSize));
|
|
|
|
|
|
|
|
/* Copy the data from sai buffer to FIFO */
|
2019-06-12 15:01:12 +08:00
|
|
|
SAI_ReadNonBlocking(base, handle->channel, handle->channelMask, handle->endChannel, handle->bitWidth, buffer,
|
|
|
|
size);
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
/* Update the internal counter */
|
|
|
|
handle->saiQueue[handle->queueDriver].dataSize -= size;
|
|
|
|
handle->saiQueue[handle->queueDriver].data += size;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (base->RCSR & I2S_RCSR_FWF_MASK)
|
|
|
|
{
|
|
|
|
uint8_t size = MIN((handle->saiQueue[handle->queueDriver].dataSize), dataSize);
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
SAI_ReadNonBlocking(base, handle->channel, handle->channelMask, handle->endChannel, handle->bitWidth, buffer,
|
|
|
|
size);
|
2018-09-20 23:18:14 +08:00
|
|
|
|
|
|
|
/* Update internal state */
|
|
|
|
handle->saiQueue[handle->queueDriver].dataSize -= size;
|
|
|
|
handle->saiQueue[handle->queueDriver].data += size;
|
|
|
|
}
|
|
|
|
#endif /* FSL_FEATURE_SAI_FIFO_COUNT */
|
|
|
|
|
|
|
|
/* If finished a blcok, call the callback function */
|
|
|
|
if (handle->saiQueue[handle->queueDriver].dataSize == 0U)
|
|
|
|
{
|
|
|
|
memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t));
|
|
|
|
handle->queueDriver = (handle->queueDriver + 1) % SAI_XFER_QUEUE_SIZE;
|
|
|
|
if (handle->callback)
|
|
|
|
{
|
|
|
|
(handle->callback)(base, handle, kStatus_SAI_RxIdle, handle->userData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If all data finished, just stop the transfer */
|
|
|
|
if (handle->saiQueue[handle->queueDriver].data == NULL)
|
|
|
|
{
|
|
|
|
SAI_TransferAbortReceive(base, handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(I2S0)
|
|
|
|
void I2S0_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[0][1]) && ((I2S0->RCSR & kSAI_FIFORequestFlag) || (I2S0->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S0->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S0->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[0][1]) && ((I2S0->RCSR & kSAI_FIFOWarningFlag) || (I2S0->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S0->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S0->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(I2S0, s_saiHandle[0][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[0][0]) && ((I2S0->TCSR & kSAI_FIFORequestFlag) || (I2S0->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S0->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S0->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[0][0]) && ((I2S0->TCSR & kSAI_FIFOWarningFlag) || (I2S0->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S0->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S0->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(I2S0, s_saiHandle[0][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S0_Tx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[0][0]);
|
|
|
|
s_saiTxIsr(I2S0, s_saiHandle[0][0]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S0_Rx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[0][1]);
|
|
|
|
s_saiRxIsr(I2S0, s_saiHandle[0][1]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* I2S0*/
|
|
|
|
|
|
|
|
#if defined(I2S1)
|
|
|
|
void I2S1_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][1]) && ((I2S1->RCSR & kSAI_FIFORequestFlag) || (I2S1->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S1->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S1->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][1]) && ((I2S1->RCSR & kSAI_FIFOWarningFlag) || (I2S1->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S1->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S1->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(I2S1, s_saiHandle[1][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][0]) && ((I2S1->TCSR & kSAI_FIFORequestFlag) || (I2S1->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S1->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S1->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][0]) && ((I2S1->TCSR & kSAI_FIFOWarningFlag) || (I2S1->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S1->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S1->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(I2S1, s_saiHandle[1][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S1_Tx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[1][0]);
|
|
|
|
s_saiTxIsr(I2S1, s_saiHandle[1][0]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S1_Rx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[1][1]);
|
|
|
|
s_saiRxIsr(I2S1, s_saiHandle[1][1]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* I2S1*/
|
|
|
|
|
|
|
|
#if defined(I2S2)
|
|
|
|
void I2S2_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[2][1]) && ((I2S2->RCSR & kSAI_FIFORequestFlag) || (I2S2->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S2->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S2->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[2][1]) && ((I2S2->RCSR & kSAI_FIFOWarningFlag) || (I2S2->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S2->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S2->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(I2S2, s_saiHandle[2][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[2][0]) && ((I2S2->TCSR & kSAI_FIFORequestFlag) || (I2S2->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S2->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S2->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[2][0]) && ((I2S2->TCSR & kSAI_FIFOWarningFlag) || (I2S2->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S2->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S2->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(I2S2, s_saiHandle[2][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S2_Tx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[2][0]);
|
|
|
|
s_saiTxIsr(I2S2, s_saiHandle[2][0]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S2_Rx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[2][1]);
|
|
|
|
s_saiRxIsr(I2S2, s_saiHandle[2][1]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* I2S2*/
|
|
|
|
|
|
|
|
#if defined(I2S3)
|
|
|
|
void I2S3_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[3][1]) && ((I2S3->RCSR & kSAI_FIFORequestFlag) || (I2S3->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S3->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S3->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[3][1]) && ((I2S3->RCSR & kSAI_FIFOWarningFlag) || (I2S3->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S3->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S3->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(I2S3, s_saiHandle[3][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[3][0]) && ((I2S3->TCSR & kSAI_FIFORequestFlag) || (I2S3->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S3->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S3->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[3][0]) && ((I2S3->TCSR & kSAI_FIFOWarningFlag) || (I2S3->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S3->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S3->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(I2S3, s_saiHandle[3][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S3_Tx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[3][0]);
|
|
|
|
s_saiTxIsr(I2S3, s_saiHandle[3][0]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S3_Rx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[3][1]);
|
|
|
|
s_saiRxIsr(I2S3, s_saiHandle[3][1]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* I2S3*/
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
#if defined(I2S4)
|
|
|
|
void I2S4_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[4][1]) && ((I2S4->RCSR & kSAI_FIFORequestFlag) || (I2S4->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S4->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S4->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[4][1]) && ((I2S4->RCSR & kSAI_FIFOWarningFlag) || (I2S4->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S4->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S4->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(I2S4, s_saiHandle[4][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[4][0]) && ((I2S4->TCSR & kSAI_FIFORequestFlag) || (I2S4->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S4->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S4->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[4][0]) && ((I2S4->TCSR & kSAI_FIFOWarningFlag) || (I2S4->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S4->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S4->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(I2S4, s_saiHandle[4][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S4_Tx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[4][0]);
|
|
|
|
s_saiTxIsr(I2S4, s_saiHandle[4][0]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S4_Rx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[4][1]);
|
|
|
|
s_saiRxIsr(I2S4, s_saiHandle[4][1]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SAI5_SAI6_SHARE_IRQ) && (FSL_FEATURE_SAI5_SAI6_SHARE_IRQ) && defined(I2S5) && defined(I2S6)
|
|
|
|
void I2S56_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
/* use index 5 to get handle when I2S5 & I2S6 share IRQ NUMBER */
|
|
|
|
I2S_Type *base = s_saiHandle[5][1]->base;
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[5][1]) && base && ((base->RCSR & kSAI_FIFORequestFlag) || (base->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((base->RCSR & kSAI_FIFORequestInterruptEnable) || (base->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[5][1]) && base && ((base->RCSR & kSAI_FIFOWarningFlag) || (base->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((base->RCSR & kSAI_FIFOWarningInterruptEnable) || (base->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(base, s_saiHandle[5][1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
base = s_saiHandle[5][0]->base;
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[5][0]) && base && ((base->TCSR & kSAI_FIFORequestFlag) || (base->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((base->TCSR & kSAI_FIFORequestInterruptEnable) || (base->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[5][0]) && base && ((base->TCSR & kSAI_FIFOWarningFlag) || (base->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((base->TCSR & kSAI_FIFOWarningInterruptEnable) || (base->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(base, s_saiHandle[5][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S56_Tx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
/* use index 5 to get handle when I2S5 & I2S6 share IRQ NUMBER */
|
|
|
|
assert(s_saiHandle[5][0]);
|
|
|
|
s_saiTxIsr(s_saiHandle[5][0]->base, s_saiHandle[5][0]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S56_Rx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
/* use index 5 to get handle when I2S5 & I2S6 share IRQ NUMBER */
|
|
|
|
assert(s_saiHandle[5][1]);
|
|
|
|
s_saiRxIsr(s_saiHandle[5][1]->base, s_saiHandle[5][1]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#if defined(I2S5)
|
|
|
|
void I2S5_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[5][1]) && ((I2S5->RCSR & kSAI_FIFORequestFlag) || (I2S5->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S5->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S5->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[5][1]) && ((I2S5->RCSR & kSAI_FIFOWarningFlag) || (I2S5->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S5->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S5->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(I2S5, s_saiHandle[5][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[5][0]) && ((I2S5->TCSR & kSAI_FIFORequestFlag) || (I2S5->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S5->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S5->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[5][0]) && ((I2S5->TCSR & kSAI_FIFOWarningFlag) || (I2S5->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S5->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S5->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(I2S5, s_saiHandle[5][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S5_Tx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[5][0]);
|
|
|
|
s_saiTxIsr(I2S5, s_saiHandle[5][0]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S5_Rx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[5][1]);
|
|
|
|
s_saiRxIsr(I2S5, s_saiHandle[5][1]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(I2S6)
|
|
|
|
void I2S6_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[6][1]) && ((I2S6->RCSR & kSAI_FIFORequestFlag) || (I2S6->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S6->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S6->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[6][1]) && ((I2S6->RCSR & kSAI_FIFOWarningFlag) || (I2S6->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S6->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S6->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(I2S6, s_saiHandle[6][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[6][0]) && ((I2S6->TCSR & kSAI_FIFORequestFlag) || (I2S6->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S6->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S6->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[6][0]) && ((I2S6->TCSR & kSAI_FIFOWarningFlag) || (I2S6->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((I2S6->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S6->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(I2S6, s_saiHandle[6][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S6_Tx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[6][0]);
|
|
|
|
s_saiTxIsr(I2S6, s_saiHandle[6][0]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void I2S6_Rx_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
assert(s_saiHandle[6][1]);
|
|
|
|
s_saiRxIsr(I2S6, s_saiHandle[6][1]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2018-09-20 23:18:14 +08:00
|
|
|
#if defined(AUDIO__SAI0)
|
|
|
|
void AUDIO_SAI0_INT_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[0][1]) &&
|
|
|
|
((AUDIO__SAI0->RCSR & kSAI_FIFORequestFlag) || (AUDIO__SAI0->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI0->RCSR & kSAI_FIFORequestInterruptEnable) || (AUDIO__SAI0->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[0][1]) &&
|
|
|
|
((AUDIO__SAI0->RCSR & kSAI_FIFOWarningFlag) || (AUDIO__SAI0->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI0->RCSR & kSAI_FIFOWarningInterruptEnable) || (AUDIO__SAI0->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(AUDIO__SAI0, s_saiHandle[0][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[0][0]) &&
|
|
|
|
((AUDIO__SAI0->TCSR & kSAI_FIFORequestFlag) || (AUDIO__SAI0->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI0->TCSR & kSAI_FIFORequestInterruptEnable) || (AUDIO__SAI0->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[0][0]) &&
|
|
|
|
((AUDIO__SAI0->TCSR & kSAI_FIFOWarningFlag) || (AUDIO__SAI0->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI0->TCSR & kSAI_FIFOWarningInterruptEnable) || (AUDIO__SAI0->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(AUDIO__SAI0, s_saiHandle[0][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* AUDIO__SAI0 */
|
|
|
|
|
|
|
|
#if defined(AUDIO__SAI1)
|
|
|
|
void AUDIO_SAI1_INT_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][1]) &&
|
|
|
|
((AUDIO__SAI1->RCSR & kSAI_FIFORequestFlag) || (AUDIO__SAI1->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI1->RCSR & kSAI_FIFORequestInterruptEnable) || (AUDIO__SAI1->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][1]) &&
|
|
|
|
((AUDIO__SAI1->RCSR & kSAI_FIFOWarningFlag) || (AUDIO__SAI1->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI1->RCSR & kSAI_FIFOWarningInterruptEnable) || (AUDIO__SAI1->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(AUDIO__SAI1, s_saiHandle[1][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][0]) &&
|
|
|
|
((AUDIO__SAI1->TCSR & kSAI_FIFORequestFlag) || (AUDIO__SAI1->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI1->TCSR & kSAI_FIFORequestInterruptEnable) || (AUDIO__SAI1->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][0]) &&
|
|
|
|
((AUDIO__SAI1->TCSR & kSAI_FIFOWarningFlag) || (AUDIO__SAI1->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI1->TCSR & kSAI_FIFOWarningInterruptEnable) || (AUDIO__SAI1->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(AUDIO__SAI1, s_saiHandle[1][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* AUDIO__SAI1 */
|
|
|
|
|
|
|
|
#if defined(AUDIO__SAI2)
|
|
|
|
void AUDIO_SAI2_INT_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[2][1]) &&
|
|
|
|
((AUDIO__SAI2->RCSR & kSAI_FIFORequestFlag) || (AUDIO__SAI2->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI2->RCSR & kSAI_FIFORequestInterruptEnable) || (AUDIO__SAI2->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[2][1]) &&
|
|
|
|
((AUDIO__SAI2->RCSR & kSAI_FIFOWarningFlag) || (AUDIO__SAI2->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI2->RCSR & kSAI_FIFOWarningInterruptEnable) || (AUDIO__SAI2->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(AUDIO__SAI2, s_saiHandle[2][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[2][0]) &&
|
|
|
|
((AUDIO__SAI2->TCSR & kSAI_FIFORequestFlag) || (AUDIO__SAI2->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI2->TCSR & kSAI_FIFORequestInterruptEnable) || (AUDIO__SAI2->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[2][0]) &&
|
|
|
|
((AUDIO__SAI2->TCSR & kSAI_FIFOWarningFlag) || (AUDIO__SAI2->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI2->TCSR & kSAI_FIFOWarningInterruptEnable) || (AUDIO__SAI2->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(AUDIO__SAI2, s_saiHandle[2][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* AUDIO__SAI2 */
|
|
|
|
|
|
|
|
#if defined(AUDIO__SAI3)
|
|
|
|
void AUDIO_SAI3_INT_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[3][1]) &&
|
|
|
|
((AUDIO__SAI3->RCSR & kSAI_FIFORequestFlag) || (AUDIO__SAI3->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI3->RCSR & kSAI_FIFORequestInterruptEnable) || (AUDIO__SAI3->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[3][1]) &&
|
|
|
|
((AUDIO__SAI3->RCSR & kSAI_FIFOWarningFlag) || (AUDIO__SAI3->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI3->RCSR & kSAI_FIFOWarningInterruptEnable) || (AUDIO__SAI3->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(AUDIO__SAI3, s_saiHandle[3][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[3][0]) &&
|
|
|
|
((AUDIO__SAI3->TCSR & kSAI_FIFORequestFlag) || (AUDIO__SAI3->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI3->TCSR & kSAI_FIFORequestInterruptEnable) || (AUDIO__SAI3->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[3][0]) &&
|
|
|
|
((AUDIO__SAI3->TCSR & kSAI_FIFOWarningFlag) || (AUDIO__SAI3->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI3->TCSR & kSAI_FIFOWarningInterruptEnable) || (AUDIO__SAI3->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(AUDIO__SAI3, s_saiHandle[3][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(AUDIO__SAI6)
|
|
|
|
void AUDIO_SAI6_INT_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[6][1]) &&
|
|
|
|
((AUDIO__SAI6->RCSR & kSAI_FIFORequestFlag) || (AUDIO__SAI6->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI6->RCSR & kSAI_FIFORequestInterruptEnable) || (AUDIO__SAI6->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[6][1]) &&
|
|
|
|
((AUDIO__SAI6->RCSR & kSAI_FIFOWarningFlag) || (AUDIO__SAI6->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI6->RCSR & kSAI_FIFOWarningInterruptEnable) || (AUDIO__SAI6->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(AUDIO__SAI6, s_saiHandle[6][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[6][0]) &&
|
|
|
|
((AUDIO__SAI6->TCSR & kSAI_FIFORequestFlag) || (AUDIO__SAI6->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI6->TCSR & kSAI_FIFORequestInterruptEnable) || (AUDIO__SAI6->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[6][0]) &&
|
|
|
|
((AUDIO__SAI6->TCSR & kSAI_FIFOWarningFlag) || (AUDIO__SAI6->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI6->TCSR & kSAI_FIFOWarningInterruptEnable) || (AUDIO__SAI6->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(AUDIO__SAI6, s_saiHandle[6][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* AUDIO__SAI6 */
|
|
|
|
|
|
|
|
#if defined(AUDIO__SAI7)
|
|
|
|
void AUDIO_SAI7_INT_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[7][1]) &&
|
|
|
|
((AUDIO__SAI7->RCSR & kSAI_FIFORequestFlag) || (AUDIO__SAI7->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI7->RCSR & kSAI_FIFORequestInterruptEnable) || (AUDIO__SAI7->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[7][1]) &&
|
|
|
|
((AUDIO__SAI7->RCSR & kSAI_FIFOWarningFlag) || (AUDIO__SAI7->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI7->RCSR & kSAI_FIFOWarningInterruptEnable) || (AUDIO__SAI7->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(AUDIO__SAI7, s_saiHandle[7][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[7][0]) &&
|
|
|
|
((AUDIO__SAI7->TCSR & kSAI_FIFORequestFlag) || (AUDIO__SAI7->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI7->TCSR & kSAI_FIFORequestInterruptEnable) || (AUDIO__SAI7->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[7][0]) &&
|
|
|
|
((AUDIO__SAI7->TCSR & kSAI_FIFOWarningFlag) || (AUDIO__SAI7->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((AUDIO__SAI7->TCSR & kSAI_FIFOWarningInterruptEnable) || (AUDIO__SAI7->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(AUDIO__SAI7, s_saiHandle[7][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* AUDIO__SAI7 */
|
|
|
|
|
|
|
|
#if defined(ADMA__SAI0)
|
|
|
|
void ADMA_SAI0_INT_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][1]) && ((ADMA__SAI0->RCSR & kSAI_FIFORequestFlag) || (ADMA__SAI0->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI0->RCSR & kSAI_FIFORequestInterruptEnable) || (ADMA__SAI0->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][1]) && ((ADMA__SAI0->RCSR & kSAI_FIFOWarningFlag) || (ADMA__SAI0->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI0->RCSR & kSAI_FIFOWarningInterruptEnable) || (ADMA__SAI0->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(ADMA__SAI0, s_saiHandle[1][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][0]) && ((ADMA__SAI0->TCSR & kSAI_FIFORequestFlag) || (ADMA__SAI0->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI0->TCSR & kSAI_FIFORequestInterruptEnable) || (ADMA__SAI0->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][0]) && ((ADMA__SAI0->TCSR & kSAI_FIFOWarningFlag) || (ADMA__SAI0->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI0->TCSR & kSAI_FIFOWarningInterruptEnable) || (ADMA__SAI0->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(ADMA__SAI0, s_saiHandle[1][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* ADMA__SAI0 */
|
|
|
|
|
|
|
|
#if defined(ADMA__SAI1)
|
|
|
|
void ADMA_SAI1_INT_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][1]) && ((ADMA__SAI1->RCSR & kSAI_FIFORequestFlag) || (ADMA__SAI1->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI1->RCSR & kSAI_FIFORequestInterruptEnable) || (ADMA__SAI1->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][1]) && ((ADMA__SAI1->RCSR & kSAI_FIFOWarningFlag) || (ADMA__SAI1->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI1->RCSR & kSAI_FIFOWarningInterruptEnable) || (ADMA__SAI1->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(ADMA__SAI1, s_saiHandle[1][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][0]) && ((ADMA__SAI1->TCSR & kSAI_FIFORequestFlag) || (ADMA__SAI1->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI1->TCSR & kSAI_FIFORequestInterruptEnable) || (ADMA__SAI1->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][0]) && ((ADMA__SAI1->TCSR & kSAI_FIFOWarningFlag) || (ADMA__SAI1->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI1->TCSR & kSAI_FIFOWarningInterruptEnable) || (ADMA__SAI1->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(ADMA__SAI1, s_saiHandle[1][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* ADMA__SAI1 */
|
|
|
|
|
|
|
|
#if defined(ADMA__SAI2)
|
|
|
|
void ADMA_SAI2_INT_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][1]) && ((ADMA__SAI2->RCSR & kSAI_FIFORequestFlag) || (ADMA__SAI2->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI2->RCSR & kSAI_FIFORequestInterruptEnable) || (ADMA__SAI2->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][1]) && ((ADMA__SAI2->RCSR & kSAI_FIFOWarningFlag) || (ADMA__SAI2->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI2->RCSR & kSAI_FIFOWarningInterruptEnable) || (ADMA__SAI2->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(ADMA__SAI2, s_saiHandle[1][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][0]) && ((ADMA__SAI2->TCSR & kSAI_FIFORequestFlag) || (ADMA__SAI2->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI2->TCSR & kSAI_FIFORequestInterruptEnable) || (ADMA__SAI2->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][0]) && ((ADMA__SAI2->TCSR & kSAI_FIFOWarningFlag) || (ADMA__SAI2->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI2->TCSR & kSAI_FIFOWarningInterruptEnable) || (ADMA__SAI2->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(ADMA__SAI2, s_saiHandle[1][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* ADMA__SAI2 */
|
|
|
|
|
|
|
|
#if defined(ADMA__SAI3)
|
|
|
|
void ADMA_SAI3_INT_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][1]) && ((ADMA__SAI3->RCSR & kSAI_FIFORequestFlag) || (ADMA__SAI3->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI3->RCSR & kSAI_FIFORequestInterruptEnable) || (ADMA__SAI3->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][1]) && ((ADMA__SAI3->RCSR & kSAI_FIFOWarningFlag) || (ADMA__SAI3->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI3->RCSR & kSAI_FIFOWarningInterruptEnable) || (ADMA__SAI3->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(ADMA__SAI3, s_saiHandle[1][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][0]) && ((ADMA__SAI3->TCSR & kSAI_FIFORequestFlag) || (ADMA__SAI3->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI3->TCSR & kSAI_FIFORequestInterruptEnable) || (ADMA__SAI3->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][0]) && ((ADMA__SAI3->TCSR & kSAI_FIFOWarningFlag) || (ADMA__SAI3->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI3->TCSR & kSAI_FIFOWarningInterruptEnable) || (ADMA__SAI3->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(ADMA__SAI3, s_saiHandle[1][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* ADMA__SAI3 */
|
|
|
|
|
|
|
|
#if defined(ADMA__SAI4)
|
|
|
|
void ADMA_SAI4_INT_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][1]) && ((ADMA__SAI4->RCSR & kSAI_FIFORequestFlag) || (ADMA__SAI4->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI4->RCSR & kSAI_FIFORequestInterruptEnable) || (ADMA__SAI4->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][1]) && ((ADMA__SAI4->RCSR & kSAI_FIFOWarningFlag) || (ADMA__SAI4->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI4->RCSR & kSAI_FIFOWarningInterruptEnable) || (ADMA__SAI4->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(ADMA__SAI4, s_saiHandle[1][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][0]) && ((ADMA__SAI4->TCSR & kSAI_FIFORequestFlag) || (ADMA__SAI4->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI4->TCSR & kSAI_FIFORequestInterruptEnable) || (ADMA__SAI4->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][0]) && ((ADMA__SAI4->TCSR & kSAI_FIFOWarningFlag) || (ADMA__SAI4->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI4->TCSR & kSAI_FIFOWarningInterruptEnable) || (ADMA__SAI4->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(ADMA__SAI4, s_saiHandle[1][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* ADMA__SAI4 */
|
|
|
|
|
|
|
|
#if defined(ADMA__SAI5)
|
|
|
|
void ADMA_SAI5_INT_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][1]) && ((ADMA__SAI5->RCSR & kSAI_FIFORequestFlag) || (ADMA__SAI5->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI5->RCSR & kSAI_FIFORequestInterruptEnable) || (ADMA__SAI5->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][1]) && ((ADMA__SAI5->RCSR & kSAI_FIFOWarningFlag) || (ADMA__SAI5->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI5->RCSR & kSAI_FIFOWarningInterruptEnable) || (ADMA__SAI5->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(ADMA__SAI5, s_saiHandle[1][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][0]) && ((ADMA__SAI5->TCSR & kSAI_FIFORequestFlag) || (ADMA__SAI5->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI5->TCSR & kSAI_FIFORequestInterruptEnable) || (ADMA__SAI5->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][0]) && ((ADMA__SAI5->TCSR & kSAI_FIFOWarningFlag) || (ADMA__SAI5->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((ADMA__SAI5->TCSR & kSAI_FIFOWarningInterruptEnable) || (ADMA__SAI5->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(ADMA__SAI5, s_saiHandle[1][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* ADMA__SAI5 */
|
|
|
|
|
|
|
|
#if defined(SAI0)
|
|
|
|
void SAI0_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[0][1]) && ((SAI0->RCSR & kSAI_FIFORequestFlag) || (SAI0->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI0->RCSR & kSAI_FIFORequestInterruptEnable) || (SAI0->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[0][1]) && ((SAI0->RCSR & kSAI_FIFOWarningFlag) || (SAI0->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI0->RCSR & kSAI_FIFOWarningInterruptEnable) || (SAI0->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(SAI0, s_saiHandle[0][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[0][0]) && ((SAI0->TCSR & kSAI_FIFORequestFlag) || (SAI0->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI0->TCSR & kSAI_FIFORequestInterruptEnable) || (SAI0->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[0][0]) && ((SAI0->TCSR & kSAI_FIFOWarningFlag) || (SAI0->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI0->TCSR & kSAI_FIFOWarningInterruptEnable) || (SAI0->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(AUDIO__SAI0, s_saiHandle[0][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* SAI0 */
|
|
|
|
|
|
|
|
#if defined(SAI1)
|
|
|
|
void SAI1_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][1]) && ((SAI1->RCSR & kSAI_FIFORequestFlag) || (SAI1->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI1->RCSR & kSAI_FIFORequestInterruptEnable) || (SAI1->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][1]) && ((SAI1->RCSR & kSAI_FIFOWarningFlag) || (SAI1->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI1->RCSR & kSAI_FIFOWarningInterruptEnable) || (SAI1->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(SAI1, s_saiHandle[1][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[1][0]) && ((SAI1->TCSR & kSAI_FIFORequestFlag) || (SAI1->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI1->TCSR & kSAI_FIFORequestInterruptEnable) || (SAI1->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[1][0]) && ((SAI1->TCSR & kSAI_FIFOWarningFlag) || (SAI1->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI1->TCSR & kSAI_FIFOWarningInterruptEnable) || (SAI1->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(SAI1, s_saiHandle[1][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* SAI1 */
|
|
|
|
|
|
|
|
#if defined(SAI2)
|
|
|
|
void SAI2_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[2][1]) && ((SAI2->RCSR & kSAI_FIFORequestFlag) || (SAI2->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI2->RCSR & kSAI_FIFORequestInterruptEnable) || (SAI2->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[2][1]) && ((SAI2->RCSR & kSAI_FIFOWarningFlag) || (SAI2->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI2->RCSR & kSAI_FIFOWarningInterruptEnable) || (SAI2->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(SAI2, s_saiHandle[2][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[2][0]) && ((SAI2->TCSR & kSAI_FIFORequestFlag) || (SAI2->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI2->TCSR & kSAI_FIFORequestInterruptEnable) || (SAI2->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[2][0]) && ((SAI2->TCSR & kSAI_FIFOWarningFlag) || (SAI2->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI2->TCSR & kSAI_FIFOWarningInterruptEnable) || (SAI2->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(SAI2, s_saiHandle[2][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* SAI2 */
|
|
|
|
|
|
|
|
#if defined(SAI3)
|
|
|
|
void SAI3_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[3][1]) && ((SAI3->RCSR & kSAI_FIFORequestFlag) || (SAI3->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI3->RCSR & kSAI_FIFORequestInterruptEnable) || (SAI3->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[3][1]) && ((SAI3->RCSR & kSAI_FIFOWarningFlag) || (SAI3->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI3->RCSR & kSAI_FIFOWarningInterruptEnable) || (SAI3->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(SAI3, s_saiHandle[3][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[3][0]) && ((SAI3->TCSR & kSAI_FIFORequestFlag) || (SAI3->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI3->TCSR & kSAI_FIFORequestInterruptEnable) || (SAI3->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[3][0]) && ((SAI3->TCSR & kSAI_FIFOWarningFlag) || (SAI3->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI3->TCSR & kSAI_FIFOWarningInterruptEnable) || (SAI3->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(SAI3, s_saiHandle[3][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
void SAI3_TX_DriverIRQHandler(void)
|
2018-09-20 23:18:14 +08:00
|
|
|
{
|
|
|
|
assert(s_saiHandle[3][0]);
|
|
|
|
s_saiTxIsr(SAI3, s_saiHandle[3][0]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
void SAI3_RX_DriverIRQHandler(void)
|
2018-09-20 23:18:14 +08:00
|
|
|
{
|
|
|
|
assert(s_saiHandle[3][1]);
|
|
|
|
s_saiRxIsr(SAI3, s_saiHandle[3][1]);
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* SAI3 */
|
|
|
|
|
|
|
|
#if defined(SAI4)
|
|
|
|
void SAI4_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[4][1]) && ((SAI4->RCSR & kSAI_FIFORequestFlag) || (SAI4->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI4->RCSR & kSAI_FIFORequestInterruptEnable) || (SAI4->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[4][1]) && ((SAI4->RCSR & kSAI_FIFOWarningFlag) || (SAI4->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI4->RCSR & kSAI_FIFOWarningInterruptEnable) || (SAI4->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(SAI4, s_saiHandle[4][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[4][0]) && ((SAI4->TCSR & kSAI_FIFORequestFlag) || (SAI4->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI4->TCSR & kSAI_FIFORequestInterruptEnable) || (SAI4->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[4][0]) && ((SAI4->TCSR & kSAI_FIFOWarningFlag) || (SAI4->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI4->TCSR & kSAI_FIFOWarningInterruptEnable) || (SAI4->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(SAI4, s_saiHandle[4][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* SAI4 */
|
|
|
|
|
|
|
|
#if defined(SAI5)
|
|
|
|
void SAI5_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[5][1]) && ((SAI5->RCSR & kSAI_FIFORequestFlag) || (SAI5->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI5->RCSR & kSAI_FIFORequestInterruptEnable) || (SAI5->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[5][1]) && ((SAI5->RCSR & kSAI_FIFOWarningFlag) || (SAI5->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI5->RCSR & kSAI_FIFOWarningInterruptEnable) || (SAI5->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(SAI5, s_saiHandle[5][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[5][0]) && ((SAI5->TCSR & kSAI_FIFORequestFlag) || (SAI5->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI5->TCSR & kSAI_FIFORequestInterruptEnable) || (SAI5->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[5][0]) && ((SAI5->TCSR & kSAI_FIFOWarningFlag) || (SAI5->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI5->TCSR & kSAI_FIFOWarningInterruptEnable) || (SAI5->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(SAI5, s_saiHandle[5][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* SAI5 */
|
|
|
|
|
|
|
|
#if defined(SAI6)
|
|
|
|
void SAI6_DriverIRQHandler(void)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[6][1]) && ((SAI6->RCSR & kSAI_FIFORequestFlag) || (SAI6->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI6->RCSR & kSAI_FIFORequestInterruptEnable) || (SAI6->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[6][1]) && ((SAI6->RCSR & kSAI_FIFOWarningFlag) || (SAI6->RCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI6->RCSR & kSAI_FIFOWarningInterruptEnable) || (SAI6->RCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiRxIsr(SAI6, s_saiHandle[6][1]);
|
|
|
|
}
|
|
|
|
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
|
|
|
|
if ((s_saiHandle[6][0]) && ((SAI6->TCSR & kSAI_FIFORequestFlag) || (SAI6->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI6->TCSR & kSAI_FIFORequestInterruptEnable) || (SAI6->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#else
|
|
|
|
if ((s_saiHandle[6][0]) && ((SAI6->TCSR & kSAI_FIFOWarningFlag) || (SAI6->TCSR & kSAI_FIFOErrorFlag)) &&
|
|
|
|
((SAI6->TCSR & kSAI_FIFOWarningInterruptEnable) || (SAI6->TCSR & kSAI_FIFOErrorInterruptEnable)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_saiTxIsr(SAI6, s_saiHandle[6][0]);
|
|
|
|
}
|
|
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
|
|
exception return operation might vector to incorrect interrupt */
|
|
|
|
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
|
|
|
__DSB();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* SAI6 */
|