aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/macros.rs12
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs104
2 files changed, 66 insertions, 50 deletions
diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs
index ae53deb08..000773e2d 100644
--- a/embassy-stm32/src/macros.rs
+++ b/embassy-stm32/src/macros.rs
@@ -85,6 +85,18 @@ macro_rules! dma_trait_impl {
85 }; 85 };
86} 86}
87 87
88#[allow(unused)]
89macro_rules! new_dma_nonopt {
90 ($name:ident) => {{
91 let dma = $name.into_ref();
92 let request = dma.request();
93 crate::dma::ChannelAndRequest {
94 channel: dma.map_into(),
95 request,
96 }
97 }};
98}
99
88macro_rules! new_dma { 100macro_rules! new_dma {
89 ($name:ident) => {{ 101 ($name:ident) => {{
90 let dma = $name.into_ref(); 102 let dma = $name.into_ref();
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 8af2f8381..d8671caf7 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -12,7 +12,8 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
12use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; 13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};
14 14
15use crate::dma::NoDma; 15#[cfg(sdmmc_v1)]
16use crate::dma::ChannelAndRequest;
16#[cfg(gpio_v2)] 17#[cfg(gpio_v2)]
17use crate::gpio::Pull; 18use crate::gpio::Pull;
18use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; 19use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed};
@@ -301,10 +302,10 @@ impl Default for Config {
301} 302}
302 303
303/// Sdmmc device 304/// Sdmmc device
304pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> { 305pub struct Sdmmc<'d, T: Instance> {
305 _peri: PeripheralRef<'d, T>, 306 _peri: PeripheralRef<'d, T>,
306 #[allow(unused)] 307 #[cfg(sdmmc_v1)]
307 dma: PeripheralRef<'d, Dma>, 308 dma: ChannelAndRequest<'d>,
308 309
309 clk: PeripheralRef<'d, AnyPin>, 310 clk: PeripheralRef<'d, AnyPin>,
310 cmd: PeripheralRef<'d, AnyPin>, 311 cmd: PeripheralRef<'d, AnyPin>,
@@ -334,18 +335,18 @@ const CMD_AF: AfType = AfType::output_pull(OutputType::PushPull, Speed::VeryHigh
334const DATA_AF: AfType = CMD_AF; 335const DATA_AF: AfType = CMD_AF;
335 336
336#[cfg(sdmmc_v1)] 337#[cfg(sdmmc_v1)]
337impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { 338impl<'d, T: Instance> Sdmmc<'d, T> {
338 /// Create a new SDMMC driver, with 1 data lane. 339 /// Create a new SDMMC driver, with 1 data lane.
339 pub fn new_1bit( 340 pub fn new_1bit(
340 sdmmc: impl Peripheral<P = T> + 'd, 341 sdmmc: impl Peripheral<P = T> + 'd,
341 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 342 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
342 dma: impl Peripheral<P = Dma> + 'd, 343 dma: impl Peripheral<P = impl SdmmcDma<T>> + 'd,
343 clk: impl Peripheral<P = impl CkPin<T>> + 'd, 344 clk: impl Peripheral<P = impl CkPin<T>> + 'd,
344 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, 345 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
345 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 346 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
346 config: Config, 347 config: Config,
347 ) -> Self { 348 ) -> Self {
348 into_ref!(clk, cmd, d0); 349 into_ref!(dma, clk, cmd, d0);
349 350
350 critical_section::with(|_| { 351 critical_section::with(|_| {
351 clk.set_as_af(clk.af_num(), CLK_AF); 352 clk.set_as_af(clk.af_num(), CLK_AF);
@@ -355,7 +356,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
355 356
356 Self::new_inner( 357 Self::new_inner(
357 sdmmc, 358 sdmmc,
358 dma, 359 new_dma_nonopt!(dma),
359 clk.map_into(), 360 clk.map_into(),
360 cmd.map_into(), 361 cmd.map_into(),
361 d0.map_into(), 362 d0.map_into(),
@@ -370,7 +371,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
370 pub fn new_4bit( 371 pub fn new_4bit(
371 sdmmc: impl Peripheral<P = T> + 'd, 372 sdmmc: impl Peripheral<P = T> + 'd,
372 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 373 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
373 dma: impl Peripheral<P = Dma> + 'd, 374 dma: impl Peripheral<P = impl SdmmcDma<T>> + 'd,
374 clk: impl Peripheral<P = impl CkPin<T>> + 'd, 375 clk: impl Peripheral<P = impl CkPin<T>> + 'd,
375 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, 376 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
376 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 377 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
@@ -392,7 +393,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
392 393
393 Self::new_inner( 394 Self::new_inner(
394 sdmmc, 395 sdmmc,
395 dma, 396 new_dma_nonopt!(dma),
396 clk.map_into(), 397 clk.map_into(),
397 cmd.map_into(), 398 cmd.map_into(),
398 d0.map_into(), 399 d0.map_into(),
@@ -405,7 +406,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
405} 406}
406 407
407#[cfg(sdmmc_v2)] 408#[cfg(sdmmc_v2)]
408impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { 409impl<'d, T: Instance> Sdmmc<'d, T> {
409 /// Create a new SDMMC driver, with 1 data lane. 410 /// Create a new SDMMC driver, with 1 data lane.
410 pub fn new_1bit( 411 pub fn new_1bit(
411 sdmmc: impl Peripheral<P = T> + 'd, 412 sdmmc: impl Peripheral<P = T> + 'd,
@@ -425,7 +426,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
425 426
426 Self::new_inner( 427 Self::new_inner(
427 sdmmc, 428 sdmmc,
428 NoDma.into_ref(),
429 clk.map_into(), 429 clk.map_into(),
430 cmd.map_into(), 430 cmd.map_into(),
431 d0.map_into(), 431 d0.map_into(),
@@ -461,7 +461,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
461 461
462 Self::new_inner( 462 Self::new_inner(
463 sdmmc, 463 sdmmc,
464 NoDma.into_ref(),
465 clk.map_into(), 464 clk.map_into(),
466 cmd.map_into(), 465 cmd.map_into(),
467 d0.map_into(), 466 d0.map_into(),
@@ -473,10 +472,10 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
473 } 472 }
474} 473}
475 474
476impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { 475impl<'d, T: Instance> Sdmmc<'d, T> {
477 fn new_inner( 476 fn new_inner(
478 sdmmc: impl Peripheral<P = T> + 'd, 477 sdmmc: impl Peripheral<P = T> + 'd,
479 dma: impl Peripheral<P = Dma> + 'd, 478 #[cfg(sdmmc_v1)] dma: ChannelAndRequest<'d>,
480 clk: PeripheralRef<'d, AnyPin>, 479 clk: PeripheralRef<'d, AnyPin>,
481 cmd: PeripheralRef<'d, AnyPin>, 480 cmd: PeripheralRef<'d, AnyPin>,
482 d0: PeripheralRef<'d, AnyPin>, 481 d0: PeripheralRef<'d, AnyPin>,
@@ -485,7 +484,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
485 d3: Option<PeripheralRef<'d, AnyPin>>, 484 d3: Option<PeripheralRef<'d, AnyPin>>,
486 config: Config, 485 config: Config,
487 ) -> Self { 486 ) -> Self {
488 into_ref!(sdmmc, dma); 487 into_ref!(sdmmc);
489 488
490 rcc::enable_and_reset::<T>(); 489 rcc::enable_and_reset::<T>();
491 490
@@ -514,6 +513,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
514 513
515 Self { 514 Self {
516 _peri: sdmmc, 515 _peri: sdmmc,
516 #[cfg(sdmmc_v1)]
517 dma, 517 dma,
518 518
519 clk, 519 clk,
@@ -567,7 +567,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
567 #[allow(unused_variables)] 567 #[allow(unused_variables)]
568 fn prepare_datapath_read<'a>( 568 fn prepare_datapath_read<'a>(
569 config: &Config, 569 config: &Config,
570 dma: &'a mut PeripheralRef<'d, Dma>, 570 #[cfg(sdmmc_v1)] dma: &'a mut ChannelAndRequest<'d>,
571 buffer: &'a mut [u32], 571 buffer: &'a mut [u32],
572 length_bytes: u32, 572 length_bytes: u32,
573 block_size: u8, 573 block_size: u8,
@@ -583,16 +583,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
583 regs.dlenr().write(|w| w.set_datalength(length_bytes)); 583 regs.dlenr().write(|w| w.set_datalength(length_bytes));
584 584
585 #[cfg(sdmmc_v1)] 585 #[cfg(sdmmc_v1)]
586 let transfer = unsafe { 586 let transfer = unsafe { dma.read(regs.fifor().as_ptr() as *mut u32, buffer, DMA_TRANSFER_OPTIONS) };
587 let request = dma.request();
588 Transfer::new_read(
589 dma,
590 request,
591 regs.fifor().as_ptr() as *mut u32,
592 buffer,
593 DMA_TRANSFER_OPTIONS,
594 )
595 };
596 #[cfg(sdmmc_v2)] 587 #[cfg(sdmmc_v2)]
597 let transfer = { 588 let transfer = {
598 regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); 589 regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32));
@@ -632,14 +623,8 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
632 623
633 #[cfg(sdmmc_v1)] 624 #[cfg(sdmmc_v1)]
634 let transfer = unsafe { 625 let transfer = unsafe {
635 let request = self.dma.request(); 626 self.dma
636 Transfer::new_write( 627 .write(buffer, regs.fifor().as_ptr() as *mut u32, DMA_TRANSFER_OPTIONS)
637 &mut self.dma,
638 request,
639 buffer,
640 regs.fifor().as_ptr() as *mut u32,
641 DMA_TRANSFER_OPTIONS,
642 )
643 }; 628 };
644 #[cfg(sdmmc_v2)] 629 #[cfg(sdmmc_v2)]
645 let transfer = { 630 let transfer = {
@@ -735,7 +720,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
735 let regs = T::regs(); 720 let regs = T::regs();
736 let on_drop = OnDrop::new(|| Self::on_drop()); 721 let on_drop = OnDrop::new(|| Self::on_drop());
737 722
738 let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6); 723 let transfer = Self::prepare_datapath_read(
724 &self.config,
725 #[cfg(sdmmc_v1)]
726 &mut self.dma,
727 status.as_mut(),
728 64,
729 6,
730 );
739 InterruptHandler::<T>::data_interrupts(true); 731 InterruptHandler::<T>::data_interrupts(true);
740 Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6 732 Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6
741 733
@@ -821,7 +813,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
821 let regs = T::regs(); 813 let regs = T::regs();
822 let on_drop = OnDrop::new(|| Self::on_drop()); 814 let on_drop = OnDrop::new(|| Self::on_drop());
823 815
824 let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6); 816 let transfer = Self::prepare_datapath_read(
817 &self.config,
818 #[cfg(sdmmc_v1)]
819 &mut self.dma,
820 status.as_mut(),
821 64,
822 6,
823 );
825 InterruptHandler::<T>::data_interrupts(true); 824 InterruptHandler::<T>::data_interrupts(true);
826 Self::cmd(Cmd::card_status(0), true)?; 825 Self::cmd(Cmd::card_status(0), true)?;
827 826
@@ -924,7 +923,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
924 let regs = T::regs(); 923 let regs = T::regs();
925 let on_drop = OnDrop::new(|| Self::on_drop()); 924 let on_drop = OnDrop::new(|| Self::on_drop());
926 925
927 let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, scr, 8, 3); 926 let transfer = Self::prepare_datapath_read(
927 &self.config,
928 #[cfg(sdmmc_v1)]
929 &mut self.dma,
930 scr,
931 8,
932 3,
933 );
928 InterruptHandler::<T>::data_interrupts(true); 934 InterruptHandler::<T>::data_interrupts(true);
929 Self::cmd(Cmd::cmd51(), true)?; 935 Self::cmd(Cmd::cmd51(), true)?;
930 936
@@ -1214,7 +1220,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1214 let regs = T::regs(); 1220 let regs = T::regs();
1215 let on_drop = OnDrop::new(|| Self::on_drop()); 1221 let on_drop = OnDrop::new(|| Self::on_drop());
1216 1222
1217 let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, buffer, 512, 9); 1223 let transfer = Self::prepare_datapath_read(
1224 &self.config,
1225 #[cfg(sdmmc_v1)]
1226 &mut self.dma,
1227 buffer,
1228 512,
1229 9,
1230 );
1218 InterruptHandler::<T>::data_interrupts(true); 1231 InterruptHandler::<T>::data_interrupts(true);
1219 Self::cmd(Cmd::read_single_block(address), true)?; 1232 Self::cmd(Cmd::read_single_block(address), true)?;
1220 1233
@@ -1347,7 +1360,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1347 } 1360 }
1348} 1361}
1349 1362
1350impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> { 1363impl<'d, T: Instance> Drop for Sdmmc<'d, T> {
1351 fn drop(&mut self) { 1364 fn drop(&mut self) {
1352 T::Interrupt::disable(); 1365 T::Interrupt::disable();
1353 Self::on_drop(); 1366 Self::on_drop();
@@ -1484,15 +1497,6 @@ pin_trait!(D7Pin, Instance);
1484#[cfg(sdmmc_v1)] 1497#[cfg(sdmmc_v1)]
1485dma_trait!(SdmmcDma, Instance); 1498dma_trait!(SdmmcDma, Instance);
1486 1499
1487/// DMA instance trait.
1488///
1489/// This is only implemented for `NoDma`, since SDMMCv2 has DMA built-in, instead of
1490/// using ST's system-wide DMA peripheral.
1491#[cfg(sdmmc_v2)]
1492pub trait SdmmcDma<T: Instance> {}
1493#[cfg(sdmmc_v2)]
1494impl<T: Instance> SdmmcDma<T> for NoDma {}
1495
1496foreach_peripheral!( 1500foreach_peripheral!(
1497 (sdmmc, $inst:ident) => { 1501 (sdmmc, $inst:ident) => {
1498 impl SealedInstance for peripherals::$inst { 1502 impl SealedInstance for peripherals::$inst {
@@ -1512,7 +1516,7 @@ foreach_peripheral!(
1512 }; 1516 };
1513); 1517);
1514 1518
1515impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> block_device_driver::BlockDevice<512> for Sdmmc<'d, T, Dma> { 1519impl<'d, T: Instance> block_device_driver::BlockDevice<512> for Sdmmc<'d, T> {
1516 type Error = Error; 1520 type Error = Error;
1517 type Align = aligned::A4; 1521 type Align = aligned::A4;
1518 1522