mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-10-02 14:44:32 +00:00
support 8 lane data bus
This commit is contained in:
parent
b92eb948b5
commit
0a231505d8
@ -145,6 +145,8 @@ pub enum Error {
|
|||||||
Crc,
|
Crc,
|
||||||
/// No card inserted.
|
/// No card inserted.
|
||||||
NoCard,
|
NoCard,
|
||||||
|
/// 8-lane buses are not supported for SD cards.
|
||||||
|
BusWidth,
|
||||||
/// Bad clock supplied to the SDMMC peripheral.
|
/// Bad clock supplied to the SDMMC peripheral.
|
||||||
BadClock,
|
BadClock,
|
||||||
/// Signaling switch failed.
|
/// Signaling switch failed.
|
||||||
@ -365,6 +367,10 @@ pub struct Sdmmc<'d, T: Instance> {
|
|||||||
d1: Option<Peri<'d, AnyPin>>,
|
d1: Option<Peri<'d, AnyPin>>,
|
||||||
d2: Option<Peri<'d, AnyPin>>,
|
d2: Option<Peri<'d, AnyPin>>,
|
||||||
d3: Option<Peri<'d, AnyPin>>,
|
d3: Option<Peri<'d, AnyPin>>,
|
||||||
|
d4: Option<Peri<'d, AnyPin>>,
|
||||||
|
d5: Option<Peri<'d, AnyPin>>,
|
||||||
|
d6: Option<Peri<'d, AnyPin>>,
|
||||||
|
d7: Option<Peri<'d, AnyPin>>,
|
||||||
|
|
||||||
config: Config,
|
config: Config,
|
||||||
/// Current clock to card
|
/// Current clock to card
|
||||||
@ -413,6 +419,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
|
|||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
config,
|
config,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -448,6 +458,60 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
|
|||||||
Some(d1.into()),
|
Some(d1.into()),
|
||||||
Some(d2.into()),
|
Some(d2.into()),
|
||||||
Some(d3.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<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
|
dma: Peri<'d, impl SdmmcDma<T>>,
|
||||||
|
clk: Peri<'d, impl CkPin<T>>,
|
||||||
|
cmd: Peri<'d, impl CmdPin<T>>,
|
||||||
|
d0: Peri<'d, impl D0Pin<T>>,
|
||||||
|
d1: Peri<'d, impl D1Pin<T>>,
|
||||||
|
d2: Peri<'d, impl D2Pin<T>>,
|
||||||
|
d3: Peri<'d, impl D3Pin<T>>,
|
||||||
|
d4: Peri<'d, impl D4Pin<T>>,
|
||||||
|
d5: Peri<'d, impl D5Pin<T>>,
|
||||||
|
d6: Peri<'d, impl D6Pin<T>>,
|
||||||
|
d7: Peri<'d, impl D7Pin<T>>,
|
||||||
|
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,
|
config,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -470,7 +534,20 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
|
|||||||
d0.set_as_af(d0.af_num(), DATA_AF);
|
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.
|
/// Create a new SDMMC driver, with 4 data lanes.
|
||||||
@ -502,6 +579,58 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
|
|||||||
Some(d1.into()),
|
Some(d1.into()),
|
||||||
Some(d2.into()),
|
Some(d2.into()),
|
||||||
Some(d3.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<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
|
clk: Peri<'d, impl CkPin<T>>,
|
||||||
|
cmd: Peri<'d, impl CmdPin<T>>,
|
||||||
|
d0: Peri<'d, impl D0Pin<T>>,
|
||||||
|
d1: Peri<'d, impl D1Pin<T>>,
|
||||||
|
d2: Peri<'d, impl D2Pin<T>>,
|
||||||
|
d3: Peri<'d, impl D3Pin<T>>,
|
||||||
|
d4: Peri<'d, impl D4Pin<T>>,
|
||||||
|
d5: Peri<'d, impl D5Pin<T>>,
|
||||||
|
d6: Peri<'d, impl D6Pin<T>>,
|
||||||
|
d7: Peri<'d, impl D7Pin<T>>,
|
||||||
|
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,
|
config,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -517,6 +646,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
|
|||||||
d1: Option<Peri<'d, AnyPin>>,
|
d1: Option<Peri<'d, AnyPin>>,
|
||||||
d2: Option<Peri<'d, AnyPin>>,
|
d2: Option<Peri<'d, AnyPin>>,
|
||||||
d3: Option<Peri<'d, AnyPin>>,
|
d3: Option<Peri<'d, AnyPin>>,
|
||||||
|
d4: Option<Peri<'d, AnyPin>>,
|
||||||
|
d5: Option<Peri<'d, AnyPin>>,
|
||||||
|
d6: Option<Peri<'d, AnyPin>>,
|
||||||
|
d7: Option<Peri<'d, AnyPin>>,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
rcc::enable_and_reset::<T>();
|
rcc::enable_and_reset::<T>();
|
||||||
@ -555,6 +688,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
|
|||||||
d1,
|
d1,
|
||||||
d2,
|
d2,
|
||||||
d3,
|
d3,
|
||||||
|
d4,
|
||||||
|
d5,
|
||||||
|
d6,
|
||||||
|
d7,
|
||||||
|
|
||||||
config,
|
config,
|
||||||
clock: SD_INIT_FREQ,
|
clock: SD_INIT_FREQ,
|
||||||
@ -1039,6 +1176,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
|
|||||||
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.
|
/// Initializes card (if present) and sets the bus at the specified frequency.
|
||||||
pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> {
|
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 regs = T::regs();
|
||||||
let ker_ck = T::frequency();
|
let ker_ck = T::frequency();
|
||||||
|
|
||||||
@ -1419,9 +1560,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
|
|||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
let ker_ck = T::frequency();
|
let ker_ck = T::frequency();
|
||||||
|
|
||||||
let bus_width = match self.d3.is_some() {
|
let bus_width = match (self.d3.is_some(), self.d7.is_some()) {
|
||||||
true => BusWidth::Four,
|
(true, true) => BusWidth::Eight,
|
||||||
false => BusWidth::One,
|
(true, false) => BusWidth::Four,
|
||||||
|
_ => BusWidth::One,
|
||||||
};
|
};
|
||||||
|
|
||||||
// While the SD/SDIO card or eMMC is in identification mode,
|
// 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 {
|
if let Some(x) = &mut self.d3 {
|
||||||
x.set_as_disconnected();
|
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();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user