Page 2 of 2

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

Posted: Fri Jul 27, 2018 3:01 pm
by Giovanni
Interesting, that is on the F7 which has a FIFO but flushing the data register after stopping the master clock and DMAs could be a solution. Another option would be to reset the SPI peripheral on i2sStart().

Giovanni

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

Posted: Fri Oct 26, 2018 3:08 pm
by tsichevski
I've managed to recover from this problem. Before starting DMA, I explicitly fetch a few half-words from the I2S data register, and find where the sample start sequence begins. Unfortunately, this solution is not universal: is works for my particular codec chip :(

Regards,
Vladimir

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

Posted: Sun Nov 10, 2019 10:25 am
by Giovanni
bump

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

Posted: Fri Nov 29, 2019 10:57 pm
by jpp
Hello,

This is my first post in this forum :)

I think I just ran into this same problem though I did not fully characterized the issue on an STM32F429 (discovery board) and in RX mode.

I found those two links that seem related:
https://community.st.com/s/question/0D5 ... hing-issue
https://community.st.com/s/question/0D5 ... er-restart

So it seems that the issue comes from the fact that when I2S is turned off some data may still arrive into the DR register and those data will get as first data for next reception and shift all the data by 1 channel.

Also I found that ST dedicated a paragraph on "Disabling the SPI" because it is probably a bit tricky and I suppose it applies to the I2S even more.

The interresting sequence they describe is as follow:
- wait for RXNE=1 (this will be the second to last data receive)
- disable the SPI : SPE=0
- wait for RXNE=1 (this is the last)

And this is how I changed the stop_exchange routine:

Code: Select all

void i2s_lld_stop_exchange(I2SDriver *i2sp) {

  /* Stop TX DMA, if enabled.*/
  if (NULL != i2sp->dmatx) {
    dmaStreamDisable(i2sp->dmatx);

    /* From the RM: To switch off the I2S, by clearing I2SE, it is mandatory
       to wait for TXE = 1 and BSY = 0.*/
    while ((i2sp->spi->SR & (SPI_SR_TXE | SPI_SR_BSY)) != SPI_SR_TXE)
      ;
  }

  /* Stop RX DMA, if enabled.*/
  if (NULL != i2sp->dmarx) {
    dmaStreamDisable(i2sp->dmarx);
    while ((i2sp->spi->SR & SPI_SR_RXNE) != SPI_SR_RXNE);
  }

  /* Stop SPI/I2S peripheral.*/
  i2sp->spi->I2SCFGR &= ~SPI_I2SCFGR_I2SE;

  /* Drain the last DATA to clean for next exchange */
  if (NULL != i2sp->dmarx) {
    while (i2sp->spi->SR & SPI_SR_RXNE)
      i2sp->spi->DR;
  }
}


What I believe it could happen before is that:
- Disable SPI : SPE=0
- Disable DMA before that last data arrive
- The last data may arrive but nobody to discard it and let the pipeline clean for next exchange

What I believe it fixes the issue:
- Disable DMA
- Wait for last data (so that we are sure it is here and perhaps preventing other to arrive as there is no buffer)
- Disable SPI : SPE=0
- Drain the last data

This seems to work for me.
Again I don't fully understand what's happening only suppositions.

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

Posted: Sat Nov 30, 2019 5:59 am
by Giovanni
Hi,

Thanks for experimenting with this, I need to look at that paragraph.

The fix makes sense, I wonder if it should go in the SPI driver too when stopping a continuous transfer.

Giovanni

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

Posted: Sat Dec 07, 2019 9:54 am
by Giovanni
Hi,

I committed the change in trunk, just removed an extra condition, could you check everything is OK?

Code: Select all

void i2s_lld_stop_exchange(I2SDriver *i2sp) {

  /* Stop TX DMA, if enabled.*/
  if (NULL != i2sp->dmatx) {
    dmaStreamDisable(i2sp->dmatx);

    /* From the RM: To switch off the I2S, by clearing I2SE, it is mandatory
       to wait for TXE = 1 and BSY = 0.*/
    while ((i2sp->spi->SR & (SPI_SR_TXE | SPI_SR_BSY)) != SPI_SR_TXE)
      ;

    /* Stop SPI/I2S peripheral.*/
    i2sp->spi->I2SCFGR &= ~SPI_I2SCFGR_I2SE;
  }

  /* Stop RX DMA, if enabled then draining the RX DR.*/
  if (NULL != i2sp->dmarx) {
    dmaStreamDisable(i2sp->dmarx);

    /* Waiting for some data to be present in RX DR.*/
    while ((i2sp->spi->SR & SPI_SR_RXNE) != SPI_SR_RXNE)
      ;

    /* Stop SPI/I2S peripheral.*/
    i2sp->spi->I2SCFGR &= ~SPI_I2SCFGR_I2SE;

    /* Purging data in DR.*/
    while ((i2sp->spi->SR & SPI_SR_RXNE) != 0)
      (void) i2sp->spi->DR;
  }
}


Giovanni

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

Posted: Sat Jan 11, 2020 10:30 am
by Giovanni
Any comment on this?

Giovanni

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

Posted: Mon Feb 24, 2020 11:04 pm
by jpp
Hello Giovanni I am sorry I completely forgot about this and did not see the notifications...

I cannot try to run your code immediately but I have been running my version of the change since my first post and it is working when I can very easily reproduce the old issue.

BUT I am only using 1 I2S driver in RX and 1 I2S driver in TX

Carefully reading you code comparing to my patch makes me think that it is absolutely the same IF the I2S driver is exclusively either in RX or TX mode.

I believe that if the driver could operate in both TX and RX mode this would not work, but double checking the Ref Manual there is no RX+TX (full duplex) mode in I2S. Well ... there is but it is done via a I2S_ext peripherals which I think are kind of "virtual". I don't know what is your intention but I think the current version of the driver is only supporting Half-Duplex (only RX or TX) as you don't seem to play with the I2S_ext peripheral.
So if the driver is meant only to operate either the RX or the TX mode then your patch looks fine to me.

Again really sorry for the delay here...
JP:

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

Posted: Thu Feb 27, 2020 6:17 pm
by Giovanni
Hi,

Don't worry. Let me know if you have a chance to test it.

The driver does not support full duplex mode so it should be fine.

Giovanni

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

Posted: Sat Feb 13, 2021 10:33 am
by Giovanni
Any news on this?

Giovanni