aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs34
1 files changed, 21 insertions, 13 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index c91f3c8bf..a52c65b92 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -18,6 +18,9 @@ use crate::rcc::RccPeripheral;
18use crate::time::Hertz; 18use crate::time::Hertz;
19use crate::{peripherals, Peripheral}; 19use crate::{peripherals, Peripheral};
20 20
21/// Frequency used for SD Card initialization. Must be no higher than 400 kHz.
22const SD_INIT_FREQ: Hertz = Hertz(400_000);
23
21/// The signalling scheme used on the SDMMC bus 24/// The signalling scheme used on the SDMMC bus
22#[non_exhaustive] 25#[non_exhaustive]
23#[derive(Debug, Copy, Clone, PartialEq, Eq)] 26#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -295,7 +298,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
295 T::reset(); 298 T::reset();
296 299
297 let inner = T::inner(); 300 let inner = T::inner();
298 let clock = unsafe { inner.new_inner(T::frequency()) }; 301 unsafe { inner.new_inner() };
299 302
300 irq.set_handler(Self::on_interrupt); 303 irq.set_handler(Self::on_interrupt);
301 irq.unpend(); 304 irq.unpend();
@@ -314,7 +317,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
314 d3, 317 d3,
315 318
316 config, 319 config,
317 clock, 320 clock: SD_INIT_FREQ,
318 signalling: Default::default(), 321 signalling: Default::default(),
319 card: None, 322 card: None,
320 } 323 }
@@ -415,7 +418,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
415 T::reset(); 418 T::reset();
416 419
417 let inner = T::inner(); 420 let inner = T::inner();
418 let clock = unsafe { inner.new_inner(T::frequency()) }; 421 unsafe { inner.new_inner() };
419 422
420 irq.set_handler(Self::on_interrupt); 423 irq.set_handler(Self::on_interrupt);
421 irq.unpend(); 424 irq.unpend();
@@ -434,7 +437,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
434 d3, 437 d3,
435 438
436 config, 439 config,
437 clock, 440 clock: SD_INIT_FREQ,
438 signalling: Default::default(), 441 signalling: Default::default(),
439 card: None, 442 card: None,
440 } 443 }
@@ -561,16 +564,10 @@ impl SdmmcInner {
561 /// # Safety 564 /// # Safety
562 /// 565 ///
563 /// Access to `regs` registers should be exclusive 566 /// Access to `regs` registers should be exclusive
564 unsafe fn new_inner(&self, kernel_clk: Hertz) -> Hertz { 567 unsafe fn new_inner(&self) {
565 let regs = self.0; 568 let regs = self.0;
566 569
567 // While the SD/SDIO card or eMMC is in identification mode,
568 // the SDMMC_CK frequency must be less than 400 kHz.
569 let (clkdiv, clock) = unwrap!(clk_div(kernel_clk, 400_000));
570
571 regs.clkcr().write(|w| { 570 regs.clkcr().write(|w| {
572 w.set_widbus(0);
573 w.set_clkdiv(clkdiv);
574 w.set_pwrsav(false); 571 w.set_pwrsav(false);
575 w.set_negedge(false); 572 w.set_negedge(false);
576 w.set_hwfc_en(true); 573 w.set_hwfc_en(true);
@@ -582,8 +579,6 @@ impl SdmmcInner {
582 // Power off, writen 00: Clock to the card is stopped; 579 // Power off, writen 00: Clock to the card is stopped;
583 // D[7:0], CMD, and CK are driven high. 580 // D[7:0], CMD, and CK are driven high.
584 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8)); 581 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8));
585
586 clock
587 } 582 }
588 583
589 /// Initializes card (if present) and sets the bus at the 584 /// Initializes card (if present) and sets the bus at the
@@ -605,6 +600,19 @@ impl SdmmcInner {
605 600
606 // NOTE(unsafe) We have exclusive access to the peripheral 601 // NOTE(unsafe) We have exclusive access to the peripheral
607 unsafe { 602 unsafe {
603 // While the SD/SDIO card or eMMC is in identification mode,
604 // the SDMMC_CK frequency must be no more than 400 kHz.
605 let (clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0));
606 *clock = init_clock;
607
608 // CPSMACT and DPSMACT must be 0 to set WIDBUS
609 self.wait_idle();
610
611 regs.clkcr().modify(|w| {
612 w.set_widbus(0);
613 w.set_clkdiv(clkdiv);
614 });
615
608 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); 616 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
609 self.cmd(Cmd::idle(), false)?; 617 self.cmd(Cmd::idle(), false)?;
610 618