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!