aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/dma/bdma.rs374
-rw-r--r--embassy-stm32/src/dma/dma.rs445
-rw-r--r--embassy-stm32/src/dma/mod.rs195
-rw-r--r--embassy-stm32/src/i2c/v2.rs10
-rw-r--r--embassy-stm32/src/spi/v1.rs27
-rw-r--r--embassy-stm32/src/spi/v2.rs27
-rw-r--r--embassy-stm32/src/spi/v3.rs27
-rw-r--r--embassy-stm32/src/usart/v1.rs10
-rw-r--r--embassy-stm32/src/usart/v2.rs11
9 files changed, 579 insertions, 547 deletions
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index 528e49f42..1dcd0c228 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -1,20 +1,29 @@
1#![macro_use] 1#![macro_use]
2 2
3use core::future::Future;
4use core::sync::atomic::{fence, Ordering}; 3use core::sync::atomic::{fence, Ordering};
5use core::task::{Poll, Waker}; 4use core::task::Waker;
6 5
7use embassy::interrupt::{Interrupt, InterruptExt}; 6use embassy::interrupt::{Interrupt, InterruptExt};
8use embassy::waitqueue::AtomicWaker; 7use embassy::waitqueue::AtomicWaker;
9use embassy_hal_common::drop::OnDrop;
10use futures::future::poll_fn;
11 8
12use crate::dma::{Channel, Request}; 9use crate::dma::Request;
13use crate::interrupt; 10use crate::interrupt;
14use crate::pac; 11use crate::pac;
15use crate::pac::bdma::vals; 12use crate::pac::bdma::vals;
16use crate::rcc::sealed::RccPeripheral; 13use crate::rcc::sealed::RccPeripheral;
17 14
15use super::{Word, WordSize};
16
17impl From<WordSize> for vals::Size {
18 fn from(raw: WordSize) -> Self {
19 match raw {
20 WordSize::OneByte => Self::BITS8,
21 WordSize::TwoBytes => Self::BITS16,
22 WordSize::FourBytes => Self::BITS32,
23 }
24 }
25}
26
18const CH_COUNT: usize = pac::peripheral_count!(bdma) * 8; 27const CH_COUNT: usize = pac::peripheral_count!(bdma) * 8;
19 28
20struct State { 29struct State {
@@ -32,118 +41,6 @@ impl State {
32 41
33static STATE: State = State::new(); 42static STATE: State = State::new();
34 43
35#[allow(unused)]
36pub(crate) unsafe fn do_transfer(
37 dma: pac::bdma::Dma,
38 channel_number: u8,
39 state_number: u8,
40 request: Request,
41 dir: vals::Dir,
42 peri_addr: *const u8,
43 mem_addr: *mut u8,
44 mem_len: usize,
45 incr_mem: bool,
46 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
47 #[cfg(dmamux)] dmamux_ch_num: u8,
48) -> impl Future<Output = ()> {
49 // ndtr is max 16 bits.
50 assert!(mem_len <= 0xFFFF);
51
52 let ch = dma.ch(channel_number as _);
53
54 // Reset status
55 dma.ifcr().write(|w| {
56 w.set_tcif(channel_number as _, true);
57 w.set_teif(channel_number as _, true);
58 });
59
60 let on_drop = OnDrop::new(move || unsafe {
61 _stop(dma, channel_number);
62 });
63
64 #[cfg(dmamux)]
65 super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
66
67 #[cfg(bdma_v2)]
68 critical_section::with(|_| {
69 dma.cselr()
70 .modify(|w| w.set_cs(channel_number as _, request))
71 });
72
73 // "Preceding reads and writes cannot be moved past subsequent writes."
74 fence(Ordering::Release);
75
76 ch.par().write_value(peri_addr as u32);
77 ch.mar().write_value(mem_addr as u32);
78 ch.ndtr().write(|w| w.set_ndt(mem_len as u16));
79 ch.cr().write(|w| {
80 w.set_psize(vals::Size::BITS8);
81 w.set_msize(vals::Size::BITS8);
82 if incr_mem {
83 w.set_minc(vals::Inc::ENABLED);
84 } else {
85 w.set_minc(vals::Inc::DISABLED);
86 }
87 w.set_dir(dir);
88 w.set_teie(true);
89 w.set_tcie(true);
90 w.set_en(true);
91 });
92
93 async move {
94 let res = poll_fn(|cx| {
95 STATE.ch_wakers[state_number as usize].register(cx.waker());
96
97 let isr = dma.isr().read();
98
99 // TODO handle error
100 assert!(!isr.teif(channel_number as _));
101
102 if isr.tcif(channel_number as _) {
103 Poll::Ready(())
104 } else {
105 Poll::Pending
106 }
107 })
108 .await;
109
110 drop(on_drop)
111 }
112}
113
114unsafe fn _stop(dma: pac::bdma::Dma, ch: u8) {
115 let ch = dma.ch(ch as _);
116
117 // Disable the channel and interrupts with the default value.
118 ch.cr().write(|_| ());
119
120 // Wait for the transfer to complete when it was ongoing.
121 while ch.cr().read().en() {}
122
123 // "Subsequent reads and writes cannot be moved ahead of preceding reads."
124 fence(Ordering::Acquire);
125}
126
127unsafe fn _is_stopped(dma: pac::bdma::Dma, ch: u8) -> bool {
128 let ch = dma.ch(ch as _);
129 ch.cr().read().en()
130}
131
132/// Gets the total remaining transfers for the channel
133/// Note: this will be zero for transfers that completed without cancellation.
134unsafe fn _get_remaining_transfers(dma: pac::bdma::Dma, ch: u8) -> u16 {
135 // get a handle on the channel itself
136 let ch = dma.ch(ch as _);
137 // read the remaining transfer count. If this is zero, the transfer completed fully.
138 ch.ndtr().read().ndt()
139}
140
141/// Sets the waker for the specified DMA channel
142unsafe fn _set_waker(_dma: pac::bdma::Dma, state_number: u8, waker: &Waker) {
143 let n = state_number as usize;
144 STATE.ch_wakers[n].register(waker);
145}
146
147macro_rules! dma_num { 44macro_rules! dma_num {
148 (DMA1) => { 45 (DMA1) => {
149 0 46 0
@@ -190,100 +87,87 @@ pub(crate) unsafe fn init() {
190 87
191pac::dma_channels! { 88pac::dma_channels! {
192 ($channel_peri:ident, $dma_peri:ident, bdma, $channel_num:expr, $dmamux:tt) => { 89 ($channel_peri:ident, $dma_peri:ident, bdma, $channel_num:expr, $dmamux:tt) => {
193 impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {} 90 impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
194 impl Channel for crate::peripherals::$channel_peri 91
195 { 92 unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut u32) {
196 type ReadFuture<'a> = impl Future<Output = ()> + 'a; 93 low_level_api::reset_status(crate::pac::$dma_peri, $channel_num);
197 type WriteFuture<'a> = impl Future<Output = ()> + 'a; 94 low_level_api::start_transfer(
198 95 crate::pac::$dma_peri,
199 fn read<'a>( 96 $channel_num,
200 &'a mut self, 97 #[cfg(any(bdma_v2, dmamux))]
201 request: Request, 98 request,
202 src: *mut u8, 99 vals::Dir::FROMMEMORY,
203 buf: &'a mut [u8], 100 reg_addr as *const u32,
204 ) -> Self::ReadFuture<'a> { 101 buf.as_ptr() as *mut u32,
205 unsafe { 102 buf.len(),
206 do_transfer( 103 true,
207 crate::pac::$dma_peri, 104 vals::Size::from(W::bits()),
208 $channel_num, 105 #[cfg(dmamux)]
209 (dma_num!($dma_peri) * 8) + $channel_num, 106 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
210 request, 107 #[cfg(dmamux)]
211 vals::Dir::FROMPERIPHERAL, 108 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
212 src, 109 );
213 buf.as_mut_ptr(),
214 buf.len(),
215 true,
216 #[cfg(dmamux)]
217 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
218 #[cfg(dmamux)]
219 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
220 )
221 }
222 } 110 }
223 111
224 fn write<'a>( 112
225 &'a mut self, 113 unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut u32) {
226 request: Request, 114 let buf = [repeated];
227 buf: &'a [u8], 115 low_level_api::reset_status(crate::pac::$dma_peri, $channel_num);
228 dst: *mut u8, 116 low_level_api::start_transfer(
229 ) -> Self::WriteFuture<'a> { 117 crate::pac::$dma_peri,
230 unsafe { 118 $channel_num,
231 do_transfer( 119 #[cfg(any(bdma_v2, dmamux))]
232 crate::pac::$dma_peri, 120 request,
233 $channel_num, 121 vals::Dir::FROMMEMORY,
234 (dma_num!($dma_peri) * 8) + $channel_num, 122 reg_addr as *const u32,
235 request, 123 buf.as_ptr() as *mut u32,
236 vals::Dir::FROMMEMORY, 124 count,
237 dst, 125 false,
238 buf.as_ptr() as *mut u8, 126 vals::Size::from(W::bits()),
239 buf.len(), 127 #[cfg(dmamux)]
240 true, 128 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
241 #[cfg(dmamux)] 129 #[cfg(dmamux)]
242 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, 130 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
243 #[cfg(dmamux)] 131 )
244 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
245 )
246 }
247 } 132 }
248 133
249 fn write_x<'a>( 134 unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *mut u32, buf: &mut [W]) {
250 &'a mut self, 135 low_level_api::reset_status(crate::pac::$dma_peri, $channel_num);
251 request: Request, 136 low_level_api::start_transfer(
252 word: &u8, 137 crate::pac::$dma_peri,
253 count: usize, 138 $channel_num,
254 dst: *mut u8, 139 #[cfg(any(bdma_v2, dmamux))]
255 ) -> Self::WriteFuture<'a> { 140 request,
256 unsafe { 141 vals::Dir::FROMPERIPHERAL,
257 do_transfer( 142 reg_addr as *const u32,
258 crate::pac::$dma_peri, 143 buf.as_ptr() as *mut u32,
259 $channel_num, 144 buf.len(),
260 (dma_num!($dma_peri) * 8) + $channel_num, 145 true,
261 request, 146 vals::Size::from(W::bits()),
262 vals::Dir::FROMMEMORY, 147 #[cfg(dmamux)]
263 dst, 148 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
264 word as *const u8 as *mut u8, 149 #[cfg(dmamux)]
265 count, 150 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
266 false, 151 );
267 #[cfg(dmamux)]
268 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
269 #[cfg(dmamux)]
270 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
271 )
272 }
273 } 152 }
274 fn stop <'a>(&'a mut self){ 153
275 unsafe {_stop(crate::pac::$dma_peri, $channel_num);} 154 fn request_stop(&mut self){
155 unsafe {low_level_api::request_stop(crate::pac::$dma_peri, $channel_num);}
276 } 156 }
277 fn is_stopped<'a>(&'a self) -> bool { 157
278 unsafe {_is_stopped(crate::pac::$dma_peri, $channel_num)} 158 fn is_stopped(&self) -> bool {
159 unsafe {low_level_api::is_stopped(crate::pac::$dma_peri, $channel_num)}
279 } 160 }
280 fn remaining_transfers<'a>(&'a mut self) -> u16 { 161 fn remaining_transfers(&mut self) -> u16 {
281 unsafe {_get_remaining_transfers(crate::pac::$dma_peri, $channel_num)} 162 unsafe {low_level_api::get_remaining_transfers(crate::pac::$dma_peri, $channel_num)}
282 } 163 }
283 fn set_waker<'a>(&'a mut self, waker: &'a Waker) { 164
284 unsafe {_set_waker(crate::pac::$dma_peri, $channel_num, waker )} 165 fn set_waker(&mut self, waker: &Waker) {
166 unsafe {low_level_api::set_waker(crate::pac::$dma_peri, $channel_num, waker )}
285 } 167 }
286 } 168 }
169
170 impl crate::dma::Channel for crate::peripherals::$channel_peri {}
287 }; 171 };
288} 172}
289 173
@@ -295,3 +179,91 @@ pac::interrupts! {
295 } 179 }
296 }; 180 };
297} 181}
182
183mod low_level_api {
184 use super::*;
185
186 pub unsafe fn start_transfer(
187 dma: pac::bdma::Dma,
188 channel_number: u8,
189 #[cfg(any(bdma_v2, dmamux))] request: Request,
190 dir: vals::Dir,
191 peri_addr: *const u32,
192 mem_addr: *mut u32,
193 mem_len: usize,
194 incr_mem: bool,
195 data_size: vals::Size,
196 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
197 #[cfg(dmamux)] dmamux_ch_num: u8,
198 ) {
199 let ch = dma.ch(channel_number as _);
200
201 #[cfg(dmamux)]
202 super::super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
203
204 #[cfg(bdma_v2)]
205 critical_section::with(|_| {
206 dma.cselr()
207 .modify(|w| w.set_cs(channel_number as _, request))
208 });
209
210 // "Preceding reads and writes cannot be moved past subsequent writes."
211 fence(Ordering::SeqCst);
212
213 ch.par().write_value(peri_addr as u32);
214 ch.mar().write_value(mem_addr as u32);
215 ch.ndtr().write(|w| w.set_ndt(mem_len as u16));
216 ch.cr().write(|w| {
217 w.set_psize(data_size);
218 w.set_msize(data_size);
219 if incr_mem {
220 w.set_minc(vals::Inc::ENABLED);
221 } else {
222 w.set_minc(vals::Inc::DISABLED);
223 }
224 w.set_dir(dir);
225 w.set_teie(true);
226 w.set_tcie(true);
227 w.set_en(true);
228 });
229 }
230
231 pub unsafe fn request_stop(dma: pac::bdma::Dma, channel_number: u8) {
232 reset_status(dma, channel_number);
233
234 let ch = dma.ch(channel_number as _);
235
236 // Disable the channel and interrupts with the default value.
237 ch.cr().write(|_| ());
238
239 // "Subsequent reads and writes cannot be moved ahead of preceding reads."
240 fence(Ordering::SeqCst);
241 }
242
243 pub unsafe fn is_stopped(dma: pac::bdma::Dma, ch: u8) -> bool {
244 let ch = dma.ch(ch as _);
245 ch.cr().read().en()
246 }
247
248 /// Gets the total remaining transfers for the channel
249 /// Note: this will be zero for transfers that completed without cancellation.
250 pub unsafe fn get_remaining_transfers(dma: pac::bdma::Dma, ch: u8) -> u16 {
251 // get a handle on the channel itself
252 let ch = dma.ch(ch as _);
253 // read the remaining transfer count. If this is zero, the transfer completed fully.
254 ch.ndtr().read().ndt()
255 }
256
257 /// Sets the waker for the specified DMA channel
258 pub unsafe fn set_waker(_dma: pac::bdma::Dma, state_number: u8, waker: &Waker) {
259 let n = state_number as usize;
260 STATE.ch_wakers[n].register(waker);
261 }
262
263 pub unsafe fn reset_status(dma: pac::bdma::Dma, channel_number: u8) {
264 dma.ifcr().write(|w| {
265 w.set_tcif(channel_number as _, true);
266 w.set_teif(channel_number as _, true);
267 });
268 }
269}
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index 257f21a73..c99ff27ba 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -1,21 +1,28 @@
1use core::future::Future;
2use core::sync::atomic::{fence, Ordering}; 1use core::sync::atomic::{fence, Ordering};
3use core::task::{Poll, Waker}; 2use core::task::Waker;
4 3
5use embassy::interrupt::{Interrupt, InterruptExt}; 4use embassy::interrupt::{Interrupt, InterruptExt};
6use embassy::waitqueue::AtomicWaker; 5use embassy::waitqueue::AtomicWaker;
7use embassy_hal_common::drop::OnDrop;
8use futures::future::poll_fn;
9 6
10use crate::interrupt; 7use crate::interrupt;
11use crate::pac; 8use crate::pac;
12use crate::pac::dma::{regs, vals}; 9use crate::pac::dma::{regs, vals};
13use crate::rcc::sealed::RccPeripheral; 10use crate::rcc::sealed::RccPeripheral;
14 11
15use super::{Channel, Request}; 12use super::{Request, Word, WordSize};
16 13
17const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8; 14const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8;
18 15
16impl From<WordSize> for vals::Size {
17 fn from(raw: WordSize) -> Self {
18 match raw {
19 WordSize::OneByte => Self::BITS8,
20 WordSize::TwoBytes => Self::BITS16,
21 WordSize::FourBytes => Self::BITS32,
22 }
23 }
24}
25
19struct State { 26struct State {
20 ch_wakers: [AtomicWaker; CH_COUNT], 27 ch_wakers: [AtomicWaker; CH_COUNT],
21} 28}
@@ -31,164 +38,6 @@ impl State {
31 38
32static STATE: State = State::new(); 39static STATE: State = State::new();
33 40
34//async unsafe fn do_transfer(ch: &mut impl Channel, ch_func: u8, src: *const u8, dst: &mut [u8]) {
35
36#[allow(unused)]
37pub(crate) unsafe fn do_transfer(
38 dma: pac::dma::Dma,
39 channel_number: u8,
40 state_number: u8,
41 request: Request,
42 dir: vals::Dir,
43 peri_addr: *const u8,
44 mem_addr: *mut u8,
45 mem_len: usize,
46 incr_mem: bool,
47 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
48 #[cfg(dmamux)] dmamux_ch_num: u8,
49) -> impl Future<Output = ()> {
50 // ndtr is max 16 bits.
51 assert!(mem_len <= 0xFFFF);
52
53 // Reset status
54 let isrn = channel_number as usize / 4;
55 let isrbit = channel_number as usize % 4;
56 _reset_status(&dma, isrn, isrbit);
57
58 let ch = dma.st(channel_number as _);
59
60 let on_drop = OnDrop::new(move || unsafe {
61 _stop(&dma, channel_number);
62 });
63
64 // "Preceding reads and writes cannot be moved past subsequent writes."
65 fence(Ordering::Release);
66
67 // Actually start the transaction
68 _start_transfer(
69 request,
70 dir,
71 peri_addr,
72 mem_addr,
73 mem_len,
74 incr_mem,
75 ch,
76 #[cfg(dmamux)]
77 dmamux_regs,
78 #[cfg(dmamux)]
79 dmamux_ch_num,
80 );
81
82 async move {
83 let res = poll_fn(|cx| {
84 let n = state_number as usize;
85 STATE.ch_wakers[n].register(cx.waker());
86
87 let isr = dma.isr(isrn).read();
88
89 // TODO handle error
90 assert!(!isr.teif(isrbit));
91
92 if isr.tcif(isrbit) {
93 Poll::Ready(())
94 } else {
95 Poll::Pending
96 }
97 })
98 .await;
99
100 drop(on_drop)
101 }
102}
103
104unsafe fn _reset_status(dma: &crate::pac::dma::Dma, isrn: usize, isrbit: usize) {
105 dma.ifcr(isrn).write(|w| {
106 w.set_tcif(isrbit, true);
107 w.set_teif(isrbit, true);
108 });
109}
110
111unsafe fn _start_transfer(
112 request: Request,
113 dir: vals::Dir,
114 peri_addr: *const u8,
115 mem_addr: *mut u8,
116 mem_len: usize,
117 incr_mem: bool,
118 ch: crate::pac::dma::St,
119 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
120 #[cfg(dmamux)] dmamux_ch_num: u8,
121) {
122 #[cfg(dmamux)]
123 super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
124
125 // "Preceding reads and writes cannot be moved past subsequent writes."
126 fence(Ordering::Release);
127
128 ch.par().write_value(peri_addr as u32);
129 ch.m0ar().write_value(mem_addr as u32);
130 ch.ndtr().write_value(regs::Ndtr(mem_len as _));
131 ch.cr().write(|w| {
132 w.set_dir(dir);
133 w.set_msize(vals::Size::BITS8);
134 w.set_psize(vals::Size::BITS8);
135 if incr_mem {
136 w.set_minc(vals::Inc::INCREMENTED);
137 } else {
138 w.set_minc(vals::Inc::FIXED);
139 }
140 w.set_pinc(vals::Inc::FIXED);
141 w.set_teie(true);
142 w.set_tcie(true);
143 #[cfg(dma_v1)]
144 w.set_trbuff(true);
145
146 #[cfg(dma_v2)]
147 w.set_chsel(request);
148
149 w.set_en(true);
150 });
151}
152
153/// Stops the DMA channel.
154unsafe fn _stop(dma: &pac::dma::Dma, ch: u8) {
155 // get a handle on the channel itself
156 let ch = dma.st(ch as _);
157
158 // Disable the channel and interrupts with the default value.
159 ch.cr().write(|_| ());
160
161 // Wait for the transfer to complete when it was ongoing.
162 while ch.cr().read().en() {}
163
164 // "Subsequent reads and writes cannot be moved ahead of preceding reads."
165 fence(Ordering::Acquire);
166}
167
168/// Gets the running status of the channel
169unsafe fn _is_stopped(dma: &pac::dma::Dma, ch: u8) -> bool {
170 // get a handle on the channel itself
171 let ch = dma.st(ch as _);
172
173 // Wait for the transfer to complete when it was ongoing.
174 ch.cr().read().en()
175}
176
177/// Gets the total remaining transfers for the channel
178/// Note: this will be zero for transfers that completed without cancellation.
179unsafe fn _get_remaining_transfers(dma: &pac::dma::Dma, ch: u8) -> u16 {
180 // get a handle on the channel itself
181 let ch = dma.st(ch as _);
182 // read the remaining transfer count. If this is zero, the transfer completed fully.
183 ch.ndtr().read().ndt()
184}
185
186/// Sets the waker for the specified DMA channel
187unsafe fn _set_waker(_dma: &pac::dma::Dma, state_number: u8, waker: &Waker) {
188 let n = state_number as usize;
189 STATE.ch_wakers[n].register(waker);
190}
191
192macro_rules! dma_num { 41macro_rules! dma_num {
193 (DMA1) => { 42 (DMA1) => {
194 0 43 0
@@ -234,120 +83,86 @@ pub(crate) unsafe fn init() {
234 83
235pac::dma_channels! { 84pac::dma_channels! {
236 ($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $dmamux:tt) => { 85 ($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $dmamux:tt) => {
237 impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {} 86 impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
238 impl Channel for crate::peripherals::$channel_peri 87 unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut u32) {
239 { 88 let isrn = $channel_num as usize / 4;
240 type ReadFuture<'a> = impl Future<Output = ()> + 'a; 89 let isrbit = $channel_num as usize % 4;
241 type WriteFuture<'a> = impl Future<Output = ()> + 'a; 90 low_level_api::reset_status(&crate::pac::$dma_peri, isrn, isrbit);
242 91 low_level_api::start_transfer(
243 fn read<'a>( 92 request,
244 &'a mut self, 93 vals::Dir::MEMORYTOPERIPHERAL,
245 request: Request, 94 reg_addr as *const u32,
246 src: *mut u8, 95 buf.as_ptr() as *mut u32,
247 buf: &'a mut [u8], 96 buf.len(),
248 ) -> Self::ReadFuture<'a> { 97 true,
249 unsafe { 98 crate::pac::$dma_peri.st($channel_num as _),
250 do_transfer( 99 vals::Size::from(W::bits()),
251 crate::pac::$dma_peri, 100 #[cfg(dmamux)]
252 $channel_num, 101 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
253 (dma_num!($dma_peri) * 8) + $channel_num, 102 #[cfg(dmamux)]
254 request, 103 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
255 vals::Dir::PERIPHERALTOMEMORY, 104 )
256 src,
257 buf.as_mut_ptr(),
258 buf.len(),
259 true,
260 #[cfg(dmamux)]
261 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
262 #[cfg(dmamux)]
263 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
264 )
265 }
266 } 105 }
267 106
268 fn write<'a>( 107 unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut u32) {
269 &'a mut self, 108 let buf = [repeated];
270 request: Request, 109 let isrn = $channel_num as usize / 4;
271 buf: &'a [u8], 110 let isrbit = $channel_num as usize % 4;
272 dst: *mut u8, 111 low_level_api::reset_status(&crate::pac::$dma_peri, isrn, isrbit);
273 ) -> Self::WriteFuture<'a> { 112 low_level_api::start_transfer(
274 unsafe { 113 request,
275 do_transfer( 114 vals::Dir::MEMORYTOPERIPHERAL,
276 crate::pac::$dma_peri, 115 reg_addr as *const u32,
277 $channel_num, 116 buf.as_ptr() as *mut u32,
278 (dma_num!($dma_peri) * 8) + $channel_num, 117 count,
279 request, 118 false,
280 vals::Dir::MEMORYTOPERIPHERAL, 119 crate::pac::$dma_peri.st($channel_num as _),
281 dst, 120 vals::Size::from(W::bits()),
282 buf.as_ptr() as *mut u8, 121 #[cfg(dmamux)]
283 buf.len(), 122 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
284 true, 123 #[cfg(dmamux)]
285 #[cfg(dmamux)] 124 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
286 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, 125 )
287 #[cfg(dmamux)]
288 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
289 )
290 }
291 } 126 }
292 127
293 fn write_x<'a>( 128 unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *mut u32, buf: &mut [W]) {
294 &'a mut self, 129 let isrn = $channel_num as usize / 4;
295 request: Request, 130 let isrbit = $channel_num as usize % 4;
296 word: &u8, 131 low_level_api::reset_status(&crate::pac::$dma_peri, isrn, isrbit);
297 num: usize, 132 low_level_api::start_transfer(
298 dst: *mut u8, 133 request,
299 ) -> Self::WriteFuture<'a> { 134 vals::Dir::PERIPHERALTOMEMORY,
300 unsafe { 135 reg_addr as *const u32,
301 do_transfer( 136 buf.as_ptr() as *mut u32,
302 crate::pac::$dma_peri, 137 buf.len(),
303 $channel_num, 138 true,
304 (dma_num!($dma_peri) * 8) + $channel_num, 139 crate::pac::$dma_peri.st($channel_num as _),
305 request, 140 vals::Size::from(W::bits()),
306 vals::Dir::MEMORYTOPERIPHERAL, 141 #[cfg(dmamux)]
307 dst, 142 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
308 word as *const u8 as *mut u8, 143 #[cfg(dmamux)]
309 num, 144 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
310 false, 145 );
311 #[cfg(dmamux)]
312 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
313 #[cfg(dmamux)]
314 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
315 )
316 }
317 }
318 fn stop <'a>(&'a mut self){
319 unsafe {_stop(&crate::pac::$dma_peri, $channel_num);}
320 } 146 }
321 fn is_stopped<'a>(&'a self) -> bool { 147
322 unsafe {_is_stopped(&crate::pac::$dma_peri, $channel_num)} 148 fn request_stop(&mut self) {
149 unsafe {low_level_api::request_stop(&crate::pac::$dma_peri, $channel_num);}
323 } 150 }
324 fn remaining_transfers<'a>(&'a mut self) -> u16 { 151
325 unsafe {_get_remaining_transfers(&crate::pac::$dma_peri, $channel_num)} 152 fn is_stopped(&self) -> bool {
153 unsafe {low_level_api::is_stopped(&crate::pac::$dma_peri, $channel_num)}
326 } 154 }
327 fn set_waker<'a>(&'a mut self, waker: &'a Waker) { 155
328 unsafe {_set_waker(&crate::pac::$dma_peri, $channel_num, waker )} 156 fn remaining_transfers(&mut self) -> u16 {
157 unsafe {low_level_api::get_remaining_transfers(&crate::pac::$dma_peri, $channel_num)}
329 } 158 }
330 fn start<'a>(&'a mut self, request: Request, buf: &'a [u8], dst: *mut u8){ 159
331 unsafe { 160 fn set_waker(&mut self, waker: &Waker) {
332 let isrn = $channel_num as usize / 4; 161 unsafe {low_level_api::set_waker(&crate::pac::$dma_peri, $channel_num, waker )}
333 let isrbit = $channel_num as usize % 4;
334 _reset_status(&crate::pac::$dma_peri, isrn, isrbit);
335 _start_transfer(
336 request,
337 vals::Dir::MEMORYTOPERIPHERAL,
338 dst,
339 buf.as_ptr() as *mut u8,
340 buf.len(),
341 true,
342 crate::pac::$dma_peri.st($channel_num as _),
343 #[cfg(dmamux)]
344 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
345 #[cfg(dmamux)]
346 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
347 )
348 }
349 } 162 }
350 } 163 }
164
165 impl crate::dma::Channel for crate::peripherals::$channel_peri { }
351 }; 166 };
352} 167}
353 168
@@ -359,3 +174,99 @@ pac::interrupts! {
359 } 174 }
360 }; 175 };
361} 176}
177
178mod low_level_api {
179 use super::*;
180
181 pub unsafe fn start_transfer(
182 request: Request,
183 dir: vals::Dir,
184 peri_addr: *const u32,
185 mem_addr: *mut u32,
186 mem_len: usize,
187 incr_mem: bool,
188 ch: crate::pac::dma::St,
189 data_size: vals::Size,
190 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
191 #[cfg(dmamux)] dmamux_ch_num: u8,
192 ) {
193 #[cfg(dmamux)]
194 super::super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
195
196 // "Preceding reads and writes cannot be moved past subsequent writes."
197 fence(Ordering::SeqCst);
198
199 ch.par().write_value(peri_addr as u32);
200 ch.m0ar().write_value(mem_addr as u32);
201 ch.ndtr().write_value(regs::Ndtr(mem_len as _));
202 ch.cr().write(|w| {
203 w.set_dir(dir);
204 w.set_msize(data_size);
205 w.set_psize(data_size);
206 w.set_pl(vals::Pl::VERYHIGH);
207 if incr_mem {
208 w.set_minc(vals::Inc::INCREMENTED);
209 } else {
210 w.set_minc(vals::Inc::FIXED);
211 }
212 w.set_pinc(vals::Inc::FIXED);
213 w.set_teie(true);
214 w.set_tcie(true);
215 #[cfg(dma_v1)]
216 w.set_trbuff(true);
217
218 #[cfg(dma_v2)]
219 w.set_chsel(request);
220
221 w.set_en(true);
222 });
223 }
224
225 /// Stops the DMA channel.
226 pub unsafe fn request_stop(dma: &pac::dma::Dma, channel_number: u8) {
227 // Reset status
228 let isrn = channel_number as usize / 4;
229 let isrbit = channel_number as usize % 4;
230 reset_status(dma, isrn, isrbit);
231
232 // get a handle on the channel itself
233 let ch = dma.st(channel_number as _);
234
235 // Disable the channel and interrupts with the default value.
236 ch.cr().write(|_| ());
237
238 // "Subsequent reads and writes cannot be moved ahead of preceding reads."
239 fence(Ordering::SeqCst);
240 }
241
242 /// Gets the running status of the channel
243 pub unsafe fn is_stopped(dma: &pac::dma::Dma, ch: u8) -> bool {
244 // get a handle on the channel itself
245 let ch = dma.st(ch as _);
246
247 // Wait for the transfer to complete when it was ongoing.
248 ch.cr().read().en()
249 }
250
251 /// Gets the total remaining transfers for the channel
252 /// Note: this will be zero for transfers that completed without cancellation.
253 pub unsafe fn get_remaining_transfers(dma: &pac::dma::Dma, ch: u8) -> u16 {
254 // get a handle on the channel itself
255 let ch = dma.st(ch as _);
256 // read the remaining transfer count. If this is zero, the transfer completed fully.
257 ch.ndtr().read().ndt()
258 }
259
260 /// Sets the waker for the specified DMA channel
261 pub unsafe fn set_waker(_dma: &pac::dma::Dma, state_number: u8, waker: &Waker) {
262 let n = state_number as usize;
263 STATE.ch_wakers[n].register(waker);
264 }
265
266 pub unsafe fn reset_status(dma: &crate::pac::dma::Dma, isrn: usize, isrbit: usize) {
267 dma.ifcr(isrn).write(|w| {
268 w.set_tcif(isrbit, true);
269 w.set_teif(isrbit, true);
270 });
271 }
272}
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 48b229c2e..3928bbb92 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -8,62 +8,183 @@ mod dmamux;
8#[cfg(dmamux)] 8#[cfg(dmamux)]
9pub use dmamux::*; 9pub use dmamux::*;
10 10
11use core::future::Future;
12use core::task::Waker;
13use embassy::util::Unborrow; 11use embassy::util::Unborrow;
14 12
13#[cfg(feature = "unstable-pac")]
14pub use transfers::*;
15
16#[cfg(not(feature = "unstable-pac"))]
17pub(crate) use transfers::*;
18
15#[cfg(any(bdma_v2, dma_v2, dmamux))] 19#[cfg(any(bdma_v2, dma_v2, dmamux))]
16pub type Request = u8; 20pub type Request = u8;
17#[cfg(not(any(bdma_v2, dma_v2, dmamux)))] 21#[cfg(not(any(bdma_v2, dma_v2, dmamux)))]
18pub type Request = (); 22pub type Request = ();
19 23
20pub(crate) mod sealed { 24pub(crate) mod sealed {
21 pub trait Channel {} 25 use super::*;
26 use core::task::Waker;
27 pub trait Channel {
28 /// Starts this channel for writing a stream of words.
29 unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut u32);
30
31 /// Starts this channel for writing a word repeatedly.
32 unsafe fn start_write_repeated<W: Word>(
33 &mut self,
34 request: Request,
35 repeated: W,
36 count: usize,
37 reg_addr: *mut u32,
38 );
39
40 /// Starts this channel for reading a stream of words.
41 unsafe fn start_read<W: Word>(
42 &mut self,
43 request: Request,
44 reg_addr: *mut u32,
45 buf: &mut [W],
46 );
47
48 /// Stops this channel.
49 fn request_stop(&mut self);
50
51 /// Returns whether this channel is active or stopped.
52 fn is_stopped(&self) -> bool;
53
54 /// Returns the total number of remaining transfers.
55 fn remaining_transfers(&mut self) -> u16;
56
57 /// Sets the waker that is called when this channel completes.
58 fn set_waker(&mut self, waker: &Waker);
59 }
22} 60}
23 61
24pub trait Channel: sealed::Channel { 62pub enum WordSize {
25 type ReadFuture<'a>: Future<Output = ()> + 'a 63 OneByte,
26 where 64 TwoBytes,
27 Self: 'a; 65 FourBytes,
66}
67pub trait Word {
68 fn bits() -> WordSize;
69}
70
71impl Word for u8 {
72 fn bits() -> WordSize {
73 WordSize::OneByte
74 }
75}
28 76
29 type WriteFuture<'a>: Future<Output = ()> + 'a 77impl Word for u16 {
30 where 78 fn bits() -> WordSize {
31 Self: 'a; 79 WordSize::TwoBytes
80 }
81}
82impl Word for u32 {
83 fn bits() -> WordSize {
84 WordSize::FourBytes
85 }
86}
32 87
33 fn read<'a>( 88mod transfers {
34 &'a mut self, 89 use core::task::Poll;
90
91 use super::Channel;
92 use embassy_hal_common::{drop::OnDrop, unborrow};
93 use futures::future::poll_fn;
94
95 use super::*;
96
97 #[allow(unused)]
98 pub async fn read<'a, W: Word>(
99 channel: &mut impl Unborrow<Target = impl Channel>,
35 request: Request, 100 request: Request,
36 src: *mut u8, 101 reg_addr: *mut u32,
37 buf: &'a mut [u8], 102 buf: &'a mut [W],
38 ) -> Self::ReadFuture<'a>; 103 ) {
104 assert!(buf.len() <= 0xFFFF);
105 let drop_clone = unsafe { channel.unborrow() };
106 unborrow!(channel);
39 107
40 fn write<'a>( 108 channel.request_stop();
41 &'a mut self, 109 let on_drop = OnDrop::new({
110 let mut channel = drop_clone;
111 move || {
112 channel.request_stop();
113 }
114 });
115
116 unsafe { channel.start_read::<W>(request, reg_addr, buf) };
117 wait_for_stopped(&mut channel).await;
118 drop(on_drop)
119 }
120
121 #[allow(unused)]
122 pub async fn write<'a, W: Word>(
123 channel: &mut impl Unborrow<Target = impl Channel>,
42 request: Request, 124 request: Request,
43 buf: &'a [u8], 125 buf: &'a [W],
44 dst: *mut u8, 126 reg_addr: *mut u32,
45 ) -> Self::WriteFuture<'a>; 127 ) {
128 assert!(buf.len() <= 0xFFFF);
129 let drop_clone = unsafe { channel.unborrow() };
130 unborrow!(channel);
131
132 channel.request_stop();
133 let on_drop = OnDrop::new({
134 let mut channel = drop_clone;
135 move || {
136 channel.request_stop();
137 }
138 });
139
140 unsafe { channel.start_write::<W>(request, buf, reg_addr) };
141 wait_for_stopped(&mut channel).await;
142 drop(on_drop)
143 }
46 144
47 fn write_x<'a>( 145 #[allow(unused)]
48 &'a mut self, 146 pub async fn write_repeated<W: Word>(
147 channel: &mut impl Unborrow<Target = impl Channel>,
49 request: Request, 148 request: Request,
50 word: &u8, 149 repeated: W,
51 num: usize, 150 count: usize,
52 dst: *mut u8, 151 reg_addr: *mut u32,
53 ) -> Self::WriteFuture<'a>; 152 ) {
54 153 let drop_clone = unsafe { channel.unborrow() };
55 /// Stops this channel. 154 unborrow!(channel);
56 fn stop<'a>(&'a mut self); 155
57 /// Returns whether this channel is active or stopped. 156 channel.request_stop();
58 fn is_stopped<'a>(&self) -> bool; 157 let on_drop = OnDrop::new({
59 /// Returns the total number of remaining transfers . 158 let mut channel = drop_clone;
60 fn remaining_transfers<'a>(&'a mut self) -> u16; 159 move || {
61 /// Sets the waker that is called when this channel completes/ 160 channel.request_stop();
62 fn set_waker(&mut self, waker: &Waker); 161 }
63 /// Starts this channel. 162 });
64 fn start<'a>(&'a mut self, request: Request, buf: &'a [u8], dst: *mut u8); 163
164 unsafe { channel.start_write_repeated::<W>(request, repeated, count, reg_addr) };
165 wait_for_stopped(&mut channel).await;
166 drop(on_drop)
167 }
168
169 async fn wait_for_stopped(channel: &mut impl Unborrow<Target = impl Channel>) {
170 unborrow!(channel);
171 poll_fn(move |cx| {
172 channel.set_waker(cx.waker());
173
174 // TODO in the future, error checking could be added so that this function returns an error
175
176 if channel.is_stopped() {
177 Poll::Ready(())
178 } else {
179 Poll::Pending
180 }
181 })
182 .await
183 }
65} 184}
66 185
186pub trait Channel: sealed::Channel + Unborrow<Target = Self> {}
187
67pub struct NoDma; 188pub struct NoDma;
68 189
69unsafe impl Unborrow for NoDma { 190unsafe impl Unborrow for NoDma {
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 11c8ab975..af3ac74bc 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -415,10 +415,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
415 w.set_tcie(true); 415 w.set_tcie(true);
416 } 416 }
417 }); 417 });
418 let dst = regs.txdr().ptr() as *mut u8; 418 let dst = regs.txdr().ptr() as *mut u32;
419 419
420 let ch = &mut self.tx_dma; 420 let ch = &mut self.tx_dma;
421 ch.write(ch.request(), bytes, dst) 421 let request = ch.request();
422 crate::dma::write(ch, request, bytes, dst)
422 }; 423 };
423 424
424 let state_number = T::state_number(); 425 let state_number = T::state_number();
@@ -507,10 +508,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
507 w.set_rxdmaen(true); 508 w.set_rxdmaen(true);
508 w.set_tcie(true); 509 w.set_tcie(true);
509 }); 510 });
510 let src = regs.rxdr().ptr() as *mut u8; 511 let src = regs.rxdr().ptr() as *mut u32;
511 512
512 let ch = &mut self.rx_dma; 513 let ch = &mut self.rx_dma;
513 ch.read(ch.request(), src, buffer) 514 let request = ch.request();
515 crate::dma::read(ch, request, src, buffer)
514 }; 516 };
515 517
516 let state_number = T::state_number(); 518 let state_number = T::state_number();
diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs
index 92449ea80..98f05770b 100644
--- a/embassy-stm32/src/spi/v1.rs
+++ b/embassy-stm32/src/spi/v1.rs
@@ -20,7 +20,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
20 20
21 let request = self.txdma.request(); 21 let request = self.txdma.request();
22 let dst = T::regs().tx_ptr(); 22 let dst = T::regs().tx_ptr();
23 let f = self.txdma.write(request, write, dst); 23 let f = crate::dma::write(&mut self.txdma, request, write, dst);
24 24
25 unsafe { 25 unsafe {
26 T::regs().cr2().modify(|reg| { 26 T::regs().cr2().modify(|reg| {
@@ -54,14 +54,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
54 54
55 let rx_request = self.rxdma.request(); 55 let rx_request = self.rxdma.request();
56 let rx_src = T::regs().rx_ptr(); 56 let rx_src = T::regs().rx_ptr();
57 let rx_f = self.rxdma.read(rx_request, rx_src, read); 57 let rx_f = crate::dma::read(&mut self.rxdma, rx_request, rx_src, read);
58 58
59 let tx_request = self.txdma.request(); 59 let tx_request = self.txdma.request();
60 let tx_dst = T::regs().tx_ptr(); 60 let tx_dst = T::regs().tx_ptr();
61 let clock_byte = 0x00; 61 let clock_byte = 0x00u8;
62 let tx_f = self 62 let tx_f = crate::dma::write_repeated(
63 .txdma 63 &mut self.txdma,
64 .write_x(tx_request, &clock_byte, clock_byte_count, tx_dst); 64 tx_request,
65 clock_byte,
66 clock_byte_count,
67 tx_dst,
68 );
65 69
66 unsafe { 70 unsafe {
67 T::regs().cr2().modify(|reg| { 71 T::regs().cr2().modify(|reg| {
@@ -110,13 +114,16 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
110 114
111 let rx_request = self.rxdma.request(); 115 let rx_request = self.rxdma.request();
112 let rx_src = T::regs().rx_ptr(); 116 let rx_src = T::regs().rx_ptr();
113 let rx_f = self 117 let rx_f = crate::dma::read(
114 .rxdma 118 &mut self.rxdma,
115 .read(rx_request, rx_src, &mut read[0..write.len()]); 119 rx_request,
120 rx_src,
121 &mut read[0..write.len()],
122 );
116 123
117 let tx_request = self.txdma.request(); 124 let tx_request = self.txdma.request();
118 let tx_dst = T::regs().tx_ptr(); 125 let tx_dst = T::regs().tx_ptr();
119 let tx_f = self.txdma.write(tx_request, write, tx_dst); 126 let tx_f = crate::dma::write(&mut self.txdma, tx_request, write, tx_dst);
120 127
121 unsafe { 128 unsafe {
122 T::regs().cr2().modify(|reg| { 129 T::regs().cr2().modify(|reg| {
diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs
index e24710dfe..286976329 100644
--- a/embassy-stm32/src/spi/v2.rs
+++ b/embassy-stm32/src/spi/v2.rs
@@ -24,7 +24,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
24 24
25 let request = self.txdma.request(); 25 let request = self.txdma.request();
26 let dst = T::regs().tx_ptr(); 26 let dst = T::regs().tx_ptr();
27 let f = self.txdma.write(request, write, dst); 27 let f = crate::dma::write(&mut self.txdma, request, write, dst);
28 28
29 unsafe { 29 unsafe {
30 T::regs().cr2().modify(|reg| { 30 T::regs().cr2().modify(|reg| {
@@ -67,14 +67,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
67 67
68 let rx_request = self.rxdma.request(); 68 let rx_request = self.rxdma.request();
69 let rx_src = T::regs().rx_ptr(); 69 let rx_src = T::regs().rx_ptr();
70 let rx_f = self.rxdma.read(rx_request, rx_src, read); 70 let rx_f = crate::dma::read(&mut self.rxdma, rx_request, rx_src, read);
71 71
72 let tx_request = self.txdma.request(); 72 let tx_request = self.txdma.request();
73 let tx_dst = T::regs().tx_ptr(); 73 let tx_dst = T::regs().tx_ptr();
74 let clock_byte = 0x00; 74 let clock_byte = 0x00u8;
75 let tx_f = self 75 let tx_f = crate::dma::write_repeated(
76 .txdma 76 &mut self.txdma,
77 .write_x(tx_request, &clock_byte, clock_byte_count, tx_dst); 77 tx_request,
78 clock_byte,
79 clock_byte_count,
80 tx_dst,
81 );
78 82
79 unsafe { 83 unsafe {
80 T::regs().cr2().modify(|reg| { 84 T::regs().cr2().modify(|reg| {
@@ -128,13 +132,16 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
128 132
129 let rx_request = self.rxdma.request(); 133 let rx_request = self.rxdma.request();
130 let rx_src = T::regs().rx_ptr(); 134 let rx_src = T::regs().rx_ptr();
131 let rx_f = self 135 let rx_f = crate::dma::read(
132 .rxdma 136 &mut self.rxdma,
133 .read(rx_request, rx_src, &mut read[0..write.len()]); 137 rx_request,
138 rx_src,
139 &mut read[0..write.len()],
140 );
134 141
135 let tx_request = self.txdma.request(); 142 let tx_request = self.txdma.request();
136 let tx_dst = T::regs().tx_ptr(); 143 let tx_dst = T::regs().tx_ptr();
137 let tx_f = self.txdma.write(tx_request, write, tx_dst); 144 let tx_f = crate::dma::write(&mut self.txdma, tx_request, write, tx_dst);
138 145
139 unsafe { 146 unsafe {
140 T::regs().cr2().modify(|reg| { 147 T::regs().cr2().modify(|reg| {
diff --git a/embassy-stm32/src/spi/v3.rs b/embassy-stm32/src/spi/v3.rs
index 6d75de035..c31415a2f 100644
--- a/embassy-stm32/src/spi/v3.rs
+++ b/embassy-stm32/src/spi/v3.rs
@@ -24,7 +24,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
24 24
25 let request = self.txdma.request(); 25 let request = self.txdma.request();
26 let dst = T::regs().tx_ptr(); 26 let dst = T::regs().tx_ptr();
27 let f = self.txdma.write(request, write, dst); 27 let f = crate::dma::write(&mut self.txdma, request, write, dst);
28 28
29 unsafe { 29 unsafe {
30 T::regs().cfg1().modify(|reg| { 30 T::regs().cfg1().modify(|reg| {
@@ -70,14 +70,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
70 70
71 let rx_request = self.rxdma.request(); 71 let rx_request = self.rxdma.request();
72 let rx_src = T::regs().rx_ptr(); 72 let rx_src = T::regs().rx_ptr();
73 let rx_f = self.rxdma.read(rx_request, rx_src, read); 73 let rx_f = crate::dma::read(&mut self.rxdma, rx_request, rx_src, read);
74 74
75 let tx_request = self.txdma.request(); 75 let tx_request = self.txdma.request();
76 let tx_dst = T::regs().tx_ptr(); 76 let tx_dst = T::regs().tx_ptr();
77 let clock_byte = 0x00; 77 let clock_byte = 0x00u8;
78 let tx_f = self 78 let tx_f = crate::dma::write_repeated(
79 .txdma 79 &mut self.txdma,
80 .write_x(tx_request, &clock_byte, clock_byte_count, tx_dst); 80 tx_request,
81 clock_byte,
82 clock_byte_count,
83 tx_dst,
84 );
81 85
82 unsafe { 86 unsafe {
83 T::regs().cfg1().modify(|reg| { 87 T::regs().cfg1().modify(|reg| {
@@ -132,13 +136,16 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
132 136
133 let rx_request = self.rxdma.request(); 137 let rx_request = self.rxdma.request();
134 let rx_src = T::regs().rx_ptr(); 138 let rx_src = T::regs().rx_ptr();
135 let rx_f = self 139 let rx_f = crate::dma::read(
136 .rxdma 140 &mut self.rxdma,
137 .read(rx_request, rx_src, &mut read[0..write.len()]); 141 rx_request,
142 rx_src,
143 &mut read[0..write.len()],
144 );
138 145
139 let tx_request = self.txdma.request(); 146 let tx_request = self.txdma.request();
140 let tx_dst = T::regs().tx_ptr(); 147 let tx_dst = T::regs().tx_ptr();
141 let tx_f = self.txdma.write(tx_request, write, tx_dst); 148 let tx_f = crate::dma::write(&mut self.txdma, tx_request, write, tx_dst);
142 149
143 unsafe { 150 unsafe {
144 T::regs().cfg1().modify(|reg| { 151 T::regs().cfg1().modify(|reg| {
diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs
index 8cd392d18..3a8c1d340 100644
--- a/embassy-stm32/src/usart/v1.rs
+++ b/embassy-stm32/src/usart/v1.rs
@@ -70,14 +70,15 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
70 TxDma: crate::usart::TxDma<T>, 70 TxDma: crate::usart::TxDma<T>,
71 { 71 {
72 let ch = &mut self.tx_dma; 72 let ch = &mut self.tx_dma;
73 let request = ch.request();
73 unsafe { 74 unsafe {
74 self.inner.regs().cr3().modify(|reg| { 75 self.inner.regs().cr3().modify(|reg| {
75 reg.set_dmat(true); 76 reg.set_dmat(true);
76 }); 77 });
77 } 78 }
78 let r = self.inner.regs(); 79 let r = self.inner.regs();
79 let dst = r.dr().ptr() as *mut u8; 80 let dst = r.dr().ptr() as *mut u32;
80 ch.write(ch.request(), buffer, dst).await; 81 crate::dma::write(ch, request, buffer, dst).await;
81 Ok(()) 82 Ok(())
82 } 83 }
83 84
@@ -86,14 +87,15 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
86 RxDma: crate::usart::RxDma<T>, 87 RxDma: crate::usart::RxDma<T>,
87 { 88 {
88 let ch = &mut self.rx_dma; 89 let ch = &mut self.rx_dma;
90 let request = ch.request();
89 unsafe { 91 unsafe {
90 self.inner.regs().cr3().modify(|reg| { 92 self.inner.regs().cr3().modify(|reg| {
91 reg.set_dmar(true); 93 reg.set_dmar(true);
92 }); 94 });
93 } 95 }
94 let r = self.inner.regs(); 96 let r = self.inner.regs();
95 let src = r.dr().ptr() as *mut u8; 97 let src = r.dr().ptr() as *mut u32;
96 ch.read(ch.request(), src, buffer).await; 98 crate::dma::read(ch, request, src, buffer).await;
97 Ok(()) 99 Ok(())
98 } 100 }
99 101
diff --git a/embassy-stm32/src/usart/v2.rs b/embassy-stm32/src/usart/v2.rs
index e6e5f69db..cd70afec7 100644
--- a/embassy-stm32/src/usart/v2.rs
+++ b/embassy-stm32/src/usart/v2.rs
@@ -80,14 +80,15 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
80 TxDma: crate::usart::TxDma<T>, 80 TxDma: crate::usart::TxDma<T>,
81 { 81 {
82 let ch = &mut self.tx_dma; 82 let ch = &mut self.tx_dma;
83 let request = ch.request();
83 unsafe { 84 unsafe {
84 self.inner.regs().cr3().modify(|reg| { 85 self.inner.regs().cr3().modify(|reg| {
85 reg.set_dmat(true); 86 reg.set_dmat(true);
86 }); 87 });
87 } 88 }
88 let r = self.inner.regs(); 89 let r = self.inner.regs();
89 let dst = r.tdr().ptr() as *mut u8; 90 let dst = r.tdr().ptr() as *mut u32;
90 ch.write(ch.request(), buffer, dst).await; 91 crate::dma::write(ch, request, buffer, dst).await;
91 Ok(()) 92 Ok(())
92 } 93 }
93 94
@@ -96,14 +97,16 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
96 RxDma: crate::usart::RxDma<T>, 97 RxDma: crate::usart::RxDma<T>,
97 { 98 {
98 let ch = &mut self.rx_dma; 99 let ch = &mut self.rx_dma;
100 let request = ch.request();
99 unsafe { 101 unsafe {
100 self.inner.regs().cr3().modify(|reg| { 102 self.inner.regs().cr3().modify(|reg| {
101 reg.set_dmar(true); 103 reg.set_dmar(true);
102 }); 104 });
103 } 105 }
104 let r = self.inner.regs(); 106 let r = self.inner.regs();
105 let src = r.rdr().ptr() as *mut u8; 107 let src = r.rdr().ptr() as *mut u32;
106 ch.read(ch.request(), src, buffer).await; 108
109 crate::dma::read(ch, request, src, buffer).await;
107 Ok(()) 110 Ok(())
108 } 111 }
109 112