aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchemicstry <[email protected]>2022-03-16 18:52:06 +0200
committerchemicstry <[email protected]>2022-03-16 18:52:06 +0200
commit34b5175d2c94b0254828ae600ed25c32b2837b66 (patch)
tree518cac813893bec7cf6e7bf9ff9afa3a51cc4fb4
parent2d224cf6a072bf9f12c56147c9a0339302ef47ce (diff)
Add more options to DMA
-rw-r--r--embassy-stm32/src/dma/dma.rs36
-rw-r--r--embassy-stm32/src/dma/mod.rs54
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;
9use crate::pac; 9use crate::pac;
10use crate::pac::dma::{regs, vals}; 10use crate::pac::dma::{regs, vals};
11 11
12use super::{Request, Word, WordSize}; 12use super::{Burst, FlowControl, Request, TransferOptions, Word, WordSize};
13 13
14impl From<WordSize> for vals::Size { 14impl 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
24impl 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
35impl 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
24struct State { 44struct 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() {
49foreach_dma_channel! { 69foreach_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
132pub 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
143pub enum FlowControl {
144 /// Flow control by DMA
145 Dma,
146 /// Flow control by peripheral
147 Peripheral,
148}
149
150pub 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
159impl 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
129mod transfers { 169mod 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 }