cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f407 i2s interface sync in slave mode

albert2
Associate II
Posted on July 17, 2015 at 10:58

Hello, I'd like to know if there is a 'magical' way to syncronize the bit stream with the channel signal in the i2s receivers. I don't have control on the external stream ( slave mode), so the serial clock is free running, and the only way I've found to use the interface is to wait for the correct time to enable it.

Perhaps there is some way to do it using the receiver but I've been unable to find it.

If this is a 'feature', perhaps it would be wise to modify the silicon on next iterations/products to allow for an automatical way to sync the receiver with the data stream.

Thank you very much.

Albert

#i2s #stm32f407 #sync
1 ACCEPTED SOLUTION

Accepted Solutions
albert2
Associate II
Posted on May 07, 2018 at 09:37

I answer myself. I forgot about this question pending here.

There is an easy way to synchronize the enable. The appropiate levels of the WS signal depend on the exact protocol you're using. Change as needed.

You must do the following procedure:

-disable the interface

-reset the interface

-wait for a rising edge of the ws signal

-disable interrupts

-count the clock cycles that you're using (bits) less 1, using the rising/falling edges of the clock signal

-enable the interface

-enable interrupts

this way, on the next bit clock, the interface will start with the first bit correctly clocked.

I have impolemented it this way and its working flawlessly.

Albert

View solution in original post

12 REPLIES 12
Posted on July 17, 2015 at 17:05

Isn't that the purpose of the WS signal?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
albert2
Associate II
Posted on July 20, 2015 at 08:18

Hi Clive

Yup, that's exactly the purpose of the WS signal, but the hardware implementation seems to ignore it in slave mode.

That's why i'm asking the question. It may be that i'm not implementing it well enough in the firmware (most probable), or it may be that the silicon implememntation has 'forgotten' to use it to reset the bit counter.

HoRyong Kang
Associate II
Posted on May 07, 2018 at 07:20

Hello

I have the same problem.

The only way is to control the timing of enable I2S.

But it is not exact about 1 bit.

1 bit is very large sound because it means the sound is 2 times louder.

albert2
Associate II
Posted on May 07, 2018 at 09:37

I answer myself. I forgot about this question pending here.

There is an easy way to synchronize the enable. The appropiate levels of the WS signal depend on the exact protocol you're using. Change as needed.

You must do the following procedure:

-disable the interface

-reset the interface

-wait for a rising edge of the ws signal

-disable interrupts

-count the clock cycles that you're using (bits) less 1, using the rising/falling edges of the clock signal

-enable the interface

-enable interrupts

this way, on the next bit clock, the interface will start with the first bit correctly clocked.

I have impolemented it this way and its working flawlessly.

Albert

Posted on May 07, 2018 at 09:51

I'd put the 'disable interrupts' before 'wait for a rising edge of the WS signal' (and, as you've said before, it may be 'wait for a falling edge' in some protocols).

The reason is that there's a hardware bug in the I2S module implementation in the 'classic' 'F2xx/'F4xx in that the

https://community.st.com/0D50X00009XkW2ISAV

circuit is level-sensitive instead of being properly edge-sensitive. It is described in the errata and corrected in the newer 'Fxx.

JW

Posted on May 07, 2018 at 10:47

Thank you for your reply

This is my code that starts I2S.

The delay is unstable.

Some times 1bit(1clock) earlier some times 1bit

(1clock)

later.

What do you mean '

count the clock cycles'?

Is it different from the while loop delay(

while(counter--);)

?

void I2S_Fit()

{

__disable_irq();

I2S_Cmd(SPI2, DISABLE);

Init_I2S();

uint32_t counter = 26;

while(1){

if(!I2S_WS_IN_PIN_READ) break;

}

while(1){

if(I2S_WS_IN_PIN_READ) break;

}

while(I2S_WS_IN_PIN_READ){

}

while(counter--);//Delay

SPI2->I2SCFGR |= 0x0400;//enables I2S

// I2S_Cmd(SPI2, ENABLE);

__enable_irq();

XXX(11, ('I2S_Fit\n'));

}
Posted on May 07, 2018 at 11:50

Count the clock cycles:

while(counter--){

   while(I2S_CLOCK_PIN_READ);//waits until the clock signal is low

 while(!I2S_CLOCK_PIN_READ);

//waits until the clock signal is high

}

Depending on the clock polarity you're using you may need to change the order.

Posted on May 07, 2018 at 21:08

I don't think it's necessary. I believe it's enough to wait until the 'inactive' level of WS, and then enable the I2S.

JW

Posted on May 08, 2018 at 01:20

I have tested to count the I2S clock.

But still the timing is unstable by 1 bit.

The I2S clock is too fast to count by pin reading.

My MCU is STM32F105RB with 25mHz(internal 72mhz).

I put the test code like this.

//Count the clock cycles:

while(counter--){

TEST1_PIN_SET;

while(I2S_CK_PIN_READ);//waits until the clock signal is low

TEST1_PIN_RESET;

while(!I2S_CK_PIN_READ);//waits until the clock signal is high

}

As the oscilloscope wave, reading the clock pin do not catch up the I2S clock speed.

I think the best way is that ST release the bug fixed version which supports I2S WS signal sync.

Any body knows that ST have released the I2S WS sync bug fixed version MCU?

If not, I need to make TTL circuit to read the I2S correctly.

It is too wast of PCB space. T.T