cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 I2S High speed trouble

alexandr
Associate II
Posted on March 09, 2013 at 17:28

Hello peolpes,

maybe somebody can help me. For a testing I use two I2S - one(I2S3) for transmitting, second (I2S2) - for receiving, phisicaly connected at the PCB. At both I use Double Buffer DMA. I fill the sending buffer with the constant, and looking for a receiving buffer to get the same values. I use external clock at PC9 49MHz (by the way - what is the maximum alloud frequency?). At all speeds up to 96K it works fvery goood, but at 192K it totaly not work! Everytime I get a failed values in the receiving buffer, also frame error at I2S2 (receiver). I'm doing everithing according to the datasheet and errata sheet, but I thin something wrong in initialisation (maybe I forget to clear some flags?)

// this is receiver r init:
void I2S2_RCV_Init(void)
{
I2S_InitTypeDef I2S2_InitStructure;
//------------------------------------------------
 I2SGPIO_Init(); 
//
I2S_StructInit(&I2S2_InitStructure);
I2S2_InitStructure.I2S_AudioFreq =I2S_AudioFreq_Default;
I2S2_InitStructure.I2S_CPOL = I2S_CPOL_Low;
I2S2_InitStructure.I2S_Mode = I2S_Mode_SlaveRx;
I2S2_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
I2S2_InitStructure.I2S_Standard = I2S_Standard_MSB;
 I2S2_InitStructure.I2S_DataFormat = I2S_DataFormat_32b;
// wait for WS=1 the for WS=0, i.e. \_ front
WaitForWCLK(1));
WaitForWCLK(0));
I2S_Init(SPI2, &I2S2_InitStructure);
I2S2_DMA_Init();
DMA_Cmd( Rx_DMAStream, ENABLE );
I2S_Cmd(SPI2, ENABLE);
}
// WS waiting function:
static u8 WaitForWCLK(u8 edge)
{
TOTmr1ms = WCLK_TIMEOUT; // TOTmr1ms is decremented in SysTick interrupt
if(edge>0){ // wait for WCLK=1
while (0==(GPIOB->IDR & GPIO_Pin_12)){
if(TOTmr1ms==0) 
return 0;
} 
return 1;
}else{ // wait for WCLK=0
while (0!=(GPIOB->IDR & GPIO_Pin_12)){
if(TOTmr1ms==0) 
return 0;
} 
return 1;
}
}

DMA Function:

static __INLINE void I2S2_DMA_Init( void ) // ******* D M A RECEIVER ****************
{
DMA_InitTypeDef DMA_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
DMA_Cmd( Rx_DMAStream, DISABLE );
while( DMA_GetCmdStatus( Rx_DMAStream ) == ENABLE ); // wait for the last DMA end
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
// From:
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR); // I2S Data
// To:
DMA_InitStruct.DMA_Memory0BaseAddr = (u32)&DMARCVBUF[0][0]; // memory start
DMA_InitStruct.DMA_BufferSize = DMARCVBUF_SIZE; // length
// With parameters:
DMA_InitStruct.DMA_Channel = DMA_Channel_0; 
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory; // direction
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; 
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 16 bit per
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 16 bit memory
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; // circ
DMA_InitStruct.DMA_Priority = DMA_Priority_High; // prority
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single; 
DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init( Rx_DMAStream, &DMA_InitStruct ); // Init New
DMA_ITConfig( DMA1_Stream3, DMA_IT_TC, ENABLE ); 
DMA_DoubleBufferModeConfig(Rx_DMAStream, (uint32_t)RCVBuffer_2, DMA_Memory_0 );
DMA_DoubleBufferModeCmd( Rx_DMAStream, ENABLE );
SPI_I2S_DMACmd( SPI2, SPI_I2S_DMAReq_Rx, ENABLE);
}

P.S. CPU - STM32F407VG #stm32f4xx-i2s-dma
14 REPLIES 14
martinmartin9129
Associate II
Posted on March 11, 2013 at 09:50

Nobody use this?

Posted on March 11, 2013 at 10:38

> I use external clock at PC9 49MHz (by the way - what is the maximum alloud frequency?).

While I could not find any relevant data (the whole I2S timing section in datasheet is still TBD and the table does not contain an entry for external clock either), I believe the value for min EXTINT pulse = 10ns is somewhat pertinent for this value too (i.e. 50MHz should be a relatively safe limit).

> At all speeds up to 96K it works fvery goood, but at 192K it totaly not work!

Please be more specific - in what way it ''totaly not work''? All received values are incorrect, or just some of them? In what way are they incorrect - whole word shifted, or inversed bits?

I don't use the I2S as slave but running a full-duplex I2S (i.e. the respective I2SExt is the slave), at 187.5ksps and did not encounter troubles of this kind so far.

JW

alexandr
Associate II
Posted on March 11, 2013 at 22:21

Yes, ALL received values are incorrect, and FRE flag is always set.

Posted on March 12, 2013 at 08:20

And I thought it's only the management types who can't answer more than one question per post... 😉

Okay, so once again:

 

In what way are they incorrect - whole word shifted, or inversed bits?

You might also try to use an internal clock source, does the problem persist?

You might also post a minimal but complete, compilable example which exhibits the problem, so that it could be reproduced elsewhere.

JW

martinmartin9129
Associate II
Posted on March 12, 2013 at 10:16

I send:  0xA1A25354  and 0x1B2C3D4E

I got:  0xAA0DD129 and 0xA750961E

or 0x6A83344A and 0xA9D46587

Why you suggst to use internal clock? Receiver is not use it.

Example I will be able to send later - I need to change it, tha it can work not at my PCB only.

Posted on March 12, 2013 at 12:28

While you did not provide enough information again (do you transmit only these two words circularly infinitely, are the received data always one of those couples of words repeating infinitely, etc.), these are shifted versions of the transmitted words (and the answer to my first question above is ''no'', more different tx data follow).

Seems like your ''wait for sync'' does not work as it should.

Could you try simply removing the timeout from it?

> Why you suggst to use internal clock? Receiver is not use it.

Because it's easy and could reveal a potential problem you have mentioned too (the max. input frequency is not specified).

JW

martinmartin9129
Associate II
Posted on March 12, 2013 at 13:52

I send the constant values, circularly infinitely.

Yes, the received data always one of those couples of words repeating infinitely.

After every a reset - the received data ara constant, but can cahnged after another reset.

Of course, I understand that this is ''wait for sync'' problem, but I donn't understand what else I can do!

Without timeout - the same.

> Because it's easy and could reveal a potential problem you have mentioned too (the max. input frequency is not specified).

OK, but what the matter, if receiver does not use this signal? Tranmitting is OK, the sigmal at the receiver's input is OK - the same word as I send.

(I saw this with oscillocsope, that can decode the bus signals).

See the latest source in attachment.

martinmartin9129
Associate II
alexandr
Associate II
Posted on March 13, 2013 at 22:56

Now I add I2S interrupt on FRE, where I make 2 things: read I2S2->SR and ->DR to clear FRE, and set the programming flag.

In the main loop I check this flag, and if it is set I clere it and re-init I2S.

So, re-init will be up to FRE dissapeared.

This helps, a little bit -now 192K works, but after the first init it takes 200ms-1s (!) to stabilize, which means  than 192K is still unusable :(