Bug report: fsl_sai_edma ignores multichannel SAI module

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Bug report: fsl_sai_edma ignores multichannel SAI module

2,362 Views
jacobjennings
Contributor III

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

Labels (1)
Tags (3)
3 Replies

1,781 Views
henrique1
Contributor III

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.Capture.PNG

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

0 Kudos

1,781 Views
jacobjennings
Contributor III

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.

1,781 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

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  */
}