Skip to main content
jw56
Associate III
September 23, 2021
Question

Feeding the next buffer to SAI DMA

  • September 23, 2021
  • 3 replies
  • 2066 views

Sorry if this has been answered elsewhere, but I'm not seeing it. For background, I do a lot of work with Nordic, and in their I2S implementation, you feed two buffers to the peripheral, then every time a buffer has been transmitted/received, it switches over to transmit/receive the second buffer automatically while you point it to the buffer to use when that one is done (usually the one that just got freed). In this way you never miss any data.

I'm currently trying to implement an I2S receiver using SAI on an STM32L476. I get the data via SAI in DMA mode fine, but then I have to kick off another DMA receive (HAL_SAI_Receive_DMA) when I get the interrupt from the previous one. My sampling clock is running around 3MHz, which doesn't leave much time to point the next buffer to the SAI. So my question is, is there a standard way of handling this? How do other people guarantee that the SAI DMA will have a pointer to the next buffer when it is done the current transfer? Do you somehow leverage the FIFO as well since you presumably have eight words worth of time to start a new receive? What happens if you have a few other interrupts to service in the meantime?

This topic has been closed for replies.

3 replies

waclawek.jan
Super User
September 23, 2021

Double-buffering in the single-port DMA in 'L4 (as opposed to double-port DMA in 'F2/'F4/'F7) is accomplished by using the half-transfer interrupt.

I don't use Cube so don't know the exact Cube incantation for that, but it's quite clearly described in DMA chapter of RM.

JW

jw56
jw56Author
Associate III
September 23, 2021

Hmmm, that is exactly the chapter I have been reading, and I don't see anything about the validity of setting a pointer to a new buffer on half-transfer. Are you sure you have the right part? A search for the word "half" on pages 336 - 360 in rm0351 only turns up information about how to enable that interrupt. I haven't seen anything about double buffering at all in several reads through that chapter, maybe there is a different term they are using?

waclawek.jan
Super User
September 23, 2021

Yes, that's the case. At the end of the day, you are most likely going to process that freshly received data anyway. You probably could use memory-to-memory DMA run at a different channel to shovel the data away, if you need so, but I'm not sure that has some point. You also probably may be able to stop/readjust/restart, if you can keep the transfer-complete-latency low enough.

As I've said above, what you are looking for is the dual-port DMA IP used in 'F2/'F4/'F7.

JW

Piranha
Principal III
September 25, 2021

I've used FIFO and DMA in normal (run once) mode and that works reliably. At least for audio stream 8 words are more than enough to disable-reconfigure-enable DMA stream.

That said, the solution described by Jan is the best. Set DMA to circular mode and implement a combined copy+process code from capture buffers to send buffers.