Skip to content

Commit 04a90bb

Browse files
committed
Merge commit 'fab9d04' into cyw4373
2 parents 11edfb0 + fab9d04 commit 04a90bb

2 files changed

Lines changed: 27 additions & 26 deletions

File tree

embassy-stm32/src/sdmmc/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -784,8 +784,6 @@ impl<'d> Sdmmc<'d> {
784784

785785
// Use buffer.len() not size_of_val: Aligned<A4, [u8]> is #[repr(C)]
786786
// with alignment 4, so size_of_val rounds up to a multiple of 4.
787-
// This causes DLEN to exceed the CMD53 byte count for non-4-aligned
788-
// sizes, resulting in data timeouts.
789787
regs.dlenr().write(|w| w.set_datalength(buffer.len() as u32));
790788

791789
// SAFETY: No other functions use the dma
@@ -846,6 +844,8 @@ impl<'d> Sdmmc<'d> {
846844
self.wait_idle();
847845
self.clear_interrupt_flags();
848846

847+
// Use buffer.len() not size_of_val: Aligned<A4, [u8]> is #[repr(C)]
848+
// with alignment 4, so size_of_val rounds up to a multiple of 4.
849849
regs.dlenr().write(|w| w.set_datalength(buffer.len() as u32));
850850

851851
// SAFETY: No other functions use the dma
@@ -905,6 +905,12 @@ impl<'d> Sdmmc<'d> {
905905
}
906906

907907
fn init_idle(&mut self) -> Result<CommandResponse<Rz>, Error> {
908+
self.start_clocks()?;
909+
self.cmd(common_cmd::idle(), true, false)
910+
}
911+
912+
/// Start the SDMMC clock at 400 kHz without performing any card initialization.
913+
pub fn start_clocks(&mut self) -> Result<(), Error> {
908914
let regs = self.info.regs;
909915

910916
self.clkcr_set_clkdiv(SD_INIT_FREQ, BusWidth::One)?;
@@ -916,7 +922,7 @@ impl<'d> Sdmmc<'d> {
916922
// Wait 74 cycles
917923
block_for_us((74_000_000 / SD_INIT_FREQ.0) as u64);
918924

919-
self.cmd(common_cmd::idle(), true, false)
925+
Ok(())
920926
}
921927

922928
/// Start the SDMMC clock at 400 kHz without performing any card initialization.

embassy-stm32/src/sdmmc/sdio.rs

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use core::task::Poll;
55

66
use aligned::{A4, Aligned};
77
#[cfg(feature = "time")]
8-
use embassy_time::Timer;
8+
use embassy_time::{Duration, Ticker};
99
use sdio_host::common_cmd::{R1, Resp, cmd};
1010
use sdio_host::sd::{BusWidth, OCR, RCA, SD};
1111
use sdio_host::{Cmd, sd_cmd};
@@ -110,30 +110,25 @@ impl<'a, 'b> SerialDataInterface<'a, 'b> {
110110
// the SDMMC_CK frequency must be no more than 400 kHz.
111111
self.sdmmc.init_idle()?;
112112

113-
// Retry CMD5 (IO_SEND_OP_COND) up to 500 times with 1 ms delays, matching the
114-
// Infineon/Cypress WHD driver (SDIO_ENUMERATION_TRIES / SDIO_RETRY_DELAY_MS).
115-
// The SDMMC peripheral stays POWER_ON throughout so the card clock keeps running,
116-
// which is required for SDIO chips (e.g. CYW4373) that need the clock during
117-
// their internal power-up sequence before they can ACK CMD5.
118-
let _ocr: OCR<SD> = {
119-
let mut result = Err(Error::Timeout);
120-
for _ in 0..500u16 {
121-
match self.sdmmc.cmd(io_send_op_cond(false, 0x0), false, false) {
122-
Ok(r) => {
123-
result = Ok(r);
124-
break;
125-
}
126-
Err(Error::Timeout) => {
127-
#[cfg(feature = "time")]
128-
Timer::after_millis(1).await;
129-
#[cfg(not(feature = "time"))]
130-
crate::block_for_us(1000);
131-
}
132-
Err(e) => return Err(e),
113+
// Get IO OCR
114+
#[cfg(feature = "time")]
115+
let mut ticker = Ticker::every(Duration::from_millis(1));
116+
let mut i = 0;
117+
118+
let _ocr: OCR<SD> = loop {
119+
match self.sdmmc.cmd(io_send_op_cond(false, 0x0), false, false) {
120+
Ok(r) => break Ok(r),
121+
Err(Error::Timeout) if i == 500 => break Err(Error::Timeout),
122+
Err(Error::Timeout) => {
123+
i += 1;
124+
125+
#[cfg(feature = "time")]
126+
ticker.next().await;
133127
}
128+
Err(e) => break Err(e),
134129
}
135-
result?.into()
136-
};
130+
}?
131+
.into();
137132

138133
// UDB-based SDIO does not support io volt switch sequence
139134

0 commit comments

Comments
 (0)