aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-12-11 08:00:24 -0600
committerxoviat <[email protected]>2025-12-11 08:00:24 -0600
commit48100a2e8d15364f6243d3db0a649e5c90c9ffe7 (patch)
tree7789d3f97012c14d8444df8acbaa52a6c9eb0fa5 /embassy-stm32
parent32a1d0ef7ea52d3cee9959ff52d47fd13fc6b4b9 (diff)
sdmmc: factor out sd and add sdio mod
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs823
-rw-r--r--embassy-stm32/src/sdmmc/sd.rs693
-rw-r--r--embassy-stm32/src/sdmmc/sdio.rs177
3 files changed, 980 insertions, 713 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 0d5260016..12086cd3a 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -4,18 +4,15 @@
4use core::default::Default; 4use 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};
8use core::slice; 7use core::slice;
9use core::task::Poll; 8use core::task::Poll;
10 9
11use embassy_hal_internal::drop::OnDrop;
12use embassy_hal_internal::{Peri, PeripheralType}; 10use embassy_hal_internal::{Peri, PeripheralType};
13use embassy_sync::waitqueue::AtomicWaker; 11use embassy_sync::waitqueue::AtomicWaker;
12use sdio_host::Cmd;
14use sdio_host::common_cmd::{self, R1, R2, R3, Resp, ResponseLen, Rz}; 13use sdio_host::common_cmd::{self, R1, R2, R3, Resp, ResponseLen, Rz};
15use sdio_host::emmc::{EMMC, ExtCSD}; 14use sdio_host::sd::{BusWidth, CardStatus};
16use sdio_host::sd::{BusWidth, CIC, CID, CSD, CardCapacity, CardStatus, CurrentState, OCR, RCA, SCR, SD, SDStatus};
17use sdio_host::sd_cmd::{R6, R7}; 15use sdio_host::sd_cmd::{R6, R7};
18use sdio_host::{Cmd, emmc_cmd, sd_cmd};
19 16
20#[cfg(sdmmc_v1)] 17#[cfg(sdmmc_v1)]
21use crate::dma::ChannelAndRequest; 18use crate::dma::ChannelAndRequest;
@@ -25,9 +22,16 @@ use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed};
25use crate::interrupt::typelevel::Interrupt; 22use crate::interrupt::typelevel::Interrupt;
26use crate::pac::sdmmc::Sdmmc as RegBlock; 23use crate::pac::sdmmc::Sdmmc as RegBlock;
27use crate::rcc::{self, RccInfo, RccPeripheral, SealedRccPeripheral}; 24use crate::rcc::{self, RccInfo, RccPeripheral, SealedRccPeripheral};
28use crate::time::{Hertz, mhz}; 25use crate::sdmmc::sd::Addressable;
26use crate::time::Hertz;
29use crate::{interrupt, peripherals}; 27use crate::{interrupt, peripherals};
30 28
29/// Module for SD and EMMC cards
30pub mod sd;
31
32/// Module for SDIO interface
33pub mod sdio;
34
31/// Interrupt handler. 35/// Interrupt handler.
32pub struct InterruptHandler<T: Instance> { 36pub struct InterruptHandler<T: Instance> {
33 _phantom: PhantomData<T>, 37 _phantom: PhantomData<T>,
@@ -135,59 +139,14 @@ impl Default for Signalling {
135 } 139 }
136} 140}
137 141
138/// Aligned data block for SDMMC transfers. 142const fn slice8_mut(x: &mut [u32]) -> &mut [u8] {
139///
140/// This is a 512-byte array, aligned to 4 bytes to satisfy DMA requirements.
141#[repr(align(4))]
142#[derive(Debug, Clone, PartialEq, Eq)]
143#[cfg_attr(feature = "defmt", derive(defmt::Format))]
144pub struct DataBlock(pub [u8; 512]);
145
146impl Deref for DataBlock {
147 type Target = [u8; 512];
148
149 fn deref(&self) -> &Self::Target {
150 &self.0
151 }
152}
153
154impl DerefMut for DataBlock {
155 fn deref_mut(&mut self) -> &mut Self::Target {
156 &mut self.0
157 }
158}
159
160fn slice8_mut(x: &mut [u32]) -> &mut [u8] {
161 let len = x.len() * 4; 143 let len = x.len() * 4;
162 unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } 144 unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) }
163} 145}
164 146
165/// Command Block buffer for SDMMC command transfers. 147const fn slice8_ref(x: &[u32]) -> &[u8] {
166/// 148 let len = x.len() * 4;
167/// This is a 16-word array, exposed so that DMA commpatible memory can be used if required. 149 unsafe { slice::from_raw_parts(x.as_ptr() as _, len) }
168#[derive(Debug, Clone, PartialEq, Eq)]
169#[cfg_attr(feature = "defmt", derive(defmt::Format))]
170pub struct CmdBlock(pub [u32; 16]);
171
172impl CmdBlock {
173 /// Creates a new instance of CmdBlock
174 pub const fn new() -> Self {
175 Self([0u32; 16])
176 }
177}
178
179impl Deref for CmdBlock {
180 type Target = [u32; 16];
181
182 fn deref(&self) -> &Self::Target {
183 &self.0
184 }
185}
186
187impl DerefMut for CmdBlock {
188 fn deref_mut(&mut self) -> &mut Self::Target {
189 &mut self.0
190 }
191} 150}
192 151
193/// Errors 152/// Errors
@@ -222,610 +181,6 @@ pub enum Error {
222 StBitErr, 181 StBitErr,
223} 182}
224 183
225/// Represents either an SD or EMMC card
226pub trait Addressable: Sized + Clone {
227 /// Associated type
228 type Ext;
229
230 /// Get this peripheral's address on the SDMMC bus
231 fn get_address(&self) -> u16;
232
233 /// Is this a standard or high capacity peripheral?
234 fn get_capacity(&self) -> CardCapacity;
235
236 /// Size in bytes
237 fn size(&self) -> u64;
238}
239
240/// Storage Device
241pub struct StorageDevice<'a, 'b, T: Addressable> {
242 info: T,
243 /// Inner member
244 pub sdmmc: &'a mut Sdmmc<'b>,
245}
246
247/// Card Storage Device
248impl<'a, 'b> StorageDevice<'a, 'b, Card> {
249 /// Create a new SD card
250 pub async fn new_sd_card(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> {
251 let mut s = Self {
252 info: Card::default(),
253 sdmmc,
254 };
255
256 s.acquire(cmd_block, freq).await?;
257
258 Ok(s)
259 }
260
261 /// Initializes the card into a known state (or at least tries to).
262 pub async fn acquire(&mut self, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<(), Error> {
263 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
264 let regs = self.sdmmc.info.regs;
265
266 let _bus_width = match self.sdmmc.bus_width() {
267 BusWidth::Eight => return Err(Error::BusWidth),
268 bus_width => bus_width,
269 };
270
271 // While the SD/SDIO card or eMMC is in identification mode,
272 // the SDMMC_CK frequency must be no more than 400 kHz.
273 self.sdmmc.init_idle()?;
274
275 // Check if cards supports CMD8 (with pattern)
276 self.sdmmc.cmd(sd_cmd::send_if_cond(1, 0xAA), false)?;
277 let cic = CIC::from(regs.respr(0).read().cardstatus());
278
279 if cic.pattern() != 0xAA {
280 return Err(Error::UnsupportedCardVersion);
281 }
282
283 if cic.voltage_accepted() & 1 == 0 {
284 return Err(Error::UnsupportedVoltage);
285 }
286
287 let ocr = loop {
288 // Signal that next command is a app command
289 self.sdmmc.cmd(common_cmd::app_cmd(0), false)?; // CMD55
290
291 // 3.2-3.3V
292 let voltage_window = 1 << 5;
293 // Initialize card
294 match self
295 .sdmmc
296 .cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window), false)
297 {
298 // ACMD41
299 Ok(_) => (),
300 Err(Error::Crc) => (),
301 Err(err) => return Err(err),
302 }
303
304 let ocr: OCR<SD> = regs.respr(0).read().cardstatus().into();
305 if !ocr.is_busy() {
306 // Power up done
307 break ocr;
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 }
363
364 /// Switch mode using CMD6.
365 ///
366 /// Attempt to set a new signalling mode. The selected
367 /// signalling mode is returned. Expects the current clock
368 /// frequency to be > 12.5MHz.
369 ///
370 /// SD only.
371 async fn switch_signalling_mode(
372 &self,
373 cmd_block: &mut CmdBlock,
374 signalling: Signalling,
375 ) -> Result<Signalling, Error> {
376 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
377 // necessary"
378
379 let set_function = 0x8000_0000
380 | match signalling {
381 // See PLSS v7_10 Table 4-11
382 Signalling::DDR50 => 0xFF_FF04,
383 Signalling::SDR104 => 0xFF_1F03,
384 Signalling::SDR50 => 0xFF_1F02,
385 Signalling::SDR25 => 0xFF_FF01,
386 Signalling::SDR12 => 0xFF_FF00,
387 };
388
389 // Arm `OnDrop` after the buffer, so it will be dropped first
390 let on_drop = OnDrop::new(|| self.sdmmc.on_drop());
391
392 let transfer = self.sdmmc.prepare_datapath_read(cmd_block.as_mut(), 64, 6);
393 self.sdmmc.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
394
395 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
396
397 // Host is allowed to use the new functions at least 8
398 // clocks after the end of the switch command
399 // transaction. We know the current clock period is < 80ns,
400 // so a total delay of 640ns is required here
401 for _ in 0..300 {
402 cortex_m::asm::nop();
403 }
404
405 on_drop.defuse();
406
407 // Function Selection of Function Group 1
408 let selection = (u32::from_be(cmd_block[4]) >> 24) & 0xF;
409
410 match selection {
411 0 => Ok(Signalling::SDR12),
412 1 => Ok(Signalling::SDR25),
413 2 => Ok(Signalling::SDR50),
414 3 => Ok(Signalling::SDR104),
415 4 => Ok(Signalling::DDR50),
416 _ => Err(Error::UnsupportedCardType),
417 }
418 }
419
420 /// Reads the SCR register.
421 ///
422 /// SD only.
423 async fn get_scr(&self, cmd_block: &mut CmdBlock) -> Result<SCR, Error> {
424 // Read the 64-bit SCR register
425 self.sdmmc.cmd(common_cmd::set_block_length(8), false)?; // CMD16
426 self.sdmmc.cmd(common_cmd::app_cmd(self.info.rca), false)?;
427
428 let scr = &mut cmd_block.0[..2];
429
430 // Arm `OnDrop` after the buffer, so it will be dropped first
431 let on_drop = OnDrop::new(|| self.sdmmc.on_drop());
432
433 let transfer = self.sdmmc.prepare_datapath_read(scr, 8, 3);
434 self.sdmmc.cmd(sd_cmd::send_scr(), true)?;
435
436 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
437
438 on_drop.defuse();
439
440 Ok(SCR(u64::from_be_bytes(unwrap!(slice8_mut(scr).try_into()))))
441 }
442
443 /// Reads the SD Status (ACMD13)
444 ///
445 /// SD only.
446 async fn read_sd_status(&self, cmd_block: &mut CmdBlock) -> Result<SDStatus, Error> {
447 let rca = self.info.rca;
448
449 self.sdmmc.cmd(common_cmd::set_block_length(64), false)?; // CMD16
450 self.sdmmc.cmd(common_cmd::app_cmd(rca), false)?; // APP
451
452 let status = cmd_block;
453
454 // Arm `OnDrop` after the buffer, so it will be dropped first
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)?;
459
460 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
461
462 on_drop.defuse();
463
464 for byte in status.iter_mut() {
465 *byte = u32::from_be(*byte);
466 }
467
468 Ok(status.0.into())
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;
544 }
545 }
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(())
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,
772}
773
774impl Addressable for Card {
775 type Ext = SD;
776
777 /// Get this peripheral's address on the SDMMC bus
778 fn get_address(&self) -> u16 {
779 self.rca
780 }
781
782 /// Is this a standard or high capacity peripheral?
783 fn get_capacity(&self) -> CardCapacity {
784 self.card_type
785 }
786
787 /// Size in bytes
788 fn size(&self) -> u64 {
789 u64::from(self.csd.block_count()) * 512
790 }
791}
792
793#[derive(Clone, Copy, Debug, Default)]
794/// eMMC storage
795pub struct Emmc {
796 /// The capacity of this card
797 pub capacity: CardCapacity,
798 /// Operation Conditions Register
799 pub ocr: OCR<EMMC>,
800 /// Relative Card Address
801 pub rca: u16,
802 /// Card ID
803 pub cid: CID<EMMC>,
804 /// Card Specific Data
805 pub csd: CSD<EMMC>,
806 /// Extended Card Specific Data
807 pub ext_csd: ExtCSD,
808}
809
810impl Addressable for Emmc {
811 type Ext = EMMC;
812
813 /// Get this peripheral's address on the SDMMC bus
814 fn get_address(&self) -> u16 {
815 self.rca
816 }
817
818 /// Is this a standard or high capacity peripheral?
819 fn get_capacity(&self) -> CardCapacity {
820 self.capacity
821 }
822
823 /// Size in bytes
824 fn size(&self) -> u64 {
825 u64::from(self.ext_csd.sector_count()) * 512
826 }
827}
828
829#[repr(u8)] 184#[repr(u8)]
830enum PowerCtrl { 185enum PowerCtrl {
831 Off = 0b00, 186 Off = 0b00,
@@ -877,6 +232,46 @@ fn bus_width_vals(bus_width: BusWidth) -> (u8, u32) {
877 } 232 }
878} 233}
879 234
235#[repr(u8)]
236enum BlockSize {
237 Size1 = 0b0000,
238 Size2 = 0b0001,
239 Size4 = 0b0010,
240 Size8 = 0b0011,
241 Size16 = 0b0100,
242 Size32 = 0b0101,
243 Size64 = 0b0110,
244 Size128 = 0b0111,
245 Size256 = 0b1000,
246 Size512 = 0b1001,
247 Size1024 = 0b1010,
248 Size2048 = 0b1011,
249 Size4096 = 0b1100,
250 Size8192 = 0b1101,
251 Size16384 = 0b1110,
252}
253
254const fn block_size(bytes: usize) -> BlockSize {
255 match bytes {
256 1 => BlockSize::Size1,
257 2 => BlockSize::Size2,
258 4 => BlockSize::Size4,
259 8 => BlockSize::Size8,
260 16 => BlockSize::Size16,
261 32 => BlockSize::Size32,
262 64 => BlockSize::Size64,
263 128 => BlockSize::Size128,
264 256 => BlockSize::Size256,
265 512 => BlockSize::Size512,
266 1024 => BlockSize::Size1024,
267 2048 => BlockSize::Size2048,
268 4096 => BlockSize::Size4096,
269 8192 => BlockSize::Size8192,
270 16384 => BlockSize::Size16384,
271 _ => core::unreachable!(),
272 }
273}
274
880/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to 275/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to
881/// `sdmmc_ck` in Hertz. 276/// `sdmmc_ck` in Hertz.
882/// 277///
@@ -904,6 +299,34 @@ struct Transfer<'a> {
904 _dummy: PhantomData<&'a ()>, 299 _dummy: PhantomData<&'a ()>,
905} 300}
906 301
302struct WrappedTransfer<'a> {
303 _transfer: Transfer<'a>,
304 sdmmc: &'a Sdmmc<'a>,
305 defused: bool,
306}
307
308impl<'a> WrappedTransfer<'a> {
309 pub const fn new(_transfer: Transfer<'a>, sdmmc: &'a Sdmmc) -> Self {
310 Self {
311 _transfer,
312 sdmmc,
313 defused: false,
314 }
315 }
316
317 pub fn defuse(&mut self) {
318 self.defused = true;
319 }
320}
321
322impl<'a> Drop for WrappedTransfer<'a> {
323 fn drop(&mut self) {
324 if !self.defused {
325 self.sdmmc.on_drop();
326 }
327 }
328}
329
907#[cfg(all(sdmmc_v1, dma))] 330#[cfg(all(sdmmc_v1, dma))]
908const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions { 331const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions {
909 pburst: crate::dma::Burst::Incr4, 332 pburst: crate::dma::Burst::Incr4,
@@ -1343,15 +766,19 @@ impl<'d> Sdmmc<'d> {
1343 /// 766 ///
1344 /// `buffer` must be valid for the whole transfer and word aligned 767 /// `buffer` must be valid for the whole transfer and word aligned
1345 #[allow(unused_variables)] 768 #[allow(unused_variables)]
1346 fn prepare_datapath_read<'a>(&'a self, buffer: &'a mut [u32], length_bytes: u32, block_size: u8) -> Transfer<'a> { 769 fn prepare_datapath_read<'a>(
1347 assert!(block_size <= 14, "Block size up to 2^14 bytes"); 770 &'a self,
771 buffer: &'a mut [u32],
772 block_size: BlockSize,
773 byte_mode: bool,
774 ) -> WrappedTransfer<'a> {
1348 let regs = self.info.regs; 775 let regs = self.info.regs;
1349 776
1350 // Command AND Data state machines must be idle 777 // Command AND Data state machines must be idle
1351 self.wait_idle(); 778 self.wait_idle();
1352 self.clear_interrupt_flags(); 779 self.clear_interrupt_flags();
1353 780
1354 regs.dlenr().write(|w| w.set_datalength(length_bytes)); 781 regs.dlenr().write(|w| w.set_datalength(size_of_val(buffer) as u32));
1355 782
1356 // SAFETY: No other functions use the dma 783 // SAFETY: No other functions use the dma
1357 #[cfg(sdmmc_v1)] 784 #[cfg(sdmmc_v1)]
@@ -1368,8 +795,12 @@ impl<'d> Sdmmc<'d> {
1368 } 795 }
1369 }; 796 };
1370 797
798 #[cfg(sdmmc_v2)]
799 let byte_mode = byte_mode as u8;
800
1371 regs.dctrl().modify(|w| { 801 regs.dctrl().modify(|w| {
1372 w.set_dblocksize(block_size); 802 w.set_dtmode(byte_mode);
803 w.set_dblocksize(block_size as u8);
1373 w.set_dtdir(true); 804 w.set_dtdir(true);
1374 #[cfg(sdmmc_v1)] 805 #[cfg(sdmmc_v1)]
1375 { 806 {
@@ -1380,21 +811,25 @@ impl<'d> Sdmmc<'d> {
1380 811
1381 self.enable_interrupts(); 812 self.enable_interrupts();
1382 813
1383 transfer 814 WrappedTransfer::new(transfer, &self)
1384 } 815 }
1385 816
1386 /// # Safety 817 /// # Safety
1387 /// 818 ///
1388 /// `buffer` must be valid for the whole transfer and word aligned 819 /// `buffer` must be valid for the whole transfer and word aligned
1389 fn prepare_datapath_write<'a>(&'a self, buffer: &'a [u32], length_bytes: u32, block_size: u8) -> Transfer<'a> { 820 fn prepare_datapath_write<'a>(
1390 assert!(block_size <= 14, "Block size up to 2^14 bytes"); 821 &'a self,
822 buffer: &'a [u32],
823 block_size: BlockSize,
824 byte_mode: bool,
825 ) -> WrappedTransfer<'a> {
1391 let regs = self.info.regs; 826 let regs = self.info.regs;
1392 827
1393 // Command AND Data state machines must be idle 828 // Command AND Data state machines must be idle
1394 self.wait_idle(); 829 self.wait_idle();
1395 self.clear_interrupt_flags(); 830 self.clear_interrupt_flags();
1396 831
1397 regs.dlenr().write(|w| w.set_datalength(length_bytes)); 832 regs.dlenr().write(|w| w.set_datalength(size_of_val(buffer) as u32));
1398 833
1399 // SAFETY: No other functions use the dma 834 // SAFETY: No other functions use the dma
1400 #[cfg(sdmmc_v1)] 835 #[cfg(sdmmc_v1)]
@@ -1411,8 +846,12 @@ impl<'d> Sdmmc<'d> {
1411 } 846 }
1412 }; 847 };
1413 848
849 #[cfg(sdmmc_v2)]
850 let byte_mode = byte_mode as u8;
851
1414 regs.dctrl().modify(|w| { 852 regs.dctrl().modify(|w| {
1415 w.set_dblocksize(block_size); 853 w.set_dtmode(byte_mode);
854 w.set_dblocksize(block_size as u8);
1416 w.set_dtdir(false); 855 w.set_dtdir(false);
1417 #[cfg(sdmmc_v1)] 856 #[cfg(sdmmc_v1)]
1418 { 857 {
@@ -1423,7 +862,7 @@ impl<'d> Sdmmc<'d> {
1423 862
1424 self.enable_interrupts(); 863 self.enable_interrupts();
1425 864
1426 transfer 865 WrappedTransfer::new(transfer, &self)
1427 } 866 }
1428 867
1429 /// Stops the DMA datapath 868 /// Stops the DMA datapath
@@ -1649,7 +1088,7 @@ impl<'d> Sdmmc<'d> {
1649 /// Wait for a previously started datapath transfer to complete from an interrupt. 1088 /// Wait for a previously started datapath transfer to complete from an interrupt.
1650 #[inline] 1089 #[inline]
1651 #[allow(unused)] 1090 #[allow(unused)]
1652 async fn complete_datapath_transfer(&self, transfer: Transfer<'_>, block: bool) -> Result<(), Error> { 1091 async fn complete_datapath_transfer(&self, mut transfer: WrappedTransfer<'_>, block: bool) -> Result<(), Error> {
1653 let res = poll_fn(|cx| { 1092 let res = poll_fn(|cx| {
1654 // Compiler might not be sufficiently constrained here 1093 // Compiler might not be sufficiently constrained here
1655 // https://github.com/embassy-rs/embassy/issues/4723 1094 // https://github.com/embassy-rs/embassy/issues/4723
@@ -1686,6 +1125,7 @@ impl<'d> Sdmmc<'d> {
1686 self.clear_interrupt_flags(); 1125 self.clear_interrupt_flags();
1687 self.stop_datapath(); 1126 self.stop_datapath();
1688 1127
1128 transfer.defuse();
1689 drop(transfer); 1129 drop(transfer);
1690 1130
1691 res 1131 res
@@ -1800,46 +1240,3 @@ foreach_peripheral!(
1800 } 1240 }
1801 }; 1241 };
1802); 1242);
1803
1804impl<'d, 'e, A: Addressable> block_device_driver::BlockDevice<512> for StorageDevice<'d, 'e, A> {
1805 type Error = Error;
1806 type Align = aligned::A4;
1807
1808 async fn read(
1809 &mut self,
1810 block_address: u32,
1811 buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>],
1812 ) -> Result<(), Self::Error> {
1813 // TODO: I think block_address needs to be adjusted by the partition start offset
1814 if buf.len() == 1 {
1815 let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut crate::sdmmc::DataBlock) };
1816 self.read_block(block_address, block).await?;
1817 } else {
1818 let blocks: &mut [DataBlock] =
1819 unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut DataBlock, buf.len()) };
1820 self.read_blocks(block_address, blocks).await?;
1821 }
1822 Ok(())
1823 }
1824
1825 async fn write(
1826 &mut self,
1827 block_address: u32,
1828 buf: &[aligned::Aligned<Self::Align, [u8; 512]>],
1829 ) -> Result<(), Self::Error> {
1830 // TODO: I think block_address needs to be adjusted by the partition start offset
1831 if buf.len() == 1 {
1832 let block = unsafe { &*(&buf[0] as *const _ as *const crate::sdmmc::DataBlock) };
1833 self.write_block(block_address, block).await?;
1834 } else {
1835 let blocks: &[DataBlock] =
1836 unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const DataBlock, buf.len()) };
1837 self.write_blocks(block_address, blocks).await?;
1838 }
1839 Ok(())
1840 }
1841
1842 async fn size(&mut self) -> Result<u64, Self::Error> {
1843 Ok(self.info.size())
1844 }
1845}
diff --git a/embassy-stm32/src/sdmmc/sd.rs b/embassy-stm32/src/sdmmc/sd.rs
new file mode 100644
index 000000000..6190226b8
--- /dev/null
+++ b/embassy-stm32/src/sdmmc/sd.rs
@@ -0,0 +1,693 @@
1use core::default::Default;
2use core::ops::{Deref, DerefMut};
3
4use sdio_host::emmc::{EMMC, ExtCSD};
5use sdio_host::sd::{BusWidth, CIC, CID, CSD, CardCapacity, CardStatus, CurrentState, OCR, RCA, SCR, SD, SDStatus};
6use sdio_host::{common_cmd, emmc_cmd, sd_cmd};
7
8use crate::sdmmc::{BlockSize, Error, Sdmmc, Signalling, block_size, bus_width_vals, slice8_mut, slice8_ref};
9use crate::time::{Hertz, mhz};
10
11/// Aligned data block for SDMMC transfers.
12///
13/// This is a 512-byte array, aligned to 4 bytes to satisfy DMA requirements.
14#[repr(align(4))]
15#[derive(Debug, Clone, PartialEq, Eq)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17pub struct DataBlock(pub [u32; 128]);
18
19impl DataBlock {
20 /// Create a new DataBlock
21 pub const fn new() -> Self {
22 DataBlock([0u32; 128])
23 }
24}
25
26impl Deref for DataBlock {
27 type Target = [u8; 512];
28
29 fn deref(&self) -> &Self::Target {
30 unwrap!(slice8_ref(&self.0[..]).try_into())
31 }
32}
33
34impl DerefMut for DataBlock {
35 fn deref_mut(&mut self) -> &mut Self::Target {
36 unwrap!(slice8_mut(&mut self.0[..]).try_into())
37 }
38}
39
40/// Command Block buffer for SDMMC command transfers.
41///
42/// This is a 16-word array, exposed so that DMA commpatible memory can be used if required.
43#[derive(Debug, Clone, PartialEq, Eq)]
44#[cfg_attr(feature = "defmt", derive(defmt::Format))]
45pub struct CmdBlock(pub [u32; 16]);
46
47impl CmdBlock {
48 /// Creates a new instance of CmdBlock
49 pub const fn new() -> Self {
50 Self([0u32; 16])
51 }
52}
53
54impl Deref for CmdBlock {
55 type Target = [u32; 16];
56
57 fn deref(&self) -> &Self::Target {
58 &self.0
59 }
60}
61
62impl DerefMut for CmdBlock {
63 fn deref_mut(&mut self) -> &mut Self::Target {
64 &mut self.0
65 }
66}
67
68/// Represents either an SD or EMMC card
69pub trait Addressable: Sized + Clone {
70 /// Associated type
71 type Ext;
72
73 /// Get this peripheral's address on the SDMMC bus
74 fn get_address(&self) -> u16;
75
76 /// Is this a standard or high capacity peripheral?
77 fn get_capacity(&self) -> CardCapacity;
78
79 /// Size in bytes
80 fn size(&self) -> u64;
81}
82
83/// Storage Device
84pub struct StorageDevice<'a, 'b, T: Addressable> {
85 info: T,
86 /// Inner member
87 pub sdmmc: &'a mut Sdmmc<'b>,
88}
89
90/// Card Storage Device
91impl<'a, 'b> StorageDevice<'a, 'b, Card> {
92 /// Create a new SD card
93 pub async fn new_sd_card(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> {
94 let mut s = Self {
95 info: Card::default(),
96 sdmmc,
97 };
98
99 s.acquire(cmd_block, freq).await?;
100
101 Ok(s)
102 }
103
104 /// Initializes the card into a known state (or at least tries to).
105 async fn acquire(&mut self, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<(), Error> {
106 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
107 let regs = self.sdmmc.info.regs;
108
109 let _bus_width = match self.sdmmc.bus_width() {
110 BusWidth::Eight => return Err(Error::BusWidth),
111 bus_width => bus_width,
112 };
113
114 // While the SD/SDIO card or eMMC is in identification mode,
115 // the SDMMC_CK frequency must be no more than 400 kHz.
116 self.sdmmc.init_idle()?;
117
118 // Check if cards supports CMD8 (with pattern)
119 self.sdmmc.cmd(sd_cmd::send_if_cond(1, 0xAA), false)?;
120 let cic = CIC::from(regs.respr(0).read().cardstatus());
121
122 if cic.pattern() != 0xAA {
123 return Err(Error::UnsupportedCardVersion);
124 }
125
126 if cic.voltage_accepted() & 1 == 0 {
127 return Err(Error::UnsupportedVoltage);
128 }
129
130 let ocr = loop {
131 // Signal that next command is a app command
132 self.sdmmc.cmd(common_cmd::app_cmd(0), false)?; // CMD55
133
134 // 3.2-3.3V
135 let voltage_window = 1 << 5;
136 // Initialize card
137 match self
138 .sdmmc
139 .cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window), false)
140 {
141 // ACMD41
142 Ok(_) => (),
143 Err(Error::Crc) => (),
144 Err(err) => return Err(err),
145 }
146
147 let ocr: OCR<SD> = regs.respr(0).read().cardstatus().into();
148 if !ocr.is_busy() {
149 // Power up done
150 break ocr;
151 }
152 };
153
154 if ocr.high_capacity() {
155 // Card is SDHC or SDXC or SDUC
156 self.info.card_type = CardCapacity::HighCapacity;
157 } else {
158 self.info.card_type = CardCapacity::StandardCapacity;
159 }
160 self.info.ocr = ocr;
161
162 self.info.cid = self.sdmmc.get_cid()?.into();
163
164 self.sdmmc.cmd(sd_cmd::send_relative_address(), false)?;
165 let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus());
166 self.info.rca = rca.address();
167
168 self.info.csd = self.sdmmc.get_csd(self.info.get_address())?.into();
169 self.sdmmc.select_card(Some(self.info.get_address()))?;
170
171 self.info.scr = self.get_scr(cmd_block).await?;
172
173 let (bus_width, acmd_arg) = if !self.info.scr.bus_width_four() {
174 (BusWidth::One, 0)
175 } else {
176 (BusWidth::Four, 2)
177 };
178
179 self.sdmmc.cmd(common_cmd::app_cmd(self.info.rca), false)?;
180 self.sdmmc.cmd(sd_cmd::cmd6(acmd_arg), false)?;
181
182 self.sdmmc.clkcr_set_clkdiv(freq.clamp(mhz(0), mhz(25)), bus_width)?;
183
184 // Read status
185 self.info.status = self.read_sd_status(cmd_block).await?;
186
187 if freq > mhz(25) {
188 // Switch to SDR25
189 self.sdmmc.signalling = self.switch_signalling_mode(cmd_block, Signalling::SDR25).await?;
190
191 if self.sdmmc.signalling == Signalling::SDR25 {
192 // Set final clock frequency
193 self.sdmmc.clkcr_set_clkdiv(freq, bus_width)?;
194
195 if self.sdmmc.read_status(&self.info)?.state() != CurrentState::Transfer {
196 return Err(Error::SignalingSwitchFailed);
197 }
198 }
199
200 // Read status after signalling change
201 self.read_sd_status(cmd_block).await?;
202 }
203
204 Ok(())
205 }
206
207 /// Switch mode using CMD6.
208 ///
209 /// Attempt to set a new signalling mode. The selected
210 /// signalling mode is returned. Expects the current clock
211 /// frequency to be > 12.5MHz.
212 ///
213 /// SD only.
214 async fn switch_signalling_mode(
215 &self,
216 cmd_block: &mut CmdBlock,
217 signalling: Signalling,
218 ) -> Result<Signalling, Error> {
219 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
220 // necessary"
221
222 let set_function = 0x8000_0000
223 | match signalling {
224 // See PLSS v7_10 Table 4-11
225 Signalling::DDR50 => 0xFF_FF04,
226 Signalling::SDR104 => 0xFF_1F03,
227 Signalling::SDR50 => 0xFF_1F02,
228 Signalling::SDR25 => 0xFF_FF01,
229 Signalling::SDR12 => 0xFF_FF00,
230 };
231
232 let buffer = &mut cmd_block.0[..64 / 4];
233
234 let transfer = self
235 .sdmmc
236 .prepare_datapath_read(buffer, block_size(size_of_val(buffer)), false);
237
238 self.sdmmc.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
239
240 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
241
242 // Host is allowed to use the new functions at least 8
243 // clocks after the end of the switch command
244 // transaction. We know the current clock period is < 80ns,
245 // so a total delay of 640ns is required here
246 for _ in 0..300 {
247 cortex_m::asm::nop();
248 }
249
250 // Function Selection of Function Group 1
251 let selection = (u32::from_be(cmd_block[4]) >> 24) & 0xF;
252
253 match selection {
254 0 => Ok(Signalling::SDR12),
255 1 => Ok(Signalling::SDR25),
256 2 => Ok(Signalling::SDR50),
257 3 => Ok(Signalling::SDR104),
258 4 => Ok(Signalling::DDR50),
259 _ => Err(Error::UnsupportedCardType),
260 }
261 }
262
263 /// Reads the SCR register.
264 ///
265 /// SD only.
266 async fn get_scr(&self, cmd_block: &mut CmdBlock) -> Result<SCR, Error> {
267 // Read the 64-bit SCR register
268 self.sdmmc.cmd(common_cmd::set_block_length(8), false)?; // CMD16
269 self.sdmmc.cmd(common_cmd::app_cmd(self.info.rca), false)?;
270
271 let scr = &mut cmd_block.0[..2];
272
273 // Arm `OnDrop` after the buffer, so it will be dropped first
274
275 let transfer = self.sdmmc.prepare_datapath_read(scr, BlockSize::Size8, false);
276 self.sdmmc.cmd(sd_cmd::send_scr(), true)?;
277
278 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
279
280 Ok(SCR(u64::from_be_bytes(unwrap!(slice8_mut(scr).try_into()))))
281 }
282
283 /// Reads the SD Status (ACMD13)
284 ///
285 /// SD only.
286 async fn read_sd_status(&self, cmd_block: &mut CmdBlock) -> Result<SDStatus, Error> {
287 let rca = self.info.rca;
288
289 self.sdmmc.cmd(common_cmd::set_block_length(64), false)?; // CMD16
290 self.sdmmc.cmd(common_cmd::app_cmd(rca), false)?; // APP
291
292 let buffer = &mut cmd_block.as_mut()[..64 / 4];
293
294 let transfer = self
295 .sdmmc
296 .prepare_datapath_read(buffer, block_size(size_of_val(buffer)), false);
297 self.sdmmc.cmd(sd_cmd::sd_status(), true)?;
298
299 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
300
301 for byte in cmd_block.iter_mut() {
302 *byte = u32::from_be(*byte);
303 }
304
305 Ok(cmd_block.0.into())
306 }
307}
308
309/// Emmc storage device
310impl<'a, 'b> StorageDevice<'a, 'b, Emmc> {
311 /// Create a new EMMC card
312 pub async fn new_emmc(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> {
313 let mut s = Self {
314 info: Emmc::default(),
315 sdmmc,
316 };
317
318 s.acquire(cmd_block, freq).await?;
319
320 Ok(s)
321 }
322
323 async fn acquire(&mut self, _cmd_block: &mut CmdBlock, freq: Hertz) -> Result<(), Error> {
324 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
325 let regs = self.sdmmc.info.regs;
326
327 let bus_width = self.sdmmc.bus_width();
328
329 // While the SD/SDIO card or eMMC is in identification mode,
330 // the SDMMC_CK frequency must be no more than 400 kHz.
331 self.sdmmc.init_idle()?;
332
333 let ocr = loop {
334 let high_voltage = 0b0 << 7;
335 let access_mode = 0b10 << 29;
336 let op_cond = high_voltage | access_mode | 0b1_1111_1111 << 15;
337 // Initialize card
338 match self.sdmmc.cmd(emmc_cmd::send_op_cond(op_cond), false) {
339 Ok(_) => (),
340 Err(Error::Crc) => (),
341 Err(err) => return Err(err),
342 }
343 let ocr: OCR<EMMC> = regs.respr(0).read().cardstatus().into();
344 if !ocr.is_busy() {
345 // Power up done
346 break ocr;
347 }
348 };
349
350 self.info.capacity = if ocr.access_mode() == 0b10 {
351 // Card is SDHC or SDXC or SDUC
352 CardCapacity::HighCapacity
353 } else {
354 CardCapacity::StandardCapacity
355 };
356 self.info.ocr = ocr;
357
358 self.info.cid = self.sdmmc.get_cid()?.into();
359
360 self.info.rca = 1u16.into();
361 self.sdmmc
362 .cmd(emmc_cmd::assign_relative_address(self.info.rca), false)?;
363
364 self.info.csd = self.sdmmc.get_csd(self.info.get_address())?.into();
365 self.sdmmc.select_card(Some(self.info.get_address()))?;
366
367 let (widbus, _) = bus_width_vals(bus_width);
368
369 // Write bus width to ExtCSD byte 183
370 self.sdmmc.cmd(
371 emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus),
372 false,
373 )?;
374
375 // Wait for ready after R1b response
376 loop {
377 let status = self.sdmmc.read_status(&self.info)?;
378
379 if status.ready_for_data() {
380 break;
381 }
382 }
383
384 self.sdmmc.clkcr_set_clkdiv(freq.clamp(mhz(0), mhz(25)), bus_width)?;
385 self.info.ext_csd = self.read_ext_csd().await?;
386
387 Ok(())
388 }
389
390 /// Gets the EXT_CSD register.
391 ///
392 /// eMMC only.
393 async fn read_ext_csd(&self) -> Result<ExtCSD, Error> {
394 // Note: cmd_block can't be used because ExtCSD is too long to fit.
395 let mut data_block = DataBlock::new();
396
397 self.sdmmc
398 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)
399 .unwrap(); // CMD16
400
401 let transfer = self
402 .sdmmc
403 .prepare_datapath_read(&mut data_block.0, block_size(size_of::<DataBlock>()), false);
404 self.sdmmc.cmd(emmc_cmd::send_ext_csd(), true)?;
405
406 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
407
408 Ok(data_block.0.into())
409 }
410}
411
412/// Card or Emmc storage device
413impl<'a, 'b, A: Addressable> StorageDevice<'a, 'b, A> {
414 /// Write a block
415 pub fn card(&self) -> A {
416 self.info.clone()
417 }
418
419 /// Read a data block.
420 #[inline]
421 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
422 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
423 let card_capacity = self.info.get_capacity();
424
425 // Always read 1 block of 512 bytes
426 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
427 let address = match card_capacity {
428 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
429 _ => block_idx,
430 };
431 self.sdmmc
432 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
433
434 let transfer = self
435 .sdmmc
436 .prepare_datapath_read(&mut buffer.0, block_size(size_of::<DataBlock>()), false);
437 self.sdmmc.cmd(common_cmd::read_single_block(address), true)?;
438
439 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
440
441 Ok(())
442 }
443
444 /// Read multiple data blocks.
445 #[inline]
446 pub async fn read_blocks(&mut self, block_idx: u32, blocks: &mut [DataBlock]) -> Result<(), Error> {
447 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
448 let card_capacity = self.info.get_capacity();
449
450 // NOTE(unsafe) reinterpret buffer as &mut [u32]
451 let buffer = unsafe {
452 core::slice::from_raw_parts_mut(
453 blocks.as_mut_ptr() as *mut u32,
454 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
455 )
456 };
457
458 // Always read 1 block of 512 bytes
459 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
460 let address = match card_capacity {
461 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
462 _ => block_idx,
463 };
464 self.sdmmc
465 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
466
467 let transfer = self
468 .sdmmc
469 .prepare_datapath_read(buffer, block_size(size_of::<DataBlock>()), false);
470 self.sdmmc.cmd(common_cmd::read_multiple_blocks(address), true)?;
471
472 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
473
474 self.sdmmc.cmd(common_cmd::stop_transmission(), false)?; // CMD12
475 self.sdmmc.clear_interrupt_flags();
476
477 Ok(())
478 }
479
480 /// Write a data block.
481 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error>
482 where
483 CardStatus<A::Ext>: From<u32>,
484 {
485 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
486
487 // Always read 1 block of 512 bytes
488 // cards are byte addressed hence the blockaddress is in multiples of 512 bytes
489 let address = match self.info.get_capacity() {
490 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
491 _ => block_idx,
492 };
493 self.sdmmc
494 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
495
496 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
497 #[cfg(sdmmc_v1)]
498 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?;
499
500 let transfer = self
501 .sdmmc
502 .prepare_datapath_write(&buffer.0, block_size(size_of::<DataBlock>()), false);
503
504 #[cfg(sdmmc_v2)]
505 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?;
506
507 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
508
509 // TODO: Make this configurable
510 let mut timeout: u32 = 0x00FF_FFFF;
511
512 while timeout > 0 {
513 let ready_for_data = self.sdmmc.read_status(&self.info)?.ready_for_data();
514 if ready_for_data {
515 return Ok(());
516 }
517 timeout -= 1;
518 }
519
520 Err(Error::SoftwareTimeout)
521 }
522
523 /// Write multiple data blocks.
524 pub async fn write_blocks(&mut self, block_idx: u32, blocks: &[DataBlock]) -> Result<(), Error>
525 where
526 CardStatus<A::Ext>: From<u32>,
527 {
528 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
529
530 // NOTE(unsafe) reinterpret buffer as &[u32]
531 let buffer = unsafe {
532 core::slice::from_raw_parts(
533 blocks.as_ptr() as *const u32,
534 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
535 )
536 };
537 // Always read 1 block of 512 bytes
538 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
539 let address = match self.info.get_capacity() {
540 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
541 _ => block_idx,
542 };
543
544 self.sdmmc
545 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
546
547 #[cfg(sdmmc_v1)]
548 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
549
550 // Setup write command
551 let transfer = self
552 .sdmmc
553 .prepare_datapath_write(buffer, block_size(size_of::<DataBlock>()), false);
554
555 #[cfg(sdmmc_v2)]
556 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
557
558 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
559
560 self.sdmmc.cmd(common_cmd::stop_transmission(), false)?; // CMD12
561 self.sdmmc.clear_interrupt_flags();
562
563 // TODO: Make this configurable
564 let mut timeout: u32 = 0x00FF_FFFF;
565
566 while timeout > 0 {
567 let ready_for_data = self.sdmmc.read_status(&self.info)?.ready_for_data();
568
569 if ready_for_data {
570 return Ok(());
571 }
572 timeout -= 1;
573 }
574 Err(Error::SoftwareTimeout)
575 }
576}
577
578#[derive(Clone, Copy, Debug, Default)]
579/// SD Card
580pub struct Card {
581 /// The type of this card
582 pub card_type: CardCapacity,
583 /// Operation Conditions Register
584 pub ocr: OCR<SD>,
585 /// Relative Card Address
586 pub rca: u16,
587 /// Card ID
588 pub cid: CID<SD>,
589 /// Card Specific Data
590 pub csd: CSD<SD>,
591 /// SD CARD Configuration Register
592 pub scr: SCR,
593 /// SD Status
594 pub status: SDStatus,
595}
596
597impl Addressable for Card {
598 type Ext = SD;
599
600 /// Get this peripheral's address on the SDMMC bus
601 fn get_address(&self) -> u16 {
602 self.rca
603 }
604
605 /// Is this a standard or high capacity peripheral?
606 fn get_capacity(&self) -> CardCapacity {
607 self.card_type
608 }
609
610 /// Size in bytes
611 fn size(&self) -> u64 {
612 u64::from(self.csd.block_count()) * 512
613 }
614}
615
616#[derive(Clone, Copy, Debug, Default)]
617/// eMMC storage
618pub struct Emmc {
619 /// The capacity of this card
620 pub capacity: CardCapacity,
621 /// Operation Conditions Register
622 pub ocr: OCR<EMMC>,
623 /// Relative Card Address
624 pub rca: u16,
625 /// Card ID
626 pub cid: CID<EMMC>,
627 /// Card Specific Data
628 pub csd: CSD<EMMC>,
629 /// Extended Card Specific Data
630 pub ext_csd: ExtCSD,
631}
632
633impl Addressable for Emmc {
634 type Ext = EMMC;
635
636 /// Get this peripheral's address on the SDMMC bus
637 fn get_address(&self) -> u16 {
638 self.rca
639 }
640
641 /// Is this a standard or high capacity peripheral?
642 fn get_capacity(&self) -> CardCapacity {
643 self.capacity
644 }
645
646 /// Size in bytes
647 fn size(&self) -> u64 {
648 u64::from(self.ext_csd.sector_count()) * 512
649 }
650}
651
652impl<'d, 'e, A: Addressable> block_device_driver::BlockDevice<512> for StorageDevice<'d, 'e, A> {
653 type Error = Error;
654 type Align = aligned::A4;
655
656 async fn read(
657 &mut self,
658 block_address: u32,
659 buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>],
660 ) -> Result<(), Self::Error> {
661 // TODO: I think block_address needs to be adjusted by the partition start offset
662 if buf.len() == 1 {
663 let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut DataBlock) };
664 self.read_block(block_address, block).await?;
665 } else {
666 let blocks: &mut [DataBlock] =
667 unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut DataBlock, buf.len()) };
668 self.read_blocks(block_address, blocks).await?;
669 }
670 Ok(())
671 }
672
673 async fn write(
674 &mut self,
675 block_address: u32,
676 buf: &[aligned::Aligned<Self::Align, [u8; 512]>],
677 ) -> Result<(), Self::Error> {
678 // TODO: I think block_address needs to be adjusted by the partition start offset
679 if buf.len() == 1 {
680 let block = unsafe { &*(&buf[0] as *const _ as *const DataBlock) };
681 self.write_block(block_address, block).await?;
682 } else {
683 let blocks: &[DataBlock] =
684 unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const DataBlock, buf.len()) };
685 self.write_blocks(block_address, blocks).await?;
686 }
687 Ok(())
688 }
689
690 async fn size(&mut self) -> Result<u64, Self::Error> {
691 Ok(self.info.size())
692 }
693}
diff --git a/embassy-stm32/src/sdmmc/sdio.rs b/embassy-stm32/src/sdmmc/sdio.rs
new file mode 100644
index 000000000..1412b21fc
--- /dev/null
+++ b/embassy-stm32/src/sdmmc/sdio.rs
@@ -0,0 +1,177 @@
1use core::ops::{Deref, DerefMut};
2
3use sdio_host::common_cmd::{R1, Rz, cmd};
4use sdio_host::sd::BusWidth;
5use sdio_host::sd_cmd;
6
7use crate::sdmmc::{Error, Sdmmc, block_size, slice8_mut, slice8_ref};
8use crate::time::Hertz;
9
10/// Aligned data block for SDMMC transfers.
11///
12/// This is a 64-byte array, aligned to 4 bytes to satisfy DMA requirements.
13#[repr(align(4))]
14#[derive(Debug, Clone, PartialEq, Eq)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub struct DataBlock(pub [u32; 16]);
17
18impl DataBlock {
19 /// Create a new DataBlock
20 pub const fn new() -> Self {
21 DataBlock([0u32; 16])
22 }
23}
24
25impl Deref for DataBlock {
26 type Target = [u8; 64];
27
28 fn deref(&self) -> &Self::Target {
29 unwrap!(slice8_ref(&self.0[..]).try_into())
30 }
31}
32
33impl DerefMut for DataBlock {
34 fn deref_mut(&mut self) -> &mut Self::Target {
35 unwrap!(slice8_mut(&mut self.0[..]).try_into())
36 }
37}
38
39/// Storage Device
40pub struct SerialDataInterface<'a, 'b> {
41 /// Inner member
42 pub sdmmc: &'a mut Sdmmc<'b>,
43}
44
45/// Card Storage Device
46impl<'a, 'b> SerialDataInterface<'a, 'b> {
47 /// Create a new SD card
48 pub async fn new(sdmmc: &'a mut Sdmmc<'b>, freq: Hertz) -> Result<Self, Error> {
49 let mut s = Self { sdmmc };
50
51 s.acquire(freq).await?;
52
53 Ok(s)
54 }
55
56 /// Initializes the card into a known state (or at least tries to).
57 async fn acquire(&mut self, _freq: Hertz) -> Result<(), Error> {
58 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
59
60 let _bus_width = match self.sdmmc.bus_width() {
61 BusWidth::Eight => return Err(Error::BusWidth),
62 bus_width => bus_width,
63 };
64
65 // While the SD/SDIO card or eMMC is in identification mode,
66 // the SDMMC_CK frequency must be no more than 400 kHz.
67 self.sdmmc.init_idle()?;
68
69 self.sdmmc.cmd(cmd::<Rz>(5, 0), false)?;
70
71 // Get RCA
72 let rca = self.sdmmc.cmd(sd_cmd::send_relative_address(), false)?;
73
74 // Select the card with RCA
75 self.sdmmc.select_card(Some(rca.try_into().unwrap()))?;
76
77 Ok(())
78 }
79
80 /// Set the bus to the 4-bit high-speed frequency
81 pub fn set_bus_to_high_speed(&mut self, frequency: Hertz) -> Result<(), Error> {
82 self.sdmmc.clkcr_set_clkdiv(frequency, BusWidth::Four)?;
83
84 Ok(())
85 }
86
87 /// Run cmd52
88 pub async fn cmd52(&mut self, arg: u32) -> Result<u32, Error> {
89 self.sdmmc.cmd(cmd::<R1>(52, arg), false)
90 }
91
92 /// Read in block mode using cmd53
93 pub async fn cmd53_block_read(&mut self, arg: u32, blocks: &mut [DataBlock]) -> Result<(), Error> {
94 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
95
96 // NOTE(unsafe) reinterpret buffer as &mut [u32]
97 let buffer = unsafe {
98 core::slice::from_raw_parts_mut(
99 blocks.as_mut_ptr() as *mut u32,
100 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
101 )
102 };
103
104 let transfer = self
105 .sdmmc
106 .prepare_datapath_read(buffer, block_size(size_of::<DataBlock>()), false);
107 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
108
109 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
110 self.sdmmc.clear_interrupt_flags();
111
112 Ok(())
113 }
114
115 /// Read in multibyte mode using cmd53
116 pub async fn cmd53_byte_read(&mut self, arg: u32, buffer: &mut [u32]) -> Result<(), Error> {
117 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
118
119 let transfer = self
120 .sdmmc
121 .prepare_datapath_read(buffer, block_size(size_of::<DataBlock>()), true);
122 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
123
124 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
125 self.sdmmc.clear_interrupt_flags();
126
127 Ok(())
128 }
129
130 /// Write in block mode using cmd53
131 pub async fn cmd53_block_write(&mut self, arg: u32, blocks: &[DataBlock]) -> Result<(), Error> {
132 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
133
134 // NOTE(unsafe) reinterpret buffer as &mut [u32]
135 let buffer = unsafe {
136 core::slice::from_raw_parts_mut(
137 blocks.as_ptr() as *mut u32,
138 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
139 )
140 };
141
142 #[cfg(sdmmc_v1)]
143 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
144
145 let transfer = self
146 .sdmmc
147 .prepare_datapath_read(buffer, block_size(size_of::<DataBlock>()), false);
148
149 #[cfg(sdmmc_v2)]
150 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
151
152 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
153 self.sdmmc.clear_interrupt_flags();
154
155 Ok(())
156 }
157
158 /// Write in multibyte mode using cmd53
159 pub async fn cmd53_byte_write(&mut self, arg: u32, buffer: &[u32]) -> Result<(), Error> {
160 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
161
162 #[cfg(sdmmc_v1)]
163 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
164
165 let transfer = self
166 .sdmmc
167 .prepare_datapath_write(buffer, block_size(size_of::<DataBlock>()), true);
168
169 #[cfg(sdmmc_v2)]
170 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
171
172 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
173 self.sdmmc.clear_interrupt_flags();
174
175 Ok(())
176 }
177}