Skip to main content
pk84
Associate III
October 5, 2023
Solved

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

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

This topic has been closed for replies.
LCE
LCEBest answer
Principal III
October 5, 2023

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".

10 replies

LCE
LCEBest answer
Principal III
October 5, 2023

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".

pk84
pk84Author
Associate III
October 5, 2023

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



LCE
Principal III
October 5, 2023

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)

pk84
pk84Author
Associate III
October 5, 2023

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 III
October 5, 2023

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?

pk84
pk84Author
Associate III
October 6, 2023

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 III
October 6, 2023

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.

pk84
pk84Author
Associate III
October 12, 2023

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

 

LCE
Principal III
October 12, 2023

Maybe it's not necessary if your buffer has a clean sine from start to end of buffer.
So check your buffer content.

Otherwise :

HAL_StatusTypeDef HAL_I2S_Transmit_DMA(I2S_HandleTypeDef *hi2s, const uint16_t *pData, uint16_t Size);

Set "Size" (in your case "nsamples") to the sine length.
The size you hand over to DMA can be smaller than the actual buffer size (but must NOT be bigger!).