aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-12-10 22:42:33 +0000
committerGitHub <[email protected]>2025-12-10 22:42:33 +0000
commit3f3a7cd97aba396203ab67fe6a91c9ff898b78fc (patch)
tree7eab60d9d4e666ee8cae1246dcdde974e3432a7f /embassy-stm32
parent4915b9f530877f3db1e9c2a7813b52795b5a4ec3 (diff)
parent14079f148c2796889db04e1442181afa3165c5b6 (diff)
Merge pull request #5024 from xoviat/sdio
sdmmc: more refactoring
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs1260
1 files changed, 578 insertions, 682 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index ad00b4398..0d5260016 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -5,14 +5,16 @@ use core::default::Default;
5use core::future::poll_fn; 5use core::future::poll_fn;
6use core::marker::PhantomData; 6use core::marker::PhantomData;
7use core::ops::{Deref, DerefMut}; 7use core::ops::{Deref, DerefMut};
8use core::slice;
8use core::task::Poll; 9use core::task::Poll;
9 10
10use embassy_hal_internal::drop::OnDrop; 11use embassy_hal_internal::drop::OnDrop;
11use embassy_hal_internal::{Peri, PeripheralType}; 12use embassy_hal_internal::{Peri, PeripheralType};
12use embassy_sync::waitqueue::AtomicWaker; 13use embassy_sync::waitqueue::AtomicWaker;
13use sdio_host::common_cmd::{self, Resp, ResponseLen}; 14use sdio_host::common_cmd::{self, R1, R2, R3, Resp, ResponseLen, Rz};
14use sdio_host::emmc::{EMMC, ExtCSD}; 15use sdio_host::emmc::{EMMC, ExtCSD};
15use sdio_host::sd::{BusWidth, CIC, CID, CSD, CardCapacity, CardStatus, CurrentState, OCR, RCA, SCR, SD, SDStatus}; 16use sdio_host::sd::{BusWidth, CIC, CID, CSD, CardCapacity, CardStatus, CurrentState, OCR, RCA, SCR, SD, SDStatus};
17use sdio_host::sd_cmd::{R6, R7};
16use sdio_host::{Cmd, emmc_cmd, sd_cmd}; 18use sdio_host::{Cmd, emmc_cmd, sd_cmd};
17 19
18#[cfg(sdmmc_v1)] 20#[cfg(sdmmc_v1)]
@@ -23,7 +25,7 @@ use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed};
23use crate::interrupt::typelevel::Interrupt; 25use crate::interrupt::typelevel::Interrupt;
24use crate::pac::sdmmc::Sdmmc as RegBlock; 26use crate::pac::sdmmc::Sdmmc as RegBlock;
25use crate::rcc::{self, RccInfo, RccPeripheral, SealedRccPeripheral}; 27use crate::rcc::{self, RccInfo, RccPeripheral, SealedRccPeripheral};
26use crate::time::Hertz; 28use crate::time::{Hertz, mhz};
27use crate::{interrupt, peripherals}; 29use crate::{interrupt, peripherals};
28 30
29/// Interrupt handler. 31/// Interrupt handler.
@@ -60,6 +62,57 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
60 } 62 }
61} 63}
62 64
65struct U128(pub u128);
66
67trait TypedResp: Resp {
68 type Word: From<U128>;
69}
70
71impl From<U128> for () {
72 fn from(value: U128) -> Self {
73 match value.0 {
74 0 => (),
75 _ => unreachable!(),
76 }
77 }
78}
79
80impl From<U128> for u32 {
81 fn from(value: U128) -> Self {
82 unwrap!(value.0.try_into())
83 }
84}
85
86impl From<U128> for u128 {
87 fn from(value: U128) -> Self {
88 value.0
89 }
90}
91
92impl TypedResp for Rz {
93 type Word = ();
94}
95
96impl TypedResp for R1 {
97 type Word = u32;
98}
99
100impl TypedResp for R2 {
101 type Word = u128;
102}
103
104impl TypedResp for R3 {
105 type Word = u32;
106}
107
108impl TypedResp for R6 {
109 type Word = u32;
110}
111
112impl TypedResp for R7 {
113 type Word = u32;
114}
115
63/// Frequency used for SD Card initialization. Must be no higher than 400 kHz. 116/// Frequency used for SD Card initialization. Must be no higher than 400 kHz.
64const SD_INIT_FREQ: Hertz = Hertz(400_000); 117const SD_INIT_FREQ: Hertz = Hertz(400_000);
65 118
@@ -104,6 +157,11 @@ impl DerefMut for DataBlock {
104 } 157 }
105} 158}
106 159
160fn slice8_mut(x: &mut [u32]) -> &mut [u8] {
161 let len = x.len() * 4;
162 unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) }
163}
164
107/// Command Block buffer for SDMMC command transfers. 165/// Command Block buffer for SDMMC command transfers.
108/// 166///
109/// This is a 16-word array, exposed so that DMA commpatible memory can be used if required. 167/// This is a 16-word array, exposed so that DMA commpatible memory can be used if required.
@@ -190,70 +248,119 @@ pub struct StorageDevice<'a, 'b, T: Addressable> {
190impl<'a, 'b> StorageDevice<'a, 'b, Card> { 248impl<'a, 'b> StorageDevice<'a, 'b, Card> {
191 /// Create a new SD card 249 /// Create a new SD card
192 pub async fn new_sd_card(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> { 250 pub async fn new_sd_card(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> {
193 let info = sdmmc.init_sd_card(cmd_block, freq).await?; 251 let mut s = Self {
252 info: Card::default(),
253 sdmmc,
254 };
255
256 s.acquire(cmd_block, freq).await?;
194 257
195 Ok(Self { info, sdmmc }) 258 Ok(s)
196 } 259 }
197}
198 260
199/// Emmc storage device 261 /// Initializes the card into a known state (or at least tries to).
200impl<'a, 'b> StorageDevice<'a, 'b, Emmc> { 262 pub async fn acquire(&mut self, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<(), Error> {
201 /// Create a new EMMC card 263 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
202 pub async fn new_emmc(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> { 264 let regs = self.sdmmc.info.regs;
203 let info = sdmmc.init_emmc(cmd_block, freq).await?;
204 265
205 Ok(Self { info, sdmmc }) 266 let _bus_width = match self.sdmmc.bus_width() {
206 } 267 BusWidth::Eight => return Err(Error::BusWidth),
207} 268 bus_width => bus_width,
269 };
208 270
209/// Card or Emmc storage device 271 // While the SD/SDIO card or eMMC is in identification mode,
210impl<'a, 'b, T: Addressable> StorageDevice<'a, 'b, T> { 272 // the SDMMC_CK frequency must be no more than 400 kHz.
211 /// Write a block 273 self.sdmmc.init_idle()?;
212 pub fn card(&self) -> T {
213 self.info.clone()
214 }
215 274
216 /// Write a block 275 // Check if cards supports CMD8 (with pattern)
217 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> { 276 self.sdmmc.cmd(sd_cmd::send_if_cond(1, 0xAA), false)?;
218 self.sdmmc.write_block(&mut self.info, block_idx, buffer).await 277 let cic = CIC::from(regs.respr(0).read().cardstatus());
219 }
220 278
221 /// Write a block 279 if cic.pattern() != 0xAA {
222 pub async fn write_blocks(&mut self, block_idx: u32, blocks: &[DataBlock]) -> Result<(), Error> { 280 return Err(Error::UnsupportedCardVersion);
223 self.sdmmc.write_blocks(&mut self.info, block_idx, blocks).await 281 }
224 }
225 282
226 /// Read a block 283 if cic.voltage_accepted() & 1 == 0 {
227 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> { 284 return Err(Error::UnsupportedVoltage);
228 self.sdmmc.read_block(&mut self.info, block_idx, buffer).await 285 }
229 }
230 286
231 /// Read a block 287 let ocr = loop {
232 pub async fn read_blocks(&mut self, block_idx: u32, blocks: &mut [DataBlock]) -> Result<(), Error> { 288 // Signal that next command is a app command
233 self.sdmmc.read_blocks(&mut self.info, block_idx, blocks).await 289 self.sdmmc.cmd(common_cmd::app_cmd(0), false)?; // CMD55
234 }
235}
236 290
237#[derive(Clone, Copy, Debug, Default)] 291 // 3.2-3.3V
238/// SD Card 292 let voltage_window = 1 << 5;
239pub struct Card { 293 // Initialize card
240 /// The type of this card 294 match self
241 pub card_type: CardCapacity, 295 .sdmmc
242 /// Operation Conditions Register 296 .cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window), false)
243 pub ocr: OCR<SD>, 297 {
244 /// Relative Card Address 298 // ACMD41
245 pub rca: u16, 299 Ok(_) => (),
246 /// Card ID 300 Err(Error::Crc) => (),
247 pub cid: CID<SD>, 301 Err(err) => return Err(err),
248 /// Card Specific Data 302 }
249 pub csd: CSD<SD>, 303
250 /// SD CARD Configuration Register 304 let ocr: OCR<SD> = regs.respr(0).read().cardstatus().into();
251 pub scr: SCR, 305 if !ocr.is_busy() {
252 /// SD Status 306 // Power up done
253 pub status: SDStatus, 307 break ocr;
254} 308 }
309 };
310
311 if ocr.high_capacity() {
312 // Card is SDHC or SDXC or SDUC
313 self.info.card_type = CardCapacity::HighCapacity;
314 } else {
315 self.info.card_type = CardCapacity::StandardCapacity;
316 }
317 self.info.ocr = ocr;
318
319 self.info.cid = self.sdmmc.get_cid()?.into();
320
321 self.sdmmc.cmd(sd_cmd::send_relative_address(), false)?;
322 let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus());
323 self.info.rca = rca.address();
324
325 self.info.csd = self.sdmmc.get_csd(self.info.get_address())?.into();
326 self.sdmmc.select_card(Some(self.info.get_address()))?;
327
328 self.info.scr = self.get_scr(cmd_block).await?;
329
330 let (bus_width, acmd_arg) = if !self.info.scr.bus_width_four() {
331 (BusWidth::One, 0)
332 } else {
333 (BusWidth::Four, 2)
334 };
335
336 self.sdmmc.cmd(common_cmd::app_cmd(self.info.rca), false)?;
337 self.sdmmc.cmd(sd_cmd::cmd6(acmd_arg), false)?;
338
339 self.sdmmc.clkcr_set_clkdiv(freq.clamp(mhz(0), mhz(25)), bus_width)?;
340
341 // Read status
342 self.info.status = self.read_sd_status(cmd_block).await?;
343
344 if freq > mhz(25) {
345 // Switch to SDR25
346 self.sdmmc.signalling = self.switch_signalling_mode(cmd_block, Signalling::SDR25).await?;
347
348 if self.sdmmc.signalling == Signalling::SDR25 {
349 // Set final clock frequency
350 self.sdmmc.clkcr_set_clkdiv(freq, bus_width)?;
351
352 if self.sdmmc.read_status(&self.info)?.state() != CurrentState::Transfer {
353 return Err(Error::SignalingSwitchFailed);
354 }
355 }
356
357 // Read status after signalling change
358 self.read_sd_status(cmd_block).await?;
359 }
360
361 Ok(())
362 }
255 363
256impl Card {
257 /// Switch mode using CMD6. 364 /// Switch mode using CMD6.
258 /// 365 ///
259 /// Attempt to set a new signalling mode. The selected 366 /// Attempt to set a new signalling mode. The selected
@@ -261,9 +368,8 @@ impl Card {
261 /// frequency to be > 12.5MHz. 368 /// frequency to be > 12.5MHz.
262 /// 369 ///
263 /// SD only. 370 /// SD only.
264 async fn switch_signalling_mode<'a>( 371 async fn switch_signalling_mode(
265 &mut self, 372 &self,
266 sdmmc: &mut Sdmmc<'a>,
267 cmd_block: &mut CmdBlock, 373 cmd_block: &mut CmdBlock,
268 signalling: Signalling, 374 signalling: Signalling,
269 ) -> Result<Signalling, Error> { 375 ) -> Result<Signalling, Error> {
@@ -281,13 +387,12 @@ impl Card {
281 }; 387 };
282 388
283 // Arm `OnDrop` after the buffer, so it will be dropped first 389 // Arm `OnDrop` after the buffer, so it will be dropped first
284 let on_drop = OnDrop::new(|| sdmmc.on_drop()); 390 let on_drop = OnDrop::new(|| self.sdmmc.on_drop());
285 391
286 let transfer = sdmmc.prepare_datapath_read(&sdmmc.config, cmd_block.as_mut(), 64, 6); 392 let transfer = self.sdmmc.prepare_datapath_read(cmd_block.as_mut(), 64, 6);
287 sdmmc.enable_interrupts(); 393 self.sdmmc.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
288 sdmmc.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
289 394
290 let res = sdmmc.complete_datapath_transfer(true).await; 395 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
291 396
292 // Host is allowed to use the new functions at least 8 397 // Host is allowed to use the new functions at least 8
293 // clocks after the end of the switch command 398 // clocks after the end of the switch command
@@ -297,92 +402,373 @@ impl Card {
297 cortex_m::asm::nop(); 402 cortex_m::asm::nop();
298 } 403 }
299 404
300 match res { 405 on_drop.defuse();
301 Ok(_) => { 406
302 on_drop.defuse(); 407 // Function Selection of Function Group 1
303 sdmmc.stop_datapath(); 408 let selection = (u32::from_be(cmd_block[4]) >> 24) & 0xF;
304 drop(transfer); 409
305 410 match selection {
306 // Function Selection of Function Group 1 411 0 => Ok(Signalling::SDR12),
307 let selection = (u32::from_be(cmd_block[4]) >> 24) & 0xF; 412 1 => Ok(Signalling::SDR25),
308 413 2 => Ok(Signalling::SDR50),
309 match selection { 414 3 => Ok(Signalling::SDR104),
310 0 => Ok(Signalling::SDR12), 415 4 => Ok(Signalling::DDR50),
311 1 => Ok(Signalling::SDR25), 416 _ => Err(Error::UnsupportedCardType),
312 2 => Ok(Signalling::SDR50),
313 3 => Ok(Signalling::SDR104),
314 4 => Ok(Signalling::DDR50),
315 _ => Err(Error::UnsupportedCardType),
316 }
317 }
318 Err(e) => Err(e),
319 } 417 }
320 } 418 }
321 419
322 /// Reads the SCR register. 420 /// Reads the SCR register.
323 /// 421 ///
324 /// SD only. 422 /// SD only.
325 async fn get_scr<'a>(&mut self, sdmmc: &mut Sdmmc<'a>, cmd_block: &mut CmdBlock) -> Result<(), Error> { 423 async fn get_scr(&self, cmd_block: &mut CmdBlock) -> Result<SCR, Error> {
326 // Read the 64-bit SCR register 424 // Read the 64-bit SCR register
327 sdmmc.cmd(common_cmd::set_block_length(8), false)?; // CMD16 425 self.sdmmc.cmd(common_cmd::set_block_length(8), false)?; // CMD16
328 sdmmc.cmd(common_cmd::app_cmd(self.rca), false)?; 426 self.sdmmc.cmd(common_cmd::app_cmd(self.info.rca), false)?;
329 427
330 let scr = &mut cmd_block.0[..2]; 428 let scr = &mut cmd_block.0[..2];
331 429
332 // Arm `OnDrop` after the buffer, so it will be dropped first 430 // Arm `OnDrop` after the buffer, so it will be dropped first
333 let on_drop = OnDrop::new(|| sdmmc.on_drop()); 431 let on_drop = OnDrop::new(|| self.sdmmc.on_drop());
334 432
335 let transfer = sdmmc.prepare_datapath_read(&sdmmc.config, scr, 8, 3); 433 let transfer = self.sdmmc.prepare_datapath_read(scr, 8, 3);
336 sdmmc.enable_interrupts(); 434 self.sdmmc.cmd(sd_cmd::send_scr(), true)?;
337 sdmmc.cmd(sd_cmd::send_scr(), true)?;
338 435
339 let res = sdmmc.complete_datapath_transfer(true).await; 436 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
340 437
341 if res.is_ok() { 438 on_drop.defuse();
342 on_drop.defuse();
343 sdmmc.stop_datapath();
344 drop(transfer);
345 439
346 unsafe { 440 Ok(SCR(u64::from_be_bytes(unwrap!(slice8_mut(scr).try_into()))))
347 let scr_bytes = &*(&scr as *const _ as *const [u8; 8]);
348 self.scr = SCR(u64::from_be_bytes(*scr_bytes));
349 }
350 }
351 res
352 } 441 }
353 442
354 /// Reads the SD Status (ACMD13) 443 /// Reads the SD Status (ACMD13)
355 /// 444 ///
356 /// SD only. 445 /// SD only.
357 async fn read_sd_status<'a>(&mut self, sdmmc: &mut Sdmmc<'a>, cmd_block: &mut CmdBlock) -> Result<(), Error> { 446 async fn read_sd_status(&self, cmd_block: &mut CmdBlock) -> Result<SDStatus, Error> {
358 let rca = self.rca; 447 let rca = self.info.rca;
359 448
360 sdmmc.cmd(common_cmd::set_block_length(64), false)?; // CMD16 449 self.sdmmc.cmd(common_cmd::set_block_length(64), false)?; // CMD16
361 sdmmc.cmd(common_cmd::app_cmd(rca), false)?; // APP 450 self.sdmmc.cmd(common_cmd::app_cmd(rca), false)?; // APP
362 451
363 let status = cmd_block; 452 let status = cmd_block;
364 453
365 // Arm `OnDrop` after the buffer, so it will be dropped first 454 // Arm `OnDrop` after the buffer, so it will be dropped first
366 let on_drop = OnDrop::new(|| sdmmc.on_drop()); 455 let on_drop = OnDrop::new(|| self.sdmmc.on_drop());
456
457 let transfer = self.sdmmc.prepare_datapath_read(status.as_mut(), 64, 6);
458 self.sdmmc.cmd(sd_cmd::sd_status(), true)?;
367 459
368 let transfer = sdmmc.prepare_datapath_read(&sdmmc.config, status.as_mut(), 64, 6); 460 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
369 sdmmc.enable_interrupts();
370 sdmmc.cmd(sd_cmd::sd_status(), true)?;
371 461
372 let res = sdmmc.complete_datapath_transfer(true).await; 462 on_drop.defuse();
373 463
374 if res.is_ok() { 464 for byte in status.iter_mut() {
375 on_drop.defuse(); 465 *byte = u32::from_be(*byte);
376 sdmmc.stop_datapath(); 466 }
377 drop(transfer);
378 467
379 for byte in status.iter_mut() { 468 Ok(status.0.into())
380 *byte = u32::from_be(*byte); 469 }
470}
471
472/// Emmc storage device
473impl<'a, 'b> StorageDevice<'a, 'b, Emmc> {
474 /// Create a new EMMC card
475 pub async fn new_emmc(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> {
476 let mut s = Self {
477 info: Emmc::default(),
478 sdmmc,
479 };
480
481 s.acquire(cmd_block, freq).await?;
482
483 Ok(s)
484 }
485
486 async fn acquire(&mut self, _cmd_block: &mut CmdBlock, freq: Hertz) -> Result<(), Error> {
487 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
488 let regs = self.sdmmc.info.regs;
489
490 let bus_width = self.sdmmc.bus_width();
491
492 // While the SD/SDIO card or eMMC is in identification mode,
493 // the SDMMC_CK frequency must be no more than 400 kHz.
494 self.sdmmc.init_idle()?;
495
496 let ocr = loop {
497 let high_voltage = 0b0 << 7;
498 let access_mode = 0b10 << 29;
499 let op_cond = high_voltage | access_mode | 0b1_1111_1111 << 15;
500 // Initialize card
501 match self.sdmmc.cmd(emmc_cmd::send_op_cond(op_cond), false) {
502 Ok(_) => (),
503 Err(Error::Crc) => (),
504 Err(err) => return Err(err),
505 }
506 let ocr: OCR<EMMC> = regs.respr(0).read().cardstatus().into();
507 if !ocr.is_busy() {
508 // Power up done
509 break ocr;
510 }
511 };
512
513 self.info.capacity = if ocr.access_mode() == 0b10 {
514 // Card is SDHC or SDXC or SDUC
515 CardCapacity::HighCapacity
516 } else {
517 CardCapacity::StandardCapacity
518 };
519 self.info.ocr = ocr;
520
521 self.info.cid = self.sdmmc.get_cid()?.into();
522
523 self.info.rca = 1u16.into();
524 self.sdmmc
525 .cmd(emmc_cmd::assign_relative_address(self.info.rca), false)?;
526
527 self.info.csd = self.sdmmc.get_csd(self.info.get_address())?.into();
528 self.sdmmc.select_card(Some(self.info.get_address()))?;
529
530 let (widbus, _) = bus_width_vals(bus_width);
531
532 // Write bus width to ExtCSD byte 183
533 self.sdmmc.cmd(
534 emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus),
535 false,
536 )?;
537
538 // Wait for ready after R1b response
539 loop {
540 let status = self.sdmmc.read_status(&self.info)?;
541
542 if status.ready_for_data() {
543 break;
381 } 544 }
382 self.status = status.0.into();
383 } 545 }
384 res 546
547 self.sdmmc.clkcr_set_clkdiv(freq.clamp(mhz(0), mhz(25)), bus_width)?;
548 self.info.ext_csd = self.read_ext_csd().await?;
549
550 Ok(())
385 } 551 }
552
553 /// Gets the EXT_CSD register.
554 ///
555 /// eMMC only.
556 async fn read_ext_csd(&self) -> Result<ExtCSD, Error> {
557 // Note: cmd_block can't be used because ExtCSD is too long to fit.
558 let mut data_block = DataBlock([0u8; 512]);
559
560 // NOTE(unsafe) DataBlock uses align 4
561 let buffer = unsafe { &mut *((&mut data_block.0) as *mut [u8; 512] as *mut [u32; 128]) };
562
563 self.sdmmc.cmd(common_cmd::set_block_length(512), false).unwrap(); // CMD16
564
565 let transfer = self.sdmmc.prepare_datapath_read(buffer, 512, 9);
566 self.sdmmc.cmd(emmc_cmd::send_ext_csd(), true)?;
567
568 // Arm `OnDrop` after the buffer, so it will be dropped first
569 let on_drop = OnDrop::new(|| self.sdmmc.on_drop());
570
571 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
572
573 on_drop.defuse();
574
575 Ok(unsafe { core::mem::transmute::<_, [u32; 128]>(data_block.0) }.into())
576 }
577}
578
579/// Card or Emmc storage device
580impl<'a, 'b, A: Addressable> StorageDevice<'a, 'b, A> {
581 /// Write a block
582 pub fn card(&self) -> A {
583 self.info.clone()
584 }
585
586 /// Read a data block.
587 #[inline]
588 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
589 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
590 let card_capacity = self.info.get_capacity();
591
592 // NOTE(unsafe) DataBlock uses align 4
593 let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) };
594
595 // Always read 1 block of 512 bytes
596 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
597 let address = match card_capacity {
598 CardCapacity::StandardCapacity => block_idx * 512,
599 _ => block_idx,
600 };
601 self.sdmmc.cmd(common_cmd::set_block_length(512), false)?; // CMD16
602
603 let on_drop = OnDrop::new(|| self.sdmmc.on_drop());
604
605 let transfer = self.sdmmc.prepare_datapath_read(buffer, 512, 9);
606 self.sdmmc.cmd(common_cmd::read_single_block(address), true)?;
607
608 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
609
610 on_drop.defuse();
611
612 Ok(())
613 }
614
615 /// Read multiple data blocks.
616 #[inline]
617 pub async fn read_blocks(&mut self, block_idx: u32, blocks: &mut [DataBlock]) -> Result<(), Error> {
618 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
619 let card_capacity = self.info.get_capacity();
620
621 // NOTE(unsafe) reinterpret buffer as &mut [u32]
622 let buffer = unsafe {
623 let ptr = blocks.as_mut_ptr() as *mut u32;
624 let len = blocks.len() * 128;
625 core::slice::from_raw_parts_mut(ptr, len)
626 };
627
628 // Always read 1 block of 512 bytes
629 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
630 let address = match card_capacity {
631 CardCapacity::StandardCapacity => block_idx * 512,
632 _ => block_idx,
633 };
634 self.sdmmc.cmd(common_cmd::set_block_length(512), false)?; // CMD16
635
636 let on_drop = OnDrop::new(|| self.sdmmc.on_drop());
637 let transfer = self.sdmmc.prepare_datapath_read(buffer, 512 * blocks.len() as u32, 9);
638 self.sdmmc.cmd(common_cmd::read_multiple_blocks(address), true)?;
639
640 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
641
642 self.sdmmc.cmd(common_cmd::stop_transmission(), false)?; // CMD12
643 self.sdmmc.clear_interrupt_flags();
644
645 on_drop.defuse();
646
647 Ok(())
648 }
649
650 /// Write a data block.
651 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error>
652 where
653 CardStatus<A::Ext>: From<u32>,
654 {
655 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
656
657 // NOTE(unsafe) DataBlock uses align 4
658 let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) };
659
660 // Always read 1 block of 512 bytes
661 // cards are byte addressed hence the blockaddress is in multiples of 512 bytes
662 let address = match self.info.get_capacity() {
663 CardCapacity::StandardCapacity => block_idx * 512,
664 _ => block_idx,
665 };
666 self.sdmmc.cmd(common_cmd::set_block_length(512), false)?; // CMD16
667
668 let on_drop = OnDrop::new(|| self.sdmmc.on_drop());
669
670 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
671 #[cfg(sdmmc_v1)]
672 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?;
673
674 let transfer = self.sdmmc.prepare_datapath_write(buffer, 512, 9);
675
676 #[cfg(sdmmc_v2)]
677 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?;
678
679 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
680
681 on_drop.defuse();
682
683 // TODO: Make this configurable
684 let mut timeout: u32 = 0x00FF_FFFF;
685
686 while timeout > 0 {
687 let ready_for_data = self.sdmmc.read_status(&self.info)?.ready_for_data();
688 if ready_for_data {
689 return Ok(());
690 }
691 timeout -= 1;
692 }
693
694 Err(Error::SoftwareTimeout)
695 }
696
697 /// Write multiple data blocks.
698 pub async fn write_blocks(&mut self, block_idx: u32, blocks: &[DataBlock]) -> Result<(), Error>
699 where
700 CardStatus<A::Ext>: From<u32>,
701 {
702 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
703
704 // NOTE(unsafe) reinterpret buffer as &[u32]
705 let buffer = unsafe {
706 let ptr = blocks.as_ptr() as *const u32;
707 let len = blocks.len() * 128;
708 core::slice::from_raw_parts(ptr, len)
709 };
710
711 // Always read 1 block of 512 bytes
712 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
713 let address = match self.info.get_capacity() {
714 CardCapacity::StandardCapacity => block_idx * 512,
715 _ => block_idx,
716 };
717
718 self.sdmmc.cmd(common_cmd::set_block_length(512), false)?; // CMD16
719
720 let block_count = blocks.len();
721
722 let on_drop = OnDrop::new(|| self.sdmmc.on_drop());
723
724 #[cfg(sdmmc_v1)]
725 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
726
727 // Setup write command
728 let transfer = self.sdmmc.prepare_datapath_write(buffer, 512 * block_count as u32, 9);
729
730 #[cfg(sdmmc_v2)]
731 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
732
733 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
734
735 self.sdmmc.cmd(common_cmd::stop_transmission(), false)?; // CMD12
736 self.sdmmc.clear_interrupt_flags();
737
738 on_drop.defuse();
739
740 // TODO: Make this configurable
741 let mut timeout: u32 = 0x00FF_FFFF;
742
743 while timeout > 0 {
744 let ready_for_data = self.sdmmc.read_status(&self.info)?.ready_for_data();
745
746 if ready_for_data {
747 return Ok(());
748 }
749 timeout -= 1;
750 }
751 Err(Error::SoftwareTimeout)
752 }
753}
754
755#[derive(Clone, Copy, Debug, Default)]
756/// SD Card
757pub struct Card {
758 /// The type of this card
759 pub card_type: CardCapacity,
760 /// Operation Conditions Register
761 pub ocr: OCR<SD>,
762 /// Relative Card Address
763 pub rca: u16,
764 /// Card ID
765 pub cid: CID<SD>,
766 /// Card Specific Data
767 pub csd: CSD<SD>,
768 /// SD CARD Configuration Register
769 pub scr: SCR,
770 /// SD Status
771 pub status: SDStatus,
386} 772}
387 773
388impl Addressable for Card { 774impl Addressable for Card {
@@ -421,40 +807,6 @@ pub struct Emmc {
421 pub ext_csd: ExtCSD, 807 pub ext_csd: ExtCSD,
422} 808}
423 809
424impl Emmc {
425 /// Gets the EXT_CSD register.
426 ///
427 /// eMMC only.
428 async fn read_ext_csd<'a>(&mut self, sdmmc: &mut Sdmmc<'a>) -> Result<(), Error> {
429 // Note: cmd_block can't be used because ExtCSD is too long to fit.
430 let mut data_block = DataBlock([0u8; 512]);
431
432 // NOTE(unsafe) DataBlock uses align 4
433 let buffer = unsafe { &mut *((&mut data_block.0) as *mut [u8; 512] as *mut [u32; 128]) };
434
435 sdmmc.cmd(common_cmd::set_block_length(512), false).unwrap(); // CMD16
436
437 let transfer = sdmmc.prepare_datapath_read(&sdmmc.config, buffer, 512, 9);
438 sdmmc.enable_interrupts();
439 sdmmc.cmd(emmc_cmd::send_ext_csd(), true)?;
440
441 // Arm `OnDrop` after the buffer, so it will be dropped first
442 let on_drop = OnDrop::new(|| sdmmc.on_drop());
443
444 let res = sdmmc.complete_datapath_transfer(true).await;
445
446 if res.is_ok() {
447 on_drop.defuse();
448 sdmmc.stop_datapath();
449 drop(transfer);
450
451 self.ext_csd = unsafe { core::mem::transmute::<_, [u32; 128]>(data_block.0) }.into();
452 }
453
454 res
455 }
456}
457
458impl Addressable for Emmc { 810impl Addressable for Emmc {
459 type Ext = EMMC; 811 type Ext = EMMC;
460 812
@@ -516,6 +868,15 @@ fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u8, Hertz), Error> {
516 Ok((false, clk_div, clk_f)) 868 Ok((false, clk_div, clk_f))
517} 869}
518 870
871fn bus_width_vals(bus_width: BusWidth) -> (u8, u32) {
872 match bus_width {
873 BusWidth::One => (0, 1u32),
874 BusWidth::Four => (1, 4u32),
875 BusWidth::Eight => (2, 8u32),
876 _ => panic!("Invalid Bus Width"),
877 }
878}
879
519/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to 880/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to
520/// `sdmmc_ck` in Hertz. 881/// `sdmmc_ck` in Hertz.
521/// 882///
@@ -580,25 +941,6 @@ impl Default for Config {
580 } 941 }
581} 942}
582 943
583/// Peripheral that can be operated over SDMMC
584#[derive(Clone, Copy, Debug)]
585pub enum SdmmcPeripheral {
586 /// SD Card
587 SdCard(Card),
588 /// eMMC memory
589 Emmc(Emmc),
590}
591
592impl SdmmcPeripheral {
593 /// Get this peripheral's address on the SDMMC bus
594 fn get_address(&self) -> u16 {
595 match self {
596 Self::SdCard(c) => c.rca,
597 Self::Emmc(e) => e.rca,
598 }
599 }
600}
601
602/// Sdmmc device 944/// Sdmmc device
603pub struct Sdmmc<'d> { 945pub struct Sdmmc<'d> {
604 info: &'static Info, 946 info: &'static Info,
@@ -989,17 +1331,19 @@ impl<'d> Sdmmc<'d> {
989 while self.data_active() || self.cmd_active() {} 1331 while self.data_active() || self.cmd_active() {}
990 } 1332 }
991 1333
1334 fn bus_width(&self) -> BusWidth {
1335 match (self.d3.is_some(), self.d7.is_some()) {
1336 (true, true) => BusWidth::Eight,
1337 (true, false) => BusWidth::Four,
1338 _ => BusWidth::One,
1339 }
1340 }
1341
992 /// # Safety 1342 /// # Safety
993 /// 1343 ///
994 /// `buffer` must be valid for the whole transfer and word aligned 1344 /// `buffer` must be valid for the whole transfer and word aligned
995 #[allow(unused_variables)] 1345 #[allow(unused_variables)]
996 fn prepare_datapath_read<'a>( 1346 fn prepare_datapath_read<'a>(&'a self, buffer: &'a mut [u32], length_bytes: u32, block_size: u8) -> Transfer<'a> {
997 &'a self,
998 config: &Config,
999 buffer: &'a mut [u32],
1000 length_bytes: u32,
1001 block_size: u8,
1002 ) -> Transfer<'a> {
1003 assert!(block_size <= 14, "Block size up to 2^14 bytes"); 1347 assert!(block_size <= 14, "Block size up to 2^14 bytes");
1004 let regs = self.info.regs; 1348 let regs = self.info.regs;
1005 1349
@@ -1034,6 +1378,8 @@ impl<'d> Sdmmc<'d> {
1034 } 1378 }
1035 }); 1379 });
1036 1380
1381 self.enable_interrupts();
1382
1037 transfer 1383 transfer
1038 } 1384 }
1039 1385
@@ -1075,6 +1421,8 @@ impl<'d> Sdmmc<'d> {
1075 } 1421 }
1076 }); 1422 });
1077 1423
1424 self.enable_interrupts();
1425
1078 transfer 1426 transfer
1079 } 1427 }
1080 1428
@@ -1091,18 +1439,23 @@ impl<'d> Sdmmc<'d> {
1091 regs.idmactrlr().modify(|w| w.set_idmaen(false)); 1439 regs.idmactrlr().modify(|w| w.set_idmaen(false));
1092 } 1440 }
1093 1441
1094 /// Sets the CLKDIV field in CLKCR. Updates clock field in self 1442 fn init_idle(&mut self) -> Result<(), Error> {
1095 fn clkcr_set_clkdiv(&mut self, freq: u32, width: BusWidth) -> Result<(), Error> {
1096 let regs = self.info.regs; 1443 let regs = self.info.regs;
1097 1444
1098 let width_u32 = match width { 1445 self.clkcr_set_clkdiv(SD_INIT_FREQ, BusWidth::One)?;
1099 BusWidth::One => 1u32, 1446 regs.dtimer()
1100 BusWidth::Four => 4u32, 1447 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
1101 BusWidth::Eight => 8u32, 1448
1102 _ => panic!("Invalid Bus Width"), 1449 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
1103 }; 1450 self.cmd(common_cmd::idle(), false)
1451 }
1452
1453 /// Sets the CLKDIV field in CLKCR. Updates clock field in self
1454 fn clkcr_set_clkdiv(&mut self, freq: Hertz, width: BusWidth) -> Result<(), Error> {
1455 let regs = self.info.regs;
1104 1456
1105 let (_bypass, clkdiv, new_clock) = clk_div(self.ker_clk, freq)?; 1457 let (widbus, width_u32) = bus_width_vals(width);
1458 let (_bypass, clkdiv, new_clock) = clk_div(self.ker_clk, freq.0)?;
1106 1459
1107 // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7 1460 // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7
1108 // Section 55.5.8 1461 // Section 55.5.8
@@ -1110,29 +1463,34 @@ impl<'d> Sdmmc<'d> {
1110 assert!(self.ker_clk.0 > 3 * sdmmc_bus_bandwidth / 32); 1463 assert!(self.ker_clk.0 > 3 * sdmmc_bus_bandwidth / 32);
1111 self.clock = new_clock; 1464 self.clock = new_clock;
1112 1465
1113 // CPSMACT and DPSMACT must be 0 to set CLKDIV 1466 // CPSMACT and DPSMACT must be 0 to set CLKDIV or WIDBUS
1114 self.wait_idle(); 1467 self.wait_idle();
1115 regs.clkcr().modify(|w| { 1468 regs.clkcr().modify(|w| {
1116 w.set_clkdiv(clkdiv); 1469 w.set_clkdiv(clkdiv);
1117 #[cfg(sdmmc_v1)] 1470 #[cfg(sdmmc_v1)]
1118 w.set_bypass(_bypass); 1471 w.set_bypass(_bypass);
1472 w.set_widbus(widbus);
1119 }); 1473 });
1120 1474
1121 Ok(()) 1475 Ok(())
1122 } 1476 }
1123 1477
1478 fn get_cid(&self) -> Result<u128, Error> {
1479 self.cmd(common_cmd::all_send_cid(), false) // CMD2
1480 }
1481
1482 fn get_csd(&self, address: u16) -> Result<u128, Error> {
1483 self.cmd(common_cmd::send_csd(address), false)
1484 }
1485
1124 /// Query the card status (CMD13, returns R1) 1486 /// Query the card status (CMD13, returns R1)
1125 fn read_status<A: Addressable>(&self, card: &A) -> Result<CardStatus<A::Ext>, Error> 1487 fn read_status<A: Addressable>(&self, card: &A) -> Result<CardStatus<A::Ext>, Error>
1126 where 1488 where
1127 CardStatus<A::Ext>: From<u32>, 1489 CardStatus<A::Ext>: From<u32>,
1128 { 1490 {
1129 let regs = self.info.regs;
1130 let rca = card.get_address(); 1491 let rca = card.get_address();
1131 1492
1132 self.cmd(common_cmd::card_status(rca, false), false)?; // CMD13 1493 Ok(self.cmd(common_cmd::card_status(rca, false), false)?.into()) // CMD13
1133
1134 let r1 = regs.respr(0).read().cardstatus();
1135 Ok(r1.into())
1136 } 1494 }
1137 1495
1138 /// Select one card and place it into the _Tranfer State_ 1496 /// Select one card and place it into the _Tranfer State_
@@ -1143,11 +1501,17 @@ impl<'d> Sdmmc<'d> {
1143 // Determine Relative Card Address (RCA) of given card 1501 // Determine Relative Card Address (RCA) of given card
1144 let rca = rca.unwrap_or(0); 1502 let rca = rca.unwrap_or(0);
1145 1503
1146 let r = self.cmd(common_cmd::select_card(rca), false); 1504 let resp = self.cmd(common_cmd::select_card(rca), false);
1147 match (r, rca) { 1505
1148 (Err(Error::Timeout), 0) => Ok(()), 1506 if let Err(Error::Timeout) = resp
1149 _ => r, 1507 && rca == 0
1508 {
1509 return Ok(());
1150 } 1510 }
1511
1512 resp?;
1513
1514 Ok(())
1151 } 1515 }
1152 1516
1153 /// Clear flags in interrupt clear register 1517 /// Clear flags in interrupt clear register
@@ -1186,7 +1550,7 @@ impl<'d> Sdmmc<'d> {
1186 1550
1187 /// Send command to card 1551 /// Send command to card
1188 #[allow(unused_variables)] 1552 #[allow(unused_variables)]
1189 fn cmd<R: Resp>(&self, cmd: Cmd<R>, data: bool) -> Result<(), Error> { 1553 fn cmd<R: TypedResp>(&self, cmd: Cmd<R>, data: bool) -> Result<R::Word, Error> {
1190 let regs = self.info.regs; 1554 let regs = self.info.regs;
1191 1555
1192 self.clear_interrupt_flags(); 1556 self.clear_interrupt_flags();
@@ -1233,7 +1597,20 @@ impl<'d> Sdmmc<'d> {
1233 } else if status.ccrcfail() { 1597 } else if status.ccrcfail() {
1234 return Err(Error::Crc); 1598 return Err(Error::Crc);
1235 } 1599 }
1236 Ok(()) 1600
1601 Ok(match R::LENGTH {
1602 ResponseLen::Zero => U128(0u128),
1603 ResponseLen::R48 => U128(self.info.regs.respr(0).read().cardstatus() as u128),
1604 ResponseLen::R136 => {
1605 let cid0 = self.info.regs.respr(0).read().cardstatus() as u128;
1606 let cid1 = self.info.regs.respr(1).read().cardstatus() as u128;
1607 let cid2 = self.info.regs.respr(2).read().cardstatus() as u128;
1608 let cid3 = self.info.regs.respr(3).read().cardstatus() as u128;
1609
1610 U128((cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3))
1611 }
1612 }
1613 .into())
1237 } 1614 }
1238 1615
1239 fn on_drop(&self) { 1616 fn on_drop(&self) {
@@ -1272,7 +1649,7 @@ impl<'d> Sdmmc<'d> {
1272 /// Wait for a previously started datapath transfer to complete from an interrupt. 1649 /// Wait for a previously started datapath transfer to complete from an interrupt.
1273 #[inline] 1650 #[inline]
1274 #[allow(unused)] 1651 #[allow(unused)]
1275 async fn complete_datapath_transfer(&self, block: bool) -> Result<(), Error> { 1652 async fn complete_datapath_transfer(&self, transfer: Transfer<'_>, block: bool) -> Result<(), Error> {
1276 let res = poll_fn(|cx| { 1653 let res = poll_fn(|cx| {
1277 // Compiler might not be sufficiently constrained here 1654 // Compiler might not be sufficiently constrained here
1278 // https://github.com/embassy-rs/embassy/issues/4723 1655 // https://github.com/embassy-rs/embassy/issues/4723
@@ -1307,498 +1684,17 @@ impl<'d> Sdmmc<'d> {
1307 .await; 1684 .await;
1308 1685
1309 self.clear_interrupt_flags(); 1686 self.clear_interrupt_flags();
1687 self.stop_datapath();
1310 1688
1311 res 1689 drop(transfer);
1312 }
1313
1314 /// Read a data block.
1315 #[inline]
1316 pub async fn read_block(
1317 &mut self,
1318 card: &mut impl Addressable,
1319 block_idx: u32,
1320 buffer: &mut DataBlock,
1321 ) -> Result<(), Error> {
1322 let _scoped_block_stop = self.info.rcc.block_stop();
1323 let card_capacity = card.get_capacity();
1324
1325 // NOTE(unsafe) DataBlock uses align 4
1326 let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) };
1327
1328 // Always read 1 block of 512 bytes
1329 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1330 let address = match card_capacity {
1331 CardCapacity::StandardCapacity => block_idx * 512,
1332 _ => block_idx,
1333 };
1334 self.cmd(common_cmd::set_block_length(512), false)?; // CMD16
1335
1336 let on_drop = OnDrop::new(|| self.on_drop());
1337
1338 let transfer = self.prepare_datapath_read(&self.config, buffer, 512, 9);
1339 self.enable_interrupts();
1340 self.cmd(common_cmd::read_single_block(address), true)?;
1341
1342 let res = self.complete_datapath_transfer(true).await;
1343
1344 if res.is_ok() {
1345 on_drop.defuse();
1346 self.stop_datapath();
1347 drop(transfer);
1348 }
1349 res
1350 }
1351
1352 /// Read multiple data blocks.
1353 #[inline]
1354 pub async fn read_blocks(
1355 &mut self,
1356 card: &mut impl Addressable,
1357 block_idx: u32,
1358 blocks: &mut [DataBlock],
1359 ) -> Result<(), Error> {
1360 let _scoped_block_stop = self.info.rcc.block_stop();
1361 let card_capacity = card.get_capacity();
1362
1363 // NOTE(unsafe) reinterpret buffer as &mut [u32]
1364 let buffer = unsafe {
1365 let ptr = blocks.as_mut_ptr() as *mut u32;
1366 let len = blocks.len() * 128;
1367 core::slice::from_raw_parts_mut(ptr, len)
1368 };
1369
1370 // Always read 1 block of 512 bytes
1371 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1372 let address = match card_capacity {
1373 CardCapacity::StandardCapacity => block_idx * 512,
1374 _ => block_idx,
1375 };
1376 self.cmd(common_cmd::set_block_length(512), false)?; // CMD16
1377
1378 let on_drop = OnDrop::new(|| self.on_drop());
1379
1380 let transfer = self.prepare_datapath_read(&self.config, buffer, 512 * blocks.len() as u32, 9);
1381 self.enable_interrupts();
1382
1383 self.cmd(common_cmd::read_multiple_blocks(address), true)?;
1384
1385 let res = self.complete_datapath_transfer(false).await;
1386
1387 self.cmd(common_cmd::stop_transmission(), false)?; // CMD12
1388 self.clear_interrupt_flags();
1389 1690
1390 if res.is_ok() {
1391 on_drop.defuse();
1392 self.stop_datapath();
1393 drop(transfer);
1394 }
1395 res 1691 res
1396 } 1692 }
1397 1693
1398 /// Write a data block.
1399 pub async fn write_block<A: Addressable>(
1400 &mut self,
1401 card: &mut A,
1402 block_idx: u32,
1403 buffer: &DataBlock,
1404 ) -> Result<(), Error>
1405 where
1406 CardStatus<A::Ext>: From<u32>,
1407 {
1408 let _scoped_block_stop = self.info.rcc.block_stop();
1409
1410 // NOTE(unsafe) DataBlock uses align 4
1411 let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) };
1412
1413 // Always read 1 block of 512 bytes
1414 // cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1415 let address = match card.get_capacity() {
1416 CardCapacity::StandardCapacity => block_idx * 512,
1417 _ => block_idx,
1418 };
1419 self.cmd(common_cmd::set_block_length(512), false)?; // CMD16
1420
1421 let on_drop = OnDrop::new(|| self.on_drop());
1422
1423 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
1424 #[cfg(sdmmc_v1)]
1425 self.cmd(common_cmd::write_single_block(address), true)?;
1426
1427 let transfer = self.prepare_datapath_write(buffer, 512, 9);
1428 self.enable_interrupts();
1429
1430 #[cfg(sdmmc_v2)]
1431 self.cmd(common_cmd::write_single_block(address), true)?;
1432
1433 let res = self.complete_datapath_transfer(true).await;
1434
1435 match res {
1436 Ok(_) => {
1437 on_drop.defuse();
1438 self.stop_datapath();
1439 drop(transfer);
1440
1441 // TODO: Make this configurable
1442 let mut timeout: u32 = 0x00FF_FFFF;
1443
1444 while timeout > 0 {
1445 let ready_for_data = self.read_status(card)?.ready_for_data();
1446 if ready_for_data {
1447 return Ok(());
1448 }
1449 timeout -= 1;
1450 }
1451 Err(Error::SoftwareTimeout)
1452 }
1453 Err(e) => Err(e),
1454 }
1455 }
1456
1457 /// Write multiple data blocks.
1458 pub async fn write_blocks<A: Addressable>(
1459 &mut self,
1460 card: &mut A,
1461 block_idx: u32,
1462 blocks: &[DataBlock],
1463 ) -> Result<(), Error>
1464 where
1465 CardStatus<A::Ext>: From<u32>,
1466 {
1467 let _scoped_block_stop = self.info.rcc.block_stop();
1468
1469 // NOTE(unsafe) reinterpret buffer as &[u32]
1470 let buffer = unsafe {
1471 let ptr = blocks.as_ptr() as *const u32;
1472 let len = blocks.len() * 128;
1473 core::slice::from_raw_parts(ptr, len)
1474 };
1475
1476 // Always read 1 block of 512 bytes
1477 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1478 let address = match card.get_capacity() {
1479 CardCapacity::StandardCapacity => block_idx * 512,
1480 _ => block_idx,
1481 };
1482
1483 self.cmd(common_cmd::set_block_length(512), false)?; // CMD16
1484
1485 let block_count = blocks.len();
1486
1487 let on_drop = OnDrop::new(|| self.on_drop());
1488
1489 #[cfg(sdmmc_v1)]
1490 self.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
1491
1492 // Setup write command
1493 let transfer = self.prepare_datapath_write(buffer, 512 * block_count as u32, 9);
1494 self.enable_interrupts();
1495
1496 #[cfg(sdmmc_v2)]
1497 self.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
1498
1499 let res = self.complete_datapath_transfer(false).await;
1500
1501 self.cmd(common_cmd::stop_transmission(), false)?; // CMD12
1502 self.clear_interrupt_flags();
1503
1504 match res {
1505 Ok(_) => {
1506 on_drop.defuse();
1507 self.stop_datapath();
1508 drop(transfer);
1509
1510 // TODO: Make this configurable
1511 let mut timeout: u32 = 0x00FF_FFFF;
1512
1513 while timeout > 0 {
1514 let ready_for_data = self.read_status(card)?.ready_for_data();
1515
1516 if ready_for_data {
1517 return Ok(());
1518 }
1519 timeout -= 1;
1520 }
1521 Err(Error::SoftwareTimeout)
1522 }
1523 Err(e) => Err(e),
1524 }
1525 }
1526
1527 /// Get the current SDMMC bus clock 1694 /// Get the current SDMMC bus clock
1528 pub fn clock(&self) -> Hertz { 1695 pub fn clock(&self) -> Hertz {
1529 self.clock 1696 self.clock
1530 } 1697 }
1531
1532 async fn init_internal(
1533 &mut self,
1534 cmd_block: &mut CmdBlock,
1535 freq: Hertz,
1536 card: &mut SdmmcPeripheral,
1537 ) -> Result<(), Error> {
1538 let _scoped_block_stop = self.info.rcc.block_stop();
1539
1540 let regs = self.info.regs;
1541
1542 let bus_width = match (self.d3.is_some(), self.d7.is_some()) {
1543 (true, true) => {
1544 if matches!(card, SdmmcPeripheral::SdCard(_)) {
1545 return Err(Error::BusWidth);
1546 }
1547 BusWidth::Eight
1548 }
1549 (true, false) => BusWidth::Four,
1550 _ => BusWidth::One,
1551 };
1552
1553 // While the SD/SDIO card or eMMC is in identification mode,
1554 // the SDMMC_CK frequency must be no more than 400 kHz.
1555 let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(self.ker_clk, SD_INIT_FREQ.0));
1556 self.clock = init_clock;
1557
1558 // CPSMACT and DPSMACT must be 0 to set WIDBUS
1559 self.wait_idle();
1560
1561 regs.clkcr().modify(|w| {
1562 w.set_widbus(0);
1563 w.set_clkdiv(clkdiv);
1564 #[cfg(sdmmc_v1)]
1565 w.set_bypass(_bypass);
1566 });
1567 regs.dtimer()
1568 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
1569
1570 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
1571 self.cmd(common_cmd::idle(), false)?;
1572
1573 match card {
1574 SdmmcPeripheral::SdCard(card) => {
1575 // Check if cards supports CMD8 (with pattern)
1576 self.cmd(sd_cmd::send_if_cond(1, 0xAA), false)?;
1577 let cic = CIC::from(regs.respr(0).read().cardstatus());
1578
1579 if cic.pattern() != 0xAA {
1580 return Err(Error::UnsupportedCardVersion);
1581 }
1582
1583 if cic.voltage_accepted() & 1 == 0 {
1584 return Err(Error::UnsupportedVoltage);
1585 }
1586
1587 let ocr = loop {
1588 // Signal that next command is a app command
1589 self.cmd(common_cmd::app_cmd(0), false)?; // CMD55
1590
1591 // 3.2-3.3V
1592 let voltage_window = 1 << 5;
1593 // Initialize card
1594 match self.cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window), false) {
1595 // ACMD41
1596 Ok(_) => (),
1597 Err(Error::Crc) => (),
1598 Err(err) => return Err(err),
1599 }
1600 let ocr: OCR<SD> = regs.respr(0).read().cardstatus().into();
1601 if !ocr.is_busy() {
1602 // Power up done
1603 break ocr;
1604 }
1605 };
1606
1607 if ocr.high_capacity() {
1608 // Card is SDHC or SDXC or SDUC
1609 card.card_type = CardCapacity::HighCapacity;
1610 } else {
1611 card.card_type = CardCapacity::StandardCapacity;
1612 }
1613 card.ocr = ocr;
1614 }
1615 SdmmcPeripheral::Emmc(emmc) => {
1616 let ocr = loop {
1617 let high_voltage = 0b0 << 7;
1618 let access_mode = 0b10 << 29;
1619 let op_cond = high_voltage | access_mode | 0b1_1111_1111 << 15;
1620 // Initialize card
1621 match self.cmd(emmc_cmd::send_op_cond(op_cond), false) {
1622 Ok(_) => (),
1623 Err(Error::Crc) => (),
1624 Err(err) => return Err(err),
1625 }
1626 let ocr: OCR<EMMC> = regs.respr(0).read().cardstatus().into();
1627 if !ocr.is_busy() {
1628 // Power up done
1629 break ocr;
1630 }
1631 };
1632
1633 emmc.capacity = if ocr.access_mode() == 0b10 {
1634 // Card is SDHC or SDXC or SDUC
1635 CardCapacity::HighCapacity
1636 } else {
1637 CardCapacity::StandardCapacity
1638 };
1639 emmc.ocr = ocr;
1640 }
1641 }
1642
1643 self.cmd(common_cmd::all_send_cid(), false)?; // CMD2
1644 let cid0 = regs.respr(0).read().cardstatus() as u128;
1645 let cid1 = regs.respr(1).read().cardstatus() as u128;
1646 let cid2 = regs.respr(2).read().cardstatus() as u128;
1647 let cid3 = regs.respr(3).read().cardstatus() as u128;
1648 let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3);
1649
1650 match card {
1651 SdmmcPeripheral::SdCard(card) => {
1652 card.cid = cid.into();
1653
1654 self.cmd(sd_cmd::send_relative_address(), false)?;
1655 let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus());
1656 card.rca = rca.address();
1657 }
1658 SdmmcPeripheral::Emmc(emmc) => {
1659 emmc.cid = cid.into();
1660
1661 emmc.rca = 1u16.into();
1662 self.cmd(emmc_cmd::assign_relative_address(emmc.rca), false)?;
1663 }
1664 }
1665
1666 self.cmd(common_cmd::send_csd(card.get_address()), false)?;
1667 let csd0 = regs.respr(0).read().cardstatus() as u128;
1668 let csd1 = regs.respr(1).read().cardstatus() as u128;
1669 let csd2 = regs.respr(2).read().cardstatus() as u128;
1670 let csd3 = regs.respr(3).read().cardstatus() as u128;
1671 let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3);
1672
1673 self.select_card(Some(card.get_address()))?;
1674
1675 let bus_width = match card {
1676 SdmmcPeripheral::SdCard(card) => {
1677 card.csd = csd.into();
1678
1679 card.get_scr(self, cmd_block).await?;
1680
1681 if !card.scr.bus_width_four() {
1682 BusWidth::One
1683 } else {
1684 BusWidth::Four
1685 }
1686 }
1687 SdmmcPeripheral::Emmc(emmc) => {
1688 emmc.csd = csd.into();
1689
1690 bus_width
1691 }
1692 };
1693
1694 // Set bus width
1695 let widbus = match bus_width {
1696 BusWidth::Eight => 2,
1697 BusWidth::Four => 1,
1698 BusWidth::One => 0,
1699 _ => unreachable!(),
1700 };
1701
1702 match card {
1703 SdmmcPeripheral::SdCard(card) => {
1704 let acmd_arg = match bus_width {
1705 BusWidth::Four if card.scr.bus_width_four() => 2,
1706 _ => 0,
1707 };
1708 self.cmd(common_cmd::app_cmd(card.rca), false)?;
1709 self.cmd(sd_cmd::cmd6(acmd_arg), false)?;
1710 }
1711 SdmmcPeripheral::Emmc(emmc) => {
1712 // Write bus width to ExtCSD byte 183
1713 self.cmd(
1714 emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus),
1715 false,
1716 )?;
1717
1718 // Wait for ready after R1b response
1719 loop {
1720 let status = self.read_status(emmc)?;
1721
1722 if status.ready_for_data() {
1723 break;
1724 }
1725 }
1726 }
1727 }
1728
1729 // CPSMACT and DPSMACT must be 0 to set WIDBUS
1730 self.wait_idle();
1731
1732 regs.clkcr().modify(|w| w.set_widbus(widbus));
1733
1734 // Set Clock
1735 if freq.0 <= 25_000_000 {
1736 // Final clock frequency
1737 self.clkcr_set_clkdiv(freq.0, bus_width)?;
1738 } else {
1739 // Switch to max clock for SDR12
1740 self.clkcr_set_clkdiv(25_000_000, bus_width)?;
1741 }
1742
1743 match card {
1744 SdmmcPeripheral::SdCard(card) => {
1745 // Read status
1746 card.read_sd_status(self, cmd_block).await?;
1747
1748 if freq.0 > 25_000_000 {
1749 // Switch to SDR25
1750 self.signalling = card.switch_signalling_mode(self, cmd_block, Signalling::SDR25).await?;
1751
1752 if self.signalling == Signalling::SDR25 {
1753 // Set final clock frequency
1754 self.clkcr_set_clkdiv(freq.0, bus_width)?;
1755
1756 if self.read_status(card)?.state() != CurrentState::Transfer {
1757 return Err(Error::SignalingSwitchFailed);
1758 }
1759 }
1760 }
1761
1762 // Read status after signalling change
1763 card.read_sd_status(self, cmd_block).await?;
1764 }
1765 SdmmcPeripheral::Emmc(emmc) => {
1766 emmc.read_ext_csd(self).await?;
1767 }
1768 }
1769
1770 Ok(())
1771 }
1772
1773 /// Initializes card (if present) and sets the bus at the specified frequency.
1774 ///
1775 /// SD only.
1776 async fn init_sd_card(&mut self, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Card, Error> {
1777 let mut card = SdmmcPeripheral::SdCard(Card::default());
1778 self.init_internal(cmd_block, freq, &mut card).await?;
1779
1780 let card = match card {
1781 SdmmcPeripheral::SdCard(card) => card,
1782 _ => unreachable!(),
1783 };
1784
1785 Ok(card)
1786 }
1787
1788 /// Initializes eMMC and sets the bus at the specified frequency.
1789 ///
1790 /// eMMC only.
1791 async fn init_emmc(&mut self, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Emmc, Error> {
1792 let mut card = SdmmcPeripheral::Emmc(Emmc::default());
1793 self.init_internal(cmd_block, freq, &mut card).await?;
1794
1795 let card = match card {
1796 SdmmcPeripheral::Emmc(card) => card,
1797 _ => unreachable!(),
1798 };
1799
1800 Ok(card)
1801 }
1802} 1698}
1803 1699
1804impl<'d> Drop for Sdmmc<'d> { 1700impl<'d> Drop for Sdmmc<'d> {