cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 I2S DMA

Smuffin
Associate

Hello everyone,

I am currently implementing an audio synthesizer. My DAC requires the I2S protocol, which is supported by my device (F446). I want to setup a circular buffer to feed the I2S peripheral using DMA. Idealy, i want to set it up and let the DMA increases the read pointer and handle the wraparound). I require the read pointer to avoid buffer overflows, so it is crucial that i have it. I am not sure if this is possible. The circular dma mode seems like exactly what i need, but i have not found a way to make it work with a ring buffer... Is there another way to do it properly? If i simply could access the internal read pointer from the DMA..
I thought about using a double buffer and having an interrupt fire every time a buffer is completely send.

 

I am thankful for every input
Chees

 

7 REPLIES 7
PGump.1
Senior II

Hi,

If your DAC can't provide the sample rate trigger, you will need to setup a timer to trigger the DMA at the appropriate sample rate.

You should also setup another timer with Callback to assist with buffer management...

I hope that helps.

Kind regards
Pedro

AI = Artificial Intelligence, NI = No Intelligence, RI = Real Intelligence.

> My DAC requires the I2S protocol, which is supported by my device (F446).

It does in two distinct peripherals: SPI/I2S, and SAI. I recommend to use the latter. Read its chapter in RM.

> If i simply could access the internal read pointer from the DMA..

You simply can (the NDTR register - although it's a counter not a pointer, but the conversion is trivial), but there are gotchas involved and there's also no need to do that in this case.

> I thought about using a double buffer and having an interrupt fire every time a buffer is completely send.

This is why the DMA has a Half-complete and a Transfer-complete interrupt. There's no need to use the double-buffer mode, that has a slightly different purpose (although can be used too, if needed). At any case, start with reading the DMA chapter in RM.

JW

 

> If your DAC can't provide the sample rate trigger

In I2S, which is the case here, the sample rate is provided inherently through the I2S bus clock mix  - the I2S master provides an explicit LRCK signal (left-right clock, also called WS - word select).

JW

Thank you for your answer!

> You simply can (the NDTR register - although it's a counter not a pointer, but the conversion is trivial), but there are gotchas involved and there's also no need to do that in this case.

why isnt this the prefered way? In my main loop i have to check against the head pointer anyway, if it is set in the interrupt or taken from the NDTR register. Having the interrupt seems like making the control flow more unpredictable and taking away some time from the signal synthesis to fill the buffer since it has to wait until half the buffer is released at once.

>This is why the DMA has a Half-complete and a Transfer-complete interrupt. There's no need to use the double-buffer mode, that has a slightly different purpose (although can be used too, if needed). At any case, start with reading the DMA chapter in RM.

Yeah you are right! I actually read the chapter last night, but apparently i was too tired since the NDTR slipped my attention.

The issue is that NDTR probably (this is not documented properly) decrements upon the peripheral side transfer, not the memory side. For transmission, which is your case, it's probably OK to use NDTR (as if it counts peripheral side, it lags to the real memory-side pointer), but for reception it's not quite so.

Nonetheless, what's the point of calculating pointers byte by byte. It's more efficient to calculate/store a whole half-buffer upon the interrupt.

JW

 

Smuffin
Associate

Thank you for clarification. You are right, by storing half a buffer every time I dont have to check the buffer capacity.

>It does in two distinct peripherals: SPI/I2S, and SAI. I recommend to use the latter. Read its chapter in RM.
I read it and it seems suited. But it seems to me like the SPI peripheral is capable of everything that i require. Is there anything majorly wrong with using it? This will be my last question!

Define "majorly" :)

It may or may not be relevant, but the SPI/I2S has a 16-bit data register, and given I2S is MSB-first, anything else but 16-bit data are an exercise in byte reordering.

I don't have the RM at hand, but IIRC SAI has some built-in FIFO, too. SAI can also be better chained for multi-channel/fullduplex operation.

Depending on your particular application, probably none of these is a showstopper.

JW