diff options
| author | etiennecollin <[email protected]> | 2025-08-25 21:10:59 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2025-09-05 14:43:29 +0200 |
| commit | 277c59857bc577e8565c920861feb5b6721ac9ae (patch) | |
| tree | a97a55eb5710c2ff1a34906e3723ab3f0e595d43 | |
| parent | c0b8e9c7e5002a424e9ade711b085c2451a58b97 (diff) | |
feat: custom DMA channel configuration
See
https://github.com/embassy-rs/embassy/pull/3923#issuecomment-2888810087
The default configuration of the channel which was done in `start()` is
now done in `new()` this allows overriding some settings through the new
`get_dma_channel` function. Only ringbuffers support this;
`LinkedListTransfer` and `Transfer` do not support that yet.
| -rw-r--r-- | embassy-stm32/src/dma/gpdma/mod.rs | 5 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/gpdma/ringbuffered.rs | 28 |
2 files changed, 27 insertions, 6 deletions
diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 7c05715ee..752b39416 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs | |||
| @@ -352,6 +352,11 @@ impl AnyChannel { | |||
| 352 | .store(table.transfer_count(), Ordering::Relaxed) | 352 | .store(table.transfer_count(), Ordering::Relaxed) |
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | fn get_dma_channel(&self) -> pac::gpdma::Channel { | ||
| 356 | let info = self.info(); | ||
| 357 | info.dma.ch(info.num) | ||
| 358 | } | ||
| 359 | |||
| 355 | fn start(&self) { | 360 | fn start(&self) { |
| 356 | let info = self.info(); | 361 | let info = self.info(); |
| 357 | let ch = info.dma.ch(info.num); | 362 | let ch = info.dma.ch(info.num); |
diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 4532bda57..66c4b74ec 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs | |||
| @@ -77,6 +77,9 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { | |||
| 77 | ]; | 77 | ]; |
| 78 | let table = Table::new(items); | 78 | let table = Table::new(items); |
| 79 | 79 | ||
| 80 | // Apply the default configuration to the channel. | ||
| 81 | unsafe { channel.configure_linked_list(&table, Default::default()) }; | ||
| 82 | |||
| 80 | Self { | 83 | Self { |
| 81 | channel, | 84 | channel, |
| 82 | ringbuf: ReadableDmaRingBuffer::new(buffer), | 85 | ringbuf: ReadableDmaRingBuffer::new(buffer), |
| @@ -85,14 +88,19 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { | |||
| 85 | } | 88 | } |
| 86 | 89 | ||
| 87 | /// Start the ring buffer operation. | 90 | /// Start the ring buffer operation. |
| 88 | /// | ||
| 89 | /// You must call this after creating it for it to work. | ||
| 90 | pub fn start(&mut self) { | 91 | pub fn start(&mut self) { |
| 91 | unsafe { self.channel.configure_linked_list(&self.table, Default::default()) }; | ||
| 92 | self.table.link(RunMode::Circular); | 92 | self.table.link(RunMode::Circular); |
| 93 | self.channel.start(); | 93 | self.channel.start(); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | /// Get a handle to the GPDMA channel for configuring the DMA. | ||
| 97 | /// | ||
| 98 | /// Usually, **this is not needed** as a default configuration is already | ||
| 99 | /// applied, but it may be useful to setup trigger sources, etc. | ||
| 100 | pub fn get_dma_channel(&mut self) -> stm32_metapac::gpdma::Channel { | ||
| 101 | self.channel.get_dma_channel() | ||
| 102 | } | ||
| 103 | |||
| 96 | /// Clear all data in the ring buffer. | 104 | /// Clear all data in the ring buffer. |
| 97 | pub fn clear(&mut self) { | 105 | pub fn clear(&mut self) { |
| 98 | self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); | 106 | self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); |
| @@ -226,6 +234,9 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { | |||
| 226 | ]; | 234 | ]; |
| 227 | let table = Table::new(items); | 235 | let table = Table::new(items); |
| 228 | 236 | ||
| 237 | // Apply the default configuration to the channel. | ||
| 238 | unsafe { channel.configure_linked_list(&table, Default::default()) }; | ||
| 239 | |||
| 229 | let this = Self { | 240 | let this = Self { |
| 230 | channel, | 241 | channel, |
| 231 | ringbuf: WritableDmaRingBuffer::new(buffer), | 242 | ringbuf: WritableDmaRingBuffer::new(buffer), |
| @@ -236,14 +247,19 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { | |||
| 236 | } | 247 | } |
| 237 | 248 | ||
| 238 | /// Start the ring buffer operation. | 249 | /// Start the ring buffer operation. |
| 239 | /// | ||
| 240 | /// You must call this after creating it for it to work. | ||
| 241 | pub fn start(&mut self) { | 250 | pub fn start(&mut self) { |
| 242 | unsafe { self.channel.configure_linked_list(&self.table, Default::default()) }; | ||
| 243 | self.table.link(RunMode::Circular); | 251 | self.table.link(RunMode::Circular); |
| 244 | self.channel.start(); | 252 | self.channel.start(); |
| 245 | } | 253 | } |
| 246 | 254 | ||
| 255 | /// Get a handle to the GPDMA channel for configuring the DMA. | ||
| 256 | /// | ||
| 257 | /// Usually, **this is not needed** as a default configuration is already | ||
| 258 | /// applied, but it may be useful to setup trigger sources, etc. | ||
| 259 | pub fn get_dma_channel(&mut self) -> stm32_metapac::gpdma::Channel { | ||
| 260 | self.channel.get_dma_channel() | ||
| 261 | } | ||
| 262 | |||
| 247 | /// Clear all data in the ring buffer. | 263 | /// Clear all data in the ring buffer. |
| 248 | pub fn clear(&mut self) { | 264 | pub fn clear(&mut self) { |
| 249 | self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); | 265 | self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); |
