aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/dma
diff options
context:
space:
mode:
authoretiennecollin <[email protected]>2025-08-25 21:10:59 +0200
committerDario Nieuwenhuis <[email protected]>2025-09-05 14:43:29 +0200
commit2f24568de08e846d4bfafff90a5b9ba352d86431 (patch)
tree764affc6badec7017d935e6e93567aa188ecdf44 /embassy-stm32/src/dma
parentf67365a067634b62747c819253fb461624c29568 (diff)
feat: custom dma configuration using RegisterUpdaters struct
See this PR comment: https://github.com/embassy-rs/embassy/pull/3923#issuecomment-2889283939
Diffstat (limited to 'embassy-stm32/src/dma')
-rw-r--r--embassy-stm32/src/dma/gpdma/linked_list.rs20
-rw-r--r--embassy-stm32/src/dma/gpdma/mod.rs22
-rw-r--r--embassy-stm32/src/dma/gpdma/ringbuffered.rs16
3 files changed, 51 insertions, 7 deletions
diff --git a/embassy-stm32/src/dma/gpdma/linked_list.rs b/embassy-stm32/src/dma/gpdma/linked_list.rs
index a95e5590e..76381def3 100644
--- a/embassy-stm32/src/dma/gpdma/linked_list.rs
+++ b/embassy-stm32/src/dma/gpdma/linked_list.rs
@@ -4,6 +4,7 @@
4use stm32_metapac::gpdma::regs; 4use stm32_metapac::gpdma::regs;
5use stm32_metapac::gpdma::vals::Dreq; 5use stm32_metapac::gpdma::vals::Dreq;
6 6
7use super::RegisterUpdaters;
7use crate::dma::word::{Word, WordSize}; 8use crate::dma::word::{Word, WordSize};
8use crate::dma::{Dir, Request}; 9use crate::dma::{Dir, Request};
9 10
@@ -41,7 +42,12 @@ pub struct LinearItem {
41 42
42impl LinearItem { 43impl LinearItem {
43 /// Create a new read DMA transfer (peripheral to memory). 44 /// Create a new read DMA transfer (peripheral to memory).
44 pub unsafe fn new_read<'d, W: Word>(request: Request, peri_addr: *mut W, buf: &'d mut [W]) -> Self { 45 pub unsafe fn new_read<'d, W: Word>(
46 request: Request,
47 peri_addr: *mut W,
48 buf: &'d mut [W],
49 register_updaters: &RegisterUpdaters,
50 ) -> Self {
45 Self::new_inner( 51 Self::new_inner(
46 request, 52 request,
47 Dir::PeripheralToMemory, 53 Dir::PeripheralToMemory,
@@ -51,11 +57,17 @@ impl LinearItem {
51 true, 57 true,
52 W::size(), 58 W::size(),
53 W::size(), 59 W::size(),
60 register_updaters,
54 ) 61 )
55 } 62 }
56 63
57 /// Create a new write DMA transfer (memory to peripheral). 64 /// Create a new write DMA transfer (memory to peripheral).
58 pub unsafe fn new_write<'d, MW: Word, PW: Word>(request: Request, buf: &'d [MW], peri_addr: *mut PW) -> Self { 65 pub unsafe fn new_write<'d, MW: Word, PW: Word>(
66 request: Request,
67 buf: &'d [MW],
68 peri_addr: *mut PW,
69 register_updaters: &RegisterUpdaters,
70 ) -> Self {
59 Self::new_inner( 71 Self::new_inner(
60 request, 72 request,
61 Dir::MemoryToPeripheral, 73 Dir::MemoryToPeripheral,
@@ -65,6 +77,7 @@ impl LinearItem {
65 true, 77 true,
66 MW::size(), 78 MW::size(),
67 PW::size(), 79 PW::size(),
80 register_updaters,
68 ) 81 )
69 } 82 }
70 83
@@ -77,6 +90,7 @@ impl LinearItem {
77 incr_mem: bool, 90 incr_mem: bool,
78 data_size: WordSize, 91 data_size: WordSize,
79 dst_size: WordSize, 92 dst_size: WordSize,
93 register_updaters: &RegisterUpdaters,
80 ) -> Self { 94 ) -> Self {
81 // BNDT is specified as bytes, not as number of transfers. 95 // BNDT is specified as bytes, not as number of transfers.
82 let Ok(bndt) = (mem_len * data_size.bytes()).try_into() else { 96 let Ok(bndt) = (mem_len * data_size.bytes()).try_into() else {
@@ -91,6 +105,7 @@ impl LinearItem {
91 tr1.set_ddw(dst_size.into()); 105 tr1.set_ddw(dst_size.into());
92 tr1.set_sinc(dir == Dir::MemoryToPeripheral && incr_mem); 106 tr1.set_sinc(dir == Dir::MemoryToPeripheral && incr_mem);
93 tr1.set_dinc(dir == Dir::PeripheralToMemory && incr_mem); 107 tr1.set_dinc(dir == Dir::PeripheralToMemory && incr_mem);
108 (register_updaters.tr1)(&mut tr1);
94 109
95 let mut tr2 = regs::ChTr2(0); 110 let mut tr2 = regs::ChTr2(0);
96 tr2.set_dreq(match dir { 111 tr2.set_dreq(match dir {
@@ -98,6 +113,7 @@ impl LinearItem {
98 Dir::PeripheralToMemory => Dreq::SOURCE_PERIPHERAL, 113 Dir::PeripheralToMemory => Dreq::SOURCE_PERIPHERAL,
99 }); 114 });
100 tr2.set_reqsel(request); 115 tr2.set_reqsel(request);
116 (register_updaters.tr2)(&mut tr2);
101 117
102 let (sar, dar) = match dir { 118 let (sar, dar) = match dir {
103 Dir::MemoryToPeripheral => (mem_addr as _, peri_addr as _), 119 Dir::MemoryToPeripheral => (mem_addr as _, peri_addr as _),
diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs
index 604db2852..58f93ffb0 100644
--- a/embassy-stm32/src/dma/gpdma/mod.rs
+++ b/embassy-stm32/src/dma/gpdma/mod.rs
@@ -73,6 +73,28 @@ impl Default for TransferOptions {
73 } 73 }
74} 74}
75 75
76/// GPDMA linked-list item register updater functions.
77#[derive(Debug, Copy, Clone)]
78#[cfg_attr(feature = "defmt", derive(defmt::Format))]
79pub struct RegisterUpdaters {
80 /// Function used to overwrite transfer register 1.
81 pub tr1: fn(&mut pac::gpdma::regs::ChTr1),
82 /// Function used to overwrite transfer register 2.
83 pub tr2: fn(&mut pac::gpdma::regs::ChTr2),
84 /// Function used to overwrite transfer register 3.
85 pub tr3: fn(&mut pac::gpdma::regs::ChTr3),
86}
87
88impl Default for RegisterUpdaters {
89 fn default() -> Self {
90 Self {
91 tr1: |_| {},
92 tr2: |_| {},
93 tr3: |_| {},
94 }
95 }
96}
97
76impl From<WordSize> for vals::Dw { 98impl From<WordSize> for vals::Dw {
77 fn from(raw: WordSize) -> Self { 99 fn from(raw: WordSize) -> Self {
78 match raw { 100 match raw {
diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs
index c74c7bd2b..dfc031627 100644
--- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs
+++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs
@@ -8,7 +8,7 @@ use core::task::Waker;
8 8
9use embassy_hal_internal::Peri; 9use embassy_hal_internal::Peri;
10 10
11use super::{AnyChannel, TransferOptions, STATE}; 11use super::{AnyChannel, RegisterUpdaters, TransferOptions, STATE};
12use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table}; 12use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table};
13use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; 13use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer};
14use crate::dma::word::Word; 14use crate::dma::word::Word;
@@ -52,6 +52,7 @@ pub struct ReadableRingBuffer<'a, W: Word> {
52 channel: Peri<'a, AnyChannel>, 52 channel: Peri<'a, AnyChannel>,
53 ringbuf: ReadableDmaRingBuffer<'a, W>, 53 ringbuf: ReadableDmaRingBuffer<'a, W>,
54 table: Table<2>, 54 table: Table<2>,
55 options: TransferOptions,
55} 56}
56 57
57impl<'a, W: Word> ReadableRingBuffer<'a, W> { 58impl<'a, W: Word> ReadableRingBuffer<'a, W> {
@@ -64,6 +65,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
64 peri_addr: *mut W, 65 peri_addr: *mut W,
65 buffer: &'a mut [W], 66 buffer: &'a mut [W],
66 options: TransferOptions, 67 options: TransferOptions,
68 register_updaters: RegisterUpdaters,
67 ) -> Self { 69 ) -> Self {
68 let channel: Peri<'a, AnyChannel> = channel.into(); 70 let channel: Peri<'a, AnyChannel> = channel.into();
69 71
@@ -72,8 +74,8 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
72 assert_eq!(half_len * 2, buffer.len()); 74 assert_eq!(half_len * 2, buffer.len());
73 75
74 let items = [ 76 let items = [
75 LinearItem::new_read(request, peri_addr, &mut buffer[..half_len]), 77 LinearItem::new_read(request, peri_addr, &mut buffer[..half_len], &register_updaters),
76 LinearItem::new_read(request, peri_addr, &mut buffer[half_len..]), 78 LinearItem::new_read(request, peri_addr, &mut buffer[half_len..], &register_updaters),
77 ]; 79 ];
78 let table = Table::new(items); 80 let table = Table::new(items);
79 81
@@ -84,6 +86,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
84 channel, 86 channel,
85 ringbuf: ReadableDmaRingBuffer::new(buffer), 87 ringbuf: ReadableDmaRingBuffer::new(buffer),
86 table, 88 table,
89 options,
87 } 90 }
88 } 91 }
89 92
@@ -211,6 +214,7 @@ pub struct WritableRingBuffer<'a, W: Word> {
211 channel: Peri<'a, AnyChannel>, 214 channel: Peri<'a, AnyChannel>,
212 ringbuf: WritableDmaRingBuffer<'a, W>, 215 ringbuf: WritableDmaRingBuffer<'a, W>,
213 table: Table<2>, 216 table: Table<2>,
217 options: TransferOptions,
214} 218}
215 219
216impl<'a, W: Word> WritableRingBuffer<'a, W> { 220impl<'a, W: Word> WritableRingBuffer<'a, W> {
@@ -221,6 +225,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> {
221 peri_addr: *mut W, 225 peri_addr: *mut W,
222 buffer: &'a mut [W], 226 buffer: &'a mut [W],
223 options: TransferOptions, 227 options: TransferOptions,
228 register_updaters: RegisterUpdaters,
224 ) -> Self { 229 ) -> Self {
225 let channel: Peri<'a, AnyChannel> = channel.into(); 230 let channel: Peri<'a, AnyChannel> = channel.into();
226 231
@@ -229,8 +234,8 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> {
229 assert_eq!(half_len * 2, buffer.len()); 234 assert_eq!(half_len * 2, buffer.len());
230 235
231 let items = [ 236 let items = [
232 LinearItem::new_write(request, &mut buffer[..half_len], peri_addr), 237 LinearItem::new_write(request, &mut buffer[..half_len], peri_addr, &register_updaters),
233 LinearItem::new_write(request, &mut buffer[half_len..], peri_addr), 238 LinearItem::new_write(request, &mut buffer[half_len..], peri_addr, &register_updaters),
234 ]; 239 ];
235 let table = Table::new(items); 240 let table = Table::new(items);
236 241
@@ -241,6 +246,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> {
241 channel, 246 channel,
242 ringbuf: WritableDmaRingBuffer::new(buffer), 247 ringbuf: WritableDmaRingBuffer::new(buffer),
243 table, 248 table,
249 options,
244 }; 250 };
245 251
246 this 252 this