diff options
| -rw-r--r-- | embassy-stm32/src/sdmmc/mod.rs | 34 |
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; | |||
| 18 | use crate::time::Hertz; | 18 | use crate::time::Hertz; |
| 19 | use crate::{peripherals, Peripheral}; | 19 | use crate::{peripherals, Peripheral}; |
| 20 | 20 | ||
| 21 | /// Frequency used for SD Card initialization. Must be no higher than 400 kHz. | ||
| 22 | const 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 | ||
