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 | 2f24568de08e846d4bfafff90a5b9ba352d86431 (patch) | |
| tree | 764affc6badec7017d935e6e93567aa188ecdf44 /embassy-stm32/src | |
| parent | f67365a067634b62747c819253fb461624c29568 (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')
| -rw-r--r-- | embassy-stm32/src/dma/gpdma/linked_list.rs | 20 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/gpdma/mod.rs | 22 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/gpdma/ringbuffered.rs | 16 | ||||
| -rw-r--r-- | embassy-stm32/src/sai/mod.rs | 5 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/ringbuffered.rs | 3 |
5 files changed, 56 insertions, 10 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 @@ | |||
| 4 | use stm32_metapac::gpdma::regs; | 4 | use stm32_metapac::gpdma::regs; |
| 5 | use stm32_metapac::gpdma::vals::Dreq; | 5 | use stm32_metapac::gpdma::vals::Dreq; |
| 6 | 6 | ||
| 7 | use super::RegisterUpdaters; | ||
| 7 | use crate::dma::word::{Word, WordSize}; | 8 | use crate::dma::word::{Word, WordSize}; |
| 8 | use crate::dma::{Dir, Request}; | 9 | use crate::dma::{Dir, Request}; |
| 9 | 10 | ||
| @@ -41,7 +42,12 @@ pub struct LinearItem { | |||
| 41 | 42 | ||
| 42 | impl LinearItem { | 43 | impl 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))] | ||
| 79 | pub 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 | |||
| 88 | impl Default for RegisterUpdaters { | ||
| 89 | fn default() -> Self { | ||
| 90 | Self { | ||
| 91 | tr1: |_| {}, | ||
| 92 | tr2: |_| {}, | ||
| 93 | tr3: |_| {}, | ||
| 94 | } | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 76 | impl From<WordSize> for vals::Dw { | 98 | impl 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 | ||
| 9 | use embassy_hal_internal::Peri; | 9 | use embassy_hal_internal::Peri; |
| 10 | 10 | ||
| 11 | use super::{AnyChannel, TransferOptions, STATE}; | 11 | use super::{AnyChannel, RegisterUpdaters, TransferOptions, STATE}; |
| 12 | use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table}; | 12 | use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table}; |
| 13 | use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; | 13 | use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; |
| 14 | use crate::dma::word::Word; | 14 | use 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 | ||
| 57 | impl<'a, W: Word> ReadableRingBuffer<'a, W> { | 58 | impl<'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], ®ister_updaters), |
| 76 | LinearItem::new_read(request, peri_addr, &mut buffer[half_len..]), | 78 | LinearItem::new_read(request, peri_addr, &mut buffer[half_len..], ®ister_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 | ||
| 216 | impl<'a, W: Word> WritableRingBuffer<'a, W> { | 220 | impl<'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, ®ister_updaters), |
| 233 | LinearItem::new_write(request, &mut buffer[half_len..], peri_addr), | 238 | LinearItem::new_write(request, &mut buffer[half_len..], peri_addr, ®ister_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 |
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 88cc225dd..ac1ab2505 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs | |||
| @@ -687,12 +687,13 @@ fn get_ring_buffer<'d, T: Instance, W: word::Word>( | |||
| 687 | //the new_write() and new_read() always use circular mode | 687 | //the new_write() and new_read() always use circular mode |
| 688 | ..Default::default() | 688 | ..Default::default() |
| 689 | }; | 689 | }; |
| 690 | let updaters = Default::default(); | ||
| 690 | match tx_rx { | 691 | match tx_rx { |
| 691 | TxRx::Transmitter => RingBuffer::Writable(unsafe { | 692 | TxRx::Transmitter => RingBuffer::Writable(unsafe { |
| 692 | WritableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts) | 693 | WritableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts, updaters) |
| 693 | }), | 694 | }), |
| 694 | TxRx::Receiver => RingBuffer::Readable(unsafe { | 695 | TxRx::Receiver => RingBuffer::Readable(unsafe { |
| 695 | ReadableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts) | 696 | ReadableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts, updaters) |
| 696 | }), | 697 | }), |
| 697 | } | 698 | } |
| 698 | } | 699 | } |
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index bea56c991..78bf4b72f 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs | |||
| @@ -103,6 +103,7 @@ impl<'d> UartRx<'d, Async> { | |||
| 103 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); | 103 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); |
| 104 | 104 | ||
| 105 | let opts = Default::default(); | 105 | let opts = Default::default(); |
| 106 | let updaters = Default::default(); | ||
| 106 | 107 | ||
| 107 | // Safety: we forget the struct before this function returns. | 108 | // Safety: we forget the struct before this function returns. |
| 108 | let rx_dma = self.rx_dma.as_mut().unwrap(); | 109 | let rx_dma = self.rx_dma.as_mut().unwrap(); |
| @@ -112,7 +113,7 @@ impl<'d> UartRx<'d, Async> { | |||
| 112 | let info = self.info; | 113 | let info = self.info; |
| 113 | let state = self.state; | 114 | let state = self.state; |
| 114 | let kernel_clock = self.kernel_clock; | 115 | let kernel_clock = self.kernel_clock; |
| 115 | let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(info.regs), dma_buf, opts) }; | 116 | let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(info.regs), dma_buf, opts, updaters) }; |
| 116 | let rx = unsafe { self.rx.as_ref().map(|x| x.clone_unchecked()) }; | 117 | let rx = unsafe { self.rx.as_ref().map(|x| x.clone_unchecked()) }; |
| 117 | let rts = unsafe { self.rts.as_ref().map(|x| x.clone_unchecked()) }; | 118 | let rts = unsafe { self.rts.as_ref().map(|x| x.clone_unchecked()) }; |
| 118 | 119 | ||
