atsamd-rs / atsamd

Target atsamd microcontrollers using Rust
https://matrix.to/#/#atsamd-rs:matrix.org
Apache License 2.0
548 stars 198 forks source link

Implement DMA abstraction #25

Closed sajattack closed 3 years ago

sajattack commented 5 years ago

Title kinda speaks for itself. I'll try to work on this but will probably need help.

sajattack commented 5 years ago

Resources: http://ww1.microchip.com/downloads/en/AppNotes/Atmel-42257-SAM-Direct-Memory-Access-Controller-Driver-DMAC_ApplicationNote_AT07683.pdf http://asf.atmel.com/docs/latest/samd21/html/dma_8c.html https://gist.github.com/sajattack/5080311aa5085f1a9748c711bea78140 https://github.com/adafruit/adafruit_zerodma https://github.com/rust-embedded/embedded-hal/issues/37

sajattack commented 5 years ago

How closely should we follow the ASF4 API @wez? What have you been doing so far?

wez commented 5 years ago

I haven't really looked at DMA on this device in detail. I recall reading the blog posts referenced from the embedded-hal issue you referenced, and have been soft-following that issue.

My currently under-educated opinion is that we should feel free to produce an implementation that works for us (eg: we don't have to wait for a trait to appear in embedded-hal), and that implementation should be reasonably rust idiomatic and safe rather than mirroring an unsafe C API that exists elsewhere.

That said, I haven't really looked at the DMA APIs for C/C++ on this device so I don't know whether I'm being too much of a rust snob, and it can be better to start out by building something (or anything!) that does the job so that there is a concrete implementation as a starting point that we can then comment on as a PR and give suggestions in review, rather than blocking on consensus in this issue.

After skimming a couple of things, I have a couple of questions on my mind that would influence how I might choose to design the API, so I'm going to ask them here; I'd like to stress that I still don't know enough to have a strong influence on direction.

DMA Channels

Our clock allocation is pretty robust and type safe and is one model that we could potentially apply to this, but I don't know if is convenient enough to translate to DMA.

Callbacks

sajattack commented 5 years ago

It looks to me like channels can be released and reallocated on the fly.

One idea I had was making a new() with all the initialization rather than like 5 or however many initialization functions the C version has.

sajattack commented 5 years ago

Follow my progress here https://github.com/sajattack/atsamd/tree/dma

tarcieri commented 3 years ago

60 had an untested port of Adafruit ZeroDMA.

This gist has some earlier work I did on SERCOM DMA: https://gist.github.com/tarcieri/61d5789e369cf5e25edc4248d26b525a

It seems like future attempts at adding DMA should be leveraging https://github.com/rust-embedded/embedded-dma

jessebraham commented 3 years ago

Just to document, and building on what @tarcieri said, there seems to have been some progress made regarding DMA. Relevant links:

https://github.com/rust-embedded/wg/issues/480 https://github.com/rust-embedded/embedded-dma https://github.com/ra-kete/dma-poc

jacobrosenthal commented 3 years ago

just saw this https://crates.io/crates/samd-dma

jbeaurivage commented 3 years ago

I have written a DMA driver that seems to be working quite well. For now it only works for the SAMD21 chips, but it could easily be adapter to all the chip families supported by this HAL. This is a pure Rust driver and is not derived from any existing C/C++ library. Currently it only builds on rustc 1.51, since it uses const generics pretty heavily. It aims to support 4 kinds of DMA transfers:

Transfers are supported for i8, u8, i16, u16, i32, u32 and f32 beat sizes.

The idea was to have a safe driver that statically guarantees the DMAC and the individual channels are correctly configured before launching transfers. It is not meant to be just a wrapper to the DMAC registers.

Channels

Channels are accessible individually through a split() method on the DMAC. They can be reused after a transfer is complete.

Interrupts

The driver does not handle interrupts or callbacks, although it is possible to enable interrupts on a channel-to-channel basis through the driver. The user would then be responsible for clearing the interrupt flags in the ISR.

Improvements

Take a look here: https://github.com/jbeaurivage/atsamd-rs/tree/dmac. An example is available for the Feather M0.

For now, I plan on refining the driver and submit a PR in time for rustc 1.51 stabilization. I would love comments, advice or suggestions!

tarcieri commented 3 years ago

@jbeaurivage would be great to have SAMD51 support as well. Perhaps https://crates.io/crates/samd-dma or #60 could serve as an inspiration?