cancel
Showing results for 
Search instead for 
Did you mean: 

I2S bits rotated

max_verem
Associate

Hi

I am working on project that receive several I2S streams from MEMS microphones. I found that "audio level" from second microphones pair had higher level then from other. After some analysis and SD lines swapping i found that I2S data received by second I2S is multiplied by 2 factor (binary shifted).

I built minimal system with on STM32F411CEUx (Black Pill board) to reproduce it.

I configured:
* I2S1: Half-Duplex Master Receive
* I2S2: Half-Duplex Slave Receive
* I2S4: Half-Duplex Slave Transmit

All I2S has same other configuration values:
* I2S Philips
* 32 Bits Data on 32 Bits Frame
* 16 KHz

GPIO pins connected that way:

/*

I2S1 GPIO I2S2 GPIO I2S4 GPIO
============== =============== ================
PA4 -> I2S1_WS <=> PB10 -> I2S2_CK <=> PA1  -> I2S4_SD
PA5 -> I2S1_CK <=> PB15 -> I2S2_SD <=> PB12 -> I2S4_WS
PA7 -> I2S1_SD <=> PB9  -> I2S2_WS <=> PB13 -> I2S4_CK

*/

I also set a maximal speed for all I2S pins:

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

 

I use STM32Cube FW_F4 V1.28.1

All I2S configured with Circular DMA

I2S4 used to transmit data:

static const uint32_t demo[4] = {
	0xBADC0FFE,
	0xE0DDF00D,
	0xBADC0FFE,
	0xE0DDF00D
}

[...]

HAL_I2S_Transmit_DMA(&hi2s4, (uint16_t*)demo, 2);

I2S1 and I2S2 used to receive data:

static int32_t i2s_buffer_1[4 * I2S_DMA_BUF_LENGTH] __attribute__((__aligned__(16))) = {0};
static int32_t i2s_buffer_2[4 * I2S_DMA_BUF_LENGTH] __attribute__((__aligned__(16))) = {0};

[..]

  HAL_I2S_RegisterCallback(&hi2s1, HAL_I2S_RX_HALF_COMPLETE_CB_ID, i2s_dma_cb_half_1);
  HAL_I2S_RegisterCallback(&hi2s1, HAL_I2S_RX_COMPLETE_CB_ID, i2s_dma_cb_full_1);
  HAL_I2S_RegisterCallback(&hi2s2, HAL_I2S_RX_HALF_COMPLETE_CB_ID, i2s_dma_cb_half_2);
  HAL_I2S_RegisterCallback(&hi2s2, HAL_I2S_RX_COMPLETE_CB_ID, i2s_dma_cb_full_2);
  HAL_I2S_Receive_DMA(&hi2s1, (uint16_t*)i2s_buffer_1, I2S_DMA_BUF_LENGTH);
  HAL_I2S_Receive_DMA(&hi2s2, (uint16_t*)i2s_buffer_2, I2S_DMA_BUF_LENGTH);

 

In ideal case i expect that i2s buffers and source buffers should be the same, but it not.

Datas in i2s receiving buffers shifted (rotated):

/*
demo[0]          0xbadc0ffe |          101110101101110000001111 11111110
i2s_buffer_1[0]  0xfebadd0f | 11111110 101110101101110100001111
i2s_buffer_2[0]  0xebadd0ff |     1110 101110101101110100001111 1111
                                                      ^

demo[1]          0xe0ddf00d |          111000001101110111110000 00001101
i2s_buffer_1[1]  0x0de0dcf0 | 00001101 111000001101110011110000
i2s_buffer_2[1]  0xde0dcf00 |     1101 111000001101110011110000 0000
*/

I already checked:
- I2S weird bit shift problem : https://community.st.com/t5/stm32-mcus-products/i2s-weird-bit-shift-problem/td-p/757051/page/2
- STM32F42xx SPI errata handling with 70pF load : https://community.st.com/t5/stm32-mcus-products/stm32f42xx-spi-errata-handling-with-70pf-load/td-p/243053
https://www.st.com/resource/en/errata_sheet/es0287-stm32f411xcxe-device-errata-stmicroelectronics.pdf

But none of solutions works.

I also did a check with osciliscope and found no suspected signal deviations

Test output pattern 0xAAAAAAAA (SD and CK lines)
i2s_SD-0xAAAAAAAA_CK.png

 

Test output pattern 0xAAAAAAAA (SD and WS lines)

 

i2s_SD-0xAAAAAAAA_WS-fall.png

 

Test output pattern 0xAAAAAAAA (SD and WS lines)

i2s_SD-0xAAAAAAAA_WS-rise.png

 

WS fall and CK:

i2s_WS-fall_CK.png

 

WS rise and CK:

i2s_WS-rise_CK.png

 

It looks like delayed WS latch

Anybody seen that before?

P.S.

APB1 periferal clock 48MHz
APB2 periferal clock 96MHz / 48MHz

Clock configuration: 
i2s_clock_configuration_.png

4 REPLIES 4

Do you observe the In I2S Slave mode, the WS level must be set by the external master when enabling the I2S erratum?

I don't know if there's any provision in Cube/HAL for this erratum, but I doubt there is. I don't use Cube.

JW

AScha.3
Chief III

Hi,

>Anybody seen that before?

Maybe...

I had DAC connected on I2S , on F411 ; as long as i was running it with 16b data, 2ch , all fine.

But then going to 32b sample size, i never got clean signal - or lets say reliable; something looked "puzzled" in the data, like data shifted or hi-lo nibble puzzled; then after some power cycles it was suddenly ok - so my settings correct, but next power cycle again wrong. So i decided: useless, with 32b data words.

And switched to H743 , on SAI with I2S mode, all perfect, also with 32b data.

 

So on F411 - try to use 16b words, at double frequency, should be same with pd micro signals.

If you feel a post has answered your question, please click "Accept as Solution".

@waclawek.jan wrote:

Do you observe the In I2S Slave mode, the WS level must be set by the external master when enabling the I2S erratum?

i seen that:

errata_2.11.6.png

but i have no idea how to implement it...

 

>> So on F411 - try to use 16b words, at double frequency, should be same with pd micro signals.

i seen it with 16 bits samples.

>> And switched to H743 , on SAI with I2S mode, all perfect, also with 32b data.

thanks for hint