diff options
| -rw-r--r-- | embassy-stm32/src/bdma/mod.rs | 439 | ||||
| -rw-r--r-- | embassy-stm32/src/bdma/v1.rs | 437 | ||||
| -rw-r--r-- | embassy-stm32/src/bdma/v2.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/dmamux/mod.rs | 80 |
4 files changed, 436 insertions, 521 deletions
diff --git a/embassy-stm32/src/bdma/mod.rs b/embassy-stm32/src/bdma/mod.rs index ae7e9d238..523dc2545 100644 --- a/embassy-stm32/src/bdma/mod.rs +++ b/embassy-stm32/src/bdma/mod.rs | |||
| @@ -1,8 +1,439 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | #[cfg_attr(bdma_v1, path = "v1.rs")] | 3 | use core::future::Future; |
| 4 | #[cfg_attr(bdma_v2, path = "v2.rs")] | 4 | use core::task::Poll; |
| 5 | mod _version; | 5 | |
| 6 | use atomic_polyfill::{AtomicU8, Ordering}; | ||
| 7 | use embassy::interrupt::{Interrupt, InterruptExt}; | ||
| 8 | use embassy::util::{AtomicWaker, OnDrop}; | ||
| 9 | use futures::future::poll_fn; | ||
| 10 | |||
| 11 | use crate::dma_traits::{ReadDma, WriteDma}; | ||
| 12 | use crate::interrupt; | ||
| 13 | use crate::pac; | ||
| 14 | use crate::pac::bdma::vals; | ||
| 15 | |||
| 16 | const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8; | ||
| 17 | const CH_STATUS_NONE: u8 = 0; | ||
| 18 | const CH_STATUS_COMPLETED: u8 = 1; | ||
| 19 | const CH_STATUS_ERROR: u8 = 2; | ||
| 20 | |||
| 21 | struct State { | ||
| 22 | ch_wakers: [AtomicWaker; CH_COUNT], | ||
| 23 | ch_status: [AtomicU8; CH_COUNT], | ||
| 24 | } | ||
| 25 | |||
| 26 | impl State { | ||
| 27 | const fn new() -> Self { | ||
| 28 | const AW: AtomicWaker = AtomicWaker::new(); | ||
| 29 | const AU: AtomicU8 = AtomicU8::new(CH_STATUS_NONE); | ||
| 30 | Self { | ||
| 31 | ch_wakers: [AW; CH_COUNT], | ||
| 32 | ch_status: [AU; CH_COUNT], | ||
| 33 | } | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | static STATE: State = State::new(); | ||
| 6 | 38 | ||
| 7 | #[allow(unused)] | 39 | #[allow(unused)] |
| 8 | pub use _version::*; | 40 | pub(crate) async unsafe fn transfer_p2m( |
| 41 | regs: pac::bdma::Ch, | ||
| 42 | state_number: usize, | ||
| 43 | src: *const u8, | ||
| 44 | dst: &mut [u8], | ||
| 45 | #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux, | ||
| 46 | #[cfg(dmamux)] dmamux_ch_num: u8, | ||
| 47 | #[cfg(dmamux)] request: u8, | ||
| 48 | ) { | ||
| 49 | // ndtr is max 16 bits. | ||
| 50 | assert!(dst.len() <= 0xFFFF); | ||
| 51 | |||
| 52 | // Reset status | ||
| 53 | // Generate a DMB here to flush the store buffer (M7) before enabling the DMA | ||
| 54 | STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release); | ||
| 55 | |||
| 56 | let on_drop = OnDrop::new(|| unsafe { | ||
| 57 | regs.cr().modify(|w| { | ||
| 58 | w.set_tcie(false); | ||
| 59 | w.set_teie(false); | ||
| 60 | w.set_en(false); | ||
| 61 | }); | ||
| 62 | while regs.cr().read().en() {} | ||
| 63 | }); | ||
| 64 | |||
| 65 | #[cfg(dmamux)] | ||
| 66 | crate::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request); | ||
| 67 | |||
| 68 | regs.par().write_value(src as u32); | ||
| 69 | regs.mar().write_value(dst.as_mut_ptr() as u32); | ||
| 70 | regs.ndtr().write(|w| w.set_ndt(dst.len() as u16)); | ||
| 71 | regs.cr().write(|w| { | ||
| 72 | w.set_psize(vals::Size::BITS8); | ||
| 73 | w.set_msize(vals::Size::BITS8); | ||
| 74 | w.set_minc(vals::Inc::ENABLED); | ||
| 75 | w.set_teie(true); | ||
| 76 | w.set_tcie(true); | ||
| 77 | w.set_en(true); | ||
| 78 | }); | ||
| 79 | |||
| 80 | let res = poll_fn(|cx| { | ||
| 81 | STATE.ch_wakers[state_number].register(cx.waker()); | ||
| 82 | match STATE.ch_status[state_number].load(Ordering::Acquire) { | ||
| 83 | CH_STATUS_NONE => Poll::Pending, | ||
| 84 | x => Poll::Ready(x), | ||
| 85 | } | ||
| 86 | }) | ||
| 87 | .await; | ||
| 88 | |||
| 89 | // TODO handle error | ||
| 90 | assert!(res == CH_STATUS_COMPLETED); | ||
| 91 | } | ||
| 92 | |||
| 93 | #[allow(unused)] | ||
| 94 | pub(crate) async unsafe fn transfer_m2p( | ||
| 95 | regs: pac::bdma::Ch, | ||
| 96 | state_number: usize, | ||
| 97 | src: &[u8], | ||
| 98 | dst: *mut u8, | ||
| 99 | #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux, | ||
| 100 | #[cfg(dmamux)] dmamux_ch_num: u8, | ||
| 101 | #[cfg(dmamux)] request: u8, | ||
| 102 | ) { | ||
| 103 | // ndtr is max 16 bits. | ||
| 104 | assert!(src.len() <= 0xFFFF); | ||
| 105 | |||
| 106 | // Reset status | ||
| 107 | // Generate a DMB here to flush the store buffer (M7) before enabling the DMA | ||
| 108 | STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release); | ||
| 109 | |||
| 110 | let on_drop = OnDrop::new(|| unsafe { | ||
| 111 | regs.cr().modify(|w| { | ||
| 112 | w.set_tcie(false); | ||
| 113 | w.set_teie(false); | ||
| 114 | w.set_en(false); | ||
| 115 | }); | ||
| 116 | while regs.cr().read().en() {} | ||
| 117 | }); | ||
| 118 | |||
| 119 | #[cfg(dmamux)] | ||
| 120 | crate::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request); | ||
| 121 | |||
| 122 | regs.par().write_value(dst as u32); | ||
| 123 | regs.mar().write_value(src.as_ptr() as u32); | ||
| 124 | regs.ndtr().write(|w| w.set_ndt(src.len() as u16)); | ||
| 125 | regs.cr().write(|w| { | ||
| 126 | w.set_psize(vals::Size::BITS8); | ||
| 127 | w.set_msize(vals::Size::BITS8); | ||
| 128 | w.set_minc(vals::Inc::ENABLED); | ||
| 129 | w.set_dir(vals::Dir::FROMMEMORY); | ||
| 130 | w.set_teie(true); | ||
| 131 | w.set_tcie(true); | ||
| 132 | w.set_en(true); | ||
| 133 | }); | ||
| 134 | |||
| 135 | let res = poll_fn(|cx| { | ||
| 136 | STATE.ch_wakers[state_number].register(cx.waker()); | ||
| 137 | match STATE.ch_status[state_number].load(Ordering::Acquire) { | ||
| 138 | CH_STATUS_NONE => Poll::Pending, | ||
| 139 | x => Poll::Ready(x), | ||
| 140 | } | ||
| 141 | }) | ||
| 142 | .await; | ||
| 143 | |||
| 144 | // TODO handle error | ||
| 145 | assert!(res == CH_STATUS_COMPLETED); | ||
| 146 | } | ||
| 147 | |||
| 148 | unsafe fn on_irq() { | ||
| 149 | pac::peripherals! { | ||
| 150 | (bdma, $dma:ident) => { | ||
| 151 | let isr = pac::$dma.isr().read(); | ||
| 152 | pac::$dma.ifcr().write_value(isr); | ||
| 153 | let dman = <crate::peripherals::$dma as sealed::Dma>::num() as usize; | ||
| 154 | |||
| 155 | for chn in 0..7 { | ||
| 156 | let n = dman * 8 + chn; | ||
| 157 | if isr.teif(chn) { | ||
| 158 | STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed); | ||
| 159 | STATE.ch_wakers[n].wake(); | ||
| 160 | } else if isr.tcif(chn) { | ||
| 161 | STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed); | ||
| 162 | STATE.ch_wakers[n].wake(); | ||
| 163 | } | ||
| 164 | } | ||
| 165 | }; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | use crate::rcc::sealed::RccPeripheral; | ||
| 170 | |||
| 171 | /// safety: must be called only once | ||
| 172 | pub(crate) unsafe fn init() { | ||
| 173 | pac::interrupts! { | ||
| 174 | (DMA, $irq:ident) => { | ||
| 175 | crate::interrupt::$irq::steal().enable(); | ||
| 176 | }; | ||
| 177 | } | ||
| 178 | pac::peripherals! { | ||
| 179 | (bdma, $peri:ident) => { | ||
| 180 | crate::peripherals::$peri::enable(); | ||
| 181 | }; | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | pub(crate) mod sealed { | ||
| 186 | use super::*; | ||
| 187 | |||
| 188 | pub trait Dma { | ||
| 189 | fn num() -> u8; | ||
| 190 | } | ||
| 191 | |||
| 192 | pub trait Channel { | ||
| 193 | fn dma_regs() -> pac::bdma::Dma; | ||
| 194 | |||
| 195 | fn state_num(&self) -> usize; | ||
| 196 | |||
| 197 | fn ch_num(&self) -> u8; | ||
| 198 | |||
| 199 | fn regs(&self) -> pac::bdma::Ch { | ||
| 200 | Self::dma_regs().ch(self.ch_num() as usize) | ||
| 201 | } | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | pub trait Dma: sealed::Dma + Sized {} | ||
| 206 | pub trait Channel: sealed::Channel + Sized {} | ||
| 207 | |||
| 208 | macro_rules! impl_dma { | ||
| 209 | ($peri:ident, $num:expr) => { | ||
| 210 | impl Dma for crate::peripherals::$peri {} | ||
| 211 | impl sealed::Dma for crate::peripherals::$peri { | ||
| 212 | fn num() -> u8 { | ||
| 213 | $num | ||
| 214 | } | ||
| 215 | } | ||
| 216 | }; | ||
| 217 | } | ||
| 218 | |||
| 219 | macro_rules! impl_dma_channel { | ||
| 220 | ($channel_peri:ident, $dma_peri:ident, $dma_num:expr, $ch_num:expr) => { | ||
| 221 | impl Channel for crate::peripherals::$channel_peri {} | ||
| 222 | impl sealed::Channel for crate::peripherals::$channel_peri { | ||
| 223 | #[inline] | ||
| 224 | fn dma_regs() -> pac::bdma::Dma { | ||
| 225 | crate::pac::$dma_peri | ||
| 226 | } | ||
| 227 | |||
| 228 | fn state_num(&self) -> usize { | ||
| 229 | ($dma_num * 8) + $ch_num | ||
| 230 | } | ||
| 231 | |||
| 232 | fn ch_num(&self) -> u8 { | ||
| 233 | $ch_num | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | #[cfg(not(dmamux))] | ||
| 238 | impl<T> WriteDma<T> for crate::peripherals::$channel_peri | ||
| 239 | where | ||
| 240 | T: 'static, | ||
| 241 | { | ||
| 242 | type WriteDmaFuture<'a> = impl Future<Output = ()>; | ||
| 243 | |||
| 244 | fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> | ||
| 245 | where | ||
| 246 | T: 'a, | ||
| 247 | { | ||
| 248 | use sealed::Channel as _Channel; | ||
| 249 | |||
| 250 | let state_num = self.state_num(); | ||
| 251 | let regs = self.regs(); | ||
| 252 | |||
| 253 | unsafe { transfer_m2p(regs, state_num, buf, dst) } | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | #[cfg(dmamux)] | ||
| 258 | impl<T> WriteDma<T> for crate::peripherals::$channel_peri | ||
| 259 | where | ||
| 260 | Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>, | ||
| 261 | T: 'static, | ||
| 262 | { | ||
| 263 | type WriteDmaFuture<'a> = impl Future<Output = ()>; | ||
| 264 | |||
| 265 | fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> | ||
| 266 | where | ||
| 267 | T: 'a, | ||
| 268 | { | ||
| 269 | use sealed::Channel as _Channel; | ||
| 270 | |||
| 271 | let state_num = self.state_num(); | ||
| 272 | let regs = self.regs(); | ||
| 273 | |||
| 274 | use crate::dmamux::sealed::Channel as _MuxChannel; | ||
| 275 | use crate::dmamux::sealed::PeripheralChannel; | ||
| 276 | let dmamux_regs = self.dmamux_regs(); | ||
| 277 | let dmamux_ch_num = self.dmamux_ch_num(); | ||
| 278 | let request = PeripheralChannel::<T, crate::dmamux::M2P>::request(self); | ||
| 279 | unsafe { | ||
| 280 | transfer_m2p( | ||
| 281 | regs, | ||
| 282 | state_num, | ||
| 283 | buf, | ||
| 284 | dst, | ||
| 285 | dmamux_regs, | ||
| 286 | dmamux_ch_num, | ||
| 287 | request, | ||
| 288 | ) | ||
| 289 | } | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | #[cfg(not(dmamux))] | ||
| 294 | impl<T> ReadDma<T> for crate::peripherals::$channel_peri | ||
| 295 | where | ||
| 296 | T: 'static, | ||
| 297 | { | ||
| 298 | type ReadDmaFuture<'a> = impl Future<Output = ()>; | ||
| 299 | |||
| 300 | fn transfer<'a>( | ||
| 301 | &'a mut self, | ||
| 302 | src: *const u8, | ||
| 303 | buf: &'a mut [u8], | ||
| 304 | ) -> Self::ReadDmaFuture<'a> | ||
| 305 | where | ||
| 306 | T: 'a, | ||
| 307 | { | ||
| 308 | use sealed::Channel as _Channel; | ||
| 309 | |||
| 310 | let state_num = self.state_num(); | ||
| 311 | let regs = self.regs(); | ||
| 312 | unsafe { transfer_p2m(regs, state_num, src, buf) } | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | #[cfg(dmamux)] | ||
| 317 | impl<T> ReadDma<T> for crate::peripherals::$channel_peri | ||
| 318 | where | ||
| 319 | Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>, | ||
| 320 | T: 'static, | ||
| 321 | { | ||
| 322 | type ReadDmaFuture<'a> = impl Future<Output = ()>; | ||
| 323 | |||
| 324 | fn transfer<'a>( | ||
| 325 | &'a mut self, | ||
| 326 | src: *const u8, | ||
| 327 | buf: &'a mut [u8], | ||
| 328 | ) -> Self::ReadDmaFuture<'a> | ||
| 329 | where | ||
| 330 | T: 'a, | ||
| 331 | { | ||
| 332 | use sealed::Channel as _Channel; | ||
| 333 | |||
| 334 | let state_num = self.state_num(); | ||
| 335 | let regs = self.regs(); | ||
| 336 | |||
| 337 | use crate::dmamux::sealed::Channel as _MuxChannel; | ||
| 338 | use crate::dmamux::sealed::PeripheralChannel; | ||
| 339 | let dmamux_regs = self.dmamux_regs(); | ||
| 340 | let dmamux_ch_num = self.dmamux_ch_num(); | ||
| 341 | let request = PeripheralChannel::<T, crate::dmamux::M2P>::request(self); | ||
| 342 | unsafe { | ||
| 343 | transfer_p2m( | ||
| 344 | regs, | ||
| 345 | state_num, | ||
| 346 | src, | ||
| 347 | buf, | ||
| 348 | dmamux_regs, | ||
| 349 | dmamux_ch_num, | ||
| 350 | request, | ||
| 351 | ) | ||
| 352 | } | ||
| 353 | } | ||
| 354 | } | ||
| 355 | }; | ||
| 356 | } | ||
| 357 | |||
| 358 | pac::peripherals! { | ||
| 359 | (bdma, DMA1) => { | ||
| 360 | impl_dma!(DMA1, 0); | ||
| 361 | pac::bdma_channels! { | ||
| 362 | ($channel_peri:ident, DMA1, $channel_num:expr) => { | ||
| 363 | impl_dma_channel!($channel_peri, DMA1, 0, $channel_num); | ||
| 364 | }; | ||
| 365 | } | ||
| 366 | }; | ||
| 367 | (bdma, DMA2) => { | ||
| 368 | impl_dma!(DMA2, 1); | ||
| 369 | pac::bdma_channels! { | ||
| 370 | ($channel_peri:ident, DMA2, $channel_num:expr) => { | ||
| 371 | impl_dma_channel!($channel_peri, DMA2, 1, $channel_num); | ||
| 372 | }; | ||
| 373 | } | ||
| 374 | }; | ||
| 375 | // Because H7cm changes the naming | ||
| 376 | (bdma, BDMA) => { | ||
| 377 | impl_dma!(BDMA, 0); | ||
| 378 | pac::bdma_channels! { | ||
| 379 | ($channel_peri:ident, BDMA, $channel_num:expr) => { | ||
| 380 | impl_dma_channel!($channel_peri, BDMA, 0, $channel_num); | ||
| 381 | }; | ||
| 382 | } | ||
| 383 | }; | ||
| 384 | } | ||
| 385 | |||
| 386 | pac::interrupts! { | ||
| 387 | (DMA, $irq:ident) => { | ||
| 388 | #[crate::interrupt] | ||
| 389 | unsafe fn $irq () { | ||
| 390 | on_irq() | ||
| 391 | } | ||
| 392 | }; | ||
| 393 | } | ||
| 394 | |||
| 395 | #[cfg(usart)] | ||
| 396 | use crate::usart; | ||
| 397 | |||
| 398 | #[cfg(not(dmamux))] | ||
| 399 | pac::peripheral_dma_channels! { | ||
| 400 | ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | ||
| 401 | impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 402 | impl usart::sealed::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 403 | }; | ||
| 404 | |||
| 405 | ($peri:ident, usart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | ||
| 406 | impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 407 | impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 408 | }; | ||
| 409 | |||
| 410 | ($peri:ident, uart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | ||
| 411 | impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 412 | impl usart::sealed::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 413 | }; | ||
| 414 | |||
| 415 | ($peri:ident, uart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | ||
| 416 | impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 417 | impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 418 | }; | ||
| 419 | } | ||
| 420 | |||
| 421 | #[cfg(dmamux)] | ||
| 422 | pac::peripherals! { | ||
| 423 | (usart, $peri:ident) => { | ||
| 424 | pac::bdma_channels! { | ||
| 425 | ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | ||
| 426 | impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 427 | impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 428 | }; | ||
| 429 | } | ||
| 430 | }; | ||
| 431 | (uart, $peri:ident) => { | ||
| 432 | pac::bdma_channels! { | ||
| 433 | ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | ||
| 434 | impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 435 | impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 436 | }; | ||
| 437 | } | ||
| 438 | }; | ||
| 439 | } | ||
diff --git a/embassy-stm32/src/bdma/v1.rs b/embassy-stm32/src/bdma/v1.rs deleted file mode 100644 index e5b0b18b1..000000000 --- a/embassy-stm32/src/bdma/v1.rs +++ /dev/null | |||
| @@ -1,437 +0,0 @@ | |||
| 1 | use core::future::Future; | ||
| 2 | use core::task::Poll; | ||
| 3 | |||
| 4 | use atomic_polyfill::{AtomicU8, Ordering}; | ||
| 5 | use embassy::interrupt::{Interrupt, InterruptExt}; | ||
| 6 | use embassy::util::{AtomicWaker, OnDrop}; | ||
| 7 | use futures::future::poll_fn; | ||
| 8 | |||
| 9 | use crate::dma_traits::{ReadDma, WriteDma}; | ||
| 10 | use crate::interrupt; | ||
| 11 | use crate::pac; | ||
| 12 | use crate::pac::bdma::vals; | ||
| 13 | |||
| 14 | const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8; | ||
| 15 | const CH_STATUS_NONE: u8 = 0; | ||
| 16 | const CH_STATUS_COMPLETED: u8 = 1; | ||
| 17 | const CH_STATUS_ERROR: u8 = 2; | ||
| 18 | |||
| 19 | struct State { | ||
| 20 | ch_wakers: [AtomicWaker; CH_COUNT], | ||
| 21 | ch_status: [AtomicU8; CH_COUNT], | ||
| 22 | } | ||
| 23 | |||
| 24 | impl State { | ||
| 25 | const fn new() -> Self { | ||
| 26 | const AW: AtomicWaker = AtomicWaker::new(); | ||
| 27 | const AU: AtomicU8 = AtomicU8::new(CH_STATUS_NONE); | ||
| 28 | Self { | ||
| 29 | ch_wakers: [AW; CH_COUNT], | ||
| 30 | ch_status: [AU; CH_COUNT], | ||
| 31 | } | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 35 | static STATE: State = State::new(); | ||
| 36 | |||
| 37 | #[allow(unused)] | ||
| 38 | pub(crate) async unsafe fn transfer_p2m( | ||
| 39 | regs: pac::bdma::Ch, | ||
| 40 | state_number: usize, | ||
| 41 | src: *const u8, | ||
| 42 | dst: &mut [u8], | ||
| 43 | #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux, | ||
| 44 | #[cfg(dmamux)] dmamux_ch_num: u8, | ||
| 45 | #[cfg(dmamux)] request: u8, | ||
| 46 | ) { | ||
| 47 | // ndtr is max 16 bits. | ||
| 48 | assert!(dst.len() <= 0xFFFF); | ||
| 49 | |||
| 50 | // Reset status | ||
| 51 | // Generate a DMB here to flush the store buffer (M7) before enabling the DMA | ||
| 52 | STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release); | ||
| 53 | |||
| 54 | let on_drop = OnDrop::new(|| unsafe { | ||
| 55 | regs.cr().modify(|w| { | ||
| 56 | w.set_tcie(false); | ||
| 57 | w.set_teie(false); | ||
| 58 | w.set_en(false); | ||
| 59 | }); | ||
| 60 | while regs.cr().read().en() {} | ||
| 61 | }); | ||
| 62 | |||
| 63 | #[cfg(dmamux)] | ||
| 64 | crate::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request); | ||
| 65 | |||
| 66 | regs.par().write_value(src as u32); | ||
| 67 | regs.mar().write_value(dst.as_mut_ptr() as u32); | ||
| 68 | regs.ndtr().write(|w| w.set_ndt(dst.len() as u16)); | ||
| 69 | regs.cr().write(|w| { | ||
| 70 | w.set_psize(vals::Size::BITS8); | ||
| 71 | w.set_msize(vals::Size::BITS8); | ||
| 72 | w.set_minc(vals::Inc::ENABLED); | ||
| 73 | w.set_teie(true); | ||
| 74 | w.set_tcie(true); | ||
| 75 | w.set_en(true); | ||
| 76 | }); | ||
| 77 | |||
| 78 | let res = poll_fn(|cx| { | ||
| 79 | STATE.ch_wakers[state_number].register(cx.waker()); | ||
| 80 | match STATE.ch_status[state_number].load(Ordering::Acquire) { | ||
| 81 | CH_STATUS_NONE => Poll::Pending, | ||
| 82 | x => Poll::Ready(x), | ||
| 83 | } | ||
| 84 | }) | ||
| 85 | .await; | ||
| 86 | |||
| 87 | // TODO handle error | ||
| 88 | assert!(res == CH_STATUS_COMPLETED); | ||
| 89 | } | ||
| 90 | |||
| 91 | #[allow(unused)] | ||
| 92 | pub(crate) async unsafe fn transfer_m2p( | ||
| 93 | regs: pac::bdma::Ch, | ||
| 94 | state_number: usize, | ||
| 95 | src: &[u8], | ||
| 96 | dst: *mut u8, | ||
| 97 | #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux, | ||
| 98 | #[cfg(dmamux)] dmamux_ch_num: u8, | ||
| 99 | #[cfg(dmamux)] request: u8, | ||
| 100 | ) { | ||
| 101 | // ndtr is max 16 bits. | ||
| 102 | assert!(src.len() <= 0xFFFF); | ||
| 103 | |||
| 104 | // Reset status | ||
| 105 | // Generate a DMB here to flush the store buffer (M7) before enabling the DMA | ||
| 106 | STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release); | ||
| 107 | |||
| 108 | let on_drop = OnDrop::new(|| unsafe { | ||
| 109 | regs.cr().modify(|w| { | ||
| 110 | w.set_tcie(false); | ||
| 111 | w.set_teie(false); | ||
| 112 | w.set_en(false); | ||
| 113 | }); | ||
| 114 | while regs.cr().read().en() {} | ||
| 115 | }); | ||
| 116 | |||
| 117 | #[cfg(dmamux)] | ||
| 118 | crate::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request); | ||
| 119 | |||
| 120 | regs.par().write_value(dst as u32); | ||
| 121 | regs.mar().write_value(src.as_ptr() as u32); | ||
| 122 | regs.ndtr().write(|w| w.set_ndt(src.len() as u16)); | ||
| 123 | regs.cr().write(|w| { | ||
| 124 | w.set_psize(vals::Size::BITS8); | ||
| 125 | w.set_msize(vals::Size::BITS8); | ||
| 126 | w.set_minc(vals::Inc::ENABLED); | ||
| 127 | w.set_dir(vals::Dir::FROMMEMORY); | ||
| 128 | w.set_teie(true); | ||
| 129 | w.set_tcie(true); | ||
| 130 | w.set_en(true); | ||
| 131 | }); | ||
| 132 | |||
| 133 | let res = poll_fn(|cx| { | ||
| 134 | STATE.ch_wakers[state_number].register(cx.waker()); | ||
| 135 | match STATE.ch_status[state_number].load(Ordering::Acquire) { | ||
| 136 | CH_STATUS_NONE => Poll::Pending, | ||
| 137 | x => Poll::Ready(x), | ||
| 138 | } | ||
| 139 | }) | ||
| 140 | .await; | ||
| 141 | |||
| 142 | // TODO handle error | ||
| 143 | assert!(res == CH_STATUS_COMPLETED); | ||
| 144 | } | ||
| 145 | |||
| 146 | unsafe fn on_irq() { | ||
| 147 | pac::peripherals! { | ||
| 148 | (bdma, $dma:ident) => { | ||
| 149 | let isr = pac::$dma.isr().read(); | ||
| 150 | pac::$dma.ifcr().write_value(isr); | ||
| 151 | let dman = <crate::peripherals::$dma as sealed::Dma>::num() as usize; | ||
| 152 | |||
| 153 | for chn in 0..7 { | ||
| 154 | let n = dman * 8 + chn; | ||
| 155 | if isr.teif(chn) { | ||
| 156 | STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed); | ||
| 157 | STATE.ch_wakers[n].wake(); | ||
| 158 | } else if isr.tcif(chn) { | ||
| 159 | STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed); | ||
| 160 | STATE.ch_wakers[n].wake(); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | }; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | use crate::rcc::sealed::RccPeripheral; | ||
| 168 | |||
| 169 | /// safety: must be called only once | ||
| 170 | pub(crate) unsafe fn init() { | ||
| 171 | pac::interrupts! { | ||
| 172 | (DMA, $irq:ident) => { | ||
| 173 | crate::interrupt::$irq::steal().enable(); | ||
| 174 | }; | ||
| 175 | } | ||
| 176 | pac::peripherals! { | ||
| 177 | (bdma, $peri:ident) => { | ||
| 178 | crate::peripherals::$peri::enable(); | ||
| 179 | }; | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | pub(crate) mod sealed { | ||
| 184 | use super::*; | ||
| 185 | |||
| 186 | pub trait Dma { | ||
| 187 | fn num() -> u8; | ||
| 188 | } | ||
| 189 | |||
| 190 | pub trait Channel { | ||
| 191 | fn dma_regs() -> pac::bdma::Dma; | ||
| 192 | |||
| 193 | fn state_num(&self) -> usize; | ||
| 194 | |||
| 195 | fn ch_num(&self) -> u8; | ||
| 196 | |||
| 197 | fn regs(&self) -> pac::bdma::Ch { | ||
| 198 | Self::dma_regs().ch(self.ch_num() as usize) | ||
| 199 | } | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | pub trait Dma: sealed::Dma + Sized {} | ||
| 204 | pub trait Channel: sealed::Channel + Sized {} | ||
| 205 | |||
| 206 | macro_rules! impl_dma { | ||
| 207 | ($peri:ident, $num:expr) => { | ||
| 208 | impl Dma for crate::peripherals::$peri {} | ||
| 209 | impl sealed::Dma for crate::peripherals::$peri { | ||
| 210 | fn num() -> u8 { | ||
| 211 | $num | ||
| 212 | } | ||
| 213 | } | ||
| 214 | }; | ||
| 215 | } | ||
| 216 | |||
| 217 | macro_rules! impl_dma_channel { | ||
| 218 | ($channel_peri:ident, $dma_peri:ident, $dma_num:expr, $ch_num:expr) => { | ||
| 219 | impl Channel for crate::peripherals::$channel_peri {} | ||
| 220 | impl sealed::Channel for crate::peripherals::$channel_peri { | ||
| 221 | #[inline] | ||
| 222 | fn dma_regs() -> pac::bdma::Dma { | ||
| 223 | crate::pac::$dma_peri | ||
| 224 | } | ||
| 225 | |||
| 226 | fn state_num(&self) -> usize { | ||
| 227 | ($dma_num * 8) + $ch_num | ||
| 228 | } | ||
| 229 | |||
| 230 | fn ch_num(&self) -> u8 { | ||
| 231 | $ch_num | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | #[cfg(not(dmamux))] | ||
| 236 | impl<T> WriteDma<T> for crate::peripherals::$channel_peri | ||
| 237 | where | ||
| 238 | T: 'static, | ||
| 239 | { | ||
| 240 | type WriteDmaFuture<'a> = impl Future<Output = ()>; | ||
| 241 | |||
| 242 | fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> | ||
| 243 | where | ||
| 244 | T: 'a, | ||
| 245 | { | ||
| 246 | use sealed::Channel as _Channel; | ||
| 247 | |||
| 248 | let state_num = self.state_num(); | ||
| 249 | let regs = self.regs(); | ||
| 250 | |||
| 251 | unsafe { transfer_m2p(regs, state_num, buf, dst) } | ||
| 252 | } | ||
| 253 | } | ||
| 254 | |||
| 255 | #[cfg(dmamux)] | ||
| 256 | impl<T> WriteDma<T> for crate::peripherals::$channel_peri | ||
| 257 | where | ||
| 258 | Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>, | ||
| 259 | T: 'static, | ||
| 260 | { | ||
| 261 | type WriteDmaFuture<'a> = impl Future<Output = ()>; | ||
| 262 | |||
| 263 | fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> | ||
| 264 | where | ||
| 265 | T: 'a, | ||
| 266 | { | ||
| 267 | use sealed::Channel as _Channel; | ||
| 268 | |||
| 269 | let state_num = self.state_num(); | ||
| 270 | let regs = self.regs(); | ||
| 271 | |||
| 272 | use crate::dmamux::sealed::Channel as _MuxChannel; | ||
| 273 | use crate::dmamux::sealed::PeripheralChannel; | ||
| 274 | let dmamux_regs = self.dmamux_regs(); | ||
| 275 | let dmamux_ch_num = self.dmamux_ch_num(); | ||
| 276 | let request = PeripheralChannel::<T, crate::dmamux::M2P>::request(self); | ||
| 277 | unsafe { | ||
| 278 | transfer_m2p( | ||
| 279 | regs, | ||
| 280 | state_num, | ||
| 281 | buf, | ||
| 282 | dst, | ||
| 283 | dmamux_regs, | ||
| 284 | dmamux_ch_num, | ||
| 285 | request, | ||
| 286 | ) | ||
| 287 | } | ||
| 288 | } | ||
| 289 | } | ||
| 290 | |||
| 291 | #[cfg(not(dmamux))] | ||
| 292 | impl<T> ReadDma<T> for crate::peripherals::$channel_peri | ||
| 293 | where | ||
| 294 | T: 'static, | ||
| 295 | { | ||
| 296 | type ReadDmaFuture<'a> = impl Future<Output = ()>; | ||
| 297 | |||
| 298 | fn transfer<'a>( | ||
| 299 | &'a mut self, | ||
| 300 | src: *const u8, | ||
| 301 | buf: &'a mut [u8], | ||
| 302 | ) -> Self::ReadDmaFuture<'a> | ||
| 303 | where | ||
| 304 | T: 'a, | ||
| 305 | { | ||
| 306 | use sealed::Channel as _Channel; | ||
| 307 | |||
| 308 | let state_num = self.state_num(); | ||
| 309 | let regs = self.regs(); | ||
| 310 | unsafe { transfer_p2m(regs, state_num, src, buf) } | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | #[cfg(dmamux)] | ||
| 315 | impl<T> ReadDma<T> for crate::peripherals::$channel_peri | ||
| 316 | where | ||
| 317 | Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>, | ||
| 318 | T: 'static, | ||
| 319 | { | ||
| 320 | type ReadDmaFuture<'a> = impl Future<Output = ()>; | ||
| 321 | |||
| 322 | fn transfer<'a>( | ||
| 323 | &'a mut self, | ||
| 324 | src: *const u8, | ||
| 325 | buf: &'a mut [u8], | ||
| 326 | ) -> Self::ReadDmaFuture<'a> | ||
| 327 | where | ||
| 328 | T: 'a, | ||
| 329 | { | ||
| 330 | use sealed::Channel as _Channel; | ||
| 331 | |||
| 332 | let state_num = self.state_num(); | ||
| 333 | let regs = self.regs(); | ||
| 334 | |||
| 335 | use crate::dmamux::sealed::Channel as _MuxChannel; | ||
| 336 | use crate::dmamux::sealed::PeripheralChannel; | ||
| 337 | let dmamux_regs = self.dmamux_regs(); | ||
| 338 | let dmamux_ch_num = self.dmamux_ch_num(); | ||
| 339 | let request = PeripheralChannel::<T, crate::dmamux::M2P>::request(self); | ||
| 340 | unsafe { | ||
| 341 | transfer_p2m( | ||
| 342 | regs, | ||
| 343 | state_num, | ||
| 344 | src, | ||
| 345 | buf, | ||
| 346 | dmamux_regs, | ||
| 347 | dmamux_ch_num, | ||
| 348 | request, | ||
| 349 | ) | ||
| 350 | } | ||
| 351 | } | ||
| 352 | } | ||
| 353 | }; | ||
| 354 | } | ||
| 355 | |||
| 356 | pac::peripherals! { | ||
| 357 | (bdma, DMA1) => { | ||
| 358 | impl_dma!(DMA1, 0); | ||
| 359 | pac::bdma_channels! { | ||
| 360 | ($channel_peri:ident, DMA1, $channel_num:expr) => { | ||
| 361 | impl_dma_channel!($channel_peri, DMA1, 0, $channel_num); | ||
| 362 | }; | ||
| 363 | } | ||
| 364 | }; | ||
| 365 | (bdma, DMA2) => { | ||
| 366 | impl_dma!(DMA2, 1); | ||
| 367 | pac::bdma_channels! { | ||
| 368 | ($channel_peri:ident, DMA2, $channel_num:expr) => { | ||
| 369 | impl_dma_channel!($channel_peri, DMA2, 1, $channel_num); | ||
| 370 | }; | ||
| 371 | } | ||
| 372 | }; | ||
| 373 | // Because H7cm changes the naming | ||
| 374 | (bdma, BDMA) => { | ||
| 375 | impl_dma!(BDMA, 0); | ||
| 376 | pac::bdma_channels! { | ||
| 377 | ($channel_peri:ident, BDMA, $channel_num:expr) => { | ||
| 378 | impl_dma_channel!($channel_peri, BDMA, 0, $channel_num); | ||
| 379 | }; | ||
| 380 | } | ||
| 381 | }; | ||
| 382 | } | ||
| 383 | |||
| 384 | pac::interrupts! { | ||
| 385 | (DMA, $irq:ident) => { | ||
| 386 | #[crate::interrupt] | ||
| 387 | unsafe fn $irq () { | ||
| 388 | on_irq() | ||
| 389 | } | ||
| 390 | }; | ||
| 391 | } | ||
| 392 | |||
| 393 | #[cfg(usart)] | ||
| 394 | use crate::usart; | ||
| 395 | |||
| 396 | #[cfg(not(dmamux))] | ||
| 397 | pac::peripheral_dma_channels! { | ||
| 398 | ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | ||
| 399 | impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 400 | impl usart::sealed::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 401 | }; | ||
| 402 | |||
| 403 | ($peri:ident, usart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | ||
| 404 | impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 405 | impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 406 | }; | ||
| 407 | |||
| 408 | ($peri:ident, uart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | ||
| 409 | impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 410 | impl usart::sealed::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 411 | }; | ||
| 412 | |||
| 413 | ($peri:ident, uart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | ||
| 414 | impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 415 | impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 416 | }; | ||
| 417 | } | ||
| 418 | |||
| 419 | #[cfg(dmamux)] | ||
| 420 | pac::peripherals! { | ||
| 421 | (usart, $peri:ident) => { | ||
| 422 | pac::bdma_channels! { | ||
| 423 | ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | ||
| 424 | impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 425 | impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 426 | }; | ||
| 427 | } | ||
| 428 | }; | ||
| 429 | (uart, $peri:ident) => { | ||
| 430 | pac::bdma_channels! { | ||
| 431 | ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | ||
| 432 | impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 433 | impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } | ||
| 434 | }; | ||
| 435 | } | ||
| 436 | }; | ||
| 437 | } | ||
diff --git a/embassy-stm32/src/bdma/v2.rs b/embassy-stm32/src/bdma/v2.rs deleted file mode 100644 index 956b83cd1..000000000 --- a/embassy-stm32/src/bdma/v2.rs +++ /dev/null | |||
| @@ -1 +0,0 @@ | |||
| 1 | pub(crate) unsafe fn init() {} | ||
diff --git a/embassy-stm32/src/dmamux/mod.rs b/embassy-stm32/src/dmamux/mod.rs index ebb1748db..0f3fb9a8f 100644 --- a/embassy-stm32/src/dmamux/mod.rs +++ b/embassy-stm32/src/dmamux/mod.rs | |||
| @@ -6,82 +6,6 @@ use crate::pac::dma_requests; | |||
| 6 | use crate::pac::peripherals; | 6 | use crate::pac::peripherals; |
| 7 | use crate::peripherals; | 7 | use crate::peripherals; |
| 8 | 8 | ||
| 9 | /* | ||
| 10 | #[allow(unused)] | ||
| 11 | pub(crate) async unsafe fn transfer_m2p( | ||
| 12 | ch: &mut impl Channel, | ||
| 13 | ch_func: u8, | ||
| 14 | src: &[u8], | ||
| 15 | dst: *mut u8, | ||
| 16 | ) { | ||
| 17 | defmt::info!( | ||
| 18 | "m2p {} func {} {}-{}", | ||
| 19 | src.len(), | ||
| 20 | ch_func, | ||
| 21 | ch.num(), | ||
| 22 | ch.dma_ch_num() | ||
| 23 | ); | ||
| 24 | let n = ch.num(); | ||
| 25 | |||
| 26 | STATE.ch_status[n].store(CH_STATUS_NONE, Ordering::Release); | ||
| 27 | |||
| 28 | let ch_regs = ch.regs(); | ||
| 29 | let dmamux_regs = ch.dmamux_regs(); | ||
| 30 | let ch_mux_regs = dmamux_regs.ccr(ch.dmamux_ch_num() as _); | ||
| 31 | |||
| 32 | ch_mux_regs.write(|reg| { | ||
| 33 | // one request? | ||
| 34 | reg.set_nbreq(0); | ||
| 35 | reg.set_dmareq_id(ch_func); | ||
| 36 | }); | ||
| 37 | |||
| 38 | ch_mux_regs.modify(|reg| { | ||
| 39 | reg.set_ege(true); | ||
| 40 | //reg.set_se(true); | ||
| 41 | //reg.set_soie(true); | ||
| 42 | }); | ||
| 43 | |||
| 44 | ch_regs.par().write_value(dst as _); | ||
| 45 | ch_regs.mar().write_value(src.as_ptr() as _); | ||
| 46 | ch_regs.ndtr().write_value(regs::Ndtr(src.len() as _)); | ||
| 47 | |||
| 48 | ch_regs.cr().write(|reg| { | ||
| 49 | reg.set_dir(vals::Dir::FROMMEMORY); | ||
| 50 | reg.set_msize(vals::Size::BITS8); | ||
| 51 | reg.set_minc(vals::Inc::ENABLED); | ||
| 52 | reg.set_pinc(vals::Inc::DISABLED); | ||
| 53 | reg.set_teie(true); | ||
| 54 | reg.set_tcie(true); | ||
| 55 | reg.set_en(true); | ||
| 56 | }); | ||
| 57 | |||
| 58 | let res = poll_fn(|cx| { | ||
| 59 | defmt::info!("poll"); | ||
| 60 | STATE.ch_wakers[n].register(cx.waker()); | ||
| 61 | match STATE.ch_status[n].load(Ordering::Acquire) { | ||
| 62 | CH_STATUS_NONE => Poll::Pending, | ||
| 63 | x => Poll::Ready(x), | ||
| 64 | } | ||
| 65 | }) | ||
| 66 | .await; | ||
| 67 | |||
| 68 | defmt::info!("cr {:b}", ch_regs.cr().read().0); | ||
| 69 | |||
| 70 | ch_regs.cr().modify(|reg| { | ||
| 71 | reg.set_en(false); | ||
| 72 | }); | ||
| 73 | |||
| 74 | ch_mux_regs.modify(|reg| { | ||
| 75 | reg.set_ege(false); | ||
| 76 | //reg.set_se(true); | ||
| 77 | //reg.set_soie(true); | ||
| 78 | }); | ||
| 79 | |||
| 80 | // TODO handle error | ||
| 81 | assert!(res == CH_STATUS_COMPLETED); | ||
| 82 | } | ||
| 83 | */ | ||
| 84 | |||
| 85 | pub(crate) unsafe fn configure_dmamux( | 9 | pub(crate) unsafe fn configure_dmamux( |
| 86 | dmamux_regs: pac::dmamux::Dmamux, | 10 | dmamux_regs: pac::dmamux::Dmamux, |
| 87 | dmamux_ch_num: u8, | 11 | dmamux_ch_num: u8, |
| @@ -89,15 +13,12 @@ pub(crate) unsafe fn configure_dmamux( | |||
| 89 | ) { | 13 | ) { |
| 90 | let ch_mux_regs = dmamux_regs.ccr(dmamux_ch_num as _); | 14 | let ch_mux_regs = dmamux_regs.ccr(dmamux_ch_num as _); |
| 91 | ch_mux_regs.write(|reg| { | 15 | ch_mux_regs.write(|reg| { |
| 92 | // one request? | ||
| 93 | reg.set_nbreq(0); | 16 | reg.set_nbreq(0); |
| 94 | reg.set_dmareq_id(request); | 17 | reg.set_dmareq_id(request); |
| 95 | }); | 18 | }); |
| 96 | 19 | ||
| 97 | ch_mux_regs.modify(|reg| { | 20 | ch_mux_regs.modify(|reg| { |
| 98 | reg.set_ege(true); | 21 | reg.set_ege(true); |
| 99 | //reg.set_se(true); | ||
| 100 | //reg.set_soie(true); | ||
| 101 | }); | 22 | }); |
| 102 | } | 23 | } |
| 103 | 24 | ||
| @@ -236,6 +157,7 @@ use crate::usart; | |||
| 236 | 157 | ||
| 237 | bdma_channels! { | 158 | bdma_channels! { |
| 238 | ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { | 159 | ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { |
| 160 | #[cfg(usart)] | ||
| 239 | impl_usart_dma_requests!($channel_peri, $dma_peri, $channel_num); | 161 | impl_usart_dma_requests!($channel_peri, $dma_peri, $channel_num); |
| 240 | }; | 162 | }; |
| 241 | } | 163 | } |
