embassy_stm32/sdmmc/
mod.rs

1//! Secure Digital / MultiMedia Card (SDMMC)
2#![macro_use]
3
4use core::default::Default;
5use core::future::poll_fn;
6use core::marker::PhantomData;
7use core::ops::{Deref, DerefMut};
8use core::task::Poll;
9
10use embassy_hal_internal::drop::OnDrop;
11use embassy_hal_internal::{into_ref, PeripheralRef};
12use embassy_sync::waitqueue::AtomicWaker;
13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};
14
15use crate::dma::NoDma;
16#[cfg(gpio_v2)]
17use crate::gpio::Pull;
18use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed};
19use crate::interrupt::typelevel::Interrupt;
20use crate::pac::sdmmc::Sdmmc as RegBlock;
21use crate::rcc::{self, RccPeripheral};
22use crate::time::Hertz;
23use crate::{interrupt, peripherals, Peripheral};
24
25/// Interrupt handler.
26pub struct InterruptHandler<T: Instance> {
27    _phantom: PhantomData<T>,
28}
29
30impl<T: Instance> InterruptHandler<T> {
31    fn data_interrupts(enable: bool) {
32        let regs = T::regs();
33        regs.maskr().write(|w| {
34            w.set_dcrcfailie(enable);
35            w.set_dtimeoutie(enable);
36            w.set_dataendie(enable);
37
38            #[cfg(sdmmc_v1)]
39            w.set_stbiterre(enable);
40            #[cfg(sdmmc_v2)]
41            w.set_dabortie(enable);
42        });
43    }
44}
45
46impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
47    unsafe fn on_interrupt() {
48        Self::data_interrupts(false);
49        T::state().wake();
50    }
51}
52
53/// Frequency used for SD Card initialization. Must be no higher than 400 kHz.
54const SD_INIT_FREQ: Hertz = Hertz(400_000);
55
56/// The signalling scheme used on the SDMMC bus
57#[non_exhaustive]
58#[allow(missing_docs)]
59#[derive(Debug, Copy, Clone, PartialEq, Eq)]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61pub enum Signalling {
62    SDR12,
63    SDR25,
64    SDR50,
65    SDR104,
66    DDR50,
67}
68
69impl Default for Signalling {
70    fn default() -> Self {
71        Signalling::SDR12
72    }
73}
74
75/// Aligned data block for SDMMC transfers.
76///
77/// This is a 512-byte array, aligned to 4 bytes to satisfy DMA requirements.
78#[repr(align(4))]
79#[derive(Debug, Clone, PartialEq, Eq)]
80#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81pub struct DataBlock(pub [u8; 512]);
82
83impl Deref for DataBlock {
84    type Target = [u8; 512];
85
86    fn deref(&self) -> &Self::Target {
87        &self.0
88    }
89}
90
91impl DerefMut for DataBlock {
92    fn deref_mut(&mut self) -> &mut Self::Target {
93        &mut self.0
94    }
95}
96
97/// Command Block buffer for SDMMC command transfers.
98///
99/// This is a 16-word array, exposed so that DMA commpatible memory can be used if required.
100#[derive(Debug, Clone, PartialEq, Eq)]
101#[cfg_attr(feature = "defmt", derive(defmt::Format))]
102pub struct CmdBlock(pub [u32; 16]);
103
104impl CmdBlock {
105    /// Creates a new instance of CmdBlock
106    pub const fn new() -> Self {
107        Self([0u32; 16])
108    }
109}
110
111impl Deref for CmdBlock {
112    type Target = [u32; 16];
113
114    fn deref(&self) -> &Self::Target {
115        &self.0
116    }
117}
118
119impl DerefMut for CmdBlock {
120    fn deref_mut(&mut self) -> &mut Self::Target {
121        &mut self.0
122    }
123}
124
125/// Errors
126#[non_exhaustive]
127#[derive(Debug, Copy, Clone, PartialEq, Eq)]
128#[cfg_attr(feature = "defmt", derive(defmt::Format))]
129pub enum Error {
130    /// Timeout reported by the hardware
131    Timeout,
132    /// Timeout reported by the software driver.
133    SoftwareTimeout,
134    /// Unsupported card version.
135    UnsupportedCardVersion,
136    /// Unsupported card type.
137    UnsupportedCardType,
138    /// CRC error.
139    Crc,
140    /// No card inserted.
141    NoCard,
142    /// Bad clock supplied to the SDMMC peripheral.
143    BadClock,
144    /// Signaling switch failed.
145    SignalingSwitchFailed,
146    /// ST bit error.
147    #[cfg(sdmmc_v1)]
148    StBitErr,
149}
150
151/// A SD command
152struct Cmd {
153    cmd: u8,
154    arg: u32,
155    resp: Response,
156}
157
158#[derive(Clone, Copy, Debug, Default)]
159/// SD Card
160pub struct Card {
161    /// The type of this card
162    pub card_type: CardCapacity,
163    /// Operation Conditions Register
164    pub ocr: OCR,
165    /// Relative Card Address
166    pub rca: u32,
167    /// Card ID
168    pub cid: CID,
169    /// Card Specific Data
170    pub csd: CSD,
171    /// SD CARD Configuration Register
172    pub scr: SCR,
173    /// SD Status
174    pub status: SDStatus,
175}
176
177impl Card {
178    /// Size in bytes
179    pub fn size(&self) -> u64 {
180        // SDHC / SDXC / SDUC
181        u64::from(self.csd.block_count()) * 512
182    }
183}
184
185#[repr(u8)]
186enum PowerCtrl {
187    Off = 0b00,
188    On = 0b11,
189}
190
191#[repr(u32)]
192#[allow(dead_code)]
193#[allow(non_camel_case_types)]
194enum CmdAppOper {
195    VOLTAGE_WINDOW_SD = 0x8010_0000,
196    HIGH_CAPACITY = 0x4000_0000,
197    SDMMC_STD_CAPACITY = 0x0000_0000,
198    SDMMC_CHECK_PATTERN = 0x0000_01AA,
199    SD_SWITCH_1_8V_CAPACITY = 0x0100_0000,
200}
201
202#[derive(Eq, PartialEq, Copy, Clone)]
203enum Response {
204    None = 0,
205    Short = 1,
206    Long = 3,
207}
208
209/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to
210/// `sdmmc_ck` in Hertz.
211///
212/// Returns `(bypass, clk_div, clk_f)`, where `bypass` enables clock divisor bypass (only sdmmc_v1),
213/// `clk_div` is the divisor register value and `clk_f` is the resulting new clock frequency.
214#[cfg(sdmmc_v1)]
215fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u8, Hertz), Error> {
216    // sdmmc_v1 maximum clock is 50 MHz
217    if sdmmc_ck > 50_000_000 {
218        return Err(Error::BadClock);
219    }
220
221    // bypass divisor
222    if ker_ck.0 <= sdmmc_ck {
223        return Ok((true, 0, ker_ck));
224    }
225
226    // `ker_ck / sdmmc_ck` rounded up
227    let clk_div = match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck {
228        0 | 1 => Ok(0),
229        x @ 2..=258 => Ok((x - 2) as u8),
230        _ => Err(Error::BadClock),
231    }?;
232
233    // SDIO_CK frequency = SDIOCLK / [CLKDIV + 2]
234    let clk_f = Hertz(ker_ck.0 / (clk_div as u32 + 2));
235    Ok((false, clk_div, clk_f))
236}
237
238/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to
239/// `sdmmc_ck` in Hertz.
240///
241/// Returns `(bypass, clk_div, clk_f)`, where `bypass` enables clock divisor bypass (only sdmmc_v1),
242/// `clk_div` is the divisor register value and `clk_f` is the resulting new clock frequency.
243#[cfg(sdmmc_v2)]
244fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u16, Hertz), Error> {
245    // `ker_ck / sdmmc_ck` rounded up
246    match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck {
247        0 | 1 => Ok((false, 0, ker_ck)),
248        x @ 2..=2046 => {
249            // SDMMC_CK frequency = SDMMCCLK / [CLKDIV * 2]
250            let clk_div = ((x + 1) / 2) as u16;
251            let clk = Hertz(ker_ck.0 / (clk_div as u32 * 2));
252
253            Ok((false, clk_div, clk))
254        }
255        _ => Err(Error::BadClock),
256    }
257}
258
259#[cfg(sdmmc_v1)]
260type Transfer<'a> = crate::dma::Transfer<'a>;
261#[cfg(sdmmc_v2)]
262struct Transfer<'a> {
263    _dummy: PhantomData<&'a ()>,
264}
265
266#[cfg(all(sdmmc_v1, dma))]
267const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions {
268    pburst: crate::dma::Burst::Incr4,
269    mburst: crate::dma::Burst::Incr4,
270    flow_ctrl: crate::dma::FlowControl::Peripheral,
271    fifo_threshold: Some(crate::dma::FifoThreshold::Full),
272    priority: crate::dma::Priority::VeryHigh,
273    circular: false,
274    half_transfer_ir: false,
275    complete_transfer_ir: true,
276};
277#[cfg(all(sdmmc_v1, not(dma)))]
278const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions {
279    priority: crate::dma::Priority::VeryHigh,
280    circular: false,
281    half_transfer_ir: false,
282    complete_transfer_ir: true,
283};
284
285/// SDMMC configuration
286///
287/// Default values:
288/// data_transfer_timeout: 5_000_000
289#[non_exhaustive]
290pub struct Config {
291    /// The timeout to be set for data transfers, in card bus clock periods
292    pub data_transfer_timeout: u32,
293}
294
295impl Default for Config {
296    fn default() -> Self {
297        Self {
298            data_transfer_timeout: 5_000_000,
299        }
300    }
301}
302
303/// Sdmmc device
304pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> {
305    _peri: PeripheralRef<'d, T>,
306    #[allow(unused)]
307    dma: PeripheralRef<'d, Dma>,
308
309    clk: PeripheralRef<'d, AnyPin>,
310    cmd: PeripheralRef<'d, AnyPin>,
311    d0: PeripheralRef<'d, AnyPin>,
312    d1: Option<PeripheralRef<'d, AnyPin>>,
313    d2: Option<PeripheralRef<'d, AnyPin>>,
314    d3: Option<PeripheralRef<'d, AnyPin>>,
315
316    config: Config,
317    /// Current clock to card
318    clock: Hertz,
319    /// Current signalling scheme to card
320    signalling: Signalling,
321    /// Card
322    card: Option<Card>,
323
324    /// An optional buffer to be used for commands
325    /// This should be used if there are special memory location requirements for dma
326    cmd_block: Option<&'d mut CmdBlock>,
327}
328
329const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh);
330#[cfg(gpio_v1)]
331const CMD_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh);
332#[cfg(gpio_v2)]
333const CMD_AF: AfType = AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up);
334const DATA_AF: AfType = CMD_AF;
335
336#[cfg(sdmmc_v1)]
337impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
338    /// Create a new SDMMC driver, with 1 data lane.
339    pub fn new_1bit(
340        sdmmc: impl Peripheral<P = T> + 'd,
341        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
342        dma: impl Peripheral<P = Dma> + 'd,
343        clk: impl Peripheral<P = impl CkPin<T>> + 'd,
344        cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
345        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
346        config: Config,
347    ) -> Self {
348        into_ref!(clk, cmd, d0);
349
350        critical_section::with(|_| {
351            clk.set_as_af(clk.af_num(), CLK_AF);
352            cmd.set_as_af(cmd.af_num(), CMD_AF);
353            d0.set_as_af(d0.af_num(), DATA_AF);
354        });
355
356        Self::new_inner(
357            sdmmc,
358            dma,
359            clk.map_into(),
360            cmd.map_into(),
361            d0.map_into(),
362            None,
363            None,
364            None,
365            config,
366        )
367    }
368
369    /// Create a new SDMMC driver, with 4 data lanes.
370    pub fn new_4bit(
371        sdmmc: impl Peripheral<P = T> + 'd,
372        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
373        dma: impl Peripheral<P = Dma> + 'd,
374        clk: impl Peripheral<P = impl CkPin<T>> + 'd,
375        cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
376        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
377        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
378        d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
379        d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
380        config: Config,
381    ) -> Self {
382        into_ref!(clk, cmd, d0, d1, d2, d3);
383
384        critical_section::with(|_| {
385            clk.set_as_af(clk.af_num(), CLK_AF);
386            cmd.set_as_af(cmd.af_num(), CMD_AF);
387            d0.set_as_af(d0.af_num(), DATA_AF);
388            d1.set_as_af(d1.af_num(), DATA_AF);
389            d2.set_as_af(d2.af_num(), DATA_AF);
390            d3.set_as_af(d3.af_num(), DATA_AF);
391        });
392
393        Self::new_inner(
394            sdmmc,
395            dma,
396            clk.map_into(),
397            cmd.map_into(),
398            d0.map_into(),
399            Some(d1.map_into()),
400            Some(d2.map_into()),
401            Some(d3.map_into()),
402            config,
403        )
404    }
405}
406
407#[cfg(sdmmc_v2)]
408impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
409    /// Create a new SDMMC driver, with 1 data lane.
410    pub fn new_1bit(
411        sdmmc: impl Peripheral<P = T> + 'd,
412        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
413        clk: impl Peripheral<P = impl CkPin<T>> + 'd,
414        cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
415        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
416        config: Config,
417    ) -> Self {
418        into_ref!(clk, cmd, d0);
419
420        critical_section::with(|_| {
421            clk.set_as_af(clk.af_num(), CLK_AF);
422            cmd.set_as_af(cmd.af_num(), CMD_AF);
423            d0.set_as_af(d0.af_num(), DATA_AF);
424        });
425
426        Self::new_inner(
427            sdmmc,
428            NoDma.into_ref(),
429            clk.map_into(),
430            cmd.map_into(),
431            d0.map_into(),
432            None,
433            None,
434            None,
435            config,
436        )
437    }
438
439    /// Create a new SDMMC driver, with 4 data lanes.
440    pub fn new_4bit(
441        sdmmc: impl Peripheral<P = T> + 'd,
442        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
443        clk: impl Peripheral<P = impl CkPin<T>> + 'd,
444        cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
445        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
446        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
447        d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
448        d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
449        config: Config,
450    ) -> Self {
451        into_ref!(clk, cmd, d0, d1, d2, d3);
452
453        critical_section::with(|_| {
454            clk.set_as_af(clk.af_num(), CLK_AF);
455            cmd.set_as_af(cmd.af_num(), CMD_AF);
456            d0.set_as_af(d0.af_num(), DATA_AF);
457            d1.set_as_af(d1.af_num(), DATA_AF);
458            d2.set_as_af(d2.af_num(), DATA_AF);
459            d3.set_as_af(d3.af_num(), DATA_AF);
460        });
461
462        Self::new_inner(
463            sdmmc,
464            NoDma.into_ref(),
465            clk.map_into(),
466            cmd.map_into(),
467            d0.map_into(),
468            Some(d1.map_into()),
469            Some(d2.map_into()),
470            Some(d3.map_into()),
471            config,
472        )
473    }
474}
475
476impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
477    fn new_inner(
478        sdmmc: impl Peripheral<P = T> + 'd,
479        dma: impl Peripheral<P = Dma> + 'd,
480        clk: PeripheralRef<'d, AnyPin>,
481        cmd: PeripheralRef<'d, AnyPin>,
482        d0: PeripheralRef<'d, AnyPin>,
483        d1: Option<PeripheralRef<'d, AnyPin>>,
484        d2: Option<PeripheralRef<'d, AnyPin>>,
485        d3: Option<PeripheralRef<'d, AnyPin>>,
486        config: Config,
487    ) -> Self {
488        into_ref!(sdmmc, dma);
489
490        rcc::enable_and_reset::<T>();
491
492        T::Interrupt::unpend();
493        unsafe { T::Interrupt::enable() };
494
495        let regs = T::regs();
496        regs.clkcr().write(|w| {
497            w.set_pwrsav(false);
498            w.set_negedge(false);
499
500            // Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors.
501            // See chip erratas for more details.
502            #[cfg(sdmmc_v1)]
503            w.set_hwfc_en(false);
504            #[cfg(sdmmc_v2)]
505            w.set_hwfc_en(true);
506
507            #[cfg(sdmmc_v1)]
508            w.set_clken(true);
509        });
510
511        // Power off, writen 00: Clock to the card is stopped;
512        // D[7:0], CMD, and CK are driven high.
513        regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8));
514
515        Self {
516            _peri: sdmmc,
517            dma,
518
519            clk,
520            cmd,
521            d0,
522            d1,
523            d2,
524            d3,
525
526            config,
527            clock: SD_INIT_FREQ,
528            signalling: Default::default(),
529            card: None,
530            cmd_block: None,
531        }
532    }
533
534    /// Data transfer is in progress
535    #[inline]
536    fn data_active() -> bool {
537        let regs = T::regs();
538
539        let status = regs.star().read();
540        #[cfg(sdmmc_v1)]
541        return status.rxact() || status.txact();
542        #[cfg(sdmmc_v2)]
543        return status.dpsmact();
544    }
545
546    /// Coammand transfer is in progress
547    #[inline]
548    fn cmd_active() -> bool {
549        let regs = T::regs();
550
551        let status = regs.star().read();
552        #[cfg(sdmmc_v1)]
553        return status.cmdact();
554        #[cfg(sdmmc_v2)]
555        return status.cpsmact();
556    }
557
558    /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2)
559    #[inline]
560    fn wait_idle() {
561        while Self::data_active() || Self::cmd_active() {}
562    }
563
564    /// # Safety
565    ///
566    /// `buffer` must be valid for the whole transfer and word aligned
567    #[allow(unused_variables)]
568    fn prepare_datapath_read<'a>(
569        config: &Config,
570        dma: &'a mut PeripheralRef<'d, Dma>,
571        buffer: &'a mut [u32],
572        length_bytes: u32,
573        block_size: u8,
574    ) -> Transfer<'a> {
575        assert!(block_size <= 14, "Block size up to 2^14 bytes");
576        let regs = T::regs();
577
578        // Command AND Data state machines must be idle
579        Self::wait_idle();
580        Self::clear_interrupt_flags();
581
582        regs.dtimer().write(|w| w.set_datatime(config.data_transfer_timeout));
583        regs.dlenr().write(|w| w.set_datalength(length_bytes));
584
585        #[cfg(sdmmc_v1)]
586        let transfer = unsafe {
587            let request = dma.request();
588            Transfer::new_read(
589                dma,
590                request,
591                regs.fifor().as_ptr() as *mut u32,
592                buffer,
593                DMA_TRANSFER_OPTIONS,
594            )
595        };
596        #[cfg(sdmmc_v2)]
597        let transfer = {
598            regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32));
599            regs.idmactrlr().modify(|w| w.set_idmaen(true));
600            Transfer {
601                _dummy: core::marker::PhantomData,
602            }
603        };
604
605        regs.dctrl().modify(|w| {
606            w.set_dblocksize(block_size);
607            w.set_dtdir(true);
608            #[cfg(sdmmc_v1)]
609            {
610                w.set_dmaen(true);
611                w.set_dten(true);
612            }
613        });
614
615        transfer
616    }
617
618    /// # Safety
619    ///
620    /// `buffer` must be valid for the whole transfer and word aligned
621    fn prepare_datapath_write<'a>(&'a mut self, buffer: &'a [u32], length_bytes: u32, block_size: u8) -> Transfer<'a> {
622        assert!(block_size <= 14, "Block size up to 2^14 bytes");
623        let regs = T::regs();
624
625        // Command AND Data state machines must be idle
626        Self::wait_idle();
627        Self::clear_interrupt_flags();
628
629        regs.dtimer()
630            .write(|w| w.set_datatime(self.config.data_transfer_timeout));
631        regs.dlenr().write(|w| w.set_datalength(length_bytes));
632
633        #[cfg(sdmmc_v1)]
634        let transfer = unsafe {
635            let request = self.dma.request();
636            Transfer::new_write(
637                &mut self.dma,
638                request,
639                buffer,
640                regs.fifor().as_ptr() as *mut u32,
641                DMA_TRANSFER_OPTIONS,
642            )
643        };
644        #[cfg(sdmmc_v2)]
645        let transfer = {
646            regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_ptr() as u32));
647            regs.idmactrlr().modify(|w| w.set_idmaen(true));
648            Transfer {
649                _dummy: core::marker::PhantomData,
650            }
651        };
652
653        regs.dctrl().modify(|w| {
654            w.set_dblocksize(block_size);
655            w.set_dtdir(false);
656            #[cfg(sdmmc_v1)]
657            {
658                w.set_dmaen(true);
659                w.set_dten(true);
660            }
661        });
662
663        transfer
664    }
665
666    /// Stops the DMA datapath
667    fn stop_datapath() {
668        let regs = T::regs();
669
670        #[cfg(sdmmc_v1)]
671        regs.dctrl().modify(|w| {
672            w.set_dmaen(false);
673            w.set_dten(false);
674        });
675        #[cfg(sdmmc_v2)]
676        regs.idmactrlr().modify(|w| w.set_idmaen(false));
677    }
678
679    /// Sets the CLKDIV field in CLKCR. Updates clock field in self
680    fn clkcr_set_clkdiv(&mut self, freq: u32, width: BusWidth) -> Result<(), Error> {
681        let regs = T::regs();
682
683        let width_u32 = match width {
684            BusWidth::One => 1u32,
685            BusWidth::Four => 4u32,
686            BusWidth::Eight => 8u32,
687            _ => panic!("Invalid Bus Width"),
688        };
689
690        let ker_ck = T::frequency();
691        let (_bypass, clkdiv, new_clock) = clk_div(ker_ck, freq)?;
692
693        // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7
694        // Section 55.5.8
695        let sdmmc_bus_bandwidth = new_clock.0 * width_u32;
696        assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32);
697        self.clock = new_clock;
698
699        // CPSMACT and DPSMACT must be 0 to set CLKDIV
700        Self::wait_idle();
701        regs.clkcr().modify(|w| {
702            w.set_clkdiv(clkdiv);
703            #[cfg(sdmmc_v1)]
704            w.set_bypass(_bypass);
705        });
706
707        Ok(())
708    }
709
710    /// Switch mode using CMD6.
711    ///
712    /// Attempt to set a new signalling mode. The selected
713    /// signalling mode is returned. Expects the current clock
714    /// frequency to be > 12.5MHz.
715    async fn switch_signalling_mode(&mut self, signalling: Signalling) -> Result<Signalling, Error> {
716        // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
717        // necessary"
718
719        let set_function = 0x8000_0000
720            | match signalling {
721                // See PLSS v7_10 Table 4-11
722                Signalling::DDR50 => 0xFF_FF04,
723                Signalling::SDR104 => 0xFF_1F03,
724                Signalling::SDR50 => 0xFF_1F02,
725                Signalling::SDR25 => 0xFF_FF01,
726                Signalling::SDR12 => 0xFF_FF00,
727            };
728
729        let status = match self.cmd_block.as_deref_mut() {
730            Some(x) => x,
731            None => &mut CmdBlock::new(),
732        };
733
734        // Arm `OnDrop` after the buffer, so it will be dropped first
735        let regs = T::regs();
736        let on_drop = OnDrop::new(|| Self::on_drop());
737
738        let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6);
739        InterruptHandler::<T>::data_interrupts(true);
740        Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6
741
742        let res = poll_fn(|cx| {
743            T::state().register(cx.waker());
744            let status = regs.star().read();
745
746            if status.dcrcfail() {
747                return Poll::Ready(Err(Error::Crc));
748            }
749            if status.dtimeout() {
750                return Poll::Ready(Err(Error::Timeout));
751            }
752            #[cfg(sdmmc_v1)]
753            if status.stbiterr() {
754                return Poll::Ready(Err(Error::StBitErr));
755            }
756            if status.dataend() {
757                return Poll::Ready(Ok(()));
758            }
759            Poll::Pending
760        })
761        .await;
762        Self::clear_interrupt_flags();
763
764        // Host is allowed to use the new functions at least 8
765        // clocks after the end of the switch command
766        // transaction. We know the current clock period is < 80ns,
767        // so a total delay of 640ns is required here
768        for _ in 0..300 {
769            cortex_m::asm::nop();
770        }
771
772        match res {
773            Ok(_) => {
774                on_drop.defuse();
775                Self::stop_datapath();
776                drop(transfer);
777
778                // Function Selection of Function Group 1
779                let selection = (u32::from_be(status[4]) >> 24) & 0xF;
780
781                match selection {
782                    0 => Ok(Signalling::SDR12),
783                    1 => Ok(Signalling::SDR25),
784                    2 => Ok(Signalling::SDR50),
785                    3 => Ok(Signalling::SDR104),
786                    4 => Ok(Signalling::DDR50),
787                    _ => Err(Error::UnsupportedCardType),
788                }
789            }
790            Err(e) => Err(e),
791        }
792    }
793
794    /// Query the card status (CMD13, returns R1)
795    fn read_status(&self, card: &Card) -> Result<CardStatus, Error> {
796        let regs = T::regs();
797        let rca = card.rca;
798
799        Self::cmd(Cmd::card_status(rca << 16), false)?; // CMD13
800
801        let r1 = regs.respr(0).read().cardstatus();
802        Ok(r1.into())
803    }
804
805    /// Reads the SD Status (ACMD13)
806    async fn read_sd_status(&mut self) -> Result<(), Error> {
807        let card = self.card.as_mut().ok_or(Error::NoCard)?;
808        let rca = card.rca;
809
810        let cmd_block = match self.cmd_block.as_deref_mut() {
811            Some(x) => x,
812            None => &mut CmdBlock::new(),
813        };
814
815        Self::cmd(Cmd::set_block_length(64), false)?; // CMD16
816        Self::cmd(Cmd::app_cmd(rca << 16), false)?; // APP
817
818        let status = cmd_block;
819
820        // Arm `OnDrop` after the buffer, so it will be dropped first
821        let regs = T::regs();
822        let on_drop = OnDrop::new(|| Self::on_drop());
823
824        let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6);
825        InterruptHandler::<T>::data_interrupts(true);
826        Self::cmd(Cmd::card_status(0), true)?;
827
828        let res = poll_fn(|cx| {
829            T::state().register(cx.waker());
830            let status = regs.star().read();
831
832            if status.dcrcfail() {
833                return Poll::Ready(Err(Error::Crc));
834            }
835            if status.dtimeout() {
836                return Poll::Ready(Err(Error::Timeout));
837            }
838            #[cfg(sdmmc_v1)]
839            if status.stbiterr() {
840                return Poll::Ready(Err(Error::StBitErr));
841            }
842            if status.dataend() {
843                return Poll::Ready(Ok(()));
844            }
845            Poll::Pending
846        })
847        .await;
848        Self::clear_interrupt_flags();
849
850        if res.is_ok() {
851            on_drop.defuse();
852            Self::stop_datapath();
853            drop(transfer);
854
855            for byte in status.iter_mut() {
856                *byte = u32::from_be(*byte);
857            }
858            self.card.as_mut().unwrap().status = status.0.into();
859        }
860        res
861    }
862
863    /// Select one card and place it into the _Tranfer State_
864    ///
865    /// If `None` is specifed for `card`, all cards are put back into
866    /// _Stand-by State_
867    fn select_card(&self, card: Option<&Card>) -> Result<(), Error> {
868        // Determine Relative Card Address (RCA) of given card
869        let rca = card.map(|c| c.rca << 16).unwrap_or(0);
870
871        let r = Self::cmd(Cmd::sel_desel_card(rca), false);
872        match (r, rca) {
873            (Err(Error::Timeout), 0) => Ok(()),
874            _ => r,
875        }
876    }
877
878    /// Clear flags in interrupt clear register
879    #[inline]
880    fn clear_interrupt_flags() {
881        let regs = T::regs();
882        regs.icr().write(|w| {
883            w.set_ccrcfailc(true);
884            w.set_dcrcfailc(true);
885            w.set_ctimeoutc(true);
886            w.set_dtimeoutc(true);
887            w.set_txunderrc(true);
888            w.set_rxoverrc(true);
889            w.set_cmdrendc(true);
890            w.set_cmdsentc(true);
891            w.set_dataendc(true);
892            w.set_dbckendc(true);
893            w.set_sdioitc(true);
894            #[cfg(sdmmc_v1)]
895            w.set_stbiterrc(true);
896
897            #[cfg(sdmmc_v2)]
898            {
899                w.set_dholdc(true);
900                w.set_dabortc(true);
901                w.set_busyd0endc(true);
902                w.set_ackfailc(true);
903                w.set_acktimeoutc(true);
904                w.set_vswendc(true);
905                w.set_ckstopc(true);
906                w.set_idmatec(true);
907                w.set_idmabtcc(true);
908            }
909        });
910    }
911
912    async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
913        // Read the the 64-bit SCR register
914        Self::cmd(Cmd::set_block_length(8), false)?; // CMD16
915        Self::cmd(Cmd::app_cmd(card.rca << 16), false)?;
916
917        let cmd_block = match self.cmd_block.as_deref_mut() {
918            Some(x) => x,
919            None => &mut CmdBlock::new(),
920        };
921        let scr = &mut cmd_block.0[..2];
922
923        // Arm `OnDrop` after the buffer, so it will be dropped first
924        let regs = T::regs();
925        let on_drop = OnDrop::new(|| Self::on_drop());
926
927        let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, scr, 8, 3);
928        InterruptHandler::<T>::data_interrupts(true);
929        Self::cmd(Cmd::cmd51(), true)?;
930
931        let res = poll_fn(|cx| {
932            T::state().register(cx.waker());
933            let status = regs.star().read();
934
935            if status.dcrcfail() {
936                return Poll::Ready(Err(Error::Crc));
937            }
938            if status.dtimeout() {
939                return Poll::Ready(Err(Error::Timeout));
940            }
941            #[cfg(sdmmc_v1)]
942            if status.stbiterr() {
943                return Poll::Ready(Err(Error::StBitErr));
944            }
945            if status.dataend() {
946                return Poll::Ready(Ok(()));
947            }
948            Poll::Pending
949        })
950        .await;
951        Self::clear_interrupt_flags();
952
953        if res.is_ok() {
954            on_drop.defuse();
955            Self::stop_datapath();
956            drop(transfer);
957
958            unsafe {
959                let scr_bytes = &*(&scr as *const _ as *const [u8; 8]);
960                card.scr = SCR(u64::from_be_bytes(*scr_bytes));
961            }
962        }
963        res
964    }
965
966    /// Send command to card
967    #[allow(unused_variables)]
968    fn cmd(cmd: Cmd, data: bool) -> Result<(), Error> {
969        let regs = T::regs();
970
971        Self::clear_interrupt_flags();
972        // CP state machine must be idle
973        while Self::cmd_active() {}
974
975        // Command arg
976        regs.argr().write(|w| w.set_cmdarg(cmd.arg));
977
978        // Command index and start CP State Machine
979        regs.cmdr().write(|w| {
980            w.set_waitint(false);
981            w.set_waitresp(cmd.resp as u8);
982            w.set_cmdindex(cmd.cmd);
983            w.set_cpsmen(true);
984
985            #[cfg(sdmmc_v2)]
986            {
987                // Special mode in CP State Machine
988                // CMD12: Stop Transmission
989                let cpsm_stop_transmission = cmd.cmd == 12;
990                w.set_cmdstop(cpsm_stop_transmission);
991                w.set_cmdtrans(data);
992            }
993        });
994
995        let mut status;
996        if cmd.resp == Response::None {
997            // Wait for CMDSENT or a timeout
998            while {
999                status = regs.star().read();
1000                !(status.ctimeout() || status.cmdsent())
1001            } {}
1002        } else {
1003            // Wait for CMDREND or CCRCFAIL or a timeout
1004            while {
1005                status = regs.star().read();
1006                !(status.ctimeout() || status.cmdrend() || status.ccrcfail())
1007            } {}
1008        }
1009
1010        if status.ctimeout() {
1011            return Err(Error::Timeout);
1012        } else if status.ccrcfail() {
1013            return Err(Error::Crc);
1014        }
1015        Ok(())
1016    }
1017
1018    fn on_drop() {
1019        let regs = T::regs();
1020        if Self::data_active() {
1021            Self::clear_interrupt_flags();
1022            // Send abort
1023            // CP state machine must be idle
1024            while Self::cmd_active() {}
1025
1026            // Command arg
1027            regs.argr().write(|w| w.set_cmdarg(0));
1028
1029            // Command index and start CP State Machine
1030            regs.cmdr().write(|w| {
1031                w.set_waitint(false);
1032                w.set_waitresp(Response::Short as u8);
1033                w.set_cmdindex(12);
1034                w.set_cpsmen(true);
1035
1036                #[cfg(sdmmc_v2)]
1037                {
1038                    w.set_cmdstop(true);
1039                    w.set_cmdtrans(false);
1040                }
1041            });
1042
1043            // Wait for the abort
1044            while Self::data_active() {}
1045        }
1046        InterruptHandler::<T>::data_interrupts(false);
1047        Self::clear_interrupt_flags();
1048        Self::stop_datapath();
1049    }
1050
1051    /// Initializes card (if present) and sets the bus at the specified frequency.
1052    pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> {
1053        let regs = T::regs();
1054        let ker_ck = T::frequency();
1055
1056        let bus_width = match self.d3.is_some() {
1057            true => BusWidth::Four,
1058            false => BusWidth::One,
1059        };
1060
1061        // While the SD/SDIO card or eMMC is in identification mode,
1062        // the SDMMC_CK frequency must be no more than 400 kHz.
1063        let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0));
1064        self.clock = init_clock;
1065
1066        // CPSMACT and DPSMACT must be 0 to set WIDBUS
1067        Self::wait_idle();
1068
1069        regs.clkcr().modify(|w| {
1070            w.set_widbus(0);
1071            w.set_clkdiv(clkdiv);
1072            #[cfg(sdmmc_v1)]
1073            w.set_bypass(_bypass);
1074        });
1075
1076        regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
1077        Self::cmd(Cmd::idle(), false)?;
1078
1079        // Check if cards supports CMD8 (with pattern)
1080        Self::cmd(Cmd::hs_send_ext_csd(0x1AA), false)?;
1081        let r1 = regs.respr(0).read().cardstatus();
1082
1083        let mut card = if r1 == 0x1AA {
1084            // Card echoed back the pattern. Must be at least v2
1085            Card::default()
1086        } else {
1087            return Err(Error::UnsupportedCardVersion);
1088        };
1089
1090        let ocr = loop {
1091            // Signal that next command is a app command
1092            Self::cmd(Cmd::app_cmd(0), false)?; // CMD55
1093
1094            let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32
1095                | CmdAppOper::HIGH_CAPACITY as u32
1096                | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32;
1097
1098            // Initialize card
1099            match Self::cmd(Cmd::app_op_cmd(arg), false) {
1100                // ACMD41
1101                Ok(_) => (),
1102                Err(Error::Crc) => (),
1103                Err(err) => return Err(err),
1104            }
1105            let ocr: OCR = regs.respr(0).read().cardstatus().into();
1106            if !ocr.is_busy() {
1107                // Power up done
1108                break ocr;
1109            }
1110        };
1111
1112        if ocr.high_capacity() {
1113            // Card is SDHC or SDXC or SDUC
1114            card.card_type = CardCapacity::SDHC;
1115        } else {
1116            card.card_type = CardCapacity::SDSC;
1117        }
1118        card.ocr = ocr;
1119
1120        Self::cmd(Cmd::all_send_cid(), false)?; // CMD2
1121        let cid0 = regs.respr(0).read().cardstatus() as u128;
1122        let cid1 = regs.respr(1).read().cardstatus() as u128;
1123        let cid2 = regs.respr(2).read().cardstatus() as u128;
1124        let cid3 = regs.respr(3).read().cardstatus() as u128;
1125        let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3);
1126        card.cid = cid.into();
1127
1128        Self::cmd(Cmd::send_rel_addr(), false)?;
1129        card.rca = regs.respr(0).read().cardstatus() >> 16;
1130
1131        Self::cmd(Cmd::send_csd(card.rca << 16), false)?;
1132        let csd0 = regs.respr(0).read().cardstatus() as u128;
1133        let csd1 = regs.respr(1).read().cardstatus() as u128;
1134        let csd2 = regs.respr(2).read().cardstatus() as u128;
1135        let csd3 = regs.respr(3).read().cardstatus() as u128;
1136        let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3);
1137        card.csd = csd.into();
1138
1139        self.select_card(Some(&card))?;
1140
1141        self.get_scr(&mut card).await?;
1142
1143        // Set bus width
1144        let (width, acmd_arg) = match bus_width {
1145            BusWidth::Eight => unimplemented!(),
1146            BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2),
1147            _ => (BusWidth::One, 0),
1148        };
1149        Self::cmd(Cmd::app_cmd(card.rca << 16), false)?;
1150        Self::cmd(Cmd::cmd6(acmd_arg), false)?;
1151
1152        // CPSMACT and DPSMACT must be 0 to set WIDBUS
1153        Self::wait_idle();
1154
1155        regs.clkcr().modify(|w| {
1156            w.set_widbus(match width {
1157                BusWidth::One => 0,
1158                BusWidth::Four => 1,
1159                BusWidth::Eight => 2,
1160                _ => panic!("Invalid Bus Width"),
1161            })
1162        });
1163
1164        // Set Clock
1165        if freq.0 <= 25_000_000 {
1166            // Final clock frequency
1167            self.clkcr_set_clkdiv(freq.0, width)?;
1168        } else {
1169            // Switch to max clock for SDR12
1170            self.clkcr_set_clkdiv(25_000_000, width)?;
1171        }
1172
1173        self.card = Some(card);
1174
1175        // Read status
1176        self.read_sd_status().await?;
1177
1178        if freq.0 > 25_000_000 {
1179            // Switch to SDR25
1180            self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?;
1181
1182            if self.signalling == Signalling::SDR25 {
1183                // Set final clock frequency
1184                self.clkcr_set_clkdiv(freq.0, width)?;
1185
1186                if self.read_status(&card)?.state() != CurrentState::Transfer {
1187                    return Err(Error::SignalingSwitchFailed);
1188                }
1189            }
1190        }
1191
1192        // Read status after signalling change
1193        self.read_sd_status().await?;
1194
1195        Ok(())
1196    }
1197
1198    /// Read a data block.
1199    #[inline]
1200    pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
1201        let card_capacity = self.card()?.card_type;
1202
1203        // NOTE(unsafe) DataBlock uses align 4
1204        let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) };
1205
1206        // Always read 1 block of 512 bytes
1207        // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1208        let address = match card_capacity {
1209            CardCapacity::SDSC => block_idx * 512,
1210            _ => block_idx,
1211        };
1212        Self::cmd(Cmd::set_block_length(512), false)?; // CMD16
1213
1214        let regs = T::regs();
1215        let on_drop = OnDrop::new(|| Self::on_drop());
1216
1217        let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, buffer, 512, 9);
1218        InterruptHandler::<T>::data_interrupts(true);
1219        Self::cmd(Cmd::read_single_block(address), true)?;
1220
1221        let res = poll_fn(|cx| {
1222            T::state().register(cx.waker());
1223            let status = regs.star().read();
1224
1225            if status.dcrcfail() {
1226                return Poll::Ready(Err(Error::Crc));
1227            }
1228            if status.dtimeout() {
1229                return Poll::Ready(Err(Error::Timeout));
1230            }
1231            #[cfg(sdmmc_v1)]
1232            if status.stbiterr() {
1233                return Poll::Ready(Err(Error::StBitErr));
1234            }
1235            if status.dataend() {
1236                return Poll::Ready(Ok(()));
1237            }
1238            Poll::Pending
1239        })
1240        .await;
1241        Self::clear_interrupt_flags();
1242
1243        if res.is_ok() {
1244            on_drop.defuse();
1245            Self::stop_datapath();
1246            drop(transfer);
1247        }
1248        res
1249    }
1250
1251    /// Write a data block.
1252    pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> {
1253        let card = self.card.as_mut().ok_or(Error::NoCard)?;
1254
1255        // NOTE(unsafe) DataBlock uses align 4
1256        let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) };
1257
1258        // Always read 1 block of 512 bytes
1259        // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1260        let address = match card.card_type {
1261            CardCapacity::SDSC => block_idx * 512,
1262            _ => block_idx,
1263        };
1264        Self::cmd(Cmd::set_block_length(512), false)?; // CMD16
1265
1266        let regs = T::regs();
1267        let on_drop = OnDrop::new(|| Self::on_drop());
1268
1269        // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
1270        #[cfg(sdmmc_v1)]
1271        Self::cmd(Cmd::write_single_block(address), true)?;
1272
1273        let transfer = self.prepare_datapath_write(buffer, 512, 9);
1274        InterruptHandler::<T>::data_interrupts(true);
1275
1276        #[cfg(sdmmc_v2)]
1277        Self::cmd(Cmd::write_single_block(address), true)?;
1278
1279        let res = poll_fn(|cx| {
1280            T::state().register(cx.waker());
1281            let status = regs.star().read();
1282
1283            if status.dcrcfail() {
1284                return Poll::Ready(Err(Error::Crc));
1285            }
1286            if status.dtimeout() {
1287                return Poll::Ready(Err(Error::Timeout));
1288            }
1289            #[cfg(sdmmc_v1)]
1290            if status.stbiterr() {
1291                return Poll::Ready(Err(Error::StBitErr));
1292            }
1293            if status.dataend() {
1294                return Poll::Ready(Ok(()));
1295            }
1296            Poll::Pending
1297        })
1298        .await;
1299        Self::clear_interrupt_flags();
1300
1301        match res {
1302            Ok(_) => {
1303                on_drop.defuse();
1304                Self::stop_datapath();
1305                drop(transfer);
1306
1307                // TODO: Make this configurable
1308                let mut timeout: u32 = 0x00FF_FFFF;
1309
1310                // Try to read card status (ACMD13)
1311                while timeout > 0 {
1312                    match self.read_sd_status().await {
1313                        Ok(_) => return Ok(()),
1314                        Err(Error::Timeout) => (), // Try again
1315                        Err(e) => return Err(e),
1316                    }
1317                    timeout -= 1;
1318                }
1319                Err(Error::SoftwareTimeout)
1320            }
1321            Err(e) => Err(e),
1322        }
1323    }
1324
1325    /// Get a reference to the initialized card
1326    ///
1327    /// # Errors
1328    ///
1329    /// Returns Error::NoCard if [`init_card`](#method.init_card)
1330    /// has not previously succeeded
1331    #[inline]
1332    pub fn card(&self) -> Result<&Card, Error> {
1333        self.card.as_ref().ok_or(Error::NoCard)
1334    }
1335
1336    /// Get the current SDMMC bus clock
1337    pub fn clock(&self) -> Hertz {
1338        self.clock
1339    }
1340
1341    /// Set a specific cmd buffer rather than using the default stack allocated one.
1342    /// This is required if stack RAM cannot be used with DMA and usually manifests
1343    /// itself as an indefinite wait on a dma transfer because the dma peripheral
1344    /// cannot access the memory.
1345    pub fn set_cmd_block(&mut self, cmd_block: &'d mut CmdBlock) {
1346        self.cmd_block = Some(cmd_block)
1347    }
1348}
1349
1350impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> {
1351    fn drop(&mut self) {
1352        T::Interrupt::disable();
1353        Self::on_drop();
1354
1355        critical_section::with(|_| {
1356            self.clk.set_as_disconnected();
1357            self.cmd.set_as_disconnected();
1358            self.d0.set_as_disconnected();
1359            if let Some(x) = &mut self.d1 {
1360                x.set_as_disconnected();
1361            }
1362            if let Some(x) = &mut self.d2 {
1363                x.set_as_disconnected();
1364            }
1365            if let Some(x) = &mut self.d3 {
1366                x.set_as_disconnected();
1367            }
1368        });
1369    }
1370}
1371
1372/// SD card Commands
1373impl Cmd {
1374    const fn new(cmd: u8, arg: u32, resp: Response) -> Cmd {
1375        Cmd { cmd, arg, resp }
1376    }
1377
1378    /// CMD0: Idle
1379    const fn idle() -> Cmd {
1380        Cmd::new(0, 0, Response::None)
1381    }
1382
1383    /// CMD2: Send CID
1384    const fn all_send_cid() -> Cmd {
1385        Cmd::new(2, 0, Response::Long)
1386    }
1387
1388    /// CMD3: Send Relative Address
1389    const fn send_rel_addr() -> Cmd {
1390        Cmd::new(3, 0, Response::Short)
1391    }
1392
1393    /// CMD6: Switch Function Command
1394    /// ACMD6: Bus Width
1395    const fn cmd6(arg: u32) -> Cmd {
1396        Cmd::new(6, arg, Response::Short)
1397    }
1398
1399    /// CMD7: Select one card and put it into the _Tranfer State_
1400    const fn sel_desel_card(rca: u32) -> Cmd {
1401        Cmd::new(7, rca, Response::Short)
1402    }
1403
1404    /// CMD8:
1405    const fn hs_send_ext_csd(arg: u32) -> Cmd {
1406        Cmd::new(8, arg, Response::Short)
1407    }
1408
1409    /// CMD9:
1410    const fn send_csd(rca: u32) -> Cmd {
1411        Cmd::new(9, rca, Response::Long)
1412    }
1413
1414    /// CMD12:
1415    //const fn stop_transmission() -> Cmd {
1416    //    Cmd::new(12, 0, Response::Short)
1417    //}
1418
1419    /// CMD13: Ask card to send status register
1420    /// ACMD13: SD Status
1421    const fn card_status(rca: u32) -> Cmd {
1422        Cmd::new(13, rca, Response::Short)
1423    }
1424
1425    /// CMD16:
1426    const fn set_block_length(blocklen: u32) -> Cmd {
1427        Cmd::new(16, blocklen, Response::Short)
1428    }
1429
1430    /// CMD17: Block Read
1431    const fn read_single_block(addr: u32) -> Cmd {
1432        Cmd::new(17, addr, Response::Short)
1433    }
1434
1435    /// CMD18: Multiple Block Read
1436    //const fn read_multiple_blocks(addr: u32) -> Cmd {
1437    //    Cmd::new(18, addr, Response::Short)
1438    //}
1439
1440    /// CMD24: Block Write
1441    const fn write_single_block(addr: u32) -> Cmd {
1442        Cmd::new(24, addr, Response::Short)
1443    }
1444
1445    const fn app_op_cmd(arg: u32) -> Cmd {
1446        Cmd::new(41, arg, Response::Short)
1447    }
1448
1449    const fn cmd51() -> Cmd {
1450        Cmd::new(51, 0, Response::Short)
1451    }
1452
1453    /// App Command. Indicates that next command will be a app command
1454    const fn app_cmd(rca: u32) -> Cmd {
1455        Cmd::new(55, rca, Response::Short)
1456    }
1457}
1458
1459//////////////////////////////////////////////////////
1460
1461trait SealedInstance {
1462    fn regs() -> RegBlock;
1463    fn state() -> &'static AtomicWaker;
1464}
1465
1466/// SDMMC instance trait.
1467#[allow(private_bounds)]
1468pub trait Instance: SealedInstance + RccPeripheral + 'static {
1469    /// Interrupt for this instance.
1470    type Interrupt: interrupt::typelevel::Interrupt;
1471}
1472
1473pin_trait!(CkPin, Instance);
1474pin_trait!(CmdPin, Instance);
1475pin_trait!(D0Pin, Instance);
1476pin_trait!(D1Pin, Instance);
1477pin_trait!(D2Pin, Instance);
1478pin_trait!(D3Pin, Instance);
1479pin_trait!(D4Pin, Instance);
1480pin_trait!(D5Pin, Instance);
1481pin_trait!(D6Pin, Instance);
1482pin_trait!(D7Pin, Instance);
1483
1484#[cfg(sdmmc_v1)]
1485dma_trait!(SdmmcDma, Instance);
1486
1487/// DMA instance trait.
1488///
1489/// This is only implemented for `NoDma`, since SDMMCv2 has DMA built-in, instead of
1490/// using ST's system-wide DMA peripheral.
1491#[cfg(sdmmc_v2)]
1492pub trait SdmmcDma<T: Instance> {}
1493#[cfg(sdmmc_v2)]
1494impl<T: Instance> SdmmcDma<T> for NoDma {}
1495
1496foreach_peripheral!(
1497    (sdmmc, $inst:ident) => {
1498        impl SealedInstance for peripherals::$inst {
1499            fn regs() -> RegBlock {
1500                crate::pac::$inst
1501            }
1502
1503            fn state() -> &'static ::embassy_sync::waitqueue::AtomicWaker {
1504                static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new();
1505                &WAKER
1506            }
1507        }
1508
1509        impl Instance for peripherals::$inst {
1510            type Interrupt = crate::interrupt::typelevel::$inst;
1511        }
1512    };
1513);
1514
1515impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> block_device_driver::BlockDevice<512> for Sdmmc<'d, T, Dma> {
1516    type Error = Error;
1517    type Align = aligned::A4;
1518
1519    async fn read(
1520        &mut self,
1521        mut block_address: u32,
1522        buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>],
1523    ) -> Result<(), Self::Error> {
1524        // FIXME/TODO because of missing read_blocks multiple we have to do this one block at a time
1525        for block in buf.iter_mut() {
1526            // safety aligned by block device
1527            let block = unsafe { &mut *(block as *mut _ as *mut crate::sdmmc::DataBlock) };
1528            self.read_block(block_address, block).await?;
1529            block_address += 1;
1530        }
1531
1532        Ok(())
1533    }
1534
1535    async fn write(
1536        &mut self,
1537        mut block_address: u32,
1538        buf: &[aligned::Aligned<Self::Align, [u8; 512]>],
1539    ) -> Result<(), Self::Error> {
1540        // FIXME/TODO because of missing read_blocks multiple we have to do this one block at a time
1541        for block in buf.iter() {
1542            // safety aligned by block device
1543            let block = unsafe { &*(block as *const _ as *const crate::sdmmc::DataBlock) };
1544            self.write_block(block_address, block).await?;
1545            block_address += 1;
1546        }
1547
1548        Ok(())
1549    }
1550
1551    async fn size(&mut self) -> Result<u64, Self::Error> {
1552        Ok(self.card()?.size())
1553    }
1554}