diff options
| author | Matous Hybl <[email protected]> | 2021-11-19 19:15:55 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-12-07 21:43:47 +0100 |
| commit | b2910558d36929dfde056f609a8af23d925e67f6 (patch) | |
| tree | bc1b02366dcc5fefeb2d56522e361d826b1c5803 | |
| parent | e2719aba104b7ae623c141aa035f1a84e7d0dc42 (diff) | |
Refactor DMA traits.
| -rw-r--r-- | embassy-stm32/src/dma/bdma.rs | 374 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/dma.rs | 445 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/mod.rs | 195 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 10 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/v1.rs | 27 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/v2.rs | 27 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/v3.rs | 27 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/v1.rs | 10 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/v2.rs | 11 |
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 | ||
| 3 | use core::future::Future; | ||
| 4 | use core::sync::atomic::{fence, Ordering}; | 3 | use core::sync::atomic::{fence, Ordering}; |
| 5 | use core::task::{Poll, Waker}; | 4 | use core::task::Waker; |
| 6 | 5 | ||
| 7 | use embassy::interrupt::{Interrupt, InterruptExt}; | 6 | use embassy::interrupt::{Interrupt, InterruptExt}; |
| 8 | use embassy::waitqueue::AtomicWaker; | 7 | use embassy::waitqueue::AtomicWaker; |
| 9 | use embassy_hal_common::drop::OnDrop; | ||
| 10 | use futures::future::poll_fn; | ||
| 11 | 8 | ||
| 12 | use crate::dma::{Channel, Request}; | 9 | use crate::dma::Request; |
| 13 | use crate::interrupt; | 10 | use crate::interrupt; |
| 14 | use crate::pac; | 11 | use crate::pac; |
| 15 | use crate::pac::bdma::vals; | 12 | use crate::pac::bdma::vals; |
| 16 | use crate::rcc::sealed::RccPeripheral; | 13 | use crate::rcc::sealed::RccPeripheral; |
| 17 | 14 | ||
| 15 | use super::{Word, WordSize}; | ||
| 16 | |||
| 17 | impl 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 | |||
| 18 | const CH_COUNT: usize = pac::peripheral_count!(bdma) * 8; | 27 | const CH_COUNT: usize = pac::peripheral_count!(bdma) * 8; |
| 19 | 28 | ||
| 20 | struct State { | 29 | struct State { |
| @@ -32,118 +41,6 @@ impl State { | |||
| 32 | 41 | ||
| 33 | static STATE: State = State::new(); | 42 | static STATE: State = State::new(); |
| 34 | 43 | ||
| 35 | #[allow(unused)] | ||
| 36 | pub(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 | |||
| 114 | unsafe 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 | |||
| 127 | unsafe 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. | ||
| 134 | unsafe 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 | ||
| 142 | unsafe 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 | |||
| 147 | macro_rules! dma_num { | 44 | macro_rules! dma_num { |
| 148 | (DMA1) => { | 45 | (DMA1) => { |
| 149 | 0 | 46 | 0 |
| @@ -190,100 +87,87 @@ pub(crate) unsafe fn init() { | |||
| 190 | 87 | ||
| 191 | pac::dma_channels! { | 88 | pac::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 | |||
| 183 | mod 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 @@ | |||
| 1 | use core::future::Future; | ||
| 2 | use core::sync::atomic::{fence, Ordering}; | 1 | use core::sync::atomic::{fence, Ordering}; |
| 3 | use core::task::{Poll, Waker}; | 2 | use core::task::Waker; |
| 4 | 3 | ||
| 5 | use embassy::interrupt::{Interrupt, InterruptExt}; | 4 | use embassy::interrupt::{Interrupt, InterruptExt}; |
| 6 | use embassy::waitqueue::AtomicWaker; | 5 | use embassy::waitqueue::AtomicWaker; |
| 7 | use embassy_hal_common::drop::OnDrop; | ||
| 8 | use futures::future::poll_fn; | ||
| 9 | 6 | ||
| 10 | use crate::interrupt; | 7 | use crate::interrupt; |
| 11 | use crate::pac; | 8 | use crate::pac; |
| 12 | use crate::pac::dma::{regs, vals}; | 9 | use crate::pac::dma::{regs, vals}; |
| 13 | use crate::rcc::sealed::RccPeripheral; | 10 | use crate::rcc::sealed::RccPeripheral; |
| 14 | 11 | ||
| 15 | use super::{Channel, Request}; | 12 | use super::{Request, Word, WordSize}; |
| 16 | 13 | ||
| 17 | const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8; | 14 | const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8; |
| 18 | 15 | ||
| 16 | impl 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 | |||
| 19 | struct State { | 26 | struct State { |
| 20 | ch_wakers: [AtomicWaker; CH_COUNT], | 27 | ch_wakers: [AtomicWaker; CH_COUNT], |
| 21 | } | 28 | } |
| @@ -31,164 +38,6 @@ impl State { | |||
| 31 | 38 | ||
| 32 | static STATE: State = State::new(); | 39 | static 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)] | ||
| 37 | pub(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 | |||
| 104 | unsafe 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 | |||
| 111 | unsafe 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. | ||
| 154 | unsafe 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 | ||
| 169 | unsafe 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. | ||
| 179 | unsafe 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 | ||
| 187 | unsafe 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 | |||
| 192 | macro_rules! dma_num { | 41 | macro_rules! dma_num { |
| 193 | (DMA1) => { | 42 | (DMA1) => { |
| 194 | 0 | 43 | 0 |
| @@ -234,120 +83,86 @@ pub(crate) unsafe fn init() { | |||
| 234 | 83 | ||
| 235 | pac::dma_channels! { | 84 | pac::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 | |||
| 178 | mod 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)] |
| 9 | pub use dmamux::*; | 9 | pub use dmamux::*; |
| 10 | 10 | ||
| 11 | use core::future::Future; | ||
| 12 | use core::task::Waker; | ||
| 13 | use embassy::util::Unborrow; | 11 | use embassy::util::Unborrow; |
| 14 | 12 | ||
| 13 | #[cfg(feature = "unstable-pac")] | ||
| 14 | pub use transfers::*; | ||
| 15 | |||
| 16 | #[cfg(not(feature = "unstable-pac"))] | ||
| 17 | pub(crate) use transfers::*; | ||
| 18 | |||
| 15 | #[cfg(any(bdma_v2, dma_v2, dmamux))] | 19 | #[cfg(any(bdma_v2, dma_v2, dmamux))] |
| 16 | pub type Request = u8; | 20 | pub type Request = u8; |
| 17 | #[cfg(not(any(bdma_v2, dma_v2, dmamux)))] | 21 | #[cfg(not(any(bdma_v2, dma_v2, dmamux)))] |
| 18 | pub type Request = (); | 22 | pub type Request = (); |
| 19 | 23 | ||
| 20 | pub(crate) mod sealed { | 24 | pub(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 | ||
| 24 | pub trait Channel: sealed::Channel { | 62 | pub enum WordSize { |
| 25 | type ReadFuture<'a>: Future<Output = ()> + 'a | 63 | OneByte, |
| 26 | where | 64 | TwoBytes, |
| 27 | Self: 'a; | 65 | FourBytes, |
| 66 | } | ||
| 67 | pub trait Word { | ||
| 68 | fn bits() -> WordSize; | ||
| 69 | } | ||
| 70 | |||
| 71 | impl Word for u8 { | ||
| 72 | fn bits() -> WordSize { | ||
| 73 | WordSize::OneByte | ||
| 74 | } | ||
| 75 | } | ||
| 28 | 76 | ||
| 29 | type WriteFuture<'a>: Future<Output = ()> + 'a | 77 | impl Word for u16 { |
| 30 | where | 78 | fn bits() -> WordSize { |
| 31 | Self: 'a; | 79 | WordSize::TwoBytes |
| 80 | } | ||
| 81 | } | ||
| 82 | impl Word for u32 { | ||
| 83 | fn bits() -> WordSize { | ||
| 84 | WordSize::FourBytes | ||
| 85 | } | ||
| 86 | } | ||
| 32 | 87 | ||
| 33 | fn read<'a>( | 88 | mod 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 | ||
| 186 | pub trait Channel: sealed::Channel + Unborrow<Target = Self> {} | ||
| 187 | |||
| 67 | pub struct NoDma; | 188 | pub struct NoDma; |
| 68 | 189 | ||
| 69 | unsafe impl Unborrow for NoDma { | 190 | unsafe 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 | ||
