nxp-mcuxpresso/mcux-sdk

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

Closed this issue · 3 comments

Using the EVK MIMXRT685 as I2S SLAVE configured as:

  • TDM / DSP mode A (mono)
  • 48kHz (SCK at ~25MHz)
  • 16 slots (channels) per frame
  • 512 SCK per frame
  • 32 SCK per slot
  • 32 bits of audio data per slot, left aligned
  • WS pulsed for one SCK time
  • Data sampled on WS rising edge

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

Screenshot 2024-04-09 at 11 38 53
  • 0x000001FF on channel 1
  • 0x00000200 on channel 2
  • 0x000003FF on channel 3
  • ...
  • 0x00001000 on channel 16

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.

Hi Carlo,

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

Regards,
Frank

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.

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.