diff options
| -rw-r--r-- | embassy-stm32/src/sdmmc/mod.rs | 26 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/sdmmc.rs | 8 |
2 files changed, 9 insertions, 25 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 7548b799c..18e53ce10 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs | |||
| @@ -133,6 +133,7 @@ cfg_if::cfg_if! { | |||
| 133 | _ => Err(Error::BadClock), | 133 | _ => Err(Error::BadClock), |
| 134 | }?; | 134 | }?; |
| 135 | 135 | ||
| 136 | // SDIO_CK frequency = SDIOCLK / [CLKDIV + 2] | ||
| 136 | let clk_f = Hertz(ker_ck.0 / (clk_div as u32 + 2)); | 137 | let clk_f = Hertz(ker_ck.0 / (clk_div as u32 + 2)); |
| 137 | Ok((clk_div, clk_f)) | 138 | Ok((clk_div, clk_f)) |
| 138 | } | 139 | } |
| @@ -159,18 +160,10 @@ cfg_if::cfg_if! { | |||
| 159 | 160 | ||
| 160 | /// SDMMC configuration | 161 | /// SDMMC configuration |
| 161 | /// | 162 | /// |
| 162 | /// You should probably change the default clock values to match your configuration | ||
| 163 | /// | ||
| 164 | /// Default values: | 163 | /// Default values: |
| 165 | /// hclk = 400_000_000 Hz | ||
| 166 | /// kernel_clk: 100_000_000 Hz | ||
| 167 | /// data_transfer_timeout: 5_000_000 | 164 | /// data_transfer_timeout: 5_000_000 |
| 168 | #[non_exhaustive] | 165 | #[non_exhaustive] |
| 169 | pub struct Config { | 166 | pub struct Config { |
| 170 | /// AHB clock | ||
| 171 | pub hclk: Hertz, | ||
| 172 | /// SDMMC kernel clock | ||
| 173 | pub kernel_clk: Hertz, | ||
| 174 | /// The timeout to be set for data transfers, in card bus clock periods | 167 | /// The timeout to be set for data transfers, in card bus clock periods |
| 175 | pub data_transfer_timeout: u32, | 168 | pub data_transfer_timeout: u32, |
| 176 | } | 169 | } |
| @@ -178,8 +171,6 @@ pub struct Config { | |||
| 178 | impl Default for Config { | 171 | impl Default for Config { |
| 179 | fn default() -> Self { | 172 | fn default() -> Self { |
| 180 | Self { | 173 | Self { |
| 181 | hclk: Hertz(400_000_000), | ||
| 182 | kernel_clk: Hertz(100_000_000), | ||
| 183 | data_transfer_timeout: 5_000_000, | 174 | data_transfer_timeout: 5_000_000, |
| 184 | } | 175 | } |
| 185 | } | 176 | } |
| @@ -219,7 +210,7 @@ impl<'d, T: Instance, P: Pins<T>, Dma: SdioDma<T>> Sdmmc<'d, T, P, Dma> { | |||
| 219 | T::reset(); | 210 | T::reset(); |
| 220 | 211 | ||
| 221 | let inner = T::inner(); | 212 | let inner = T::inner(); |
| 222 | let clock = inner.new_inner(config.kernel_clk); | 213 | let clock = inner.new_inner(T::frequency()); |
| 223 | 214 | ||
| 224 | irq.set_handler(Self::on_interrupt); | 215 | irq.set_handler(Self::on_interrupt); |
| 225 | irq.unpend(); | 216 | irq.unpend(); |
| @@ -248,8 +239,7 @@ impl<'d, T: Instance, P: Pins<T>, Dma: SdioDma<T>> Sdmmc<'d, T, P, Dma> { | |||
| 248 | P::BUSWIDTH, | 239 | P::BUSWIDTH, |
| 249 | &mut self.card, | 240 | &mut self.card, |
| 250 | &mut self.signalling, | 241 | &mut self.signalling, |
| 251 | self.config.hclk, | 242 | T::frequency(), |
| 252 | self.config.kernel_clk, | ||
| 253 | &mut self.clock, | 243 | &mut self.clock, |
| 254 | T::state(), | 244 | T::state(), |
| 255 | self.config.data_transfer_timeout, | 245 | self.config.data_transfer_timeout, |
| @@ -371,7 +361,6 @@ impl SdmmcInner { | |||
| 371 | bus_width: BusWidth, | 361 | bus_width: BusWidth, |
| 372 | old_card: &mut Option<Card>, | 362 | old_card: &mut Option<Card>, |
| 373 | signalling: &mut Signalling, | 363 | signalling: &mut Signalling, |
| 374 | hclk: Hertz, | ||
| 375 | ker_ck: Hertz, | 364 | ker_ck: Hertz, |
| 376 | clock: &mut Hertz, | 365 | clock: &mut Hertz, |
| 377 | waker_reg: &AtomicWaker, | 366 | waker_reg: &AtomicWaker, |
| @@ -474,10 +463,10 @@ impl SdmmcInner { | |||
| 474 | // Set Clock | 463 | // Set Clock |
| 475 | if freq.0 <= 25_000_000 { | 464 | if freq.0 <= 25_000_000 { |
| 476 | // Final clock frequency | 465 | // Final clock frequency |
| 477 | self.clkcr_set_clkdiv(freq.0, width, hclk, ker_ck, clock)?; | 466 | self.clkcr_set_clkdiv(freq.0, width, ker_ck, clock)?; |
| 478 | } else { | 467 | } else { |
| 479 | // Switch to max clock for SDR12 | 468 | // Switch to max clock for SDR12 |
| 480 | self.clkcr_set_clkdiv(25_000_000, width, hclk, ker_ck, clock)?; | 469 | self.clkcr_set_clkdiv(25_000_000, width, ker_ck, clock)?; |
| 481 | } | 470 | } |
| 482 | 471 | ||
| 483 | // Read status | 472 | // Read status |
| @@ -497,7 +486,7 @@ impl SdmmcInner { | |||
| 497 | 486 | ||
| 498 | if *signalling == Signalling::SDR25 { | 487 | if *signalling == Signalling::SDR25 { |
| 499 | // Set final clock frequency | 488 | // Set final clock frequency |
| 500 | self.clkcr_set_clkdiv(freq.0, width, hclk, ker_ck, clock)?; | 489 | self.clkcr_set_clkdiv(freq.0, width, ker_ck, clock)?; |
| 501 | 490 | ||
| 502 | if self.read_status(&card)?.state() != CurrentState::Transfer { | 491 | if self.read_status(&card)?.state() != CurrentState::Transfer { |
| 503 | return Err(Error::SignalingSwitchFailed); | 492 | return Err(Error::SignalingSwitchFailed); |
| @@ -804,7 +793,6 @@ impl SdmmcInner { | |||
| 804 | &self, | 793 | &self, |
| 805 | freq: u32, | 794 | freq: u32, |
| 806 | width: BusWidth, | 795 | width: BusWidth, |
| 807 | hclk: Hertz, | ||
| 808 | ker_ck: Hertz, | 796 | ker_ck: Hertz, |
| 809 | clock: &mut Hertz, | 797 | clock: &mut Hertz, |
| 810 | ) -> Result<(), Error> { | 798 | ) -> Result<(), Error> { |
| @@ -814,7 +802,7 @@ impl SdmmcInner { | |||
| 814 | // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7 | 802 | // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7 |
| 815 | // Section 55.5.8 | 803 | // Section 55.5.8 |
| 816 | let sdmmc_bus_bandwidth = new_clock.0 * (width as u32); | 804 | let sdmmc_bus_bandwidth = new_clock.0 * (width as u32); |
| 817 | assert!(hclk.0 > 3 * sdmmc_bus_bandwidth / 32); | 805 | assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32); |
| 818 | *clock = new_clock; | 806 | *clock = new_clock; |
| 819 | 807 | ||
| 820 | // NOTE(unsafe) We have exclusive access to the regblock | 808 | // NOTE(unsafe) We have exclusive access to the regblock |
diff --git a/examples/stm32f4/src/bin/sdmmc.rs b/examples/stm32f4/src/bin/sdmmc.rs index d941584be..46ac44500 100644 --- a/examples/stm32f4/src/bin/sdmmc.rs +++ b/examples/stm32f4/src/bin/sdmmc.rs | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | mod example_common; | 6 | mod example_common; |
| 7 | 7 | ||
| 8 | use embassy::executor::Spawner; | 8 | use embassy::executor::Spawner; |
| 9 | use embassy_stm32::sdmmc::{self, Sdmmc}; | 9 | use embassy_stm32::sdmmc::Sdmmc; |
| 10 | use embassy_stm32::time::U32Ext; | 10 | use embassy_stm32::time::U32Ext; |
| 11 | use embassy_stm32::{interrupt, Config, Peripherals}; | 11 | use embassy_stm32::{interrupt, Config, Peripherals}; |
| 12 | use example_common::*; | 12 | use example_common::*; |
| @@ -26,16 +26,12 @@ async fn main(_spawner: Spawner, p: Peripherals) -> ! { | |||
| 26 | 26 | ||
| 27 | let irq = interrupt::take!(SDIO); | 27 | let irq = interrupt::take!(SDIO); |
| 28 | 28 | ||
| 29 | let mut config = sdmmc::Config::default(); | ||
| 30 | config.hclk = 48.mhz().into(); | ||
| 31 | config.kernel_clk = 48.mhz().into(); | ||
| 32 | |||
| 33 | let mut sdmmc = unsafe { | 29 | let mut sdmmc = unsafe { |
| 34 | Sdmmc::new( | 30 | Sdmmc::new( |
| 35 | p.SDIO, | 31 | p.SDIO, |
| 36 | (p.PC12, p.PD2, p.PC8, p.PC9, p.PC10, p.PC11), | 32 | (p.PC12, p.PD2, p.PC8, p.PC9, p.PC10, p.PC11), |
| 37 | irq, | 33 | irq, |
| 38 | config, | 34 | Default::default(), |
| 39 | p.DMA2_CH3, | 35 | p.DMA2_CH3, |
| 40 | ) | 36 | ) |
| 41 | }; | 37 | }; |
