aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/sdmmc
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/sdmmc')
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs1389
-rw-r--r--embassy-stm32/src/sdmmc/sd.rs699
-rw-r--r--embassy-stm32/src/sdmmc/sdio.rs178
3 files changed, 1274 insertions, 992 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index ccbd16cbf..cfe18ef52 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -4,16 +4,16 @@
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}; 7use core::slice;
8use core::task::Poll; 8use core::task::Poll;
9 9
10use embassy_hal_internal::drop::OnDrop; 10use aligned::{A4, Aligned};
11use embassy_hal_internal::{Peri, PeripheralType}; 11use embassy_hal_internal::{Peri, PeripheralType};
12use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
13use sdio_host::common_cmd::{self, Resp, ResponseLen}; 13use sdio_host::Cmd;
14use sdio_host::emmc::{ExtCSD, EMMC}; 14use sdio_host::common_cmd::{self, R1, R2, R3, Resp, ResponseLen, Rz};
15use sdio_host::sd::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CIC, CID, CSD, OCR, RCA, SCR, SD}; 15use sdio_host::sd::{BusWidth, CardStatus};
16use sdio_host::{emmc_cmd, sd_cmd, Cmd}; 16use sdio_host::sd_cmd::{R6, R7};
17 17
18#[cfg(sdmmc_v1)] 18#[cfg(sdmmc_v1)]
19use crate::dma::ChannelAndRequest; 19use crate::dma::ChannelAndRequest;
@@ -22,37 +22,27 @@ use crate::gpio::Pull;
22use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; 22use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed};
23use crate::interrupt::typelevel::Interrupt; 23use crate::interrupt::typelevel::Interrupt;
24use crate::pac::sdmmc::Sdmmc as RegBlock; 24use crate::pac::sdmmc::Sdmmc as RegBlock;
25use crate::rcc::{self, RccPeripheral}; 25use crate::rcc::{self, RccInfo, RccPeripheral, SealedRccPeripheral};
26use crate::sdmmc::sd::Addressable;
26use crate::time::Hertz; 27use crate::time::Hertz;
27use crate::{interrupt, peripherals}; 28use crate::{interrupt, peripherals};
28 29
30/// Module for SD and EMMC cards
31pub mod sd;
32
33/// Module for SDIO interface
34pub mod sdio;
35
29/// Interrupt handler. 36/// Interrupt handler.
30pub struct InterruptHandler<T: Instance> { 37pub struct InterruptHandler<T: Instance> {
31 _phantom: PhantomData<T>, 38 _phantom: PhantomData<T>,
32} 39}
33 40
34impl<T: Instance> InterruptHandler<T> {
35 fn enable_interrupts() {
36 let regs = T::regs();
37 regs.maskr().write(|w| {
38 w.set_dcrcfailie(true);
39 w.set_dtimeoutie(true);
40 w.set_dataendie(true);
41 w.set_dbckendie(true);
42
43 #[cfg(sdmmc_v1)]
44 w.set_stbiterre(true);
45 #[cfg(sdmmc_v2)]
46 w.set_dabortie(true);
47 });
48 }
49}
50
51impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { 41impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
52 unsafe fn on_interrupt() { 42 unsafe fn on_interrupt() {
53 T::state().wake(); 43 T::state().waker.wake();
54 let status = T::regs().star().read(); 44 let status = T::info().regs.star().read();
55 T::regs().maskr().modify(|w| { 45 T::info().regs.maskr().modify(|w| {
56 if status.dcrcfail() { 46 if status.dcrcfail() {
57 w.set_dcrcfailie(false) 47 w.set_dcrcfailie(false)
58 } 48 }
@@ -77,6 +67,57 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
77 } 67 }
78} 68}
79 69
70struct U128(pub u128);
71
72trait TypedResp: Resp {
73 type Word: From<U128>;
74}
75
76impl From<U128> for () {
77 fn from(value: U128) -> Self {
78 match value.0 {
79 0 => (),
80 _ => unreachable!(),
81 }
82 }
83}
84
85impl From<U128> for u32 {
86 fn from(value: U128) -> Self {
87 unwrap!(value.0.try_into())
88 }
89}
90
91impl From<U128> for u128 {
92 fn from(value: U128) -> Self {
93 value.0
94 }
95}
96
97impl TypedResp for Rz {
98 type Word = ();
99}
100
101impl TypedResp for R1 {
102 type Word = u32;
103}
104
105impl TypedResp for R2 {
106 type Word = u128;
107}
108
109impl TypedResp for R3 {
110 type Word = u32;
111}
112
113impl TypedResp for R6 {
114 type Word = u32;
115}
116
117impl TypedResp for R7 {
118 type Word = u32;
119}
120
80/// Frequency used for SD Card initialization. Must be no higher than 400 kHz. 121/// Frequency used for SD Card initialization. Must be no higher than 400 kHz.
81const SD_INIT_FREQ: Hertz = Hertz(400_000); 122const SD_INIT_FREQ: Hertz = Hertz(400_000);
82 123
@@ -99,54 +140,36 @@ impl Default for Signalling {
99 } 140 }
100} 141}
101 142
102/// Aligned data block for SDMMC transfers. 143const fn aligned_mut(x: &mut [u32]) -> &mut Aligned<A4, [u8]> {
103/// 144 let len = x.len() * 4;
104/// This is a 512-byte array, aligned to 4 bytes to satisfy DMA requirements. 145 unsafe { core::mem::transmute(slice::from_raw_parts_mut(x.as_mut_ptr() as *mut u8, len)) }
105#[repr(align(4))]
106#[derive(Debug, Clone, PartialEq, Eq)]
107#[cfg_attr(feature = "defmt", derive(defmt::Format))]
108pub struct DataBlock(pub [u8; 512]);
109
110impl Deref for DataBlock {
111 type Target = [u8; 512];
112
113 fn deref(&self) -> &Self::Target {
114 &self.0
115 }
116} 146}
117 147
118impl DerefMut for DataBlock { 148const fn slice8_mut(x: &mut [u32]) -> &mut [u8] {
119 fn deref_mut(&mut self) -> &mut Self::Target { 149 let len = x.len() * 4;
120 &mut self.0 150 unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as *mut u8, len) }
121 }
122} 151}
123 152
124/// Command Block buffer for SDMMC command transfers. 153#[allow(unused)]
125/// 154const fn slice32_mut(x: &mut Aligned<A4, [u8]>) -> &mut [u32] {
126/// This is a 16-word array, exposed so that DMA commpatible memory can be used if required. 155 let len = (size_of_val(x) + 4 - 1) / 4;
127#[derive(Debug, Clone, PartialEq, Eq)] 156 unsafe { slice::from_raw_parts_mut(x as *mut Aligned<A4, [u8]> as *mut u32, len) }
128#[cfg_attr(feature = "defmt", derive(defmt::Format))]
129pub struct CmdBlock(pub [u32; 16]);
130
131impl CmdBlock {
132 /// Creates a new instance of CmdBlock
133 pub const fn new() -> Self {
134 Self([0u32; 16])
135 }
136} 157}
137 158
138impl Deref for CmdBlock { 159const fn aligned_ref(x: &[u32]) -> &Aligned<A4, [u8]> {
139 type Target = [u32; 16]; 160 let len = x.len() * 4;
161 unsafe { core::mem::transmute(slice::from_raw_parts(x.as_ptr() as *const u8, len)) }
162}
140 163
141 fn deref(&self) -> &Self::Target { 164const fn slice8_ref(x: &[u32]) -> &[u8] {
142 &self.0 165 let len = x.len() * 4;
143 } 166 unsafe { slice::from_raw_parts(x.as_ptr() as *const u8, len) }
144} 167}
145 168
146impl DerefMut for CmdBlock { 169#[allow(unused)]
147 fn deref_mut(&mut self) -> &mut Self::Target { 170const fn slice32_ref(x: &Aligned<A4, [u8]>) -> &[u32] {
148 &mut self.0 171 let len = (size_of_val(x) + 4 - 1) / 4;
149 } 172 unsafe { slice::from_raw_parts(x as *const Aligned<A4, [u8]> as *const u32, len) }
150} 173}
151 174
152/// Errors 175/// Errors
@@ -181,48 +204,17 @@ pub enum Error {
181 StBitErr, 204 StBitErr,
182} 205}
183 206
184#[derive(Clone, Copy, Debug, Default)]
185/// SD Card
186pub struct Card {
187 /// The type of this card
188 pub card_type: CardCapacity,
189 /// Operation Conditions Register
190 pub ocr: OCR<SD>,
191 /// Relative Card Address
192 pub rca: u16,
193 /// Card ID
194 pub cid: CID<SD>,
195 /// Card Specific Data
196 pub csd: CSD<SD>,
197 /// SD CARD Configuration Register
198 pub scr: SCR,
199 /// SD Status
200 pub status: SDStatus,
201}
202
203#[derive(Clone, Copy, Debug, Default)]
204/// eMMC storage
205pub struct Emmc {
206 /// The capacity of this card
207 pub capacity: CardCapacity,
208 /// Operation Conditions Register
209 pub ocr: OCR<EMMC>,
210 /// Relative Card Address
211 pub rca: u16,
212 /// Card ID
213 pub cid: CID<EMMC>,
214 /// Card Specific Data
215 pub csd: CSD<EMMC>,
216 /// Extended Card Specific Data
217 pub ext_csd: ExtCSD,
218}
219
220#[repr(u8)] 207#[repr(u8)]
221enum PowerCtrl { 208enum PowerCtrl {
222 Off = 0b00, 209 Off = 0b00,
223 On = 0b11, 210 On = 0b11,
224} 211}
225 212
213enum DatapathMode {
214 Block(BlockSize),
215 Byte,
216}
217
226fn get_waitresp_val(rlen: ResponseLen) -> u8 { 218fn get_waitresp_val(rlen: ResponseLen) -> u8 {
227 match rlen { 219 match rlen {
228 common_cmd::ResponseLen::Zero => 0, 220 common_cmd::ResponseLen::Zero => 0,
@@ -259,6 +251,55 @@ fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u8, Hertz), Error> {
259 Ok((false, clk_div, clk_f)) 251 Ok((false, clk_div, clk_f))
260} 252}
261 253
254fn bus_width_vals(bus_width: BusWidth) -> (u8, u32) {
255 match bus_width {
256 BusWidth::One => (0, 1u32),
257 BusWidth::Four => (1, 4u32),
258 BusWidth::Eight => (2, 8u32),
259 _ => panic!("Invalid Bus Width"),
260 }
261}
262
263#[repr(u8)]
264enum BlockSize {
265 Size1 = 0b0000,
266 Size2 = 0b0001,
267 Size4 = 0b0010,
268 Size8 = 0b0011,
269 Size16 = 0b0100,
270 Size32 = 0b0101,
271 Size64 = 0b0110,
272 Size128 = 0b0111,
273 Size256 = 0b1000,
274 Size512 = 0b1001,
275 Size1024 = 0b1010,
276 Size2048 = 0b1011,
277 Size4096 = 0b1100,
278 Size8192 = 0b1101,
279 Size16384 = 0b1110,
280}
281
282const fn block_size(bytes: usize) -> BlockSize {
283 match bytes {
284 1 => BlockSize::Size1,
285 2 => BlockSize::Size2,
286 4 => BlockSize::Size4,
287 8 => BlockSize::Size8,
288 16 => BlockSize::Size16,
289 32 => BlockSize::Size32,
290 64 => BlockSize::Size64,
291 128 => BlockSize::Size128,
292 256 => BlockSize::Size256,
293 512 => BlockSize::Size512,
294 1024 => BlockSize::Size1024,
295 2048 => BlockSize::Size2048,
296 4096 => BlockSize::Size4096,
297 8192 => BlockSize::Size8192,
298 16384 => BlockSize::Size16384,
299 _ => core::unreachable!(),
300 }
301}
302
262/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to 303/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to
263/// `sdmmc_ck` in Hertz. 304/// `sdmmc_ck` in Hertz.
264/// 305///
@@ -286,6 +327,34 @@ struct Transfer<'a> {
286 _dummy: PhantomData<&'a ()>, 327 _dummy: PhantomData<&'a ()>,
287} 328}
288 329
330struct WrappedTransfer<'a> {
331 _transfer: Transfer<'a>,
332 sdmmc: &'a Sdmmc<'a>,
333 defused: bool,
334}
335
336impl<'a> WrappedTransfer<'a> {
337 pub const fn new(_transfer: Transfer<'a>, sdmmc: &'a Sdmmc) -> Self {
338 Self {
339 _transfer,
340 sdmmc,
341 defused: false,
342 }
343 }
344
345 pub fn defuse(&mut self) {
346 self.defused = true;
347 }
348}
349
350impl<'a> Drop for WrappedTransfer<'a> {
351 fn drop(&mut self) {
352 if !self.defused {
353 self.sdmmc.on_drop();
354 }
355 }
356}
357
289#[cfg(all(sdmmc_v1, dma))] 358#[cfg(all(sdmmc_v1, dma))]
290const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions { 359const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions {
291 pburst: crate::dma::Burst::Incr4, 360 pburst: crate::dma::Burst::Incr4,
@@ -323,64 +392,11 @@ impl Default for Config {
323 } 392 }
324} 393}
325 394
326/// Peripheral that can be operated over SDMMC
327#[derive(Clone, Copy, Debug)]
328pub enum SdmmcPeripheral {
329 /// SD Card
330 SdCard(Card),
331 /// eMMC memory
332 Emmc(Emmc),
333}
334
335impl SdmmcPeripheral {
336 /// Get this peripheral's address on the SDMMC bus
337 fn get_address(&self) -> u16 {
338 match self {
339 Self::SdCard(c) => c.rca,
340 Self::Emmc(e) => e.rca,
341 }
342 }
343 /// Is this a standard or high capacity peripheral?
344 fn get_capacity(&self) -> CardCapacity {
345 match self {
346 Self::SdCard(c) => c.card_type,
347 Self::Emmc(e) => e.capacity,
348 }
349 }
350 /// Size in bytes
351 fn size(&self) -> u64 {
352 match self {
353 // SDHC / SDXC / SDUC
354 Self::SdCard(c) => u64::from(c.csd.block_count()) * 512,
355 // capacity > 2GB
356 Self::Emmc(e) => u64::from(e.ext_csd.sector_count()) * 512,
357 }
358 }
359
360 /// Get a mutable reference to the SD Card.
361 ///
362 /// Panics if there is another peripheral instead.
363 fn get_sd_card(&mut self) -> &mut Card {
364 match *self {
365 Self::SdCard(ref mut c) => c,
366 _ => unreachable!("SD only"),
367 }
368 }
369
370 /// Get a mutable reference to the eMMC.
371 ///
372 /// Panics if there is another peripheral instead.
373 fn get_emmc(&mut self) -> &mut Emmc {
374 match *self {
375 Self::Emmc(ref mut e) => e,
376 _ => unreachable!("eMMC only"),
377 }
378 }
379}
380
381/// Sdmmc device 395/// Sdmmc device
382pub struct Sdmmc<'d, T: Instance> { 396pub struct Sdmmc<'d> {
383 _peri: Peri<'d, T>, 397 info: &'static Info,
398 state: &'static State,
399 ker_clk: Hertz,
384 #[cfg(sdmmc_v1)] 400 #[cfg(sdmmc_v1)]
385 dma: ChannelAndRequest<'d>, 401 dma: ChannelAndRequest<'d>,
386 402
@@ -400,12 +416,6 @@ pub struct Sdmmc<'d, T: Instance> {
400 clock: Hertz, 416 clock: Hertz,
401 /// Current signalling scheme to card 417 /// Current signalling scheme to card
402 signalling: Signalling, 418 signalling: Signalling,
403 /// Card
404 card: Option<SdmmcPeripheral>,
405
406 /// An optional buffer to be used for commands
407 /// This should be used if there are special memory location requirements for dma
408 cmd_block: Option<&'d mut CmdBlock>,
409} 419}
410 420
411const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh); 421const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh);
@@ -416,9 +426,9 @@ const CMD_AF: AfType = AfType::output_pull(OutputType::PushPull, Speed::VeryHigh
416const DATA_AF: AfType = CMD_AF; 426const DATA_AF: AfType = CMD_AF;
417 427
418#[cfg(sdmmc_v1)] 428#[cfg(sdmmc_v1)]
419impl<'d, T: Instance> Sdmmc<'d, T> { 429impl<'d> Sdmmc<'d> {
420 /// Create a new SDMMC driver, with 1 data lane. 430 /// Create a new SDMMC driver, with 1 data lane.
421 pub fn new_1bit( 431 pub fn new_1bit<T: Instance>(
422 sdmmc: Peri<'d, T>, 432 sdmmc: Peri<'d, T>,
423 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 433 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
424 dma: Peri<'d, impl SdmmcDma<T>>, 434 dma: Peri<'d, impl SdmmcDma<T>>,
@@ -451,7 +461,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
451 } 461 }
452 462
453 /// Create a new SDMMC driver, with 4 data lanes. 463 /// Create a new SDMMC driver, with 4 data lanes.
454 pub fn new_4bit( 464 pub fn new_4bit<T: Instance>(
455 sdmmc: Peri<'d, T>, 465 sdmmc: Peri<'d, T>,
456 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 466 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
457 dma: Peri<'d, impl SdmmcDma<T>>, 467 dma: Peri<'d, impl SdmmcDma<T>>,
@@ -491,9 +501,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
491} 501}
492 502
493#[cfg(sdmmc_v1)] 503#[cfg(sdmmc_v1)]
494impl<'d, T: Instance> Sdmmc<'d, T> { 504impl<'d> Sdmmc<'d> {
495 /// Create a new SDMMC driver, with 8 data lanes. 505 /// Create a new SDMMC driver, with 8 data lanes.
496 pub fn new_8bit( 506 pub fn new_8bit<T: Instance>(
497 sdmmc: Peri<'d, T>, 507 sdmmc: Peri<'d, T>,
498 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 508 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
499 dma: Peri<'d, impl SdmmcDma<T>>, 509 dma: Peri<'d, impl SdmmcDma<T>>,
@@ -541,9 +551,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
541} 551}
542 552
543#[cfg(sdmmc_v2)] 553#[cfg(sdmmc_v2)]
544impl<'d, T: Instance> Sdmmc<'d, T> { 554impl<'d> Sdmmc<'d> {
545 /// Create a new SDMMC driver, with 1 data lane. 555 /// Create a new SDMMC driver, with 1 data lane.
546 pub fn new_1bit( 556 pub fn new_1bit<T: Instance>(
547 sdmmc: Peri<'d, T>, 557 sdmmc: Peri<'d, T>,
548 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 558 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
549 clk: Peri<'d, impl CkPin<T>>, 559 clk: Peri<'d, impl CkPin<T>>,
@@ -574,7 +584,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
574 } 584 }
575 585
576 /// Create a new SDMMC driver, with 4 data lanes. 586 /// Create a new SDMMC driver, with 4 data lanes.
577 pub fn new_4bit( 587 pub fn new_4bit<T: Instance>(
578 sdmmc: Peri<'d, T>, 588 sdmmc: Peri<'d, T>,
579 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 589 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
580 clk: Peri<'d, impl CkPin<T>>, 590 clk: Peri<'d, impl CkPin<T>>,
@@ -612,9 +622,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
612} 622}
613 623
614#[cfg(sdmmc_v2)] 624#[cfg(sdmmc_v2)]
615impl<'d, T: Instance> Sdmmc<'d, T> { 625impl<'d> Sdmmc<'d> {
616 /// Create a new SDMMC driver, with 8 data lanes. 626 /// Create a new SDMMC driver, with 8 data lanes.
617 pub fn new_8bit( 627 pub fn new_8bit<T: Instance>(
618 sdmmc: Peri<'d, T>, 628 sdmmc: Peri<'d, T>,
619 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 629 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
620 clk: Peri<'d, impl CkPin<T>>, 630 clk: Peri<'d, impl CkPin<T>>,
@@ -659,9 +669,24 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
659 } 669 }
660} 670}
661 671
662impl<'d, T: Instance> Sdmmc<'d, T> { 672impl<'d> Sdmmc<'d> {
663 fn new_inner( 673 fn enable_interrupts(&self) {
664 sdmmc: Peri<'d, T>, 674 let regs = self.info.regs;
675 regs.maskr().write(|w| {
676 w.set_dcrcfailie(true);
677 w.set_dtimeoutie(true);
678 w.set_dataendie(true);
679 w.set_dbckendie(true);
680
681 #[cfg(sdmmc_v1)]
682 w.set_stbiterre(true);
683 #[cfg(sdmmc_v2)]
684 w.set_dabortie(true);
685 });
686 }
687
688 fn new_inner<T: Instance>(
689 _sdmmc: Peri<'d, T>,
665 #[cfg(sdmmc_v1)] dma: ChannelAndRequest<'d>, 690 #[cfg(sdmmc_v1)] dma: ChannelAndRequest<'d>,
666 clk: Peri<'d, AnyPin>, 691 clk: Peri<'d, AnyPin>,
667 cmd: Peri<'d, AnyPin>, 692 cmd: Peri<'d, AnyPin>,
@@ -675,13 +700,16 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
675 d7: Option<Peri<'d, AnyPin>>, 700 d7: Option<Peri<'d, AnyPin>>,
676 config: Config, 701 config: Config,
677 ) -> Self { 702 ) -> Self {
678 rcc::enable_and_reset::<T>(); 703 rcc::enable_and_reset_without_stop::<T>();
679 704
680 T::Interrupt::unpend(); 705 T::Interrupt::unpend();
681 unsafe { T::Interrupt::enable() }; 706 unsafe { T::Interrupt::enable() };
682 707
683 let regs = T::regs(); 708 let info = T::info();
684 regs.clkcr().write(|w| { 709 let state = T::state();
710 let ker_clk = T::frequency();
711
712 info.regs.clkcr().write(|w| {
685 w.set_pwrsav(false); 713 w.set_pwrsav(false);
686 w.set_negedge(false); 714 w.set_negedge(false);
687 715
@@ -698,10 +726,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
698 726
699 // Power off, writen 00: Clock to the card is stopped; 727 // Power off, writen 00: Clock to the card is stopped;
700 // D[7:0], CMD, and CK are driven high. 728 // D[7:0], CMD, and CK are driven high.
701 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8)); 729 info.regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8));
702 730
703 Self { 731 Self {
704 _peri: sdmmc, 732 info,
733 state,
734 ker_clk,
705 #[cfg(sdmmc_v1)] 735 #[cfg(sdmmc_v1)]
706 dma, 736 dma,
707 737
@@ -719,15 +749,13 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
719 config, 749 config,
720 clock: SD_INIT_FREQ, 750 clock: SD_INIT_FREQ,
721 signalling: Default::default(), 751 signalling: Default::default(),
722 card: None,
723 cmd_block: None,
724 } 752 }
725 } 753 }
726 754
727 /// Data transfer is in progress 755 /// Data transfer is in progress
728 #[inline] 756 #[inline]
729 fn data_active() -> bool { 757 fn data_active(&self) -> bool {
730 let regs = T::regs(); 758 let regs = self.info.regs;
731 759
732 let status = regs.star().read(); 760 let status = regs.star().read();
733 #[cfg(sdmmc_v1)] 761 #[cfg(sdmmc_v1)]
@@ -738,8 +766,8 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
738 766
739 /// Coammand transfer is in progress 767 /// Coammand transfer is in progress
740 #[inline] 768 #[inline]
741 fn cmd_active() -> bool { 769 fn cmd_active(&self) -> bool {
742 let regs = T::regs(); 770 let regs = self.info.regs;
743 771
744 let status = regs.star().read(); 772 let status = regs.star().read();
745 #[cfg(sdmmc_v1)] 773 #[cfg(sdmmc_v1)]
@@ -750,8 +778,16 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
750 778
751 /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2) 779 /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2)
752 #[inline] 780 #[inline]
753 fn wait_idle() { 781 fn wait_idle(&self) {
754 while Self::data_active() || Self::cmd_active() {} 782 while self.data_active() || self.cmd_active() {}
783 }
784
785 fn bus_width(&self) -> BusWidth {
786 match (self.d3.is_some(), self.d7.is_some()) {
787 (true, true) => BusWidth::Eight,
788 (true, false) => BusWidth::Four,
789 _ => BusWidth::One,
790 }
755 } 791 }
756 792
757 /// # Safety 793 /// # Safety
@@ -759,23 +795,32 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
759 /// `buffer` must be valid for the whole transfer and word aligned 795 /// `buffer` must be valid for the whole transfer and word aligned
760 #[allow(unused_variables)] 796 #[allow(unused_variables)]
761 fn prepare_datapath_read<'a>( 797 fn prepare_datapath_read<'a>(
762 config: &Config, 798 &'a self,
763 #[cfg(sdmmc_v1)] dma: &'a mut ChannelAndRequest<'d>, 799 buffer: &'a mut Aligned<A4, [u8]>,
764 buffer: &'a mut [u32], 800 mode: DatapathMode,
765 length_bytes: u32, 801 ) -> WrappedTransfer<'a> {
766 block_size: u8, 802 let regs = self.info.regs;
767 ) -> Transfer<'a> { 803
768 assert!(block_size <= 14, "Block size up to 2^14 bytes"); 804 let (byte_mode, block_size) = match mode {
769 let regs = T::regs(); 805 DatapathMode::Block(block_size) => (false, block_size as u8),
806 DatapathMode::Byte => (true, 0),
807 };
770 808
771 // Command AND Data state machines must be idle 809 // Command AND Data state machines must be idle
772 Self::wait_idle(); 810 self.wait_idle();
773 Self::clear_interrupt_flags(); 811 self.clear_interrupt_flags();
774 812
775 regs.dlenr().write(|w| w.set_datalength(length_bytes)); 813 regs.dlenr().write(|w| w.set_datalength(size_of_val(buffer) as u32));
776 814
815 // SAFETY: No other functions use the dma
777 #[cfg(sdmmc_v1)] 816 #[cfg(sdmmc_v1)]
778 let transfer = unsafe { dma.read(regs.fifor().as_ptr() as *mut u32, buffer, DMA_TRANSFER_OPTIONS) }; 817 let transfer = unsafe {
818 self.dma.read_unchecked(
819 regs.fifor().as_ptr() as *mut u32,
820 slice32_mut(buffer),
821 DMA_TRANSFER_OPTIONS,
822 )
823 };
779 #[cfg(sdmmc_v2)] 824 #[cfg(sdmmc_v2)]
780 let transfer = { 825 let transfer = {
781 regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); 826 regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32));
@@ -785,8 +830,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
785 } 830 }
786 }; 831 };
787 832
833 #[cfg(sdmmc_v2)]
834 let byte_mode = byte_mode as u8;
835
788 regs.dctrl().modify(|w| { 836 regs.dctrl().modify(|w| {
789 w.set_dblocksize(block_size); 837 w.set_dtmode(byte_mode);
838 w.set_dblocksize(block_size as u8);
790 w.set_dtdir(true); 839 w.set_dtdir(true);
791 #[cfg(sdmmc_v1)] 840 #[cfg(sdmmc_v1)]
792 { 841 {
@@ -795,26 +844,36 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
795 } 844 }
796 }); 845 });
797 846
798 transfer 847 self.enable_interrupts();
848
849 WrappedTransfer::new(transfer, &self)
799 } 850 }
800 851
801 /// # Safety 852 /// # Safety
802 /// 853 ///
803 /// `buffer` must be valid for the whole transfer and word aligned 854 /// `buffer` must be valid for the whole transfer and word aligned
804 fn prepare_datapath_write<'a>(&'a mut self, buffer: &'a [u32], length_bytes: u32, block_size: u8) -> Transfer<'a> { 855 fn prepare_datapath_write<'a>(&'a self, buffer: &'a Aligned<A4, [u8]>, mode: DatapathMode) -> WrappedTransfer<'a> {
805 assert!(block_size <= 14, "Block size up to 2^14 bytes"); 856 let regs = self.info.regs;
806 let regs = T::regs(); 857
858 let (byte_mode, block_size) = match mode {
859 DatapathMode::Block(block_size) => (false, block_size as u8),
860 DatapathMode::Byte => (true, 0),
861 };
807 862
808 // Command AND Data state machines must be idle 863 // Command AND Data state machines must be idle
809 Self::wait_idle(); 864 self.wait_idle();
810 Self::clear_interrupt_flags(); 865 self.clear_interrupt_flags();
811 866
812 regs.dlenr().write(|w| w.set_datalength(length_bytes)); 867 regs.dlenr().write(|w| w.set_datalength(size_of_val(buffer) as u32));
813 868
869 // SAFETY: No other functions use the dma
814 #[cfg(sdmmc_v1)] 870 #[cfg(sdmmc_v1)]
815 let transfer = unsafe { 871 let transfer = unsafe {
816 self.dma 872 self.dma.write_unchecked(
817 .write(buffer, regs.fifor().as_ptr() as *mut u32, DMA_TRANSFER_OPTIONS) 873 slice32_ref(buffer),
874 regs.fifor().as_ptr() as *mut u32,
875 DMA_TRANSFER_OPTIONS,
876 )
818 }; 877 };
819 #[cfg(sdmmc_v2)] 878 #[cfg(sdmmc_v2)]
820 let transfer = { 879 let transfer = {
@@ -825,8 +884,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
825 } 884 }
826 }; 885 };
827 886
887 #[cfg(sdmmc_v2)]
888 let byte_mode = byte_mode as u8;
889
828 regs.dctrl().modify(|w| { 890 regs.dctrl().modify(|w| {
829 w.set_dblocksize(block_size); 891 w.set_dtmode(byte_mode);
892 w.set_dblocksize(block_size as u8);
830 w.set_dtdir(false); 893 w.set_dtdir(false);
831 #[cfg(sdmmc_v1)] 894 #[cfg(sdmmc_v1)]
832 { 895 {
@@ -835,12 +898,14 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
835 } 898 }
836 }); 899 });
837 900
838 transfer 901 self.enable_interrupts();
902
903 WrappedTransfer::new(transfer, &self)
839 } 904 }
840 905
841 /// Stops the DMA datapath 906 /// Stops the DMA datapath
842 fn stop_datapath() { 907 fn stop_datapath(&self) {
843 let regs = T::regs(); 908 let regs = self.info.regs;
844 909
845 #[cfg(sdmmc_v1)] 910 #[cfg(sdmmc_v1)]
846 regs.dctrl().modify(|w| { 911 regs.dctrl().modify(|w| {
@@ -851,49 +916,58 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
851 regs.idmactrlr().modify(|w| w.set_idmaen(false)); 916 regs.idmactrlr().modify(|w| w.set_idmaen(false));
852 } 917 }
853 918
919 fn init_idle(&mut self) -> Result<(), Error> {
920 let regs = self.info.regs;
921
922 self.clkcr_set_clkdiv(SD_INIT_FREQ, BusWidth::One)?;
923 regs.dtimer()
924 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
925
926 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
927 self.cmd(common_cmd::idle(), false)
928 }
929
854 /// Sets the CLKDIV field in CLKCR. Updates clock field in self 930 /// Sets the CLKDIV field in CLKCR. Updates clock field in self
855 fn clkcr_set_clkdiv(&mut self, freq: u32, width: BusWidth) -> Result<(), Error> { 931 fn clkcr_set_clkdiv(&mut self, freq: Hertz, width: BusWidth) -> Result<(), Error> {
856 let regs = T::regs(); 932 let regs = self.info.regs;
857
858 let width_u32 = match width {
859 BusWidth::One => 1u32,
860 BusWidth::Four => 4u32,
861 BusWidth::Eight => 8u32,
862 _ => panic!("Invalid Bus Width"),
863 };
864 933
865 let ker_ck = T::frequency(); 934 let (widbus, width_u32) = bus_width_vals(width);
866 let (_bypass, clkdiv, new_clock) = clk_div(ker_ck, freq)?; 935 let (_bypass, clkdiv, new_clock) = clk_div(self.ker_clk, freq.0)?;
867 936
868 // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7 937 // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7
869 // Section 55.5.8 938 // Section 55.5.8
870 let sdmmc_bus_bandwidth = new_clock.0 * width_u32; 939 let sdmmc_bus_bandwidth = new_clock.0 * width_u32;
871 assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32); 940 assert!(self.ker_clk.0 > 3 * sdmmc_bus_bandwidth / 32);
872 self.clock = new_clock; 941 self.clock = new_clock;
873 942
874 // CPSMACT and DPSMACT must be 0 to set CLKDIV 943 // CPSMACT and DPSMACT must be 0 to set CLKDIV or WIDBUS
875 Self::wait_idle(); 944 self.wait_idle();
876 regs.clkcr().modify(|w| { 945 regs.clkcr().modify(|w| {
877 w.set_clkdiv(clkdiv); 946 w.set_clkdiv(clkdiv);
878 #[cfg(sdmmc_v1)] 947 #[cfg(sdmmc_v1)]
879 w.set_bypass(_bypass); 948 w.set_bypass(_bypass);
949 w.set_widbus(widbus);
880 }); 950 });
881 951
882 Ok(()) 952 Ok(())
883 } 953 }
884 954
955 fn get_cid(&self) -> Result<u128, Error> {
956 self.cmd(common_cmd::all_send_cid(), false) // CMD2
957 }
958
959 fn get_csd(&self, address: u16) -> Result<u128, Error> {
960 self.cmd(common_cmd::send_csd(address), false)
961 }
962
885 /// Query the card status (CMD13, returns R1) 963 /// Query the card status (CMD13, returns R1)
886 fn read_status<Ext>(&self, card: &SdmmcPeripheral) -> Result<CardStatus<Ext>, Error> 964 fn read_status<A: Addressable>(&self, card: &A) -> Result<CardStatus<A::Ext>, Error>
887 where 965 where
888 CardStatus<Ext>: From<u32>, 966 CardStatus<A::Ext>: From<u32>,
889 { 967 {
890 let regs = T::regs();
891 let rca = card.get_address(); 968 let rca = card.get_address();
892 969
893 Self::cmd(common_cmd::card_status(rca, false), false)?; // CMD13 970 Ok(self.cmd(common_cmd::card_status(rca, false), false)?.into()) // CMD13
894
895 let r1 = regs.respr(0).read().cardstatus();
896 Ok(r1.into())
897 } 971 }
898 972
899 /// Select one card and place it into the _Tranfer State_ 973 /// Select one card and place it into the _Tranfer State_
@@ -904,17 +978,23 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
904 // Determine Relative Card Address (RCA) of given card 978 // Determine Relative Card Address (RCA) of given card
905 let rca = rca.unwrap_or(0); 979 let rca = rca.unwrap_or(0);
906 980
907 let r = Self::cmd(common_cmd::select_card(rca), false); 981 let resp = self.cmd(common_cmd::select_card(rca), false);
908 match (r, rca) { 982
909 (Err(Error::Timeout), 0) => Ok(()), 983 if let Err(Error::Timeout) = resp
910 _ => r, 984 && rca == 0
985 {
986 return Ok(());
911 } 987 }
988
989 resp?;
990
991 Ok(())
912 } 992 }
913 993
914 /// Clear flags in interrupt clear register 994 /// Clear flags in interrupt clear register
915 #[inline] 995 #[inline]
916 fn clear_interrupt_flags() { 996 fn clear_interrupt_flags(&self) {
917 let regs = T::regs(); 997 let regs = self.info.regs;
918 regs.icr().write(|w| { 998 regs.icr().write(|w| {
919 w.set_ccrcfailc(true); 999 w.set_ccrcfailc(true);
920 w.set_dcrcfailc(true); 1000 w.set_dcrcfailc(true);
@@ -947,12 +1027,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
947 1027
948 /// Send command to card 1028 /// Send command to card
949 #[allow(unused_variables)] 1029 #[allow(unused_variables)]
950 fn cmd<R: Resp>(cmd: Cmd<R>, data: bool) -> Result<(), Error> { 1030 fn cmd<R: TypedResp>(&self, cmd: Cmd<R>, data: bool) -> Result<R::Word, Error> {
951 let regs = T::regs(); 1031 let regs = self.info.regs;
952 1032
953 Self::clear_interrupt_flags(); 1033 self.clear_interrupt_flags();
954 // CP state machine must be idle 1034 // CP state machine must be idle
955 while Self::cmd_active() {} 1035 while self.cmd_active() {}
956 1036
957 // Command arg 1037 // Command arg
958 regs.argr().write(|w| w.set_cmdarg(cmd.arg)); 1038 regs.argr().write(|w| w.set_cmdarg(cmd.arg));
@@ -994,16 +1074,29 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
994 } else if status.ccrcfail() { 1074 } else if status.ccrcfail() {
995 return Err(Error::Crc); 1075 return Err(Error::Crc);
996 } 1076 }
997 Ok(()) 1077
1078 Ok(match R::LENGTH {
1079 ResponseLen::Zero => U128(0u128),
1080 ResponseLen::R48 => U128(self.info.regs.respr(0).read().cardstatus() as u128),
1081 ResponseLen::R136 => {
1082 let cid0 = self.info.regs.respr(0).read().cardstatus() as u128;
1083 let cid1 = self.info.regs.respr(1).read().cardstatus() as u128;
1084 let cid2 = self.info.regs.respr(2).read().cardstatus() as u128;
1085 let cid3 = self.info.regs.respr(3).read().cardstatus() as u128;
1086
1087 U128((cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3))
1088 }
1089 }
1090 .into())
998 } 1091 }
999 1092
1000 fn on_drop() { 1093 fn on_drop(&self) {
1001 let regs = T::regs(); 1094 let regs = self.info.regs;
1002 if Self::data_active() { 1095 if self.data_active() {
1003 Self::clear_interrupt_flags(); 1096 self.clear_interrupt_flags();
1004 // Send abort 1097 // Send abort
1005 // CP state machine must be idle 1098 // CP state machine must be idle
1006 while Self::cmd_active() {} 1099 while self.cmd_active() {}
1007 1100
1008 // Command arg 1101 // Command arg
1009 regs.argr().write(|w| w.set_cmdarg(0)); 1102 regs.argr().write(|w| w.set_cmdarg(0));
@@ -1023,21 +1116,22 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1023 }); 1116 });
1024 1117
1025 // Wait for the abort 1118 // Wait for the abort
1026 while Self::data_active() {} 1119 while self.data_active() {}
1027 } 1120 }
1028 regs.maskr().write(|_| ()); // disable irqs 1121 regs.maskr().write(|_| ()); // disable irqs
1029 Self::clear_interrupt_flags(); 1122 self.clear_interrupt_flags();
1030 Self::stop_datapath(); 1123 self.stop_datapath();
1031 } 1124 }
1032 1125
1033 /// Wait for a previously started datapath transfer to complete from an interrupt. 1126 /// Wait for a previously started datapath transfer to complete from an interrupt.
1034 #[inline] 1127 #[inline]
1035 async fn complete_datapath_transfer(block: bool) -> Result<(), Error> { 1128 #[allow(unused)]
1036 let regs = T::regs(); 1129 async fn complete_datapath_transfer(&self, mut transfer: WrappedTransfer<'_>, block: bool) -> Result<(), Error> {
1037
1038 let res = poll_fn(|cx| { 1130 let res = poll_fn(|cx| {
1039 T::state().register(cx.waker()); 1131 // Compiler might not be sufficiently constrained here
1040 let status = regs.star().read(); 1132 // https://github.com/embassy-rs/embassy/issues/4723
1133 self.state.waker.register(cx.waker());
1134 let status = self.info.regs.star().read();
1041 1135
1042 if status.dcrcfail() { 1136 if status.dcrcfail() {
1043 return Poll::Ready(Err(Error::Crc)); 1137 return Poll::Ready(Err(Error::Crc));
@@ -1052,10 +1146,13 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1052 if status.stbiterr() { 1146 if status.stbiterr() {
1053 return Poll::Ready(Err(Error::StBitErr)); 1147 return Poll::Ready(Err(Error::StBitErr));
1054 } 1148 }
1149 #[cfg(sdmmc_v1)]
1055 let done = match block { 1150 let done = match block {
1056 true => status.dbckend(), 1151 true => status.dbckend(),
1057 false => status.dataend(), 1152 false => status.dataend(),
1058 }; 1153 };
1154 #[cfg(sdmmc_v2)]
1155 let done = status.dataend();
1059 if done { 1156 if done {
1060 return Poll::Ready(Ok(())); 1157 return Poll::Ready(Ok(()));
1061 } 1158 }
@@ -1063,698 +1160,26 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1063 }) 1160 })
1064 .await; 1161 .await;
1065 1162
1066 Self::clear_interrupt_flags(); 1163 self.clear_interrupt_flags();
1067 1164 self.stop_datapath();
1068 res
1069 }
1070
1071 /// Read a data block.
1072 #[inline]
1073 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
1074 let card_capacity = self.card()?.get_capacity();
1075
1076 // NOTE(unsafe) DataBlock uses align 4
1077 let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) };
1078 1165
1079 // Always read 1 block of 512 bytes 1166 transfer.defuse();
1080 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes 1167 drop(transfer);
1081 let address = match card_capacity {
1082 CardCapacity::StandardCapacity => block_idx * 512,
1083 _ => block_idx,
1084 };
1085 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1086 1168
1087 let on_drop = OnDrop::new(|| Self::on_drop());
1088
1089 let transfer = Self::prepare_datapath_read(
1090 &self.config,
1091 #[cfg(sdmmc_v1)]
1092 &mut self.dma,
1093 buffer,
1094 512,
1095 9,
1096 );
1097 InterruptHandler::<T>::enable_interrupts();
1098 Self::cmd(common_cmd::read_single_block(address), true)?;
1099
1100 let res = Self::complete_datapath_transfer(true).await;
1101
1102 if res.is_ok() {
1103 on_drop.defuse();
1104 Self::stop_datapath();
1105 drop(transfer);
1106 }
1107 res 1169 res
1108 } 1170 }
1109 1171
1110 /// Read multiple data blocks.
1111 #[inline]
1112 pub async fn read_blocks(&mut self, block_idx: u32, blocks: &mut [DataBlock]) -> Result<(), Error> {
1113 let card_capacity = self.card()?.get_capacity();
1114
1115 // NOTE(unsafe) reinterpret buffer as &mut [u32]
1116 let buffer = unsafe {
1117 let ptr = blocks.as_mut_ptr() as *mut u32;
1118 let len = blocks.len() * 128;
1119 core::slice::from_raw_parts_mut(ptr, len)
1120 };
1121
1122 // Always read 1 block of 512 bytes
1123 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1124 let address = match card_capacity {
1125 CardCapacity::StandardCapacity => block_idx * 512,
1126 _ => block_idx,
1127 };
1128 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1129
1130 let on_drop = OnDrop::new(|| Self::on_drop());
1131
1132 let transfer = Self::prepare_datapath_read(
1133 &self.config,
1134 #[cfg(sdmmc_v1)]
1135 &mut self.dma,
1136 buffer,
1137 512 * blocks.len() as u32,
1138 9,
1139 );
1140 InterruptHandler::<T>::enable_interrupts();
1141
1142 Self::cmd(common_cmd::read_multiple_blocks(address), true)?;
1143
1144 let res = Self::complete_datapath_transfer(false).await;
1145
1146 Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12
1147 Self::clear_interrupt_flags();
1148
1149 if res.is_ok() {
1150 on_drop.defuse();
1151 Self::stop_datapath();
1152 drop(transfer);
1153 }
1154 res
1155 }
1156
1157 /// Write a data block.
1158 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> {
1159 let card = self.card.as_mut().ok_or(Error::NoCard)?;
1160
1161 // NOTE(unsafe) DataBlock uses align 4
1162 let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) };
1163
1164 // Always read 1 block of 512 bytes
1165 // cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1166 let address = match card.get_capacity() {
1167 CardCapacity::StandardCapacity => block_idx * 512,
1168 _ => block_idx,
1169 };
1170 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1171
1172 let on_drop = OnDrop::new(|| Self::on_drop());
1173
1174 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
1175 #[cfg(sdmmc_v1)]
1176 Self::cmd(common_cmd::write_single_block(address), true)?;
1177
1178 let transfer = self.prepare_datapath_write(buffer, 512, 9);
1179 InterruptHandler::<T>::enable_interrupts();
1180
1181 #[cfg(sdmmc_v2)]
1182 Self::cmd(common_cmd::write_single_block(address), true)?;
1183
1184 let res = Self::complete_datapath_transfer(true).await;
1185
1186 match res {
1187 Ok(_) => {
1188 on_drop.defuse();
1189 Self::stop_datapath();
1190 drop(transfer);
1191
1192 // TODO: Make this configurable
1193 let mut timeout: u32 = 0x00FF_FFFF;
1194
1195 let card = self.card.as_ref().unwrap();
1196 while timeout > 0 {
1197 let ready_for_data = match card {
1198 SdmmcPeripheral::Emmc(_) => self.read_status::<EMMC>(card)?.ready_for_data(),
1199 SdmmcPeripheral::SdCard(_) => self.read_status::<SD>(card)?.ready_for_data(),
1200 };
1201
1202 if ready_for_data {
1203 return Ok(());
1204 }
1205 timeout -= 1;
1206 }
1207 Err(Error::SoftwareTimeout)
1208 }
1209 Err(e) => Err(e),
1210 }
1211 }
1212
1213 /// Write multiple data blocks.
1214 pub async fn write_blocks(&mut self, block_idx: u32, blocks: &[DataBlock]) -> Result<(), Error> {
1215 let card = self.card.as_mut().ok_or(Error::NoCard)?;
1216
1217 // NOTE(unsafe) reinterpret buffer as &[u32]
1218 let buffer = unsafe {
1219 let ptr = blocks.as_ptr() as *const u32;
1220 let len = blocks.len() * 128;
1221 core::slice::from_raw_parts(ptr, len)
1222 };
1223
1224 // Always read 1 block of 512 bytes
1225 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1226 let address = match card.get_capacity() {
1227 CardCapacity::StandardCapacity => block_idx * 512,
1228 _ => block_idx,
1229 };
1230
1231 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1232
1233 let block_count = blocks.len();
1234
1235 let on_drop = OnDrop::new(|| Self::on_drop());
1236
1237 #[cfg(sdmmc_v1)]
1238 Self::cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
1239
1240 // Setup write command
1241 let transfer = self.prepare_datapath_write(buffer, 512 * block_count as u32, 9);
1242 InterruptHandler::<T>::enable_interrupts();
1243
1244 #[cfg(sdmmc_v2)]
1245 Self::cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
1246
1247 let res = Self::complete_datapath_transfer(false).await;
1248
1249 Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12
1250 Self::clear_interrupt_flags();
1251
1252 match res {
1253 Ok(_) => {
1254 on_drop.defuse();
1255 Self::stop_datapath();
1256 drop(transfer);
1257
1258 // TODO: Make this configurable
1259 let mut timeout: u32 = 0x00FF_FFFF;
1260
1261 // Try to read card status (ACMD13)
1262 while timeout > 0 {
1263 match self.read_sd_status().await {
1264 Ok(_) => return Ok(()),
1265 Err(Error::Timeout) => (), // Try again
1266 Err(e) => return Err(e),
1267 }
1268 timeout -= 1;
1269 }
1270 Err(Error::SoftwareTimeout)
1271 }
1272 Err(e) => Err(e),
1273 }
1274 }
1275
1276 /// Get a reference to the initialized card
1277 ///
1278 /// # Errors
1279 ///
1280 /// Returns Error::NoCard if [`init_sd_card`](#method.init_sd_card) or
1281 /// [`init_emmc`](#method.init_emmc) has not previously succeeded
1282 #[inline]
1283 pub fn card(&self) -> Result<&SdmmcPeripheral, Error> {
1284 self.card.as_ref().ok_or(Error::NoCard)
1285 }
1286
1287 /// Get the current SDMMC bus clock 1172 /// Get the current SDMMC bus clock
1288 pub fn clock(&self) -> Hertz { 1173 pub fn clock(&self) -> Hertz {
1289 self.clock 1174 self.clock
1290 } 1175 }
1291
1292 /// Set a specific cmd buffer rather than using the default stack allocated one.
1293 /// This is required if stack RAM cannot be used with DMA and usually manifests
1294 /// itself as an indefinite wait on a dma transfer because the dma peripheral
1295 /// cannot access the memory.
1296 pub fn set_cmd_block(&mut self, cmd_block: &'d mut CmdBlock) {
1297 self.cmd_block = Some(cmd_block)
1298 }
1299
1300 async fn init_internal(&mut self, freq: Hertz, mut card: SdmmcPeripheral) -> Result<(), Error> {
1301 let regs = T::regs();
1302 let ker_ck = T::frequency();
1303
1304 let bus_width = match (self.d3.is_some(), self.d7.is_some()) {
1305 (true, true) => {
1306 if matches!(card, SdmmcPeripheral::SdCard(_)) {
1307 return Err(Error::BusWidth);
1308 }
1309 BusWidth::Eight
1310 }
1311 (true, false) => BusWidth::Four,
1312 _ => BusWidth::One,
1313 };
1314
1315 // While the SD/SDIO card or eMMC is in identification mode,
1316 // the SDMMC_CK frequency must be no more than 400 kHz.
1317 let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0));
1318 self.clock = init_clock;
1319
1320 // CPSMACT and DPSMACT must be 0 to set WIDBUS
1321 Self::wait_idle();
1322
1323 regs.clkcr().modify(|w| {
1324 w.set_widbus(0);
1325 w.set_clkdiv(clkdiv);
1326 #[cfg(sdmmc_v1)]
1327 w.set_bypass(_bypass);
1328 });
1329 regs.dtimer()
1330 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
1331
1332 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
1333 Self::cmd(common_cmd::idle(), false)?;
1334
1335 match card {
1336 SdmmcPeripheral::SdCard(ref mut card) => {
1337 // Check if cards supports CMD8 (with pattern)
1338 Self::cmd(sd_cmd::send_if_cond(1, 0xAA), false)?;
1339 let cic = CIC::from(regs.respr(0).read().cardstatus());
1340
1341 if cic.pattern() != 0xAA {
1342 return Err(Error::UnsupportedCardVersion);
1343 }
1344
1345 if cic.voltage_accepted() & 1 == 0 {
1346 return Err(Error::UnsupportedVoltage);
1347 }
1348
1349 let ocr = loop {
1350 // Signal that next command is a app command
1351 Self::cmd(common_cmd::app_cmd(0), false)?; // CMD55
1352
1353 // 3.2-3.3V
1354 let voltage_window = 1 << 5;
1355 // Initialize card
1356 match Self::cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window), false) {
1357 // ACMD41
1358 Ok(_) => (),
1359 Err(Error::Crc) => (),
1360 Err(err) => return Err(err),
1361 }
1362 let ocr: OCR<SD> = regs.respr(0).read().cardstatus().into();
1363 if !ocr.is_busy() {
1364 // Power up done
1365 break ocr;
1366 }
1367 };
1368
1369 if ocr.high_capacity() {
1370 // Card is SDHC or SDXC or SDUC
1371 card.card_type = CardCapacity::HighCapacity;
1372 } else {
1373 card.card_type = CardCapacity::StandardCapacity;
1374 }
1375 card.ocr = ocr;
1376 }
1377 SdmmcPeripheral::Emmc(ref mut emmc) => {
1378 let ocr = loop {
1379 let high_voltage = 0b0 << 7;
1380 let access_mode = 0b10 << 29;
1381 let op_cond = high_voltage | access_mode | 0b1_1111_1111 << 15;
1382 // Initialize card
1383 match Self::cmd(emmc_cmd::send_op_cond(op_cond), false) {
1384 Ok(_) => (),
1385 Err(Error::Crc) => (),
1386 Err(err) => return Err(err),
1387 }
1388 let ocr: OCR<EMMC> = regs.respr(0).read().cardstatus().into();
1389 if !ocr.is_busy() {
1390 // Power up done
1391 break ocr;
1392 }
1393 };
1394
1395 emmc.capacity = if ocr.access_mode() == 0b10 {
1396 // Card is SDHC or SDXC or SDUC
1397 CardCapacity::HighCapacity
1398 } else {
1399 CardCapacity::StandardCapacity
1400 };
1401 emmc.ocr = ocr;
1402 }
1403 }
1404
1405 Self::cmd(common_cmd::all_send_cid(), false)?; // CMD2
1406 let cid0 = regs.respr(0).read().cardstatus() as u128;
1407 let cid1 = regs.respr(1).read().cardstatus() as u128;
1408 let cid2 = regs.respr(2).read().cardstatus() as u128;
1409 let cid3 = regs.respr(3).read().cardstatus() as u128;
1410 let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3);
1411
1412 match card {
1413 SdmmcPeripheral::SdCard(ref mut card) => {
1414 card.cid = cid.into();
1415
1416 Self::cmd(sd_cmd::send_relative_address(), false)?;
1417 let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus());
1418 card.rca = rca.address();
1419 }
1420 SdmmcPeripheral::Emmc(ref mut emmc) => {
1421 emmc.cid = cid.into();
1422
1423 emmc.rca = 1u16.into();
1424 Self::cmd(emmc_cmd::assign_relative_address(emmc.rca), false)?;
1425 }
1426 }
1427
1428 Self::cmd(common_cmd::send_csd(card.get_address()), false)?;
1429 let csd0 = regs.respr(0).read().cardstatus() as u128;
1430 let csd1 = regs.respr(1).read().cardstatus() as u128;
1431 let csd2 = regs.respr(2).read().cardstatus() as u128;
1432 let csd3 = regs.respr(3).read().cardstatus() as u128;
1433 let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3);
1434
1435 self.select_card(Some(card.get_address()))?;
1436
1437 let bus_width = match card {
1438 SdmmcPeripheral::SdCard(ref mut card) => {
1439 card.csd = csd.into();
1440
1441 self.get_scr(card).await?;
1442
1443 if !card.scr.bus_width_four() {
1444 BusWidth::One
1445 } else {
1446 BusWidth::Four
1447 }
1448 }
1449 SdmmcPeripheral::Emmc(ref mut emmc) => {
1450 emmc.csd = csd.into();
1451
1452 bus_width
1453 }
1454 };
1455
1456 // Set bus width
1457 let widbus = match bus_width {
1458 BusWidth::Eight => 2,
1459 BusWidth::Four => 1,
1460 BusWidth::One => 0,
1461 _ => unreachable!(),
1462 };
1463
1464 match card {
1465 SdmmcPeripheral::SdCard(ref mut card) => {
1466 let acmd_arg = match bus_width {
1467 BusWidth::Four if card.scr.bus_width_four() => 2,
1468 _ => 0,
1469 };
1470 Self::cmd(common_cmd::app_cmd(card.rca), false)?;
1471 Self::cmd(sd_cmd::cmd6(acmd_arg), false)?;
1472 }
1473 SdmmcPeripheral::Emmc(_) => {
1474 // Write bus width to ExtCSD byte 183
1475 Self::cmd(
1476 emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus),
1477 false,
1478 )?;
1479
1480 // Wait for ready after R1b response
1481 loop {
1482 let status = self.read_status::<EMMC>(&card)?;
1483
1484 if status.ready_for_data() {
1485 break;
1486 }
1487 }
1488 }
1489 }
1490
1491 // CPSMACT and DPSMACT must be 0 to set WIDBUS
1492 Self::wait_idle();
1493
1494 regs.clkcr().modify(|w| w.set_widbus(widbus));
1495
1496 // Set Clock
1497 if freq.0 <= 25_000_000 {
1498 // Final clock frequency
1499 self.clkcr_set_clkdiv(freq.0, bus_width)?;
1500 } else {
1501 // Switch to max clock for SDR12
1502 self.clkcr_set_clkdiv(25_000_000, bus_width)?;
1503 }
1504
1505 self.card = Some(card);
1506
1507 match card {
1508 SdmmcPeripheral::SdCard(_) => {
1509 // Read status
1510 self.read_sd_status().await?;
1511
1512 if freq.0 > 25_000_000 {
1513 // Switch to SDR25
1514 self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?;
1515
1516 if self.signalling == Signalling::SDR25 {
1517 // Set final clock frequency
1518 self.clkcr_set_clkdiv(freq.0, bus_width)?;
1519
1520 if self.read_status::<SD>(self.card.as_ref().unwrap())?.state() != CurrentState::Transfer {
1521 return Err(Error::SignalingSwitchFailed);
1522 }
1523 }
1524 }
1525
1526 // Read status after signalling change
1527 self.read_sd_status().await?;
1528 }
1529 SdmmcPeripheral::Emmc(_) => {
1530 self.read_ext_csd().await?;
1531 }
1532 }
1533
1534 Ok(())
1535 }
1536
1537 /// Initializes card (if present) and sets the bus at the specified frequency.
1538 ///
1539 /// SD only.
1540 pub async fn init_sd_card(&mut self, freq: Hertz) -> Result<(), Error> {
1541 self.init_internal(freq, SdmmcPeripheral::SdCard(Card::default())).await
1542 }
1543
1544 /// Switch mode using CMD6.
1545 ///
1546 /// Attempt to set a new signalling mode. The selected
1547 /// signalling mode is returned. Expects the current clock
1548 /// frequency to be > 12.5MHz.
1549 ///
1550 /// SD only.
1551 async fn switch_signalling_mode(&mut self, signalling: Signalling) -> Result<Signalling, Error> {
1552 let _ = self.card.as_mut().ok_or(Error::NoCard)?.get_sd_card();
1553 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
1554 // necessary"
1555
1556 let set_function = 0x8000_0000
1557 | match signalling {
1558 // See PLSS v7_10 Table 4-11
1559 Signalling::DDR50 => 0xFF_FF04,
1560 Signalling::SDR104 => 0xFF_1F03,
1561 Signalling::SDR50 => 0xFF_1F02,
1562 Signalling::SDR25 => 0xFF_FF01,
1563 Signalling::SDR12 => 0xFF_FF00,
1564 };
1565
1566 let status = match self.cmd_block.as_deref_mut() {
1567 Some(x) => x,
1568 None => &mut CmdBlock::new(),
1569 };
1570
1571 // Arm `OnDrop` after the buffer, so it will be dropped first
1572 let on_drop = OnDrop::new(|| Self::on_drop());
1573
1574 let transfer = Self::prepare_datapath_read(
1575 &self.config,
1576 #[cfg(sdmmc_v1)]
1577 &mut self.dma,
1578 status.as_mut(),
1579 64,
1580 6,
1581 );
1582 InterruptHandler::<T>::enable_interrupts();
1583 Self::cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
1584
1585 let res = Self::complete_datapath_transfer(true).await;
1586
1587 // Host is allowed to use the new functions at least 8
1588 // clocks after the end of the switch command
1589 // transaction. We know the current clock period is < 80ns,
1590 // so a total delay of 640ns is required here
1591 for _ in 0..300 {
1592 cortex_m::asm::nop();
1593 }
1594
1595 match res {
1596 Ok(_) => {
1597 on_drop.defuse();
1598 Self::stop_datapath();
1599 drop(transfer);
1600
1601 // Function Selection of Function Group 1
1602 let selection = (u32::from_be(status[4]) >> 24) & 0xF;
1603
1604 match selection {
1605 0 => Ok(Signalling::SDR12),
1606 1 => Ok(Signalling::SDR25),
1607 2 => Ok(Signalling::SDR50),
1608 3 => Ok(Signalling::SDR104),
1609 4 => Ok(Signalling::DDR50),
1610 _ => Err(Error::UnsupportedCardType),
1611 }
1612 }
1613 Err(e) => Err(e),
1614 }
1615 }
1616
1617 /// Reads the SCR register.
1618 ///
1619 /// SD only.
1620 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
1621 // Read the 64-bit SCR register
1622 Self::cmd(common_cmd::set_block_length(8), false)?; // CMD16
1623 Self::cmd(common_cmd::app_cmd(card.rca), false)?;
1624
1625 let cmd_block = match self.cmd_block.as_deref_mut() {
1626 Some(x) => x,
1627 None => &mut CmdBlock::new(),
1628 };
1629 let scr = &mut cmd_block.0[..2];
1630
1631 // Arm `OnDrop` after the buffer, so it will be dropped first
1632 let on_drop = OnDrop::new(|| Self::on_drop());
1633
1634 let transfer = Self::prepare_datapath_read(
1635 &self.config,
1636 #[cfg(sdmmc_v1)]
1637 &mut self.dma,
1638 scr,
1639 8,
1640 3,
1641 );
1642 InterruptHandler::<T>::enable_interrupts();
1643 Self::cmd(sd_cmd::send_scr(), true)?;
1644
1645 let res = Self::complete_datapath_transfer(true).await;
1646
1647 if res.is_ok() {
1648 on_drop.defuse();
1649 Self::stop_datapath();
1650 drop(transfer);
1651
1652 unsafe {
1653 let scr_bytes = &*(&scr as *const _ as *const [u8; 8]);
1654 card.scr = SCR(u64::from_be_bytes(*scr_bytes));
1655 }
1656 }
1657 res
1658 }
1659
1660 /// Reads the SD Status (ACMD13)
1661 ///
1662 /// SD only.
1663 async fn read_sd_status(&mut self) -> Result<(), Error> {
1664 let card = self.card.as_mut().ok_or(Error::NoCard)?.get_sd_card();
1665 let rca = card.rca;
1666
1667 let cmd_block = match self.cmd_block.as_deref_mut() {
1668 Some(x) => x,
1669 None => &mut CmdBlock::new(),
1670 };
1671
1672 Self::cmd(common_cmd::set_block_length(64), false)?; // CMD16
1673 Self::cmd(common_cmd::app_cmd(rca), false)?; // APP
1674
1675 let status = cmd_block;
1676
1677 // Arm `OnDrop` after the buffer, so it will be dropped first
1678 let on_drop = OnDrop::new(|| Self::on_drop());
1679
1680 let transfer = Self::prepare_datapath_read(
1681 &self.config,
1682 #[cfg(sdmmc_v1)]
1683 &mut self.dma,
1684 status.as_mut(),
1685 64,
1686 6,
1687 );
1688 InterruptHandler::<T>::enable_interrupts();
1689 Self::cmd(sd_cmd::sd_status(), true)?;
1690
1691 let res = Self::complete_datapath_transfer(true).await;
1692
1693 if res.is_ok() {
1694 on_drop.defuse();
1695 Self::stop_datapath();
1696 drop(transfer);
1697
1698 for byte in status.iter_mut() {
1699 *byte = u32::from_be(*byte);
1700 }
1701 card.status = status.0.into();
1702 }
1703 res
1704 }
1705
1706 /// Initializes eMMC and sets the bus at the specified frequency.
1707 ///
1708 /// eMMC only.
1709 pub async fn init_emmc(&mut self, freq: Hertz) -> Result<(), Error> {
1710 self.init_internal(freq, SdmmcPeripheral::Emmc(Emmc::default())).await
1711 }
1712
1713 /// Gets the EXT_CSD register.
1714 ///
1715 /// eMMC only.
1716 async fn read_ext_csd(&mut self) -> Result<(), Error> {
1717 let card = self.card.as_mut().ok_or(Error::NoCard)?.get_emmc();
1718
1719 // Note: cmd_block can't be used because ExtCSD is too long to fit.
1720 let mut data_block = DataBlock([0u8; 512]);
1721
1722 // NOTE(unsafe) DataBlock uses align 4
1723 let buffer = unsafe { &mut *((&mut data_block.0) as *mut [u8; 512] as *mut [u32; 128]) };
1724
1725 Self::cmd(common_cmd::set_block_length(512), false).unwrap(); // CMD16
1726
1727 // Arm `OnDrop` after the buffer, so it will be dropped first
1728 let on_drop = OnDrop::new(|| Self::on_drop());
1729
1730 let transfer = Self::prepare_datapath_read(
1731 &self.config,
1732 #[cfg(sdmmc_v1)]
1733 &mut self.dma,
1734 buffer,
1735 512,
1736 9,
1737 );
1738 InterruptHandler::<T>::enable_interrupts();
1739 Self::cmd(emmc_cmd::send_ext_csd(), true)?;
1740
1741 let res = Self::complete_datapath_transfer(true).await;
1742
1743 if res.is_ok() {
1744 on_drop.defuse();
1745 Self::stop_datapath();
1746 drop(transfer);
1747
1748 card.ext_csd = unsafe { core::mem::transmute::<_, [u32; 128]>(data_block.0) }.into();
1749 }
1750 res
1751 }
1752} 1176}
1753 1177
1754impl<'d, T: Instance> Drop for Sdmmc<'d, T> { 1178impl<'d> Drop for Sdmmc<'d> {
1755 fn drop(&mut self) { 1179 fn drop(&mut self) {
1756 T::Interrupt::disable(); 1180 // T::Interrupt::disable();
1757 Self::on_drop(); 1181 self.on_drop();
1182 self.info.rcc.disable_without_stop();
1758 1183
1759 critical_section::with(|_| { 1184 critical_section::with(|_| {
1760 self.clk.set_as_disconnected(); 1185 self.clk.set_as_disconnected();
@@ -1787,9 +1212,28 @@ impl<'d, T: Instance> Drop for Sdmmc<'d, T> {
1787 1212
1788////////////////////////////////////////////////////// 1213//////////////////////////////////////////////////////
1789 1214
1215type Regs = RegBlock;
1216
1217struct Info {
1218 regs: Regs,
1219 rcc: RccInfo,
1220}
1221
1222struct State {
1223 waker: AtomicWaker,
1224}
1225
1226impl State {
1227 const fn new() -> Self {
1228 Self {
1229 waker: AtomicWaker::new(),
1230 }
1231 }
1232}
1233
1790trait SealedInstance { 1234trait SealedInstance {
1791 fn regs() -> RegBlock; 1235 fn info() -> &'static Info;
1792 fn state() -> &'static AtomicWaker; 1236 fn state() -> &'static State;
1793} 1237}
1794 1238
1795/// SDMMC instance trait. 1239/// SDMMC instance trait.
@@ -1816,13 +1260,17 @@ dma_trait!(SdmmcDma, Instance);
1816foreach_peripheral!( 1260foreach_peripheral!(
1817 (sdmmc, $inst:ident) => { 1261 (sdmmc, $inst:ident) => {
1818 impl SealedInstance for peripherals::$inst { 1262 impl SealedInstance for peripherals::$inst {
1819 fn regs() -> RegBlock { 1263 fn info() -> &'static Info {
1820 crate::pac::$inst 1264 static INFO: Info = Info {
1265 regs: unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) },
1266 rcc: crate::peripherals::$inst::RCC_INFO,
1267 };
1268 &INFO
1821 } 1269 }
1822 1270
1823 fn state() -> &'static ::embassy_sync::waitqueue::AtomicWaker { 1271 fn state() -> &'static State {
1824 static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new(); 1272 static STATE: State = State::new();
1825 &WAKER 1273 &STATE
1826 } 1274 }
1827 } 1275 }
1828 1276
@@ -1831,46 +1279,3 @@ foreach_peripheral!(
1831 } 1279 }
1832 }; 1280 };
1833); 1281);
1834
1835impl<'d, T: Instance> block_device_driver::BlockDevice<512> for Sdmmc<'d, T> {
1836 type Error = Error;
1837 type Align = aligned::A4;
1838
1839 async fn read(
1840 &mut self,
1841 block_address: u32,
1842 buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>],
1843 ) -> Result<(), Self::Error> {
1844 // TODO: I think block_address needs to be adjusted by the partition start offset
1845 if buf.len() == 1 {
1846 let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut crate::sdmmc::DataBlock) };
1847 self.read_block(block_address, block).await?;
1848 } else {
1849 let blocks: &mut [DataBlock] =
1850 unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut DataBlock, buf.len()) };
1851 self.read_blocks(block_address, blocks).await?;
1852 }
1853 Ok(())
1854 }
1855
1856 async fn write(
1857 &mut self,
1858 block_address: u32,
1859 buf: &[aligned::Aligned<Self::Align, [u8; 512]>],
1860 ) -> Result<(), Self::Error> {
1861 // TODO: I think block_address needs to be adjusted by the partition start offset
1862 if buf.len() == 1 {
1863 let block = unsafe { &*(&buf[0] as *const _ as *const crate::sdmmc::DataBlock) };
1864 self.write_block(block_address, block).await?;
1865 } else {
1866 let blocks: &[DataBlock] =
1867 unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const DataBlock, buf.len()) };
1868 self.write_blocks(block_address, blocks).await?;
1869 }
1870 Ok(())
1871 }
1872
1873 async fn size(&mut self) -> Result<u64, Self::Error> {
1874 Ok(self.card()?.size())
1875 }
1876}
diff --git a/embassy-stm32/src/sdmmc/sd.rs b/embassy-stm32/src/sdmmc/sd.rs
new file mode 100644
index 000000000..20318bbfa
--- /dev/null
+++ b/embassy-stm32/src/sdmmc/sd.rs
@@ -0,0 +1,699 @@
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::{
9 BlockSize, DatapathMode, Error, Sdmmc, Signalling, aligned_mut, aligned_ref, block_size, bus_width_vals,
10 slice8_mut, slice8_ref,
11};
12use crate::time::{Hertz, mhz};
13
14/// Aligned data block for SDMMC transfers.
15///
16/// This is a 512-byte array, aligned to 4 bytes to satisfy DMA requirements.
17#[repr(align(4))]
18#[derive(Debug, Clone, PartialEq, Eq)]
19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20pub struct DataBlock(pub [u32; 128]);
21
22impl DataBlock {
23 /// Create a new DataBlock
24 pub const fn new() -> Self {
25 DataBlock([0u32; 128])
26 }
27}
28
29impl Deref for DataBlock {
30 type Target = [u8; 512];
31
32 fn deref(&self) -> &Self::Target {
33 unwrap!(slice8_ref(&self.0[..]).try_into())
34 }
35}
36
37impl DerefMut for DataBlock {
38 fn deref_mut(&mut self) -> &mut Self::Target {
39 unwrap!(slice8_mut(&mut self.0[..]).try_into())
40 }
41}
42
43/// Command Block buffer for SDMMC command transfers.
44///
45/// This is a 16-word array, exposed so that DMA commpatible memory can be used if required.
46#[derive(Debug, Clone, PartialEq, Eq)]
47#[cfg_attr(feature = "defmt", derive(defmt::Format))]
48pub struct CmdBlock(pub [u32; 16]);
49
50impl CmdBlock {
51 /// Creates a new instance of CmdBlock
52 pub const fn new() -> Self {
53 Self([0u32; 16])
54 }
55}
56
57impl Deref for CmdBlock {
58 type Target = [u32; 16];
59
60 fn deref(&self) -> &Self::Target {
61 &self.0
62 }
63}
64
65impl DerefMut for CmdBlock {
66 fn deref_mut(&mut self) -> &mut Self::Target {
67 &mut self.0
68 }
69}
70
71/// Represents either an SD or EMMC card
72pub trait Addressable: Sized + Clone {
73 /// Associated type
74 type Ext;
75
76 /// Get this peripheral's address on the SDMMC bus
77 fn get_address(&self) -> u16;
78
79 /// Is this a standard or high capacity peripheral?
80 fn get_capacity(&self) -> CardCapacity;
81
82 /// Size in bytes
83 fn size(&self) -> u64;
84}
85
86/// Storage Device
87pub struct StorageDevice<'a, 'b, T: Addressable> {
88 info: T,
89 /// Inner member
90 pub sdmmc: &'a mut Sdmmc<'b>,
91}
92
93/// Card Storage Device
94impl<'a, 'b> StorageDevice<'a, 'b, Card> {
95 /// Create a new SD card
96 pub async fn new_sd_card(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> {
97 let mut s = Self {
98 info: Card::default(),
99 sdmmc,
100 };
101
102 s.acquire(cmd_block, freq).await?;
103
104 Ok(s)
105 }
106
107 /// Initializes the card into a known state (or at least tries to).
108 async fn acquire(&mut self, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<(), Error> {
109 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
110 let regs = self.sdmmc.info.regs;
111
112 let _bus_width = match self.sdmmc.bus_width() {
113 BusWidth::Eight => return Err(Error::BusWidth),
114 bus_width => bus_width,
115 };
116
117 // While the SD/SDIO card or eMMC is in identification mode,
118 // the SDMMC_CK frequency must be no more than 400 kHz.
119 self.sdmmc.init_idle()?;
120
121 // Check if cards supports CMD8 (with pattern)
122 self.sdmmc.cmd(sd_cmd::send_if_cond(1, 0xAA), false)?;
123 let cic = CIC::from(regs.respr(0).read().cardstatus());
124
125 if cic.pattern() != 0xAA {
126 return Err(Error::UnsupportedCardVersion);
127 }
128
129 if cic.voltage_accepted() & 1 == 0 {
130 return Err(Error::UnsupportedVoltage);
131 }
132
133 let ocr = loop {
134 // Signal that next command is a app command
135 self.sdmmc.cmd(common_cmd::app_cmd(0), false)?; // CMD55
136
137 // 3.2-3.3V
138 let voltage_window = 1 << 5;
139 // Initialize card
140 match self
141 .sdmmc
142 .cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window), false)
143 {
144 // ACMD41
145 Ok(_) => (),
146 Err(Error::Crc) => (),
147 Err(err) => return Err(err),
148 }
149
150 let ocr: OCR<SD> = regs.respr(0).read().cardstatus().into();
151 if !ocr.is_busy() {
152 // Power up done
153 break ocr;
154 }
155 };
156
157 if ocr.high_capacity() {
158 // Card is SDHC or SDXC or SDUC
159 self.info.card_type = CardCapacity::HighCapacity;
160 } else {
161 self.info.card_type = CardCapacity::StandardCapacity;
162 }
163 self.info.ocr = ocr;
164
165 self.info.cid = self.sdmmc.get_cid()?.into();
166
167 self.sdmmc.cmd(sd_cmd::send_relative_address(), false)?;
168 let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus());
169 self.info.rca = rca.address();
170
171 self.info.csd = self.sdmmc.get_csd(self.info.get_address())?.into();
172 self.sdmmc.select_card(Some(self.info.get_address()))?;
173
174 self.info.scr = self.get_scr(cmd_block).await?;
175
176 let (bus_width, acmd_arg) = if !self.info.scr.bus_width_four() {
177 (BusWidth::One, 0)
178 } else {
179 (BusWidth::Four, 2)
180 };
181
182 self.sdmmc.cmd(common_cmd::app_cmd(self.info.rca), false)?;
183 self.sdmmc.cmd(sd_cmd::cmd6(acmd_arg), false)?;
184
185 self.sdmmc.clkcr_set_clkdiv(freq.clamp(mhz(0), mhz(25)), bus_width)?;
186
187 // Read status
188 self.info.status = self.read_sd_status(cmd_block).await?;
189
190 if freq > mhz(25) {
191 // Switch to SDR25
192 self.sdmmc.signalling = self.switch_signalling_mode(cmd_block, Signalling::SDR25).await?;
193
194 if self.sdmmc.signalling == Signalling::SDR25 {
195 // Set final clock frequency
196 self.sdmmc.clkcr_set_clkdiv(freq, bus_width)?;
197
198 if self.sdmmc.read_status(&self.info)?.state() != CurrentState::Transfer {
199 return Err(Error::SignalingSwitchFailed);
200 }
201 }
202
203 // Read status after signalling change
204 self.read_sd_status(cmd_block).await?;
205 }
206
207 Ok(())
208 }
209
210 /// Switch mode using CMD6.
211 ///
212 /// Attempt to set a new signalling mode. The selected
213 /// signalling mode is returned. Expects the current clock
214 /// frequency to be > 12.5MHz.
215 ///
216 /// SD only.
217 async fn switch_signalling_mode(
218 &self,
219 cmd_block: &mut CmdBlock,
220 signalling: Signalling,
221 ) -> Result<Signalling, Error> {
222 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
223 // necessary"
224
225 let set_function = 0x8000_0000
226 | match signalling {
227 // See PLSS v7_10 Table 4-11
228 Signalling::DDR50 => 0xFF_FF04,
229 Signalling::SDR104 => 0xFF_1F03,
230 Signalling::SDR50 => 0xFF_1F02,
231 Signalling::SDR25 => 0xFF_FF01,
232 Signalling::SDR12 => 0xFF_FF00,
233 };
234
235 let buffer = &mut cmd_block.0[..64 / 4];
236 let mode = DatapathMode::Block(block_size(size_of_val(buffer)));
237 let transfer = self.sdmmc.prepare_datapath_read(aligned_mut(buffer), mode);
238
239 self.sdmmc.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
240
241 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
242
243 // Host is allowed to use the new functions at least 8
244 // clocks after the end of the switch command
245 // transaction. We know the current clock period is < 80ns,
246 // so a total delay of 640ns is required here
247 for _ in 0..300 {
248 cortex_m::asm::nop();
249 }
250
251 // Function Selection of Function Group 1
252 let selection = (u32::from_be(cmd_block[4]) >> 24) & 0xF;
253
254 match selection {
255 0 => Ok(Signalling::SDR12),
256 1 => Ok(Signalling::SDR25),
257 2 => Ok(Signalling::SDR50),
258 3 => Ok(Signalling::SDR104),
259 4 => Ok(Signalling::DDR50),
260 _ => Err(Error::UnsupportedCardType),
261 }
262 }
263
264 /// Reads the SCR register.
265 ///
266 /// SD only.
267 async fn get_scr(&self, cmd_block: &mut CmdBlock) -> Result<SCR, Error> {
268 // Read the 64-bit SCR register
269 self.sdmmc.cmd(common_cmd::set_block_length(8), false)?; // CMD16
270 self.sdmmc.cmd(common_cmd::app_cmd(self.info.rca), false)?;
271
272 let scr = &mut cmd_block.0[..2];
273
274 // Arm `OnDrop` after the buffer, so it will be dropped first
275
276 let transfer = self
277 .sdmmc
278 .prepare_datapath_read(aligned_mut(scr), DatapathMode::Block(BlockSize::Size8));
279 self.sdmmc.cmd(sd_cmd::send_scr(), true)?;
280
281 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
282
283 Ok(SCR(u64::from_be_bytes(unwrap!(slice8_mut(scr).try_into()))))
284 }
285
286 /// Reads the SD Status (ACMD13)
287 ///
288 /// SD only.
289 async fn read_sd_status(&self, cmd_block: &mut CmdBlock) -> Result<SDStatus, Error> {
290 let rca = self.info.rca;
291
292 self.sdmmc.cmd(common_cmd::set_block_length(64), false)?; // CMD16
293 self.sdmmc.cmd(common_cmd::app_cmd(rca), false)?; // APP
294
295 let buffer = &mut cmd_block.as_mut()[..64 / 4];
296 let mode = DatapathMode::Block(block_size(size_of_val(buffer)));
297
298 let transfer = self.sdmmc.prepare_datapath_read(aligned_mut(buffer), mode);
299 self.sdmmc.cmd(sd_cmd::sd_status(), true)?;
300
301 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
302
303 for byte in cmd_block.iter_mut() {
304 *byte = u32::from_be(*byte);
305 }
306
307 Ok(cmd_block.0.into())
308 }
309}
310
311/// Emmc storage device
312impl<'a, 'b> StorageDevice<'a, 'b, Emmc> {
313 /// Create a new EMMC card
314 pub async fn new_emmc(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> {
315 let mut s = Self {
316 info: Emmc::default(),
317 sdmmc,
318 };
319
320 s.acquire(cmd_block, freq).await?;
321
322 Ok(s)
323 }
324
325 async fn acquire(&mut self, _cmd_block: &mut CmdBlock, freq: Hertz) -> Result<(), Error> {
326 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
327 let regs = self.sdmmc.info.regs;
328
329 let bus_width = self.sdmmc.bus_width();
330
331 // While the SD/SDIO card or eMMC is in identification mode,
332 // the SDMMC_CK frequency must be no more than 400 kHz.
333 self.sdmmc.init_idle()?;
334
335 let ocr = loop {
336 let high_voltage = 0b0 << 7;
337 let access_mode = 0b10 << 29;
338 let op_cond = high_voltage | access_mode | 0b1_1111_1111 << 15;
339 // Initialize card
340 match self.sdmmc.cmd(emmc_cmd::send_op_cond(op_cond), false) {
341 Ok(_) => (),
342 Err(Error::Crc) => (),
343 Err(err) => return Err(err),
344 }
345 let ocr: OCR<EMMC> = regs.respr(0).read().cardstatus().into();
346 if !ocr.is_busy() {
347 // Power up done
348 break ocr;
349 }
350 };
351
352 self.info.capacity = if ocr.access_mode() == 0b10 {
353 // Card is SDHC or SDXC or SDUC
354 CardCapacity::HighCapacity
355 } else {
356 CardCapacity::StandardCapacity
357 };
358 self.info.ocr = ocr;
359
360 self.info.cid = self.sdmmc.get_cid()?.into();
361
362 self.info.rca = 1u16.into();
363 self.sdmmc
364 .cmd(emmc_cmd::assign_relative_address(self.info.rca), false)?;
365
366 self.info.csd = self.sdmmc.get_csd(self.info.get_address())?.into();
367 self.sdmmc.select_card(Some(self.info.get_address()))?;
368
369 let (widbus, _) = bus_width_vals(bus_width);
370
371 // Write bus width to ExtCSD byte 183
372 self.sdmmc.cmd(
373 emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus),
374 false,
375 )?;
376
377 // Wait for ready after R1b response
378 loop {
379 let status = self.sdmmc.read_status(&self.info)?;
380
381 if status.ready_for_data() {
382 break;
383 }
384 }
385
386 self.sdmmc.clkcr_set_clkdiv(freq.clamp(mhz(0), mhz(25)), bus_width)?;
387 self.info.ext_csd = self.read_ext_csd().await?;
388
389 Ok(())
390 }
391
392 /// Gets the EXT_CSD register.
393 ///
394 /// eMMC only.
395 async fn read_ext_csd(&self) -> Result<ExtCSD, Error> {
396 // Note: cmd_block can't be used because ExtCSD is too long to fit.
397 let mut data_block = DataBlock::new();
398
399 self.sdmmc
400 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)
401 .unwrap(); // CMD16
402
403 let transfer = self.sdmmc.prepare_datapath_read(
404 aligned_mut(&mut data_block.0),
405 DatapathMode::Block(block_size(size_of::<DataBlock>())),
406 );
407 self.sdmmc.cmd(emmc_cmd::send_ext_csd(), true)?;
408
409 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
410
411 Ok(data_block.0.into())
412 }
413}
414
415/// Card or Emmc storage device
416impl<'a, 'b, A: Addressable> StorageDevice<'a, 'b, A> {
417 /// Write a block
418 pub fn card(&self) -> A {
419 self.info.clone()
420 }
421
422 /// Read a data block.
423 #[inline]
424 pub async fn read_block(&mut self, block_idx: u32, data_block: &mut DataBlock) -> Result<(), Error> {
425 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
426 let card_capacity = self.info.get_capacity();
427
428 // Always read 1 block of 512 bytes
429 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
430 let address = match card_capacity {
431 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
432 _ => block_idx,
433 };
434 self.sdmmc
435 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
436
437 let transfer = self.sdmmc.prepare_datapath_read(
438 aligned_mut(&mut data_block.0),
439 DatapathMode::Block(block_size(size_of::<DataBlock>())),
440 );
441 self.sdmmc.cmd(common_cmd::read_single_block(address), true)?;
442
443 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
444
445 Ok(())
446 }
447
448 /// Read multiple data blocks.
449 #[inline]
450 pub async fn read_blocks(&mut self, block_idx: u32, blocks: &mut [DataBlock]) -> Result<(), Error> {
451 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
452 let card_capacity = self.info.get_capacity();
453
454 // NOTE(unsafe) reinterpret buffer as &mut [u32]
455 let buffer = unsafe {
456 core::slice::from_raw_parts_mut(
457 blocks.as_mut_ptr() as *mut u32,
458 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
459 )
460 };
461
462 // Always read 1 block of 512 bytes
463 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
464 let address = match card_capacity {
465 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
466 _ => block_idx,
467 };
468 self.sdmmc
469 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
470
471 let transfer = self.sdmmc.prepare_datapath_read(
472 aligned_mut(buffer),
473 DatapathMode::Block(block_size(size_of::<DataBlock>())),
474 );
475 self.sdmmc.cmd(common_cmd::read_multiple_blocks(address), true)?;
476
477 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
478
479 self.sdmmc.cmd(common_cmd::stop_transmission(), false)?; // CMD12
480 self.sdmmc.clear_interrupt_flags();
481
482 Ok(())
483 }
484
485 /// Write a data block.
486 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error>
487 where
488 CardStatus<A::Ext>: From<u32>,
489 {
490 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
491
492 // Always read 1 block of 512 bytes
493 // cards are byte addressed hence the blockaddress is in multiples of 512 bytes
494 let address = match self.info.get_capacity() {
495 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
496 _ => block_idx,
497 };
498 self.sdmmc
499 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
500
501 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
502 #[cfg(sdmmc_v1)]
503 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?;
504
505 let transfer = self.sdmmc.prepare_datapath_write(
506 aligned_ref(&buffer.0),
507 DatapathMode::Block(block_size(size_of::<DataBlock>())),
508 );
509
510 #[cfg(sdmmc_v2)]
511 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?;
512
513 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
514
515 // TODO: Make this configurable
516 let mut timeout: u32 = 0x00FF_FFFF;
517
518 while timeout > 0 {
519 let ready_for_data = self.sdmmc.read_status(&self.info)?.ready_for_data();
520 if ready_for_data {
521 return Ok(());
522 }
523 timeout -= 1;
524 }
525
526 Err(Error::SoftwareTimeout)
527 }
528
529 /// Write multiple data blocks.
530 pub async fn write_blocks(&mut self, block_idx: u32, blocks: &[DataBlock]) -> Result<(), Error>
531 where
532 CardStatus<A::Ext>: From<u32>,
533 {
534 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
535
536 // NOTE(unsafe) reinterpret buffer as &[u32]
537 let buffer = unsafe {
538 core::slice::from_raw_parts(
539 blocks.as_ptr() as *const u32,
540 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
541 )
542 };
543 // Always read 1 block of 512 bytes
544 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
545 let address = match self.info.get_capacity() {
546 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
547 _ => block_idx,
548 };
549
550 self.sdmmc
551 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
552
553 #[cfg(sdmmc_v1)]
554 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
555
556 // Setup write command
557 let transfer = self.sdmmc.prepare_datapath_write(
558 aligned_ref(buffer),
559 DatapathMode::Block(block_size(size_of::<DataBlock>())),
560 );
561 #[cfg(sdmmc_v2)]
562 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
563
564 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
565
566 self.sdmmc.cmd(common_cmd::stop_transmission(), false)?; // CMD12
567 self.sdmmc.clear_interrupt_flags();
568
569 // TODO: Make this configurable
570 let mut timeout: u32 = 0x00FF_FFFF;
571
572 while timeout > 0 {
573 let ready_for_data = self.sdmmc.read_status(&self.info)?.ready_for_data();
574
575 if ready_for_data {
576 return Ok(());
577 }
578 timeout -= 1;
579 }
580 Err(Error::SoftwareTimeout)
581 }
582}
583
584#[derive(Clone, Copy, Debug, Default)]
585/// SD Card
586pub struct Card {
587 /// The type of this card
588 pub card_type: CardCapacity,
589 /// Operation Conditions Register
590 pub ocr: OCR<SD>,
591 /// Relative Card Address
592 pub rca: u16,
593 /// Card ID
594 pub cid: CID<SD>,
595 /// Card Specific Data
596 pub csd: CSD<SD>,
597 /// SD CARD Configuration Register
598 pub scr: SCR,
599 /// SD Status
600 pub status: SDStatus,
601}
602
603impl Addressable for Card {
604 type Ext = SD;
605
606 /// Get this peripheral's address on the SDMMC bus
607 fn get_address(&self) -> u16 {
608 self.rca
609 }
610
611 /// Is this a standard or high capacity peripheral?
612 fn get_capacity(&self) -> CardCapacity {
613 self.card_type
614 }
615
616 /// Size in bytes
617 fn size(&self) -> u64 {
618 u64::from(self.csd.block_count()) * 512
619 }
620}
621
622#[derive(Clone, Copy, Debug, Default)]
623/// eMMC storage
624pub struct Emmc {
625 /// The capacity of this card
626 pub capacity: CardCapacity,
627 /// Operation Conditions Register
628 pub ocr: OCR<EMMC>,
629 /// Relative Card Address
630 pub rca: u16,
631 /// Card ID
632 pub cid: CID<EMMC>,
633 /// Card Specific Data
634 pub csd: CSD<EMMC>,
635 /// Extended Card Specific Data
636 pub ext_csd: ExtCSD,
637}
638
639impl Addressable for Emmc {
640 type Ext = EMMC;
641
642 /// Get this peripheral's address on the SDMMC bus
643 fn get_address(&self) -> u16 {
644 self.rca
645 }
646
647 /// Is this a standard or high capacity peripheral?
648 fn get_capacity(&self) -> CardCapacity {
649 self.capacity
650 }
651
652 /// Size in bytes
653 fn size(&self) -> u64 {
654 u64::from(self.ext_csd.sector_count()) * 512
655 }
656}
657
658impl<'d, 'e, A: Addressable> block_device_driver::BlockDevice<512> for StorageDevice<'d, 'e, A> {
659 type Error = Error;
660 type Align = aligned::A4;
661
662 async fn read(
663 &mut self,
664 block_address: u32,
665 buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>],
666 ) -> Result<(), Self::Error> {
667 // TODO: I think block_address needs to be adjusted by the partition start offset
668 if buf.len() == 1 {
669 let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut DataBlock) };
670 self.read_block(block_address, block).await?;
671 } else {
672 let blocks: &mut [DataBlock] =
673 unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut DataBlock, buf.len()) };
674 self.read_blocks(block_address, blocks).await?;
675 }
676 Ok(())
677 }
678
679 async fn write(
680 &mut self,
681 block_address: u32,
682 buf: &[aligned::Aligned<Self::Align, [u8; 512]>],
683 ) -> Result<(), Self::Error> {
684 // TODO: I think block_address needs to be adjusted by the partition start offset
685 if buf.len() == 1 {
686 let block = unsafe { &*(&buf[0] as *const _ as *const DataBlock) };
687 self.write_block(block_address, block).await?;
688 } else {
689 let blocks: &[DataBlock] =
690 unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const DataBlock, buf.len()) };
691 self.write_blocks(block_address, blocks).await?;
692 }
693 Ok(())
694 }
695
696 async fn size(&mut self) -> Result<u64, Self::Error> {
697 Ok(self.info.size())
698 }
699}
diff --git a/embassy-stm32/src/sdmmc/sdio.rs b/embassy-stm32/src/sdmmc/sdio.rs
new file mode 100644
index 000000000..e436d68cb
--- /dev/null
+++ b/embassy-stm32/src/sdmmc/sdio.rs
@@ -0,0 +1,178 @@
1use core::ops::{Deref, DerefMut};
2
3use aligned::{A4, Aligned};
4use sdio_host::common_cmd::{R1, Rz, cmd};
5use sdio_host::sd::BusWidth;
6use sdio_host::sd_cmd;
7
8use crate::sdmmc::{DatapathMode, Error, Sdmmc, aligned_mut, aligned_ref, block_size, slice8_mut, slice8_ref};
9use crate::time::Hertz;
10
11/// Aligned data block for SDMMC transfers.
12///
13/// This is a 64-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; 16]);
18
19impl DataBlock {
20 /// Create a new DataBlock
21 pub const fn new() -> Self {
22 DataBlock([0u32; 16])
23 }
24}
25
26impl Deref for DataBlock {
27 type Target = [u8; 64];
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/// Storage Device
41pub struct SerialDataInterface<'a, 'b> {
42 /// Inner member
43 sdmmc: &'a mut Sdmmc<'b>,
44}
45
46/// Card Storage Device
47impl<'a, 'b> SerialDataInterface<'a, 'b> {
48 /// Create a new SD card
49 pub async fn new(sdmmc: &'a mut Sdmmc<'b>, freq: Hertz) -> Result<Self, Error> {
50 let mut s = Self { sdmmc };
51
52 s.acquire(freq).await?;
53
54 Ok(s)
55 }
56
57 /// Initializes the card into a known state (or at least tries to).
58 async fn acquire(&mut self, _freq: Hertz) -> Result<(), Error> {
59 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
60
61 let _bus_width = match self.sdmmc.bus_width() {
62 BusWidth::Eight => return Err(Error::BusWidth),
63 bus_width => bus_width,
64 };
65
66 // While the SD/SDIO card or eMMC is in identification mode,
67 // the SDMMC_CK frequency must be no more than 400 kHz.
68 self.sdmmc.init_idle()?;
69
70 self.sdmmc.cmd(cmd::<Rz>(5, 0), false)?;
71
72 // Get RCA
73 let rca = self.sdmmc.cmd(sd_cmd::send_relative_address(), false)?;
74
75 // Select the card with RCA
76 self.sdmmc.select_card(Some(rca.try_into().unwrap()))?;
77
78 Ok(())
79 }
80
81 /// Set the bus to the 4-bit high-speed frequency
82 pub fn set_bus_to_high_speed(&mut self, frequency: Hertz) -> Result<(), Error> {
83 self.sdmmc.clkcr_set_clkdiv(frequency, BusWidth::Four)?;
84
85 Ok(())
86 }
87
88 /// Run cmd52
89 pub async fn cmd52(&mut self, arg: u32) -> Result<u32, Error> {
90 self.sdmmc.cmd(cmd::<R1>(52, arg), false)
91 }
92
93 /// Read in block mode using cmd53
94 pub async fn cmd53_block_read(&mut self, arg: u32, blocks: &mut [DataBlock]) -> Result<(), Error> {
95 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
96
97 // NOTE(unsafe) reinterpret buffer as &mut [u32]
98 let buffer = unsafe {
99 core::slice::from_raw_parts_mut(
100 blocks.as_mut_ptr() as *mut u32,
101 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
102 )
103 };
104
105 let transfer = self.sdmmc.prepare_datapath_read(
106 aligned_mut(buffer),
107 DatapathMode::Block(block_size(size_of::<DataBlock>())),
108 );
109 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
110
111 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
112 self.sdmmc.clear_interrupt_flags();
113
114 Ok(())
115 }
116
117 /// Read in multibyte mode using cmd53
118 pub async fn cmd53_byte_read(&mut self, arg: u32, buffer: &mut Aligned<A4, [u8]>) -> Result<(), Error> {
119 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
120
121 let transfer = self.sdmmc.prepare_datapath_read(buffer, DatapathMode::Byte);
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.sdmmc.prepare_datapath_write(
146 aligned_ref(buffer),
147 DatapathMode::Block(block_size(size_of::<DataBlock>())),
148 );
149
150 #[cfg(sdmmc_v2)]
151 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
152
153 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
154 self.sdmmc.clear_interrupt_flags();
155
156 Ok(())
157 }
158
159 /// Write in multibyte mode using cmd53
160 pub async fn cmd53_byte_write(&mut self, arg: u32, buffer: &[u32]) -> Result<(), Error> {
161 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
162
163 #[cfg(sdmmc_v1)]
164 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
165
166 let transfer = self
167 .sdmmc
168 .prepare_datapath_write(aligned_ref(buffer), DatapathMode::Byte);
169
170 #[cfg(sdmmc_v2)]
171 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
172
173 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
174 self.sdmmc.clear_interrupt_flags();
175
176 Ok(())
177 }
178}