cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H750 with I2S non blocking-mode (DMA or IT) works only once

pk84
Senior

Hello,

As mentioned in the title, I am trying to output a simple sinusoidal audio over I2S.
It works only the first time with DMA and IT, but not afterwards.
In blocking mode it works fine. See the code below.

Does somebody maybe know why?? (It doesn't matter how long the HAL_Delay is)

 

for(uint16_t i = 0; i < 3; i++){
  HAL_Delay(1500);
  HAL_I2S_Transmit(&hi2s2, (uint16_t*)signal1, nsamples, 150); // get a sound 3 times
  //HAL_I2S_Transmit_IT(&hi2s2, (uint16_t*)signal1, nsamples); // sound only once
  //HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t*)signal1, nsamples); // sound only once
}

 


Thank you

1 ACCEPTED SOLUTION

Accepted Solutions
LCE
Principal

That's probably caused by your DMA setup, so please show that.

You need CIRCULAR mode and the correct bit width settings (start with WORD (32bit) for all settings), then it should run "forever".

View solution in original post

10 REPLIES 10
LCE
Principal

That's probably caused by your DMA setup, so please show that.

You need CIRCULAR mode and the correct bit width settings (start with WORD (32bit) for all settings), then it should run "forever".

Ah, great! I changed the mode to CIRCULAR, and now it is continuously sending a sinusoidal sound with a short pause in between. 
1) How can I stop to sending this sound now?
2) And how can I avoid this pause between?

Thank you



in Interrupt Mode it only works when I call Transmit two times (as code below), then I can also call later a Transmit.

But if I call Transmit only once, then, later it is not possible to do a Transmit again (I don't have a sound then).
I not understand this?

HAL_I2S_Transmit_IT(&hi2s2, (uint16_t*)signal1, nsamples);
HAL_I2S_Transmit_IT(&hi2s2, (uint16_t*)signal1, nsamples);

 

LCE
Principal

1) How can I stop to sending this sound now?

Check the I2S HAL file, there should be a DMA stop function.


2) And how can I avoid this pause between?

Make sure that:

- this DMA has high priority

- the buffer is big enough

- the buffer is completely filled (maybe the sine values don't fill the buffer completely)

- check use of double buffering (I think HAL still cannot do this, but not sure)

Ok thank you for these hints, and do you have any idea about following question?:

In Interrupt Mode it only works when I call Transmit two times (as code below), then I can also call later a Transmit.

But if I call Transmit only once, then, later it is not possible to do a Transmit again (I don't have a sound then).
I not understand this?

HAL_I2S_Transmit_IT(&hi2s2, (uint16_t*)signal1, nsamples);
HAL_I2S_Transmit_IT(&hi2s2, (uint16_t*)signal1, nsamples);



LCE
Principal

No idea. I have never used I2S with interrupts, only DMA.

Grab the ref manual and check the HAL and also the ISR functions, maybe you will find it out! Some flag not reset / set maybe?

ok good, just one question, which buffer do you mean with following?


@LCE wrote:
- the buffer is completely filled (maybe the sine values don't fill the buffer completely)
LCE
Principal

Example:

You have a buffer of length 1024.
You calculate one period of a sine wave with frequency fsine = 100 Hz at sampling rate fr = 100 kHz, so one sine period consists of 1000 samples
You have now 1000 samples in your buffer, the remaining buffer is still zero, but you tell the DMA that the buffer has a length of 1024, so you'll have silence for 24 of 1024 samples.
But not if you tell the DMA that the buffer length is only 1000.

Ok thank you for the explanation, but I cannot see where I tell different buffer lengths to the system, see screenshot below of my HAL function:

pk84_0-1697099485581.png