aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/dma/bdma.rs344
-rw-r--r--embassy-stm32/src/dma/dma.rs354
-rw-r--r--embassy-stm32/src/dma/mod.rs198
-rw-r--r--embassy-stm32/src/i2c/v2.rs6
-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.rs6
-rw-r--r--embassy-stm32/src/usart/v2.rs7
9 files changed, 593 insertions, 403 deletions
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index 35c0b3ee7..b4c77757e 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; 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,92 +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 // Disable the channel and interrupts with the default value.
62 ch.cr().write(|_| ());
63
64 // Wait for the transfer to complete when it was ongoing.
65 while ch.cr().read().en() {}
66
67 // "Subsequent reads and writes cannot be moved ahead of preceding reads."
68 fence(Ordering::Acquire);
69 });
70
71 #[cfg(dmamux)]
72 super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
73
74 #[cfg(bdma_v2)]
75 critical_section::with(|_| {
76 dma.cselr()
77 .modify(|w| w.set_cs(channel_number as _, request))
78 });
79
80 // "Preceding reads and writes cannot be moved past subsequent writes."
81 fence(Ordering::Release);
82
83 ch.par().write_value(peri_addr as u32);
84 ch.mar().write_value(mem_addr as u32);
85 ch.ndtr().write(|w| w.set_ndt(mem_len as u16));
86 ch.cr().write(|w| {
87 w.set_psize(vals::Size::BITS8);
88 w.set_msize(vals::Size::BITS8);
89 if incr_mem {
90 w.set_minc(vals::Inc::ENABLED);
91 } else {
92 w.set_minc(vals::Inc::DISABLED);
93 }
94 w.set_dir(dir);
95 w.set_teie(true);
96 w.set_tcie(true);
97 w.set_en(true);
98 });
99
100 async move {
101 let res = poll_fn(|cx| {
102 STATE.ch_wakers[state_number as usize].register(cx.waker());
103
104 let isr = dma.isr().read();
105
106 // TODO handle error
107 assert!(!isr.teif(channel_number as _));
108
109 if isr.tcif(channel_number as _) {
110 Poll::Ready(())
111 } else {
112 Poll::Pending
113 }
114 })
115 .await;
116
117 drop(on_drop)
118 }
119}
120
121macro_rules! dma_num { 44macro_rules! dma_num {
122 (DMA1) => { 45 (DMA1) => {
123 0 46 0
@@ -136,7 +59,7 @@ unsafe fn on_irq() {
136 let isr = pac::$dma.isr().read(); 59 let isr = pac::$dma.isr().read();
137 let dman = dma_num!($dma); 60 let dman = dma_num!($dma);
138 61
139 for chn in 0..crate::pac::dma_channels_count!($dma) { 62 for chn in 0..pac::dma_channels_count!($dma) {
140 let cr = pac::$dma.ch(chn).cr(); 63 let cr = pac::$dma.ch(chn).cr();
141 if isr.tcif(chn) && cr.read().tcie() { 64 if isr.tcif(chn) && cr.read().tcie() {
142 cr.write(|_| ()); // Disable channel interrupts with the default value. 65 cr.write(|_| ()); // Disable channel interrupts with the default value.
@@ -164,88 +87,84 @@ pub(crate) unsafe fn init() {
164 87
165pac::dma_channels! { 88pac::dma_channels! {
166 ($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) => {
167 impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {} 90 impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
168 impl Channel for crate::peripherals::$channel_peri 91
169 { 92 unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut W) {
170 type ReadFuture<'a> = impl Future<Output = ()> + 'a; 93 low_level_api::start_transfer(
171 type WriteFuture<'a> = impl Future<Output = ()> + 'a; 94 pac::$dma_peri,
172 95 $channel_num,
173 fn read<'a>( 96 #[cfg(any(bdma_v2, dmamux))]
174 &'a mut self, 97 request,
175 request: Request, 98 vals::Dir::FROMMEMORY,
176 src: *mut u8, 99 reg_addr as *const u32,
177 buf: &'a mut [u8], 100 buf.as_ptr() as *mut u32,
178 ) -> Self::ReadFuture<'a> { 101 buf.len(),
179 unsafe { 102 true,
180 do_transfer( 103 vals::Size::from(W::bits()),
181 crate::pac::$dma_peri, 104 #[cfg(dmamux)]
182 $channel_num, 105 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
183 (dma_num!($dma_peri) * 8) + $channel_num, 106 #[cfg(dmamux)]
184 request, 107 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
185 vals::Dir::FROMPERIPHERAL, 108 );
186 src,
187 buf.as_mut_ptr(),
188 buf.len(),
189 true,
190 #[cfg(dmamux)]
191 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
192 #[cfg(dmamux)]
193 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
194 )
195 }
196 } 109 }
197 110
198 fn write<'a>( 111
199 &'a mut self, 112 unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W) {
200 request: Request, 113 let buf = [repeated];
201 buf: &'a [u8], 114 low_level_api::start_transfer(
202 dst: *mut u8, 115 pac::$dma_peri,
203 ) -> Self::WriteFuture<'a> { 116 $channel_num,
204 unsafe { 117 #[cfg(any(bdma_v2, dmamux))]
205 do_transfer( 118 request,
206 crate::pac::$dma_peri, 119 vals::Dir::FROMMEMORY,
207 $channel_num, 120 reg_addr as *const u32,
208 (dma_num!($dma_peri) * 8) + $channel_num, 121 buf.as_ptr() as *mut u32,
209 request, 122 count,
210 vals::Dir::FROMMEMORY, 123 false,
211 dst, 124 vals::Size::from(W::bits()),
212 buf.as_ptr() as *mut u8, 125 #[cfg(dmamux)]
213 buf.len(), 126 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
214 true, 127 #[cfg(dmamux)]
215 #[cfg(dmamux)] 128 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
216 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, 129 )
217 #[cfg(dmamux)]
218 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
219 )
220 }
221 } 130 }
222 131
223 fn write_x<'a>( 132 unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *mut W, buf: &mut [W]) {
224 &'a mut self, 133 low_level_api::start_transfer(
225 request: Request, 134 pac::$dma_peri,
226 word: &u8, 135 $channel_num,
227 count: usize, 136 #[cfg(any(bdma_v2, dmamux))]
228 dst: *mut u8, 137 request,
229 ) -> Self::WriteFuture<'a> { 138 vals::Dir::FROMPERIPHERAL,
230 unsafe { 139 reg_addr as *const u32,
231 do_transfer( 140 buf.as_ptr() as *mut u32,
232 crate::pac::$dma_peri, 141 buf.len(),
233 $channel_num, 142 true,
234 (dma_num!($dma_peri) * 8) + $channel_num, 143 vals::Size::from(W::bits()),
235 request, 144 #[cfg(dmamux)]
236 vals::Dir::FROMMEMORY, 145 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
237 dst, 146 #[cfg(dmamux)]
238 word as *const u8 as *mut u8, 147 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
239 count, 148 );
240 false, 149 }
241 #[cfg(dmamux)] 150
242 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, 151 fn request_stop(&mut self){
243 #[cfg(dmamux)] 152 unsafe {low_level_api::request_stop(pac::$dma_peri, $channel_num);}
244 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM, 153 }
245 ) 154
246 } 155 fn is_running(&self) -> bool {
156 unsafe {low_level_api::is_running(pac::$dma_peri, $channel_num)}
157 }
158 fn remaining_transfers(&mut self) -> u16 {
159 unsafe {low_level_api::get_remaining_transfers(pac::$dma_peri, $channel_num)}
160 }
161
162 fn set_waker(&mut self, waker: &Waker) {
163 unsafe {low_level_api::set_waker(dma_num!($dma_peri) * 8 + $channel_num, waker )}
247 } 164 }
248 } 165 }
166
167 impl crate::dma::Channel for crate::peripherals::$channel_peri {}
249 }; 168 };
250} 169}
251 170
@@ -257,3 +176,92 @@ pac::interrupts! {
257 } 176 }
258 }; 177 };
259} 178}
179
180mod low_level_api {
181 use super::*;
182
183 pub unsafe fn start_transfer(
184 dma: pac::bdma::Dma,
185 channel_number: u8,
186 #[cfg(any(bdma_v2, dmamux))] request: Request,
187 dir: vals::Dir,
188 peri_addr: *const u32,
189 mem_addr: *mut u32,
190 mem_len: usize,
191 incr_mem: bool,
192 data_size: vals::Size,
193 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
194 #[cfg(dmamux)] dmamux_ch_num: u8,
195 ) {
196 let ch = dma.ch(channel_number as _);
197
198 reset_status(dma, channel_number);
199
200 #[cfg(dmamux)]
201 super::super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
202
203 #[cfg(bdma_v2)]
204 critical_section::with(|_| {
205 dma.cselr()
206 .modify(|w| w.set_cs(channel_number as _, request))
207 });
208
209 // "Preceding reads and writes cannot be moved past subsequent writes."
210 fence(Ordering::SeqCst);
211
212 ch.par().write_value(peri_addr as u32);
213 ch.mar().write_value(mem_addr as u32);
214 ch.ndtr().write(|w| w.set_ndt(mem_len as u16));
215 ch.cr().write(|w| {
216 w.set_psize(data_size);
217 w.set_msize(data_size);
218 if incr_mem {
219 w.set_minc(vals::Inc::ENABLED);
220 } else {
221 w.set_minc(vals::Inc::DISABLED);
222 }
223 w.set_dir(dir);
224 w.set_teie(true);
225 w.set_tcie(true);
226 w.set_en(true);
227 });
228 }
229
230 pub unsafe fn request_stop(dma: pac::bdma::Dma, channel_number: u8) {
231 reset_status(dma, channel_number);
232
233 let ch = dma.ch(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 pub unsafe fn is_running(dma: pac::bdma::Dma, ch: u8) -> bool {
243 let ch = dma.ch(ch as _);
244 ch.cr().read().en()
245 }
246
247 /// Gets the total remaining transfers for the channel
248 /// Note: this will be zero for transfers that completed without cancellation.
249 pub unsafe fn get_remaining_transfers(dma: pac::bdma::Dma, ch: u8) -> u16 {
250 // get a handle on the channel itself
251 let ch = dma.ch(ch as _);
252 // read the remaining transfer count. If this is zero, the transfer completed fully.
253 ch.ndtr().read().ndt()
254 }
255
256 /// Sets the waker for the specified DMA channel
257 pub unsafe fn set_waker(state_number: usize, waker: &Waker) {
258 STATE.ch_wakers[state_number].register(waker);
259 }
260
261 pub unsafe fn reset_status(dma: pac::bdma::Dma, channel_number: u8) {
262 dma.ifcr().write(|w| {
263 w.set_tcif(channel_number as _, true);
264 w.set_teif(channel_number as _, true);
265 });
266 }
267}
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index ec5ac98a0..efe4d1d9d 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; 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,100 +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 dma.ifcr(isrn).write(|w| {
57 w.set_tcif(isrbit, true);
58 w.set_teif(isrbit, true);
59 });
60
61 let ch = dma.st(channel_number as _);
62
63 let on_drop = OnDrop::new(move || unsafe {
64 // Disable the channel and interrupts with the default value.
65 ch.cr().write(|_| ());
66
67 // Wait for the transfer to complete when it was ongoing.
68 while ch.cr().read().en() {}
69
70 // "Subsequent reads and writes cannot be moved ahead of preceding reads."
71 fence(Ordering::Acquire);
72 });
73
74 #[cfg(dmamux)]
75 super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
76
77 // "Preceding reads and writes cannot be moved past subsequent writes."
78 fence(Ordering::Release);
79
80 unsafe {
81 ch.par().write_value(peri_addr as u32);
82 ch.m0ar().write_value(mem_addr as u32);
83 ch.ndtr().write_value(regs::Ndtr(mem_len as _));
84 ch.cr().write(|w| {
85 w.set_dir(dir);
86 w.set_msize(vals::Size::BITS8);
87 w.set_psize(vals::Size::BITS8);
88 if incr_mem {
89 w.set_minc(vals::Inc::INCREMENTED);
90 } else {
91 w.set_minc(vals::Inc::FIXED);
92 }
93 w.set_pinc(vals::Inc::FIXED);
94 w.set_teie(true);
95 w.set_tcie(true);
96 #[cfg(dma_v1)]
97 w.set_trbuff(true);
98
99 #[cfg(dma_v2)]
100 w.set_chsel(request);
101
102 w.set_en(true);
103 });
104 }
105
106 async move {
107 let res = poll_fn(|cx| {
108 let n = state_number as usize;
109 STATE.ch_wakers[n].register(cx.waker());
110
111 let isr = dma.isr(isrn).read();
112
113 // TODO handle error
114 assert!(!isr.teif(isrbit));
115
116 if isr.tcif(isrbit) {
117 Poll::Ready(())
118 } else {
119 Poll::Pending
120 }
121 })
122 .await;
123
124 drop(on_drop)
125 }
126}
127
128macro_rules! dma_num { 41macro_rules! dma_num {
129 (DMA1) => { 42 (DMA1) => {
130 0 43 0
@@ -170,88 +83,80 @@ pub(crate) unsafe fn init() {
170 83
171pac::dma_channels! { 84pac::dma_channels! {
172 ($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) => {
173 impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {} 86 impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
174 impl Channel for crate::peripherals::$channel_peri 87 unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut W) {
175 { 88 low_level_api::start_transfer(
176 type ReadFuture<'a> = impl Future<Output = ()> + 'a; 89 pac::$dma_peri,
177 type WriteFuture<'a> = impl Future<Output = ()> + 'a; 90 $channel_num,
178 91 request,
179 fn read<'a>( 92 vals::Dir::MEMORYTOPERIPHERAL,
180 &'a mut self, 93 reg_addr as *const u32,
181 request: Request, 94 buf.as_ptr() as *mut u32,
182 src: *mut u8, 95 buf.len(),
183 buf: &'a mut [u8], 96 true,
184 ) -> Self::ReadFuture<'a> { 97 vals::Size::from(W::bits()),
185 unsafe { 98 #[cfg(dmamux)]
186 do_transfer( 99 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
187 crate::pac::$dma_peri, 100 #[cfg(dmamux)]
188 $channel_num, 101 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
189 (dma_num!($dma_peri) * 8) + $channel_num, 102 )
190 request,
191 vals::Dir::PERIPHERALTOMEMORY,
192 src,
193 buf.as_mut_ptr(),
194 buf.len(),
195 true,
196 #[cfg(dmamux)]
197 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
198 #[cfg(dmamux)]
199 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
200 )
201 }
202 } 103 }
203 104
204 fn write<'a>( 105 unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W) {
205 &'a mut self, 106 let buf = [repeated];
206 request: Request, 107 low_level_api::start_transfer(
207 buf: &'a [u8], 108 pac::$dma_peri,
208 dst: *mut u8, 109 $channel_num,
209 ) -> Self::WriteFuture<'a> { 110 request,
210 unsafe { 111 vals::Dir::MEMORYTOPERIPHERAL,
211 do_transfer( 112 reg_addr as *const u32,
212 crate::pac::$dma_peri, 113 buf.as_ptr() as *mut u32,
213 $channel_num, 114 count,
214 (dma_num!($dma_peri) * 8) + $channel_num, 115 false,
215 request, 116 vals::Size::from(W::bits()),
216 vals::Dir::MEMORYTOPERIPHERAL, 117 #[cfg(dmamux)]
217 dst, 118 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
218 buf.as_ptr() as *mut u8, 119 #[cfg(dmamux)]
219 buf.len(), 120 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
220 true, 121 )
221 #[cfg(dmamux)]
222 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
223 #[cfg(dmamux)]
224 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
225 )
226 }
227 } 122 }
228 123
229 fn write_x<'a>( 124 unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *mut W, buf: &mut [W]) {
230 &'a mut self, 125 low_level_api::start_transfer(
231 request: Request, 126 pac::$dma_peri,
232 word: &u8, 127 $channel_num,
233 num: usize, 128 request,
234 dst: *mut u8, 129 vals::Dir::PERIPHERALTOMEMORY,
235 ) -> Self::WriteFuture<'a> { 130 reg_addr as *const u32,
236 unsafe { 131 buf.as_ptr() as *mut u32,
237 do_transfer( 132 buf.len(),
238 crate::pac::$dma_peri, 133 true,
239 $channel_num, 134 vals::Size::from(W::bits()),
240 (dma_num!($dma_peri) * 8) + $channel_num, 135 #[cfg(dmamux)]
241 request, 136 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
242 vals::Dir::MEMORYTOPERIPHERAL, 137 #[cfg(dmamux)]
243 dst, 138 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM,
244 word as *const u8 as *mut u8, 139 );
245 num, 140 }
246 false, 141
247 #[cfg(dmamux)] 142 fn request_stop(&mut self) {
248 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, 143 unsafe {low_level_api::request_stop(pac::$dma_peri, $channel_num);}
249 #[cfg(dmamux)] 144 }
250 <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_CH_NUM, 145
251 ) 146 fn is_running(&self) -> bool {
252 } 147 unsafe {low_level_api::is_running(pac::$dma_peri, $channel_num)}
148 }
149
150 fn remaining_transfers(&mut self) -> u16 {
151 unsafe {low_level_api::get_remaining_transfers(pac::$dma_peri, $channel_num)}
152 }
153
154 fn set_waker(&mut self, waker: &Waker) {
155 unsafe {low_level_api::set_waker(dma_num!($dma_peri) * 8 + $channel_num, waker )}
253 } 156 }
254 } 157 }
158
159 impl crate::dma::Channel for crate::peripherals::$channel_peri { }
255 }; 160 };
256} 161}
257 162
@@ -263,3 +168,102 @@ pac::interrupts! {
263 } 168 }
264 }; 169 };
265} 170}
171
172mod low_level_api {
173 use super::*;
174
175 pub unsafe fn start_transfer(
176 dma: pac::dma::Dma,
177 channel_number: u8,
178 request: Request,
179 dir: vals::Dir,
180 peri_addr: *const u32,
181 mem_addr: *mut u32,
182 mem_len: usize,
183 incr_mem: bool,
184 data_size: vals::Size,
185 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
186 #[cfg(dmamux)] dmamux_ch_num: u8,
187 ) {
188 #[cfg(dmamux)]
189 super::super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
190
191 // "Preceding reads and writes cannot be moved past subsequent writes."
192 fence(Ordering::SeqCst);
193
194 reset_status(dma, channel_number);
195
196 let ch = dma.st(channel_number as _);
197 ch.par().write_value(peri_addr as u32);
198 ch.m0ar().write_value(mem_addr as u32);
199 ch.ndtr().write_value(regs::Ndtr(mem_len as _));
200 ch.cr().write(|w| {
201 w.set_dir(dir);
202 w.set_msize(data_size);
203 w.set_psize(data_size);
204 w.set_pl(vals::Pl::VERYHIGH);
205 if incr_mem {
206 w.set_minc(vals::Inc::INCREMENTED);
207 } else {
208 w.set_minc(vals::Inc::FIXED);
209 }
210 w.set_pinc(vals::Inc::FIXED);
211 w.set_teie(true);
212 w.set_tcie(true);
213 #[cfg(dma_v1)]
214 w.set_trbuff(true);
215
216 #[cfg(dma_v2)]
217 w.set_chsel(request);
218
219 w.set_en(true);
220 });
221 }
222
223 /// Stops the DMA channel.
224 pub unsafe fn request_stop(dma: pac::dma::Dma, channel_number: u8) {
225 // get a handle on the channel itself
226 let ch = dma.st(channel_number as _);
227
228 // Disable the channel. Keep the IEs enabled so the irqs still fire.
229 ch.cr().write(|w| {
230 w.set_teie(true);
231 w.set_tcie(true);
232 });
233
234 // "Subsequent reads and writes cannot be moved ahead of preceding reads."
235 fence(Ordering::SeqCst);
236 }
237
238 /// Gets the running status of the channel
239 pub unsafe fn is_running(dma: pac::dma::Dma, ch: u8) -> bool {
240 // get a handle on the channel itself
241 let ch = dma.st(ch as _);
242 // Get whether it's enabled (running)
243 ch.cr().read().en()
244 }
245
246 /// Gets the total remaining transfers for the channel
247 /// Note: this will be zero for transfers that completed without cancellation.
248 pub unsafe fn get_remaining_transfers(dma: pac::dma::Dma, ch: u8) -> u16 {
249 // get a handle on the channel itself
250 let ch = dma.st(ch as _);
251 // read the remaining transfer count. If this is zero, the transfer completed fully.
252 ch.ndtr().read().ndt()
253 }
254
255 /// Sets the waker for the specified DMA channel
256 pub unsafe fn set_waker(state_number: usize, waker: &Waker) {
257 STATE.ch_wakers[state_number].register(waker);
258 }
259
260 pub unsafe fn reset_status(dma: pac::dma::Dma, channel_number: u8) {
261 let isrn = channel_number as usize / 4;
262 let isrbit = channel_number as usize % 4;
263
264 dma.ifcr(isrn).write(|w| {
265 w.set_tcif(isrbit, true);
266 w.set_teif(isrbit, true);
267 });
268 }
269}
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 60f6a3020..accc55653 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -9,7 +9,18 @@ mod dmamux;
9pub use dmamux::*; 9pub use dmamux::*;
10 10
11use core::future::Future; 11use core::future::Future;
12use core::marker::PhantomData;
13use core::pin::Pin;
14use core::task::Waker;
15use core::task::{Context, Poll};
12use embassy::util::Unborrow; 16use embassy::util::Unborrow;
17use embassy_hal_common::unborrow;
18
19#[cfg(feature = "unstable-pac")]
20pub use transfers::*;
21
22#[cfg(not(feature = "unstable-pac"))]
23pub(crate) use transfers::*;
13 24
14#[cfg(any(bdma_v2, dma_v2, dmamux))] 25#[cfg(any(bdma_v2, dma_v2, dmamux))]
15pub type Request = u8; 26pub type Request = u8;
@@ -17,41 +28,180 @@ pub type Request = u8;
17pub type Request = (); 28pub type Request = ();
18 29
19pub(crate) mod sealed { 30pub(crate) mod sealed {
20 pub trait Channel {} 31 use super::*;
32
33 pub trait Word {}
34
35 pub trait Channel {
36 /// Starts this channel for writing a stream of words.
37 ///
38 /// Safety:
39 /// - `buf` must be alive for the entire duration of the DMA transfer.
40 /// - `reg_addr` must be a valid peripheral register address to write to.
41 unsafe fn start_write<W: super::Word>(
42 &mut self,
43 request: Request,
44 buf: &[W],
45 reg_addr: *mut W,
46 );
47
48 /// Starts this channel for writing a word repeatedly.
49 ///
50 /// Safety:
51 /// - `reg_addr` must be a valid peripheral register address to write to.
52 unsafe fn start_write_repeated<W: super::Word>(
53 &mut self,
54 request: Request,
55 repeated: W,
56 count: usize,
57 reg_addr: *mut W,
58 );
59
60 /// Starts this channel for reading a stream of words.
61 ///
62 /// Safety:
63 /// - `buf` must be alive for the entire duration of the DMA transfer.
64 /// - `reg_addr` must be a valid peripheral register address to write to.
65 unsafe fn start_read<W: super::Word>(
66 &mut self,
67 request: Request,
68 reg_addr: *mut W,
69 buf: &mut [W],
70 );
71
72 /// Requests the channel to stop.
73 /// NOTE: The channel does not immediately stop, you have to wait
74 /// for `is_running() = false`.
75 fn request_stop(&mut self);
76
77 /// Returns whether this channel is running or stopped.
78 ///
79 /// The channel stops running when it either completes or is manually stopped.
80 fn is_running(&self) -> bool;
81
82 /// Returns the total number of remaining transfers.
83 fn remaining_transfers(&mut self) -> u16;
84
85 /// Sets the waker that is called when this channel stops (either completed or manually stopped)
86 fn set_waker(&mut self, waker: &Waker);
87 }
88}
89
90pub enum WordSize {
91 OneByte,
92 TwoBytes,
93 FourBytes,
94}
95pub trait Word: sealed::Word {
96 fn bits() -> WordSize;
97}
98
99impl sealed::Word for u8 {}
100impl Word for u8 {
101 fn bits() -> WordSize {
102 WordSize::OneByte
103 }
104}
105
106impl sealed::Word for u16 {}
107impl Word for u16 {
108 fn bits() -> WordSize {
109 WordSize::TwoBytes
110 }
21} 111}
22 112
23pub trait Channel: sealed::Channel { 113impl sealed::Word for u32 {}
24 type ReadFuture<'a>: Future<Output = ()> + 'a 114impl Word for u32 {
25 where 115 fn bits() -> WordSize {
26 Self: 'a; 116 WordSize::FourBytes
117 }
118}
27 119
28 type WriteFuture<'a>: Future<Output = ()> + 'a 120mod transfers {
29 where 121 use super::*;
30 Self: 'a;
31 122
32 fn read<'a>( 123 #[allow(unused)]
33 &'a mut self, 124 pub fn read<'a, W: Word>(
125 channel: impl Unborrow<Target = impl Channel> + 'a,
34 request: Request, 126 request: Request,
35 src: *mut u8, 127 reg_addr: *mut W,
36 buf: &'a mut [u8], 128 buf: &'a mut [W],
37 ) -> Self::ReadFuture<'a>; 129 ) -> impl Future<Output = ()> + 'a {
130 assert!(buf.len() <= 0xFFFF);
131 unborrow!(channel);
132
133 unsafe { channel.start_read::<W>(request, reg_addr, buf) };
134
135 Transfer {
136 channel,
137 _phantom: PhantomData,
138 }
139 }
38 140
39 fn write<'a>( 141 #[allow(unused)]
40 &'a mut self, 142 pub fn write<'a, W: Word>(
143 channel: impl Unborrow<Target = impl Channel> + 'a,
41 request: Request, 144 request: Request,
42 buf: &'a [u8], 145 buf: &'a [W],
43 dst: *mut u8, 146 reg_addr: *mut W,
44 ) -> Self::WriteFuture<'a>; 147 ) -> impl Future<Output = ()> + 'a {
148 assert!(buf.len() <= 0xFFFF);
149 unborrow!(channel);
150
151 unsafe { channel.start_write::<W>(request, buf, reg_addr) };
45 152
46 fn write_x<'a>( 153 Transfer {
47 &'a mut self, 154 channel,
155 _phantom: PhantomData,
156 }
157 }
158
159 #[allow(unused)]
160 pub fn write_repeated<'a, W: Word>(
161 channel: impl Unborrow<Target = impl Channel> + 'a,
48 request: Request, 162 request: Request,
49 word: &u8, 163 repeated: W,
50 num: usize, 164 count: usize,
51 dst: *mut u8, 165 reg_addr: *mut W,
52 ) -> Self::WriteFuture<'a>; 166 ) -> impl Future<Output = ()> + 'a {
167 unborrow!(channel);
168
169 unsafe { channel.start_write_repeated::<W>(request, repeated, count, reg_addr) };
170
171 Transfer {
172 channel,
173 _phantom: PhantomData,
174 }
175 }
176
177 struct Transfer<'a, C: Channel> {
178 channel: C,
179 _phantom: PhantomData<&'a mut C>,
180 }
181
182 impl<'a, C: Channel> Drop for Transfer<'a, C> {
183 fn drop(&mut self) {
184 self.channel.request_stop();
185 while self.channel.is_running() {}
186 }
187 }
188
189 impl<'a, C: Channel> Unpin for Transfer<'a, C> {}
190 impl<'a, C: Channel> Future for Transfer<'a, C> {
191 type Output = ();
192 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
193 self.channel.set_waker(cx.waker());
194 if self.channel.is_running() {
195 Poll::Pending
196 } else {
197 Poll::Ready(())
198 }
199 }
200 }
53} 201}
54 202
203pub trait Channel: sealed::Channel + Unborrow<Target = Self> + 'static {}
204
55pub struct NoDma; 205pub struct NoDma;
56 206
57unsafe impl Unborrow for NoDma { 207unsafe impl Unborrow for NoDma {
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 11c8ab975..94c4d9a7c 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -418,7 +418,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
418 let dst = regs.txdr().ptr() as *mut u8; 418 let dst = regs.txdr().ptr() as *mut u8;
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();
@@ -510,7 +511,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
510 let src = regs.rxdr().ptr() as *mut u8; 511 let src = regs.rxdr().ptr() as *mut u8;
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..10f87f2dd 100644
--- a/embassy-stm32/src/usart/v1.rs
+++ b/embassy-stm32/src/usart/v1.rs
@@ -70,6 +70,7 @@ 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);
@@ -77,7 +78,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
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 u8;
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,6 +87,7 @@ 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);
@@ -93,7 +95,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
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 u8;
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..697adf459 100644
--- a/embassy-stm32/src/usart/v2.rs
+++ b/embassy-stm32/src/usart/v2.rs
@@ -80,6 +80,7 @@ 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);
@@ -87,7 +88,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
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 u8;
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,6 +97,7 @@ 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);
@@ -103,7 +105,8 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
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 u8;
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