From 896764bb8562b483ceecb39db2827061fc90d598 Mon Sep 17 00:00:00 2001 From: chemicstry Date: Thu, 23 Feb 2023 17:38:52 +0200 Subject: [PATCH] stm32/sdmmc: Refactor TypeId into a macro --- embassy-stm32/src/sdmmc/mod.rs | 100 ++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 39 deletions(-) diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 0bcd42bc..2d91286f 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> Sdmmc<'d, T, Dma> { bus_width, &mut self.card, &mut self.signalling, - Self::kernel_clock(), + T::kernel_clk(), &mut self.clock, T::state(), self.config.data_transfer_timeout, @@ -563,44 +563,6 @@ impl<'d, T: Instance, Dma: SdmmcDma> Sdmmc<'d, T, Dma> { regs.data_interrupts(false); state.wake(); } - - /// Returns kernel clock (SDIOCLK) for the SD-card facing domain - fn kernel_clock() -> Hertz { - cfg_if::cfg_if! { - // TODO, these could not be implemented, because required clocks are not exposed in RCC: - // - H7 uses pll1_q_ck or pll2_r_ck depending on SDMMCSEL - // - L1 uses pll48 - // - L4 uses clk48(pll48) - // - L4+, L5, U5 uses clk48(pll48) or PLLSAI3CLK(PLLP) depending on SDMMCSEL - if #[cfg(stm32f1)] { - // F1 uses AHB1(HCLK), which is correct in PAC - T::frequency() - } else if #[cfg(any(stm32f2, stm32f4))] { - // F2, F4 always use pll48 - critical_section::with(|_| unsafe { - crate::rcc::get_freqs().pll48 - }).expect("PLL48 is required for SDIO") - } else if #[cfg(stm32f7)] { - critical_section::with(|_| unsafe { - use core::any::TypeId; - let sdmmcsel = if TypeId::of::() == TypeId::of::() { - crate::pac::RCC.dckcfgr2().read().sdmmc1sel() - } else { - crate::pac::RCC.dckcfgr2().read().sdmmc2sel() - }; - - if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYSCLK { - crate::rcc::get_freqs().sys - } else { - crate::rcc::get_freqs().pll48.expect("PLL48 is required for SDMMC") - } - }) - } else { - // Use default peripheral clock and hope it works - T::frequency() - } - } - } } impl<'d, T: Instance, Dma> Drop for Sdmmc<'d, T, Dma> { @@ -1580,6 +1542,7 @@ pub(crate) mod sealed { fn inner() -> SdmmcInner; fn state() -> &'static AtomicWaker; + fn kernel_clk() -> Hertz; } pub trait Pins {} @@ -1607,6 +1570,61 @@ cfg_if::cfg_if! { } } +cfg_if::cfg_if! { + // TODO, these could not be implemented, because required clocks are not exposed in RCC: + // - H7 uses pll1_q_ck or pll2_r_ck depending on SDMMCSEL + // - L1 uses pll48 + // - L4 uses clk48(pll48) + // - L4+, L5, U5 uses clk48(pll48) or PLLSAI3CLK(PLLP) depending on SDMMCSEL + if #[cfg(stm32f1)] { + // F1 uses AHB1(HCLK), which is correct in PAC + macro_rules! kernel_clk { + ($inst:ident) => { + peripherals::$inst::frequency() + } + } + } else if #[cfg(any(stm32f2, stm32f4))] { + // F2, F4 always use pll48 + macro_rules! kernel_clk { + ($inst:ident) => { + critical_section::with(|_| unsafe { + crate::rcc::get_freqs().pll48 + }).expect("PLL48 is required for SDIO") + } + } + } else if #[cfg(stm32f7)] { + macro_rules! kernel_clk { + (SDMMC1) => { + critical_section::with(|_| unsafe { + let sdmmcsel = crate::pac::RCC.dckcfgr2().read().sdmmc1sel(); + if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYSCLK { + crate::rcc::get_freqs().sys + } else { + crate::rcc::get_freqs().pll48.expect("PLL48 is required for SDMMC") + } + }) + }; + (SDMMC2) => { + critical_section::with(|_| unsafe { + let sdmmcsel = crate::pac::RCC.dckcfgr2().read().sdmmc2sel(); + if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYSCLK { + crate::rcc::get_freqs().sys + } else { + crate::rcc::get_freqs().pll48.expect("PLL48 is required for SDMMC") + } + }) + }; + } + } else { + // Use default peripheral clock and hope it works + macro_rules! kernel_clk { + ($inst:ident) => { + peripherals::$inst::frequency() + } + } + } +} + foreach_peripheral!( (sdmmc, $inst:ident) => { impl sealed::Instance for peripherals::$inst { @@ -1621,6 +1639,10 @@ foreach_peripheral!( static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new(); &WAKER } + + fn kernel_clk() -> Hertz { + kernel_clk!($inst) + } } impl Instance for peripherals::$inst {}