diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index f92c0260b..a0c3573a9 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -145,6 +145,8 @@ pub enum Error { Crc, /// No card inserted. NoCard, + /// 8-lane buses are not supported for SD cards. + BusWidth, /// Bad clock supplied to the SDMMC peripheral. BadClock, /// Signaling switch failed. @@ -365,6 +367,10 @@ pub struct Sdmmc<'d, T: Instance> { d1: Option>, d2: Option>, d3: Option>, + d4: Option>, + d5: Option>, + d6: Option>, + d7: Option>, config: Config, /// Current clock to card @@ -413,6 +419,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { None, None, None, + None, + None, + None, + None, config, ) } @@ -448,6 +458,60 @@ impl<'d, T: Instance> Sdmmc<'d, T> { Some(d1.into()), Some(d2.into()), Some(d3.into()), + None, + None, + None, + None, + config, + ) + } +} + +#[cfg(sdmmc_v1)] +impl<'d, T: Instance> Sdmmc<'d, T> { + /// Create a new SDMMC driver, with 8 data lanes. + pub fn new_8bit( + sdmmc: Peri<'d, T>, + _irq: impl interrupt::typelevel::Binding> + 'd, + dma: Peri<'d, impl SdmmcDma>, + clk: Peri<'d, impl CkPin>, + cmd: Peri<'d, impl CmdPin>, + d0: Peri<'d, impl D0Pin>, + d1: Peri<'d, impl D1Pin>, + d2: Peri<'d, impl D2Pin>, + d3: Peri<'d, impl D3Pin>, + d4: Peri<'d, impl D4Pin>, + d5: Peri<'d, impl D5Pin>, + d6: Peri<'d, impl D6Pin>, + d7: Peri<'d, impl D7Pin>, + config: Config, + ) -> Self { + critical_section::with(|_| { + clk.set_as_af(clk.af_num(), CLK_AF); + cmd.set_as_af(cmd.af_num(), CMD_AF); + d0.set_as_af(d0.af_num(), DATA_AF); + d1.set_as_af(d1.af_num(), DATA_AF); + d2.set_as_af(d2.af_num(), DATA_AF); + d3.set_as_af(d3.af_num(), DATA_AF); + d4.set_as_af(d4.af_num(), DATA_AF); + d5.set_as_af(d5.af_num(), DATA_AF); + d6.set_as_af(d6.af_num(), DATA_AF); + d7.set_as_af(d7.af_num(), DATA_AF); + }); + + Self::new_inner( + sdmmc, + new_dma_nonopt!(dma), + clk.into(), + cmd.into(), + d0.into(), + Some(d1.into()), + Some(d2.into()), + Some(d3.into()), + Some(d4.into()), + Some(d5.into()), + Some(d6.into()), + Some(d7.into()), config, ) } @@ -470,7 +534,20 @@ impl<'d, T: Instance> Sdmmc<'d, T> { d0.set_as_af(d0.af_num(), DATA_AF); }); - Self::new_inner(sdmmc, clk.into(), cmd.into(), d0.into(), None, None, None, config) + Self::new_inner( + sdmmc, + clk.into(), + cmd.into(), + d0.into(), + None, + None, + None, + None, + None, + None, + None, + config, + ) } /// Create a new SDMMC driver, with 4 data lanes. @@ -502,6 +579,58 @@ impl<'d, T: Instance> Sdmmc<'d, T> { Some(d1.into()), Some(d2.into()), Some(d3.into()), + None, + None, + None, + None, + config, + ) + } +} + +#[cfg(sdmmc_v2)] +impl<'d, T: Instance> Sdmmc<'d, T> { + /// Create a new SDMMC driver, with 8 data lanes. + pub fn new_8bit( + sdmmc: Peri<'d, T>, + _irq: impl interrupt::typelevel::Binding> + 'd, + clk: Peri<'d, impl CkPin>, + cmd: Peri<'d, impl CmdPin>, + d0: Peri<'d, impl D0Pin>, + d1: Peri<'d, impl D1Pin>, + d2: Peri<'d, impl D2Pin>, + d3: Peri<'d, impl D3Pin>, + d4: Peri<'d, impl D4Pin>, + d5: Peri<'d, impl D5Pin>, + d6: Peri<'d, impl D6Pin>, + d7: Peri<'d, impl D7Pin>, + config: Config, + ) -> Self { + critical_section::with(|_| { + clk.set_as_af(clk.af_num(), CLK_AF); + cmd.set_as_af(cmd.af_num(), CMD_AF); + d0.set_as_af(d0.af_num(), DATA_AF); + d1.set_as_af(d1.af_num(), DATA_AF); + d2.set_as_af(d2.af_num(), DATA_AF); + d3.set_as_af(d3.af_num(), DATA_AF); + d4.set_as_af(d4.af_num(), DATA_AF); + d5.set_as_af(d5.af_num(), DATA_AF); + d6.set_as_af(d6.af_num(), DATA_AF); + d7.set_as_af(d7.af_num(), DATA_AF); + }); + + Self::new_inner( + sdmmc, + clk.into(), + cmd.into(), + d0.into(), + Some(d1.into()), + Some(d2.into()), + Some(d3.into()), + Some(d4.into()), + Some(d5.into()), + Some(d6.into()), + Some(d7.into()), config, ) } @@ -517,6 +646,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { d1: Option>, d2: Option>, d3: Option>, + d4: Option>, + d5: Option>, + d6: Option>, + d7: Option>, config: Config, ) -> Self { rcc::enable_and_reset::(); @@ -555,6 +688,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { d1, d2, d3, + d4, + d5, + d6, + d7, config, clock: SD_INIT_FREQ, @@ -1039,6 +1176,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { impl<'d, T: Instance> Sdmmc<'d, T> { /// Initializes card (if present) and sets the bus at the specified frequency. pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> { + if self.d7.is_some() { + return Err(Error::BusWidth); + } + let regs = T::regs(); let ker_ck = T::frequency(); @@ -1419,9 +1560,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { let regs = T::regs(); let ker_ck = T::frequency(); - let bus_width = match self.d3.is_some() { - true => BusWidth::Four, - false => BusWidth::One, + let bus_width = match (self.d3.is_some(), self.d7.is_some()) { + (true, true) => BusWidth::Eight, + (true, false) => BusWidth::Four, + _ => BusWidth::One, }; // While the SD/SDIO card or eMMC is in identification mode, @@ -1613,6 +1755,18 @@ impl<'d, T: Instance> Drop for Sdmmc<'d, T> { if let Some(x) = &mut self.d3 { x.set_as_disconnected(); } + if let Some(x) = &mut self.d4 { + x.set_as_disconnected(); + } + if let Some(x) = &mut self.d5 { + x.set_as_disconnected(); + } + if let Some(x) = &mut self.d6 { + x.set_as_disconnected(); + } + if let Some(x) = &mut self.d7 { + x.set_as_disconnected(); + } }); } }