nxp-mcuxpresso / mcux-sdk

MCUXpresso SDK
BSD 3-Clause "New" or "Revised" License
301 stars 136 forks source link

First slot / channel missing in FIFO for I2S in TDM/DSP mode (16-channels / 32-bit / 48 kHz) #190

Closed carlocaione closed 2 months ago

carlocaione commented 2 months ago

Using the EVK MIMXRT685 as I2S SLAVE configured as:

Let's take as example the transmission as depicted here:

Screenshot 2024-04-09 at 11 38 53

I2S is configured in interrupt mode, as follows:

static void RxCallback(I2S_Type *base, i2s_handle_t *handle, status_t completionStatus, void *userData)
{
    i2s_transfer_t *transfer = (i2s_transfer_t *)userData;
    I2S_RxTransferNonBlocking(base, handle, *transfer);
}

void I2S_Setup(void)
{
    I2S_RxGetDefaultConfig(&s_RxConfig);

    s_RxConfig.masterSlave = kI2S_MasterSlaveNormalSlave; /* Normal Slave */
    s_RxConfig.mode = kI2S_ModeDspWsShort;                /* DSP mode, WS having one clock long pulse */
    s_RxConfig.leftJust = true;                           /* Left Justified */
    s_RxConfig.divider = 1;                               /* As slave, divider need to set to 1 according to the spec. */
    s_RxConfig.oneChannel = true;                         /* I2S data for this channel pair is treated as a single channel */
    s_RxConfig.dataLength = 32;
    s_RxConfig.frameLength = 32;

    I2S_RxInit(I2S_RX, &s_RxConfig);

    s_RxTransfer.data = &s_Buffer[0];
    s_RxTransfer.dataSize = sizeof(s_Buffer);

    I2S_RxTransferCreateHandle(I2S_RX, &s_RxHandle, RxCallback, (void *)&s_RxTransfer);
    I2S_RxTransferNonBlocking(I2S_RX, &s_RxHandle, s_RxTransfer);
}

[!WARNING] The problem is that the buffer is consistently missing the data of the first channel 0x000001FF when starting the capture. If I look at the content of FIFORD on the very first interrupt, the content is 0x00000200 instead of the data of the first channel.

frankybkimz commented 2 months ago

Hi Carlo,

Would you email me at frank.kim@nxp.com for this issue follow-up?

Regards, Frank

mcuxsusan commented 2 months ago

Hi @carlocaione, thanks for reporting the issues, I have also assigned developer to check the issues internally. Feedback may be delayed, appreciate for your patience.

carlocaione commented 2 months ago

This is due to a misconfiguration of the I2S instance on my side.

To read 16-channels we need at least I2S instances (for example I2S4 and I2S5), configured as follows:

s_RxConfig.masterSlave = kI2S_MasterSlaveNormalSlave;
s_RxConfig.mode = kI2S_ModeDspWsShort;
s_RxConfig.dataLength = 32;
s_RxConfig.frameLength = 32 * 16U;
s_RxConfig.position = 0;

I2S_RxInit(I2S5, &s_RxConfig);
I2S_EnableSecondaryChannel(I2S5, kI2S_SecondaryChannel1, false, (64 * 1));
I2S_EnableSecondaryChannel(I2S5, kI2S_SecondaryChannel2, false, (64 * 2));
I2S_EnableSecondaryChannel(I2S5, kI2S_SecondaryChannel3, false, (64 * 3));

s_RxConfig.position = 256;

I2S_RxInit(I2S4, &s_RxConfig);
I2S_EnableSecondaryChannel(I2S4, kI2S_SecondaryChannel1, false, 256 + (64 * 1));
I2S_EnableSecondaryChannel(I2S4, kI2S_SecondaryChannel2, false, 256 + (64 * 2));
I2S_EnableSecondaryChannel(I2S4, kI2S_SecondaryChannel3, false, 256 + (64 * 3));

To be perfectly honest the user manual is not crystal clear about how and when to use multiple instances and channels pairs. Thank you @frankybkimz for your support.

Closing this down.