aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs100
1 files changed, 61 insertions, 39 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 0bcd42bc2..2d91286fa 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -491,7 +491,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
491 bus_width, 491 bus_width,
492 &mut self.card, 492 &mut self.card,
493 &mut self.signalling, 493 &mut self.signalling,
494 Self::kernel_clock(), 494 T::kernel_clk(),
495 &mut self.clock, 495 &mut self.clock,
496 T::state(), 496 T::state(),
497 self.config.data_transfer_timeout, 497 self.config.data_transfer_timeout,
@@ -563,44 +563,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
563 regs.data_interrupts(false); 563 regs.data_interrupts(false);
564 state.wake(); 564 state.wake();
565 } 565 }
566
567 /// Returns kernel clock (SDIOCLK) for the SD-card facing domain
568 fn kernel_clock() -> Hertz {
569 cfg_if::cfg_if! {
570 // TODO, these could not be implemented, because required clocks are not exposed in RCC:
571 // - H7 uses pll1_q_ck or pll2_r_ck depending on SDMMCSEL
572 // - L1 uses pll48
573 // - L4 uses clk48(pll48)
574 // - L4+, L5, U5 uses clk48(pll48) or PLLSAI3CLK(PLLP) depending on SDMMCSEL
575 if #[cfg(stm32f1)] {
576 // F1 uses AHB1(HCLK), which is correct in PAC
577 T::frequency()
578 } else if #[cfg(any(stm32f2, stm32f4))] {
579 // F2, F4 always use pll48
580 critical_section::with(|_| unsafe {
581 crate::rcc::get_freqs().pll48
582 }).expect("PLL48 is required for SDIO")
583 } else if #[cfg(stm32f7)] {
584 critical_section::with(|_| unsafe {
585 use core::any::TypeId;
586 let sdmmcsel = if TypeId::of::<T>() == TypeId::of::<crate::peripherals::SDMMC1>() {
587 crate::pac::RCC.dckcfgr2().read().sdmmc1sel()
588 } else {
589 crate::pac::RCC.dckcfgr2().read().sdmmc2sel()
590 };
591
592 if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYSCLK {
593 crate::rcc::get_freqs().sys
594 } else {
595 crate::rcc::get_freqs().pll48.expect("PLL48 is required for SDMMC")
596 }
597 })
598 } else {
599 // Use default peripheral clock and hope it works
600 T::frequency()
601 }
602 }
603 }
604} 566}
605 567
606impl<'d, T: Instance, Dma> Drop for Sdmmc<'d, T, Dma> { 568impl<'d, T: Instance, Dma> Drop for Sdmmc<'d, T, Dma> {
@@ -1580,6 +1542,7 @@ pub(crate) mod sealed {
1580 1542
1581 fn inner() -> SdmmcInner; 1543 fn inner() -> SdmmcInner;
1582 fn state() -> &'static AtomicWaker; 1544 fn state() -> &'static AtomicWaker;
1545 fn kernel_clk() -> Hertz;
1583 } 1546 }
1584 1547
1585 pub trait Pins<T: Instance> {} 1548 pub trait Pins<T: Instance> {}
@@ -1607,6 +1570,61 @@ cfg_if::cfg_if! {
1607 } 1570 }
1608} 1571}
1609 1572
1573cfg_if::cfg_if! {
1574 // TODO, these could not be implemented, because required clocks are not exposed in RCC:
1575 // - H7 uses pll1_q_ck or pll2_r_ck depending on SDMMCSEL
1576 // - L1 uses pll48
1577 // - L4 uses clk48(pll48)
1578 // - L4+, L5, U5 uses clk48(pll48) or PLLSAI3CLK(PLLP) depending on SDMMCSEL
1579 if #[cfg(stm32f1)] {
1580 // F1 uses AHB1(HCLK), which is correct in PAC
1581 macro_rules! kernel_clk {
1582 ($inst:ident) => {
1583 peripherals::$inst::frequency()
1584 }
1585 }
1586 } else if #[cfg(any(stm32f2, stm32f4))] {
1587 // F2, F4 always use pll48
1588 macro_rules! kernel_clk {
1589 ($inst:ident) => {
1590 critical_section::with(|_| unsafe {
1591 crate::rcc::get_freqs().pll48
1592 }).expect("PLL48 is required for SDIO")
1593 }
1594 }
1595 } else if #[cfg(stm32f7)] {
1596 macro_rules! kernel_clk {
1597 (SDMMC1) => {
1598 critical_section::with(|_| unsafe {
1599 let sdmmcsel = crate::pac::RCC.dckcfgr2().read().sdmmc1sel();
1600 if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYSCLK {
1601 crate::rcc::get_freqs().sys
1602 } else {
1603 crate::rcc::get_freqs().pll48.expect("PLL48 is required for SDMMC")
1604 }
1605 })
1606 };
1607 (SDMMC2) => {
1608 critical_section::with(|_| unsafe {
1609 let sdmmcsel = crate::pac::RCC.dckcfgr2().read().sdmmc2sel();
1610 if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYSCLK {
1611 crate::rcc::get_freqs().sys
1612 } else {
1613 crate::rcc::get_freqs().pll48.expect("PLL48 is required for SDMMC")
1614 }
1615 })
1616 };
1617 }
1618 } else {
1619 // Use default peripheral clock and hope it works
1620 macro_rules! kernel_clk {
1621 ($inst:ident) => {
1622 peripherals::$inst::frequency()
1623 }
1624 }
1625 }
1626}
1627
1610foreach_peripheral!( 1628foreach_peripheral!(
1611 (sdmmc, $inst:ident) => { 1629 (sdmmc, $inst:ident) => {
1612 impl sealed::Instance for peripherals::$inst { 1630 impl sealed::Instance for peripherals::$inst {
@@ -1621,6 +1639,10 @@ foreach_peripheral!(
1621 static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new(); 1639 static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new();
1622 &WAKER 1640 &WAKER
1623 } 1641 }
1642
1643 fn kernel_clk() -> Hertz {
1644 kernel_clk!($inst)
1645 }
1624 } 1646 }
1625 1647
1626 impl Instance for peripherals::$inst {} 1648 impl Instance for peripherals::$inst {}