2024-02-02 03:14 PM
I've got the I2S working with DMA as slave receiver, works great, bit perfectly fills receiving buffer,
until I restart the master, or introduce noise to I2S bus, then it just loses it, fills buffer with nonsense after that.
It's not able to resync to same valid signal that was working previously.
Sure I expect to lose some frames, life happens to input signal, it should be able to resync.
So how can I make it resync?
I know that errata says I have to wait for WS high before enabling DMA, but what about after corruption?
I don't even know when the signal is invalid since there is no checksum,
I can't ask the user restart the device until it starts working..
Some audiophile DACs take I2S signal over cable, so anything could happen to it.
hi2s2.Instance = SPI2;
hi2s2.Init.Mode = I2S_MODE_SLAVE_RX;
hi2s2.Init.Standard = I2S_STANDARD_PHILIPS;
hi2s2.Init.DataFormat = I2S_DATAFORMAT_32B;
hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE;
hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_44K;
hi2s2.Init.CPOL = I2S_CPOL_LOW; /* idle low clock */
hi2s2.Init.ClockSource = I2S_CLOCK_EXTERNAL; /* not PLL */
hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE;
hdma_spi2_rx.Instance = DMA1_Stream3;
hdma_spi2_rx.Init.Channel = DMA_CHANNEL_0;
hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; /* 16 even for 32bit */
hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_spi2_rx.Init.Mode = DMA_CIRCULAR;
hdma_spi2_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
ASSERT(HAL_DMA_Init(&hdma_spi2_rx) == HAL_OK);
__HAL_LINKDMA(&hi2s2, hdmarx, hdma_spi2_rx);
/* DMA1_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
ASSERT(HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (tUI16 *)dmaTxBuf, (tUI16 *)dmaRxBuf, DMA_BUFF_LEN) == HAL_OK);
Solved! Go to Solution.
2024-02-04 03:10 AM
As I've said, you have to choose an STM32 which has this problem fixed, i.e. one which does not have the "In I2S Slave mode, the WS level must be set by the external master when enabling the I2S" erratum - e.g. the 'F446.
JW
2024-02-03 01:20 AM
You did not tell us which STM32 are you using, but it is what it is, as described in errata, in the older 'F4 I2S does not synchronize on the WS edge. Use some of the newer 'F4 or other STM32, which have this fixed, e.g. the 'F446. Or use some newer 'F4 which have SAI.
JW
2024-02-03 03:58 AM
sorry, F401.
So how do I make it robust/field ready?
2024-02-04 03:10 AM
As I've said, you have to choose an STM32 which has this problem fixed, i.e. one which does not have the "In I2S Slave mode, the WS level must be set by the external master when enabling the I2S" erratum - e.g. the 'F446.
JW
2024-02-04 03:56 AM - edited 2024-02-04 03:57 AM
>Some audiophile DACs take I2S signal over cable, so anything could happen to it.
No - if there is "noise" , the I2S will not work reliably . My experience, at least.
I2S is intended as a constant stream of data, without any interference or interruption.
So you cannot expect any tolerance to this.
As Jan explained, some (newer) STM cpu can synchronize on the WS edge and so are more tolerant to spike or noise; but still any wrong clock will generate a strong "tick" or "plopp" noise in the audio - nobody would accept this as a good audio signal.
I worked with I2S audio on F411, H743 and now H563 , no problems here. But "clean" signals , damping series resistors on all lines and max. 5 cm distance... :)