It appears that fsl_sai_edma.c uses the static s_edmaPrivateHandle to maintain callbacks for EDMA, but it reserves the 0 index for TX and 1 index for RX, ignoring SAI modules with more than one tx/rx channel (example: the K24 I am using has 2 TX and 2 RX in one SAI module).
I used the FSL_FEATURE_SAI_CHANNEL_COUNT feature indicator to amend fsl_sai_edma (see attached solution)
Original Attachment has been moved to: fsl_sai_edma.c.zip
Original Attachment has been moved to: fsl_sai_edma.h.zip
Hi!
I'm trying to make this work with 2 TX channels but am having a hard time. I've replaced the fsl driver files with the ones attached to this thread and created 2 separate handlers for each TX channel but it still doesn't work.
The closest thing I got to it working shown the result above (should have been a 1 kHz sine wave for each of the channels). I figured out that its only the first FIFO block is getting through, but further requests are being ignored until a new DMA transfer is submitted. I can easily make it work with one channel but ultimately the point is for these 2 channels to be working independently.
If you have any ideas about what may be happening, please let me know :smileyhappy:.
Thanks for your time!
Henrique
Additionally, in SAI_RxSetFormat, the active channels are zeroed out every time it's called:
base->RCR3 &= ~I2S_RCR3_RCE_MASK;
This makes it impossible to run 2 channels. With my above fix to fsl_sai_edma, as well as deleting this line zeroing RCR3, I have 2 RX channels working simultaneously with EDMA now.
Hi, Jacob,
Regarding your channel setting, first of all, if you use two channel for example SAI_RX_DATA[1:0], you should set the RCM bit as 2b'11.
With the follwoing code:
base->RCR3 &= ~I2S_RCR3_RCE_MASK;
base->RCR3 |= I2S_RCR3_RCE(1U << format->channel);
the SDK set up the receiver channels. The first line clear RCM bits so that the second line can set the bits. But the second line: base->RCR3 |= I2S_RCR3_RCE(1U << format->channel); can set up one channel instead of two, i think it is a bug of the sai driver.
If you use two channel of SAI receiver, as you did, you can modify the code as:
base->RCR3 &= ~I2S_RCR3_RCE_MASK;
//base->RCR3 |= I2S_RCR3_RCE(1U << format->channel);
base->RCR3 |= I2S_RCR3_RCE_MASK;
For transmitter, it is the same.
Hope it can help you.
BR
XiangJun Rong
void SAI_RxSetFormat(I2S_Type *base,
sai_transfer_format_t *format,
uint32_t mclkSourceClockHz,
uint32_t bclkSourceClockHz)
{
uint32_t 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;
base->RCR2 |= I2S_RCR2_DIV((bclkSourceClockHz / bclk) / 2U - 1U);
}
/* Set bitWidth */
if (format->protocol == kSAI_BusRightJustified)
{
base->RCR5 = I2S_RCR5_WNW(31U) | I2S_RCR5_W0W(31U) | I2S_RCR5_FBT(31U);
}
else
{
base->RCR5 = I2S_RCR5_WNW(31U) | I2S_RCR5_W0W(31U) | I2S_RCR5_FBT(format->bitWidth - 1);
}
/* Set mono or stereo */
base->RMR = (uint32_t)format->stereo;
/* Set data channel */
base->RCR3 &= ~I2S_RCR3_RCE_MASK;
base->RCR3 |= I2S_RCR3_RCE(1U << format->channel);
#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 */
}