Restarting an I2S transfer changes alignement in DMA RX buffer

Report here problems in any of ChibiOS components. This forum is NOT for support.
lerela
Posts: 11
Joined: Tue Mar 21, 2017 7:08 pm
Been thanked: 2 times

Restarting an I2S transfer changes alignement in DMA RX buffer

Post by lerela »

Hello,

I am getting data from a 24 bits I2S microphone on an STM32F417. As per the reference manual, I2S DMA access is done in half words.
Therefore, when I iterate over the RX buffer, i2s_rx_buf[0] is 0x8EAA and i2s_rx_buf[1] is 0x33XX if the microphone sent the word 0x8EAA33. So far so good.

However, whenever I stop then start again the I2S, i2s_rx_buf[0] now is 0x33XX and i2s_rx_buf[1] is 0x9EBB (ie. the MSB of the next sample). It looks like the transfer is just shifted by 2 bytes, which screws my logic.

I've investigated thoroughly the issue but I can't make sense of it as calling i2sStop() and i2sStart() should completely reset the DMA buffer.
I tried to add the following to dmaStreamDisable as this is what ST seems to recommend:

Code: Select all

  while (((dmastp)->channel->CCR & STM32_DMA_CR_EN) != 0)
    ;


but it did not make a difference. I don't understand where is this coming from or how to fix it. Any idea?

Code follows:

Code: Select all

#define I2S_BUFFER_SIZE                100
#define I2S_DIV                                     20

static uint16_t i2s_rx_buf[I2S_BUFFER_SIZE * 2];

static void i2scallback(I2SDriver *i2sp, size_t offset, size_t n);

static const I2SConfig i2scfg = {
    NULL,
    i2s_rx_buf,
    I2S_BUFFER_SIZE,
    i2scallback,
    SPI_I2SCFGR_DATLEN_0,
    SPI_I2SPR_I2SDIV & I2S_DIV
};

/*
 * Init the I2S module and start it
 */
static void audio_start( void) {

    /*
    * Starting and configuring the I2S driver 2.
    */
    i2sStart(&I2SD2, &i2scfg);

    /*
    * Starting continuous I2S transfer.
    */
    i2sStartExchange(&I2SD2);

    /*
     * Enable 1.8V level translator.
     */
    power_18v_mic_enable();

}


/*
 * Stop audio processing
 */
static void audio_stop( void) {

    /* Stop the I2S RX */
    i2sStopExchange(&I2SD2);

    i2sStop(&I2SD2);

    /* Disable level translator */
    power_18v_mic_disable();

}


Thanks!
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Restarting an I2S transfer changes alignement in DMA RX buffer

Post by Giovanni »

Hi,

Not sure, is it possible you need to reset the microphone too? the driver should put in memory just what it got in the same order it got it.

Giovanni
lerela
Posts: 11
Joined: Tue Mar 21, 2017 7:08 pm
Been thanked: 2 times

Re: Restarting an I2S transfer changes alignement in DMA RX buffer

Post by lerela »

Thanks for your answer. The microphone is getting a power reset before it's re-enabled, hence my hypothesis that it might be linked to the driver/the DMA, but it is hard to investigate.
The SPI SR register is 0 before restarting the I2S so everything looks good, yet the buffer begins with the least significant bytes once it's restarted. Quite strange.
lerela
Posts: 11
Joined: Tue Mar 21, 2017 7:08 pm
Been thanked: 2 times

Re: Restarting an I2S transfer changes alignement in DMA RX buffer

Post by lerela »

As a workaround, I found that not stopping the I2S driver between stop() and start() fixes the issue. I'll just stop and start the exchange instead as of now.
tsichevski
Posts: 35
Joined: Fri Feb 09, 2018 12:44 am
Has thanked: 2 times
Been thanked: 5 times

Re: Restarting an I2S transfer changes alignement in DMA RX buffer

Post by tsichevski »

Bumped exactly into the same problem. No other workaround but never stopping the I2S :( Has anybody found the solution yet?
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Restarting an I2S transfer changes alignement in DMA RX buffer

Post by Giovanni »

I haven't looked into it, moving this topic in bug reports.

So, if you don't stop the exchange, stop the driver, restart the driver and start the exchange again makes it work?

Giovanni
tsichevski
Posts: 35
Joined: Fri Feb 09, 2018 12:44 am
Has thanked: 2 times
Been thanked: 5 times

Re: Restarting an I2S transfer changes alignement in DMA RX buffer

Post by tsichevski »

No. This are the related code fragments. The mikeInit() initializes the structures once. The mikeStart() starts the transfer, the mikeStop() stops it.
The sequence:

Code: Select all

<reset the processor>
mikeInit();

// Capture the first record
mikeStart();
... collect some data, synchronization is Ok
mikeStop();
...
// Capture the second record
mikeStart();
... collect some data, synchronization is now random
mikeStop();
...


The code:

Code: Select all

static I2SConfig cs5343I2SConfig;

void mikeInit() {
  memset(&cs5343I2SConfig, 0, sizeof(cs5343I2SConfig));

  cs5343I2SConfig.tx_buffer = NULL;
  cs5343I2SConfig.rx_buffer = dmaOutputBuffer;
  cs5343I2SConfig.size = sizeof(dmaOutputBuffer) / sizeof(uint32_t);
  cs5343I2SConfig.end_cb = cs5343Cb;

  cs5343I2SConfig.i2scfgr = // I2S_MODE_MASTER_RX | I2S_STANDARD_PHILIPS  | I2S_CPOL_LOW  | I2S_24BITSAMPLE | I2S_32BITCHANNEL;
      0x0300U | 0x0000U | 0x0000U | 0x0002U | 0x0001U;

  cs5343I2SConfig.i2spr = (SPI_I2SPR_I2SDIV & CS5343_I2SDIV)
    | (SPI_I2SPR_ODD & (CS5343_I2SODD << I2SPR_I2SODD_SHIFT))
    | SPI_I2SPR_MCKOE;
}

void mikeStart() {
  i2sStart(&CS5343_I2S_DRIVER, &cs5343I2SConfig);
  i2sStartExchange(&CS5343_I2S_DRIVER);
}

void mikeStop(void) {
  i2sStopExchange(&CS5343_I2S_DRIVER);
  i2sStop(&CS5343_I2S_DRIVER);
}

User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Restarting an I2S transfer changes alignement in DMA RX buffer

Post by Giovanni »

So the problem happens after calling i2sStop() right?

Giovanni
tsichevski
Posts: 35
Joined: Fri Feb 09, 2018 12:44 am
Has thanked: 2 times
Been thanked: 5 times

Re: Restarting an I2S transfer changes alignement in DMA RX buffer

Post by tsichevski »

Yes. And it remains even if you just use i2sStopExchange/i2sStartExchange.
tsichevski
Posts: 35
Joined: Fri Feb 09, 2018 12:44 am
Has thanked: 2 times
Been thanked: 5 times

Re: Restarting an I2S transfer changes alignement in DMA RX buffer

Post by tsichevski »

BTW it seems that ST HAL users see the same problem: https://community.st.com/message/176212 ... hing-issue
Post Reply