cancel
Showing results for 
Search instead for 
Did you mean: 

I2S weird bit shift problem

baator025
Associate II

Hi,

I'm getting a problem in my project, where I tried to create a loopback between I2S3 and I2S4 on STM32F411 Disco.
It seems that only the least significant bit of 16-bit packets is somehow shifted to the next packet. The rest of the transmission is intact.
For example - I send {0x0001 0x0000 0x0000 0x0000} and I get {0x0000 0x0000 0x0001 0x0000}, but if I send {0xFFFE 0x0000 0x0000 0x0000}, I will receive {0x0000 0x0000 0x0000 0xFFFE}.
Packets order reversal is expected, but during analysis pay attention what happens with the least significant bit. Another example: transmitting {0x8001 0x0000 0x0000 0x0000} will end up with receiving {0x0000 0x0000 0x0001 0x8000} (I'd expect {0x0000 0x0000 0x000 0x8001}).
What is also interesting, readouts from logic analyzer seem to be correct.

I am not using HAL, I am configuring registers manually. I2S4 is configured as master receiver and uses DMA. I2S3 is configured as slave transmitter and I tried "feeding" it both with polling and interrupts. I always fill transmitter's buffer before initializing receiver with the first packet.

Since I've written my own abstraction layer, attaching code here may be difficult. Therefore I am uploading the link to repo: https://github.com/baator025/I2S_loopback . The most recent branch is rtos_integration.

I'd really appreciate help, because I've run out of ideas long ago.

Thanks,
Bartosz

30 REPLIES 30

Thanks, that did it! No more bit shift.

First I noticed that my implementation used APB1 for first I2S channel and APB2 for second one. There would be nothing wrong with that aside from that I set two different prescalers. After I fixed it, I noticed improvement, but some of the bits were still shifted.
After that I configured OSPEEDR and it seems that it fixed the problem.

Thanks again for the help. I'll remember to look for erratas, when I start working with a new MCU.

I found another solution to the problem, but thanks anyway. :)

You're not wrong about PDMs, it's different protocol/interface. However, I2S can be used for capturing the data. 
Take a look at this document: AN5027 

Regarding PDM2PCM lib - I described my problem here . Long story short- after calling PDM_Filter_setConfig, MCU goes into hard fault. I'd appreciate if you could take a look at this.

Cool, great - well done!

Let me look into your PDM Mic issue (even I do not use it as same MCU).
Have you debugged why HardFault_Handler was called?

BTW: I am not sure if a SPI as I2S (which works), can be used for PDM.
I assume: PDM works only with a SAI interface (configured for PDM). Or: you use the FSDM interface.

Let me look...

> I assume: PDM works only with a SAI interface (configured for PDM).

Why?

PDM is just a clocked stream of bits. SPI is just a clocked stream of bits, either; and so is basically I2S (that's why it's one interface). You need to filter it, but SAI won't do that either; and while HW filter is more comfortable/efficient, SW is viable in many cases, too.

SAI which supports PDM has one advantage, though, it supports stereo PDM in the both-edges mode. But that can be worked around with SPI/I2S, one timer, one extra pin, and a bit of thinking, too. And not all SAI support that mode, and not all STM32 have SAI at all.

JW

You are right, sorry: yes, with SPI as I2S it should be possible to connect a PDM MIC (but just in mono mode):

chrome-extension://efaihttps://www.st.com/resource/en/application_note/an5027-interfacing-pdm-digital-microphones-using-stm32-mcus-and-mpus-stmicroelectronics.pdf 

Just to bear in mind: the I2S clock for a PDM MIC is way faster as for a regular PCM I2S. And this frequency has to be configured properly in relation to the decimation factor used.

Thank you and sorry for late response.

It seems that watchdog interrupt is called, like if STM32 got stuck somewhere during performing config method. It's hard to debug it further, since the library code is not open source.

How do you know the watchdog interrupt is called?
Don't be confused: often, when code executes an INT vector which is not provided - it looks like the "watchdog" INT handler was called. But it is not true: it just looks like you are in watchdog INT handler because all use the same "Default_INTHandler" (also used on for watchdog handler which is displayed as the "next" INT Handler on display).

Potentially, you end up in the Default_INTHandler (an INT coming where no Handler was implemented).

The entire HAL library is open source: you should have all source for entire project (on this F4 MCU). If you do not see source code (when debugging) - you have not compiled with debug options (-g, -Og).

The only way to figure out which INT vector was activated is by reading the NVIC registers (registers in MCU, to see which INT was triggered, not by looking what is displayed to you: watchdog handler is the first which "uses" Default_Handler - it looks often you would be there, but you are in Default_Handler).