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: 1 time

Restarting an I2S transfer changes alignement in DMA RX buffer

Postby lerela » Thu Jul 20, 2017 5:00 pm

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: 11786
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 503 times
Been thanked: 427 times
Contact:

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

Postby Giovanni » Thu Jul 20, 2017 5:36 pm

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: 1 time

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

Postby lerela » Fri Jul 21, 2017 8:39 am

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: 1 time

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

Postby lerela » Fri Jul 21, 2017 9:32 am

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

Postby tsichevski » Sat Jun 09, 2018 8:11 pm

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: 11786
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 503 times
Been thanked: 427 times
Contact:

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

Postby Giovanni » Sat Jun 09, 2018 8:35 pm

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

Postby tsichevski » Sun Jun 10, 2018 1:01 pm

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: 11786
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 503 times
Been thanked: 427 times
Contact:

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

Postby Giovanni » Sun Jun 10, 2018 5:38 pm

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

Postby tsichevski » Mon Jun 11, 2018 6:03 pm

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

Postby tsichevski » Mon Jun 11, 2018 6:06 pm

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


Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 1 guest