diff options
| author | chemicstry <[email protected]> | 2022-03-16 18:52:06 +0200 |
|---|---|---|
| committer | chemicstry <[email protected]> | 2022-03-16 18:52:06 +0200 |
| commit | 34b5175d2c94b0254828ae600ed25c32b2837b66 (patch) | |
| tree | 518cac813893bec7cf6e7bf9ff9afa3a51cc4fb4 | |
| parent | 2d224cf6a072bf9f12c56147c9a0339302ef47ce (diff) | |
Add more options to DMA
| -rw-r--r-- | embassy-stm32/src/dma/dma.rs | 36 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/mod.rs | 54 |
2 files changed, 83 insertions, 7 deletions
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 9f88c1141..0bce37e48 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs | |||
| @@ -9,7 +9,7 @@ use crate::interrupt; | |||
| 9 | use crate::pac; | 9 | use crate::pac; |
| 10 | use crate::pac::dma::{regs, vals}; | 10 | use crate::pac::dma::{regs, vals}; |
| 11 | 11 | ||
| 12 | use super::{Request, Word, WordSize}; | 12 | use super::{Burst, FlowControl, Request, TransferOptions, Word, WordSize}; |
| 13 | 13 | ||
| 14 | impl From<WordSize> for vals::Size { | 14 | impl From<WordSize> for vals::Size { |
| 15 | fn from(raw: WordSize) -> Self { | 15 | fn from(raw: WordSize) -> Self { |
| @@ -21,6 +21,26 @@ impl From<WordSize> for vals::Size { | |||
| 21 | } | 21 | } |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | impl From<Burst> for vals::Burst { | ||
| 25 | fn from(burst: Burst) -> Self { | ||
| 26 | match burst { | ||
| 27 | Burst::Single => vals::Burst::SINGLE, | ||
| 28 | Burst::Incr4 => vals::Burst::INCR4, | ||
| 29 | Burst::Incr8 => vals::Burst::INCR8, | ||
| 30 | Burst::Incr16 => vals::Burst::INCR16, | ||
| 31 | } | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 35 | impl From<FlowControl> for vals::Pfctrl { | ||
| 36 | fn from(flow: FlowControl) -> Self { | ||
| 37 | match flow { | ||
| 38 | FlowControl::Dma => vals::Pfctrl::DMA, | ||
| 39 | FlowControl::Peripheral => vals::Pfctrl::PERIPHERAL, | ||
| 40 | } | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 24 | struct State { | 44 | struct State { |
| 25 | ch_wakers: [AtomicWaker; DMA_CHANNEL_COUNT], | 45 | ch_wakers: [AtomicWaker; DMA_CHANNEL_COUNT], |
| 26 | } | 46 | } |
| @@ -49,7 +69,7 @@ pub(crate) unsafe fn init() { | |||
| 49 | foreach_dma_channel! { | 69 | foreach_dma_channel! { |
| 50 | ($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $index:expr, $dmamux:tt) => { | 70 | ($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $index:expr, $dmamux:tt) => { |
| 51 | impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { | 71 | impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { |
| 52 | unsafe fn start_write<W: Word>(&mut self, request: Request, buf: *const [W], reg_addr: *mut W) { | 72 | unsafe fn start_write<W: Word>(&mut self, request: Request, buf: *const [W], reg_addr: *mut W, options: TransferOptions) { |
| 53 | let (ptr, len) = super::slice_ptr_parts(buf); | 73 | let (ptr, len) = super::slice_ptr_parts(buf); |
| 54 | low_level_api::start_transfer( | 74 | low_level_api::start_transfer( |
| 55 | pac::$dma_peri, | 75 | pac::$dma_peri, |
| @@ -61,6 +81,7 @@ foreach_dma_channel! { | |||
| 61 | len, | 81 | len, |
| 62 | true, | 82 | true, |
| 63 | vals::Size::from(W::bits()), | 83 | vals::Size::from(W::bits()), |
| 84 | options, | ||
| 64 | #[cfg(dmamux)] | 85 | #[cfg(dmamux)] |
| 65 | <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, | 86 | <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, |
| 66 | #[cfg(dmamux)] | 87 | #[cfg(dmamux)] |
| @@ -68,7 +89,7 @@ foreach_dma_channel! { | |||
| 68 | ) | 89 | ) |
| 69 | } | 90 | } |
| 70 | 91 | ||
| 71 | unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W) { | 92 | unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W, options: TransferOptions) { |
| 72 | let buf = [repeated]; | 93 | let buf = [repeated]; |
| 73 | low_level_api::start_transfer( | 94 | low_level_api::start_transfer( |
| 74 | pac::$dma_peri, | 95 | pac::$dma_peri, |
| @@ -80,6 +101,7 @@ foreach_dma_channel! { | |||
| 80 | count, | 101 | count, |
| 81 | false, | 102 | false, |
| 82 | vals::Size::from(W::bits()), | 103 | vals::Size::from(W::bits()), |
| 104 | options, | ||
| 83 | #[cfg(dmamux)] | 105 | #[cfg(dmamux)] |
| 84 | <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, | 106 | <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, |
| 85 | #[cfg(dmamux)] | 107 | #[cfg(dmamux)] |
| @@ -87,7 +109,7 @@ foreach_dma_channel! { | |||
| 87 | ) | 109 | ) |
| 88 | } | 110 | } |
| 89 | 111 | ||
| 90 | unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *const W, buf: *mut [W]) { | 112 | unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *const W, buf: *mut [W], options: TransferOptions) { |
| 91 | let (ptr, len) = super::slice_ptr_parts_mut(buf); | 113 | let (ptr, len) = super::slice_ptr_parts_mut(buf); |
| 92 | low_level_api::start_transfer( | 114 | low_level_api::start_transfer( |
| 93 | pac::$dma_peri, | 115 | pac::$dma_peri, |
| @@ -99,6 +121,7 @@ foreach_dma_channel! { | |||
| 99 | len, | 121 | len, |
| 100 | true, | 122 | true, |
| 101 | vals::Size::from(W::bits()), | 123 | vals::Size::from(W::bits()), |
| 124 | options, | ||
| 102 | #[cfg(dmamux)] | 125 | #[cfg(dmamux)] |
| 103 | <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, | 126 | <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, |
| 104 | #[cfg(dmamux)] | 127 | #[cfg(dmamux)] |
| @@ -146,6 +169,7 @@ mod low_level_api { | |||
| 146 | mem_len: usize, | 169 | mem_len: usize, |
| 147 | incr_mem: bool, | 170 | incr_mem: bool, |
| 148 | data_size: vals::Size, | 171 | data_size: vals::Size, |
| 172 | options: TransferOptions, | ||
| 149 | #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux, | 173 | #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux, |
| 150 | #[cfg(dmamux)] dmamux_ch_num: u8, | 174 | #[cfg(dmamux)] dmamux_ch_num: u8, |
| 151 | ) { | 175 | ) { |
| @@ -180,6 +204,10 @@ mod low_level_api { | |||
| 180 | #[cfg(dma_v2)] | 204 | #[cfg(dma_v2)] |
| 181 | w.set_chsel(request); | 205 | w.set_chsel(request); |
| 182 | 206 | ||
| 207 | w.set_pburst(options.pburst.into()); | ||
| 208 | w.set_mburst(options.mburst.into()); | ||
| 209 | w.set_pfctrl(options.flow_ctrl.into()); | ||
| 210 | |||
| 183 | w.set_en(true); | 211 | w.set_en(true); |
| 184 | }); | 212 | }); |
| 185 | } | 213 | } |
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 4768a448c..f5b05589b 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs | |||
| @@ -46,6 +46,7 @@ pub(crate) mod sealed { | |||
| 46 | request: Request, | 46 | request: Request, |
| 47 | buf: *const [W], | 47 | buf: *const [W], |
| 48 | reg_addr: *mut W, | 48 | reg_addr: *mut W, |
| 49 | options: TransferOptions, | ||
| 49 | ); | 50 | ); |
| 50 | 51 | ||
| 51 | /// Starts this channel for writing a word repeatedly. | 52 | /// Starts this channel for writing a word repeatedly. |
| @@ -58,6 +59,7 @@ pub(crate) mod sealed { | |||
| 58 | repeated: W, | 59 | repeated: W, |
| 59 | count: usize, | 60 | count: usize, |
| 60 | reg_addr: *mut W, | 61 | reg_addr: *mut W, |
| 62 | options: TransferOptions, | ||
| 61 | ); | 63 | ); |
| 62 | 64 | ||
| 63 | /// Starts this channel for reading a stream of words. | 65 | /// Starts this channel for reading a stream of words. |
| @@ -71,6 +73,7 @@ pub(crate) mod sealed { | |||
| 71 | request: Request, | 73 | request: Request, |
| 72 | reg_addr: *const W, | 74 | reg_addr: *const W, |
| 73 | buf: *mut [W], | 75 | buf: *mut [W], |
| 76 | options: TransferOptions, | ||
| 74 | ); | 77 | ); |
| 75 | 78 | ||
| 76 | /// Requests the channel to stop. | 79 | /// Requests the channel to stop. |
| @@ -126,6 +129,43 @@ impl Word for u32 { | |||
| 126 | } | 129 | } |
| 127 | } | 130 | } |
| 128 | 131 | ||
| 132 | pub enum Burst { | ||
| 133 | /// Single transfer | ||
| 134 | Single, | ||
| 135 | /// Incremental burst of 4 beats | ||
| 136 | Incr4, | ||
| 137 | /// Incremental burst of 8 beats | ||
| 138 | Incr8, | ||
| 139 | /// Incremental burst of 16 beats | ||
| 140 | Incr16, | ||
| 141 | } | ||
| 142 | |||
| 143 | pub enum FlowControl { | ||
| 144 | /// Flow control by DMA | ||
| 145 | Dma, | ||
| 146 | /// Flow control by peripheral | ||
| 147 | Peripheral, | ||
| 148 | } | ||
| 149 | |||
| 150 | pub struct TransferOptions { | ||
| 151 | /// Peripheral burst transfer configuration | ||
| 152 | pub pburst: Burst, | ||
| 153 | /// Memory burst transfer configuration | ||
| 154 | pub mburst: Burst, | ||
| 155 | /// Flow control configuration | ||
| 156 | pub flow_ctrl: FlowControl, | ||
| 157 | } | ||
| 158 | |||
| 159 | impl Default for TransferOptions { | ||
| 160 | fn default() -> Self { | ||
| 161 | Self { | ||
| 162 | pburst: Burst::Single, | ||
| 163 | mburst: Burst::Single, | ||
| 164 | flow_ctrl: FlowControl::Dma, | ||
| 165 | } | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 129 | mod transfers { | 169 | mod transfers { |
| 130 | use super::*; | 170 | use super::*; |
| 131 | 171 | ||
| @@ -139,7 +179,7 @@ mod transfers { | |||
| 139 | assert!(buf.len() > 0 && buf.len() <= 0xFFFF); | 179 | assert!(buf.len() > 0 && buf.len() <= 0xFFFF); |
| 140 | unborrow!(channel); | 180 | unborrow!(channel); |
| 141 | 181 | ||
| 142 | unsafe { channel.start_read::<W>(request, reg_addr, buf) }; | 182 | unsafe { channel.start_read::<W>(request, reg_addr, buf, Default::default()) }; |
| 143 | 183 | ||
| 144 | Transfer::new(channel) | 184 | Transfer::new(channel) |
| 145 | } | 185 | } |
| @@ -154,7 +194,7 @@ mod transfers { | |||
| 154 | assert!(buf.len() > 0 && buf.len() <= 0xFFFF); | 194 | assert!(buf.len() > 0 && buf.len() <= 0xFFFF); |
| 155 | unborrow!(channel); | 195 | unborrow!(channel); |
| 156 | 196 | ||
| 157 | unsafe { channel.start_write::<W>(request, buf, reg_addr) }; | 197 | unsafe { channel.start_write::<W>(request, buf, reg_addr, Default::default()) }; |
| 158 | 198 | ||
| 159 | Transfer::new(channel) | 199 | Transfer::new(channel) |
| 160 | } | 200 | } |
| @@ -169,7 +209,15 @@ mod transfers { | |||
| 169 | ) -> impl Future<Output = ()> + 'a { | 209 | ) -> impl Future<Output = ()> + 'a { |
| 170 | unborrow!(channel); | 210 | unborrow!(channel); |
| 171 | 211 | ||
| 172 | unsafe { channel.start_write_repeated::<W>(request, repeated, count, reg_addr) }; | 212 | unsafe { |
| 213 | channel.start_write_repeated::<W>( | ||
| 214 | request, | ||
| 215 | repeated, | ||
| 216 | count, | ||
| 217 | reg_addr, | ||
| 218 | Default::default(), | ||
| 219 | ) | ||
| 220 | }; | ||
| 173 | 221 | ||
| 174 | Transfer::new(channel) | 222 | Transfer::new(channel) |
| 175 | } | 223 | } |
