cancel
Showing results for 
Search instead for 
Did you mean: 

I2S problem on stm32f411 and HAL

leogarberoglio
Associate III
Posted on September 17, 2015 at 03:03

 

 

The original post was too long to process during our migration. Please click on the attachment to read the original post.
13 REPLIES 13
leogarberoglio
Associate III
Posted on September 18, 2015 at 13:45

anyone? I really need help on it.

thank

e1369008
Associate II
Posted on September 18, 2015 at 14:01

So why don't you use the RXCplt Callback version that is working properly? Using HAL_Delay for precise time delays is not OK. So use that callback version, or use a timer with an interrupt, if you insist.

leogarberoglio
Associate III
Posted on September 18, 2015 at 16:20

Ohh, I see, the thing is that I need to send/receive tone asyncronously. I mean, I send a tone, receive the response, make some fft, send data to other mcu, and then make another send/receive. If I do that, some tones are ok and some other are not ok. And when it is not ok I see always the same problem, 24 bits data is cut into to 16 bits data and one of them is send on L chanel and the other part on R chanel.

The problem is periodic. If I put HAL_Delay(1000) I have 5 tone ok, 5 tone wrong. If I put HAL_Delay(5000)  I get 1 tone ok, next wrong, next ok and so on.

The only way to make it working is continously send/receive data, as soon as I interrupt the process I get some send/receive problem.

I would try to go deeper on the HAL library, but some help would be very very apretiate!

thank

Posted on September 19, 2015 at 21:28

Post the waveform of clock taken together with other signals. If you have only a 2-channel scope, capture clock and data.

JW

leogarberoglio
Associate III
Posted on September 20, 2015 at 03:06

I will have the hardware again on tuesday (I work 3 days per week on this project). I will make masurement you ask.

Today I could make some test and I found that if a transmit/receive continuosly, alternating silence buffer with tone buffer (I need some time to process the data receive, that's wy I transmit some silence) the tones are ok, but I could find that echo receive by the mic is Ok just one time.. Today arrive new instrument for the project, one of it is an Agilent oscilloscope (4 chanel and logic analizer) so on tuesday I could make all the measurement you need.

I really want to make this project (it will be a comercial product) with an ST uC, but I spend a few weeks with this issue.

Thank for your answer and interest!

leogarberoglio
Associate III
Posted on September 23, 2015 at 01:04

Jan, this are 3 waveforms.

scope_0: https://flic.kr/p/y1WHcj scope_1:https://flic.kr/p/yVExxL Yellow -> WS 100 Hz Blue -> Bit Clock Green -> Data Output (from uC to Codec) I connect PB14 (pin 35) to D_IN on codec. This is I2S2_SD_ext PB15 (pin 36) to D_OUT on codec. This is I2S2_SD signal So I have to configure I2S interfaz as Master RX:

void MX_I2S2_Init(void)
{
hi2s2.Instance = SPI2;
hi2s2.Init.Mode = I2S_MODE_MASTER_RX;
hi2s2.Init.Standard = I2S_STANDARD_PHILLIPS;
hi2s2.Init.DataFormat = I2S_DATAFORMAT_24B;
hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_44K;
hi2s2.Init.CPOL = I2S_CPOL_LOW;
hi2s2.Init.ClockSource = I2S_CLOCK_PLL;
hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE;
HAL_I2S_Init(&hi2s2);
}

my main function is:

int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
MX_I2S2_Init();
/* USER CODE BEGIN 2 */
uint16_t i;
for(i=0;i<2*SAMPLES;i+=2)
{
//Left channel
OutputBuffer[i] = 0xAAAAAAAA; //I have to see 10 on oscilloscope
//Right channel
OutputBuffer[i+1] = 0; //No signal
}
//Initialize codec
codec_init();
HAL_Delay(1500);
while(1)
{
HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (uint16_t *)OutputBuffer, (uint16_t *)InputBuffer, 2*SAMPLES);
for(i=0;i<500;i++);
//HAL_Delay(1);
}
}

As you can see I put on Left (o right, we never know...) channel and 00000... on Right channel. Codec and I2S is configured on 24bits. On scope_0 you can see that 8 lsb of Data is in one channel and 16 msb of data is on the other channel. You can see Bit Clock too. On scope_1 you can see the transition of right signal (., 0000000...., .., 000000.....) a litle silence and wrong signal at the end. As I stated before the problem seems to be the ''no transmiting'' time. Next code works ok:

int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
MX_I2S2_Init();
/* USER CODE BEGIN 2 */
uint16_t i;
for(i=0;i<2*SAMPLES;i+=2)
{
//Left channel
OutputBuffer[i] = 0xAAAAAAAA; //I have to see 10 on oscilloscope
//Right channel
OutputBuffer[i+1] = 0; //No signal
OutputBuffer2[i] = 0; //No signal
OutputBuffer2[i+1] = 0; //No signal
}
//Initialize codec
codec_init();
HAL_Delay(1500);
HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (uint16_t *)OutputBuffer, (uint16_t *)InputBuffer, 2*SAMPLES);
while(1)
{
}
}


void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{
static int i=0;
if(i==0)
{
HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (uint16_t *)OutputBuffer, (uint16_t *)InputBuffer, 2*SAMPLES);
i++;
}
else
{
i=0;
HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (uint16_t *)OutputBuffer2, (uint16_t *)InputBuffer2, 2*SAMPLES);
}
}

the scope for this code is:https://flic.kr/p/yFpCBw I notice that there is 5 WS pulse on the OutputBuffer (0xAAAAAAAA) and 7 WS pulse on the OutputBuffer2(0x00000...).... I can't see if there is a desincronization on this code, but 7 WS seems to be no right. I'm thinking that maybe there is 6 WS for OutputBuffer (5 with data) and 6 WS for OutputBuffer2.... No, it's not working right this way neither. I change Buffer2 to:

for(i=0;i<2*SAMPLES;i+=2)
{
//Left channel
OutputBuffer[i] = 0xAAAAAAAA; //I have to see 10 on oscilloscope
//Right channel
OutputBuffer[i+1] = 0; //No signal
OutputBuffer2[i] = 0; //No signal
OutputBuffer2[i+1] = 0xBBBBBBBB; //.
}

and now I see this:https://flic.kr/p/yYQMrz -https://flic.kr/p/yFqSqS as you can see on the transition of buffer and buffer2 there is a problem.... So, I can't figure out what happening here Any Idea? Thank!
Posted on September 23, 2015 at 02:21

Leonardo,

I don't use Cube so the code above is all Greek to me, but if I figured it right, you use the SPI/I2S unit as a Rx master and the related I2SExt unit as a Tx slave, right?

Now the Rx master ought to emit the clocks continuously, and it does just that. The Tx slave is subject to the I2S erratum (2.4.1 for 'F411 in erratum rev.1), according to which it does not synchronize to LRCK(WS) except for the first inactive-to-active transition after enable. The formulation of erratum is slightly different but that's because discontinuous transmission is not expected for I2S (and I wouldn't be surprised if some of the codecs would fail on that either). The outcome is, that if you write to the slave Tx's data register amidst a word, it will start transmission immediately (more precisely at the nearest 8-bit boundary).

So, the workaround might be to disable the I2Sext Tx slave after transmission finished and reenabling it before next transmission, with bearing in mind the needed level of WS. But I personally wouldn't do that - as I wrote, discontinuous communication is not used in I2S. I would set up a circular double-buffered DMA, and would write the required data to be transmitted into the inactive buffer or in other way ahead of the DMA read.

I don't believe Cube is the right way to do this (but then I don't believe Cube is the right way to do anything at all - by now you probably know this is a personal bias of mine 🙂 ).

JW
leogarberoglio
Associate III
Posted on September 23, 2015 at 04:50

Jan, Thank you very much for your answer!

I've read erratum and never related that issue with my case. I asume I'm the master (and erratum is for slave). I don't take in account that Tx on ext pin is slave. You explain on a better way that ST erratum.

Soy I will try to implement double buffer DMA transfer. The buffer exchange is made on RX/TX compleat interrupt? or is it a register configuration and part of the uC hardware?

I want to move from HAL asap, but I'm new on ST and I need to use some lib's to acelerate coding process. But as soon as I make project working ok  I will start to remove hal and put my own code....

Thank again!

Posted on September 23, 2015 at 09:14

> I've read erratum and never related that issue with my case. I asume I'm the master (and erratum is for slave). I don't take in account that Tx on ext pin is slave.

It's the unfortunate (to put it politely) way of how full-duplex I2S is implemented in the 'F4 - it's two simplex I2S units (one of them - the ''ext'' - crippled to be only I2S and only slave), with internally connected clocks (there is one more I2S erratum for  '405/407 witnessing that this connection went wrong in one case).

> So I will try to implement double buffer DMA transfer. The buffer exchange is made on RX/TX compleat interrupt? or is it a register configuration and part of the uC hardware?

Hardware - see Double buffer mode sub-chapter of DMA chapter in RM. DMA_SxCR.DBM switches on the double-buffer mode; you'll need to set the second buffer's address into DMA_SxM1AR  and DMA_SxCR.CT indicates which buffer is in use by DMA (i.e. the other buffer is available for the software to be manupulated with).

The double-buffer mode is not a necessary precondition. You can use a single buffer and write ahead of the DMA's read pointer, indicated by current NDTR value.

JW