Open tyler-gilbert opened 9 months ago
linked-list dma is on the todo list but has not yet been implemented. the goal is to match the current public api for readable and writable ringbuffer.
Comments and suggestions are welcome. If I can get this working, I will open a PR.
if you can implement a readable/writable ringbuffer for gpdma, it would be a welcome contribution.
Work in progress:
https://github.com/tyler-gilbert/embassy/tree/issue-2059-ringbuffers-on-gpdma
This branch is working with the SAI both read and write. I still need to test with a speaker and amplifier but this is almost ready.
@xoviat PR is awaiting review here: https://github.com/embassy-rs/embassy/pull/2302
I just started running into this issue. I'm switching from a STM32F4 board to a STM32U5 board. I had previously implemented UART comms using the RingBufferedUartRx
struct, but it's now failing to compile due to that struct missing on the U5. Seems like I could switch to the BufferedUartRx
, but it would be nice to keep the code as similar as possible between chip types. Any idea when this might get merged?
@Dillonmcewan I can work on this over the next week. I have merged several prerequisite changes. I think I am down to just merging the circular buffer. I have been testing on I2S. I will let you know before I merge so that you can test on the UART.
Thanks @tyler-gilbert! Happy to help with testing when ready
The DMA on newer devices like the STM32U5 have a GPDMA hardware block. This is distinct from the classic DMA found on, say, STM32F4 devices. The classic DMA has built-in support for circular reads and writes. GPDMA hardware doesn't have built-in support for circular DMA is capable of circular DMA using it's linked-list design structure.
The simplest way to have circular reads/writes on GPDMA is to provide a single linked-list item that resets the write destination for DMA reads and the read source for DMA writes. Considering reads, the LLR is set to update only the source address to point to the start of the buffer.
It looks something like this to set up:
The GPDMA will need to store a 32-bit memory address in static memory for each channel (STM32U5 has 15-channels, so 60 bytes of RAM):
STATE.circular_address[channel.index()]
. The lower 2 bits must be zero (requires 4-byte alignment) are always zero. Bits 3 to 15 are stored usew.set_la((lli1 >> 2usize) & 0x3fff)
while the upper 16-bits are stored usingw.set_lba(lli1 >> 16usize)
.I still need to do some testing to make sure this approach will work but this seems like a good approach to match the circular transfers of classic DMA. Fully supporting linked-list could maybe come later as a cargo feature.
Comments and suggestions are welcome. If I can get this working, I will open a PR.