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::{Peri, PeripheralType};
12use embassy_sync::waitqueue::AtomicWaker;
13use sdio_host::common_cmd::{self, Resp, ResponseLen};
14use sdio_host::emmc::{ExtCSD, EMMC};
15use sdio_host::sd::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CIC, CID, CSD, OCR, RCA, SCR, SD};
16use sdio_host::{emmc_cmd, sd_cmd, Cmd};
17
18#[cfg(sdmmc_v1)]
19use crate::dma::ChannelAndRequest;
20#[cfg(gpio_v2)]
21use crate::gpio::Pull;
22use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed};
23use crate::interrupt::typelevel::Interrupt;
24use crate::pac::sdmmc::Sdmmc as RegBlock;
25use crate::rcc::{self, RccPeripheral};
26use crate::time::Hertz;
27use crate::{interrupt, peripherals};
28
29/// Interrupt handler.
30pub struct InterruptHandler<T: Instance> {
31    _phantom: PhantomData<T>,
32}
33
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> {
52    unsafe fn on_interrupt() {
53        T::state().wake();
54        let status = T::regs().star().read();
55        T::regs().maskr().modify(|w| {
56            if status.dcrcfail() {
57                w.set_dcrcfailie(false)
58            }
59            if status.dtimeout() {
60                w.set_dtimeoutie(false)
61            }
62            if status.dataend() {
63                w.set_dataendie(false)
64            }
65            if status.dbckend() {
66                w.set_dbckendie(false)
67            }
68            #[cfg(sdmmc_v1)]
69            if status.stbiterr() {
70                w.set_stbiterre(false)
71            }
72            #[cfg(sdmmc_v2)]
73            if status.dabort() {
74                w.set_dabortie(false)
75            }
76        });
77    }
78}
79
80/// Frequency used for SD Card initialization. Must be no higher than 400 kHz.
81const SD_INIT_FREQ: Hertz = Hertz(400_000);
82
83/// The signalling scheme used on the SDMMC bus
84#[non_exhaustive]
85#[allow(missing_docs)]
86#[derive(Debug, Copy, Clone, PartialEq, Eq)]
87#[cfg_attr(feature = "defmt", derive(defmt::Format))]
88pub enum Signalling {
89    SDR12,
90    SDR25,
91    SDR50,
92    SDR104,
93    DDR50,
94}
95
96impl Default for Signalling {
97    fn default() -> Self {
98        Signalling::SDR12
99    }
100}
101
102/// Aligned data block for SDMMC transfers.
103///
104/// This is a 512-byte array, aligned to 4 bytes to satisfy DMA requirements.
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}
117
118impl DerefMut for DataBlock {
119    fn deref_mut(&mut self) -> &mut Self::Target {
120        &mut self.0
121    }
122}
123
124/// Command Block buffer for SDMMC command transfers.
125///
126/// This is a 16-word array, exposed so that DMA commpatible memory can be used if required.
127#[derive(Debug, Clone, PartialEq, Eq)]
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}
137
138impl Deref for CmdBlock {
139    type Target = [u32; 16];
140
141    fn deref(&self) -> &Self::Target {
142        &self.0
143    }
144}
145
146impl DerefMut for CmdBlock {
147    fn deref_mut(&mut self) -> &mut Self::Target {
148        &mut self.0
149    }
150}
151
152/// Errors
153#[non_exhaustive]
154#[derive(Debug, Copy, Clone, PartialEq, Eq)]
155#[cfg_attr(feature = "defmt", derive(defmt::Format))]
156pub enum Error {
157    /// Timeout reported by the hardware
158    Timeout,
159    /// Timeout reported by the software driver.
160    SoftwareTimeout,
161    /// Unsupported card version.
162    UnsupportedCardVersion,
163    /// Unsupported card type.
164    UnsupportedCardType,
165    /// Unsupported voltage.
166    UnsupportedVoltage,
167    /// CRC error.
168    Crc,
169    /// No card inserted.
170    NoCard,
171    /// 8-lane buses are not supported for SD cards.
172    BusWidth,
173    /// Bad clock supplied to the SDMMC peripheral.
174    BadClock,
175    /// Signaling switch failed.
176    SignalingSwitchFailed,
177    /// Underrun error
178    Underrun,
179    /// ST bit error.
180    #[cfg(sdmmc_v1)]
181    StBitErr,
182}
183
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)]
221enum PowerCtrl {
222    Off = 0b00,
223    On = 0b11,
224}
225
226fn get_waitresp_val(rlen: ResponseLen) -> u8 {
227    match rlen {
228        common_cmd::ResponseLen::Zero => 0,
229        common_cmd::ResponseLen::R48 => 1,
230        common_cmd::ResponseLen::R136 => 3,
231    }
232}
233
234/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to
235/// `sdmmc_ck` in Hertz.
236///
237/// Returns `(bypass, clk_div, clk_f)`, where `bypass` enables clock divisor bypass (only sdmmc_v1),
238/// `clk_div` is the divisor register value and `clk_f` is the resulting new clock frequency.
239#[cfg(sdmmc_v1)]
240fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u8, Hertz), Error> {
241    // sdmmc_v1 maximum clock is 50 MHz
242    if sdmmc_ck > 50_000_000 {
243        return Err(Error::BadClock);
244    }
245
246    // bypass divisor
247    if ker_ck.0 <= sdmmc_ck {
248        return Ok((true, 0, ker_ck));
249    }
250
251    let clk_div = match ker_ck.0.div_ceil(sdmmc_ck) {
252        0 | 1 => Ok(0),
253        x @ 2..=258 => Ok((x - 2) as u8),
254        _ => Err(Error::BadClock),
255    }?;
256
257    // SDIO_CK frequency = SDIOCLK / [CLKDIV + 2]
258    let clk_f = Hertz(ker_ck.0 / (clk_div as u32 + 2));
259    Ok((false, clk_div, clk_f))
260}
261
262/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to
263/// `sdmmc_ck` in Hertz.
264///
265/// Returns `(bypass, clk_div, clk_f)`, where `bypass` enables clock divisor bypass (only sdmmc_v1),
266/// `clk_div` is the divisor register value and `clk_f` is the resulting new clock frequency.
267#[cfg(sdmmc_v2)]
268fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u16, Hertz), Error> {
269    match ker_ck.0.div_ceil(sdmmc_ck) {
270        0 | 1 => Ok((false, 0, ker_ck)),
271        x @ 2..=2046 => {
272            // SDMMC_CK frequency = SDMMCCLK / [CLKDIV * 2]
273            let clk_div = x.div_ceil(2) as u16;
274            let clk = Hertz(ker_ck.0 / (clk_div as u32 * 2));
275
276            Ok((false, clk_div, clk))
277        }
278        _ => Err(Error::BadClock),
279    }
280}
281
282#[cfg(sdmmc_v1)]
283type Transfer<'a> = crate::dma::Transfer<'a>;
284#[cfg(sdmmc_v2)]
285struct Transfer<'a> {
286    _dummy: PhantomData<&'a ()>,
287}
288
289#[cfg(all(sdmmc_v1, dma))]
290const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions {
291    pburst: crate::dma::Burst::Incr4,
292    mburst: crate::dma::Burst::Incr4,
293    flow_ctrl: crate::dma::FlowControl::Peripheral,
294    fifo_threshold: Some(crate::dma::FifoThreshold::Full),
295    priority: crate::dma::Priority::VeryHigh,
296    circular: false,
297    half_transfer_ir: false,
298    complete_transfer_ir: true,
299};
300#[cfg(all(sdmmc_v1, not(dma)))]
301const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions {
302    priority: crate::dma::Priority::VeryHigh,
303    circular: false,
304    half_transfer_ir: false,
305    complete_transfer_ir: true,
306};
307
308/// SDMMC configuration
309///
310/// Default values:
311/// data_transfer_timeout: 5_000_000
312#[non_exhaustive]
313pub struct Config {
314    /// The timeout to be set for data transfers, in card bus clock periods
315    pub data_transfer_timeout: u32,
316}
317
318impl Default for Config {
319    fn default() -> Self {
320        Self {
321            data_transfer_timeout: 5_000_000,
322        }
323    }
324}
325
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
382pub struct Sdmmc<'d, T: Instance> {
383    _peri: Peri<'d, T>,
384    #[cfg(sdmmc_v1)]
385    dma: ChannelAndRequest<'d>,
386
387    clk: Peri<'d, AnyPin>,
388    cmd: Peri<'d, AnyPin>,
389    d0: Peri<'d, AnyPin>,
390    d1: Option<Peri<'d, AnyPin>>,
391    d2: Option<Peri<'d, AnyPin>>,
392    d3: Option<Peri<'d, AnyPin>>,
393    d4: Option<Peri<'d, AnyPin>>,
394    d5: Option<Peri<'d, AnyPin>>,
395    d6: Option<Peri<'d, AnyPin>>,
396    d7: Option<Peri<'d, AnyPin>>,
397
398    config: Config,
399    /// Current clock to card
400    clock: Hertz,
401    /// Current signalling scheme to card
402    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}
410
411const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh);
412#[cfg(gpio_v1)]
413const CMD_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh);
414#[cfg(gpio_v2)]
415const CMD_AF: AfType = AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up);
416const DATA_AF: AfType = CMD_AF;
417
418#[cfg(sdmmc_v1)]
419impl<'d, T: Instance> Sdmmc<'d, T> {
420    /// Create a new SDMMC driver, with 1 data lane.
421    pub fn new_1bit(
422        sdmmc: Peri<'d, T>,
423        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
424        dma: Peri<'d, impl SdmmcDma<T>>,
425        clk: Peri<'d, impl CkPin<T>>,
426        cmd: Peri<'d, impl CmdPin<T>>,
427        d0: Peri<'d, impl D0Pin<T>>,
428        config: Config,
429    ) -> Self {
430        critical_section::with(|_| {
431            clk.set_as_af(clk.af_num(), CLK_AF);
432            cmd.set_as_af(cmd.af_num(), CMD_AF);
433            d0.set_as_af(d0.af_num(), DATA_AF);
434        });
435
436        Self::new_inner(
437            sdmmc,
438            new_dma_nonopt!(dma),
439            clk.into(),
440            cmd.into(),
441            d0.into(),
442            None,
443            None,
444            None,
445            None,
446            None,
447            None,
448            None,
449            config,
450        )
451    }
452
453    /// Create a new SDMMC driver, with 4 data lanes.
454    pub fn new_4bit(
455        sdmmc: Peri<'d, T>,
456        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
457        dma: Peri<'d, impl SdmmcDma<T>>,
458        clk: Peri<'d, impl CkPin<T>>,
459        cmd: Peri<'d, impl CmdPin<T>>,
460        d0: Peri<'d, impl D0Pin<T>>,
461        d1: Peri<'d, impl D1Pin<T>>,
462        d2: Peri<'d, impl D2Pin<T>>,
463        d3: Peri<'d, impl D3Pin<T>>,
464        config: Config,
465    ) -> Self {
466        critical_section::with(|_| {
467            clk.set_as_af(clk.af_num(), CLK_AF);
468            cmd.set_as_af(cmd.af_num(), CMD_AF);
469            d0.set_as_af(d0.af_num(), DATA_AF);
470            d1.set_as_af(d1.af_num(), DATA_AF);
471            d2.set_as_af(d2.af_num(), DATA_AF);
472            d3.set_as_af(d3.af_num(), DATA_AF);
473        });
474
475        Self::new_inner(
476            sdmmc,
477            new_dma_nonopt!(dma),
478            clk.into(),
479            cmd.into(),
480            d0.into(),
481            Some(d1.into()),
482            Some(d2.into()),
483            Some(d3.into()),
484            None,
485            None,
486            None,
487            None,
488            config,
489        )
490    }
491}
492
493#[cfg(sdmmc_v1)]
494impl<'d, T: Instance> Sdmmc<'d, T> {
495    /// Create a new SDMMC driver, with 8 data lanes.
496    pub fn new_8bit(
497        sdmmc: Peri<'d, T>,
498        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
499        dma: Peri<'d, impl SdmmcDma<T>>,
500        clk: Peri<'d, impl CkPin<T>>,
501        cmd: Peri<'d, impl CmdPin<T>>,
502        d0: Peri<'d, impl D0Pin<T>>,
503        d1: Peri<'d, impl D1Pin<T>>,
504        d2: Peri<'d, impl D2Pin<T>>,
505        d3: Peri<'d, impl D3Pin<T>>,
506        d4: Peri<'d, impl D4Pin<T>>,
507        d5: Peri<'d, impl D5Pin<T>>,
508        d6: Peri<'d, impl D6Pin<T>>,
509        d7: Peri<'d, impl D7Pin<T>>,
510        config: Config,
511    ) -> Self {
512        critical_section::with(|_| {
513            clk.set_as_af(clk.af_num(), CLK_AF);
514            cmd.set_as_af(cmd.af_num(), CMD_AF);
515            d0.set_as_af(d0.af_num(), DATA_AF);
516            d1.set_as_af(d1.af_num(), DATA_AF);
517            d2.set_as_af(d2.af_num(), DATA_AF);
518            d3.set_as_af(d3.af_num(), DATA_AF);
519            d4.set_as_af(d4.af_num(), DATA_AF);
520            d5.set_as_af(d5.af_num(), DATA_AF);
521            d6.set_as_af(d6.af_num(), DATA_AF);
522            d7.set_as_af(d7.af_num(), DATA_AF);
523        });
524
525        Self::new_inner(
526            sdmmc,
527            new_dma_nonopt!(dma),
528            clk.into(),
529            cmd.into(),
530            d0.into(),
531            Some(d1.into()),
532            Some(d2.into()),
533            Some(d3.into()),
534            Some(d4.into()),
535            Some(d5.into()),
536            Some(d6.into()),
537            Some(d7.into()),
538            config,
539        )
540    }
541}
542
543#[cfg(sdmmc_v2)]
544impl<'d, T: Instance> Sdmmc<'d, T> {
545    /// Create a new SDMMC driver, with 1 data lane.
546    pub fn new_1bit(
547        sdmmc: Peri<'d, T>,
548        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
549        clk: Peri<'d, impl CkPin<T>>,
550        cmd: Peri<'d, impl CmdPin<T>>,
551        d0: Peri<'d, impl D0Pin<T>>,
552        config: Config,
553    ) -> Self {
554        critical_section::with(|_| {
555            clk.set_as_af(clk.af_num(), CLK_AF);
556            cmd.set_as_af(cmd.af_num(), CMD_AF);
557            d0.set_as_af(d0.af_num(), DATA_AF);
558        });
559
560        Self::new_inner(
561            sdmmc,
562            clk.into(),
563            cmd.into(),
564            d0.into(),
565            None,
566            None,
567            None,
568            None,
569            None,
570            None,
571            None,
572            config,
573        )
574    }
575
576    /// Create a new SDMMC driver, with 4 data lanes.
577    pub fn new_4bit(
578        sdmmc: Peri<'d, T>,
579        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
580        clk: Peri<'d, impl CkPin<T>>,
581        cmd: Peri<'d, impl CmdPin<T>>,
582        d0: Peri<'d, impl D0Pin<T>>,
583        d1: Peri<'d, impl D1Pin<T>>,
584        d2: Peri<'d, impl D2Pin<T>>,
585        d3: Peri<'d, impl D3Pin<T>>,
586        config: Config,
587    ) -> Self {
588        critical_section::with(|_| {
589            clk.set_as_af(clk.af_num(), CLK_AF);
590            cmd.set_as_af(cmd.af_num(), CMD_AF);
591            d0.set_as_af(d0.af_num(), DATA_AF);
592            d1.set_as_af(d1.af_num(), DATA_AF);
593            d2.set_as_af(d2.af_num(), DATA_AF);
594            d3.set_as_af(d3.af_num(), DATA_AF);
595        });
596
597        Self::new_inner(
598            sdmmc,
599            clk.into(),
600            cmd.into(),
601            d0.into(),
602            Some(d1.into()),
603            Some(d2.into()),
604            Some(d3.into()),
605            None,
606            None,
607            None,
608            None,
609            config,
610        )
611    }
612}
613
614#[cfg(sdmmc_v2)]
615impl<'d, T: Instance> Sdmmc<'d, T> {
616    /// Create a new SDMMC driver, with 8 data lanes.
617    pub fn new_8bit(
618        sdmmc: Peri<'d, T>,
619        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
620        clk: Peri<'d, impl CkPin<T>>,
621        cmd: Peri<'d, impl CmdPin<T>>,
622        d0: Peri<'d, impl D0Pin<T>>,
623        d1: Peri<'d, impl D1Pin<T>>,
624        d2: Peri<'d, impl D2Pin<T>>,
625        d3: Peri<'d, impl D3Pin<T>>,
626        d4: Peri<'d, impl D4Pin<T>>,
627        d5: Peri<'d, impl D5Pin<T>>,
628        d6: Peri<'d, impl D6Pin<T>>,
629        d7: Peri<'d, impl D7Pin<T>>,
630        config: Config,
631    ) -> Self {
632        critical_section::with(|_| {
633            clk.set_as_af(clk.af_num(), CLK_AF);
634            cmd.set_as_af(cmd.af_num(), CMD_AF);
635            d0.set_as_af(d0.af_num(), DATA_AF);
636            d1.set_as_af(d1.af_num(), DATA_AF);
637            d2.set_as_af(d2.af_num(), DATA_AF);
638            d3.set_as_af(d3.af_num(), DATA_AF);
639            d4.set_as_af(d4.af_num(), DATA_AF);
640            d5.set_as_af(d5.af_num(), DATA_AF);
641            d6.set_as_af(d6.af_num(), DATA_AF);
642            d7.set_as_af(d7.af_num(), DATA_AF);
643        });
644
645        Self::new_inner(
646            sdmmc,
647            clk.into(),
648            cmd.into(),
649            d0.into(),
650            Some(d1.into()),
651            Some(d2.into()),
652            Some(d3.into()),
653            Some(d4.into()),
654            Some(d5.into()),
655            Some(d6.into()),
656            Some(d7.into()),
657            config,
658        )
659    }
660}
661
662impl<'d, T: Instance> Sdmmc<'d, T> {
663    fn new_inner(
664        sdmmc: Peri<'d, T>,
665        #[cfg(sdmmc_v1)] dma: ChannelAndRequest<'d>,
666        clk: Peri<'d, AnyPin>,
667        cmd: Peri<'d, AnyPin>,
668        d0: Peri<'d, AnyPin>,
669        d1: Option<Peri<'d, AnyPin>>,
670        d2: Option<Peri<'d, AnyPin>>,
671        d3: Option<Peri<'d, AnyPin>>,
672        d4: Option<Peri<'d, AnyPin>>,
673        d5: Option<Peri<'d, AnyPin>>,
674        d6: Option<Peri<'d, AnyPin>>,
675        d7: Option<Peri<'d, AnyPin>>,
676        config: Config,
677    ) -> Self {
678        rcc::enable_and_reset::<T>();
679
680        T::Interrupt::unpend();
681        unsafe { T::Interrupt::enable() };
682
683        let regs = T::regs();
684        regs.clkcr().write(|w| {
685            w.set_pwrsav(false);
686            w.set_negedge(false);
687
688            // Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors.
689            // See chip erratas for more details.
690            #[cfg(sdmmc_v1)]
691            w.set_hwfc_en(false);
692            #[cfg(sdmmc_v2)]
693            w.set_hwfc_en(true);
694
695            #[cfg(sdmmc_v1)]
696            w.set_clken(true);
697        });
698
699        // Power off, writen 00: Clock to the card is stopped;
700        // D[7:0], CMD, and CK are driven high.
701        regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8));
702
703        Self {
704            _peri: sdmmc,
705            #[cfg(sdmmc_v1)]
706            dma,
707
708            clk,
709            cmd,
710            d0,
711            d1,
712            d2,
713            d3,
714            d4,
715            d5,
716            d6,
717            d7,
718
719            config,
720            clock: SD_INIT_FREQ,
721            signalling: Default::default(),
722            card: None,
723            cmd_block: None,
724        }
725    }
726
727    /// Data transfer is in progress
728    #[inline]
729    fn data_active() -> bool {
730        let regs = T::regs();
731
732        let status = regs.star().read();
733        #[cfg(sdmmc_v1)]
734        return status.rxact() || status.txact();
735        #[cfg(sdmmc_v2)]
736        return status.dpsmact();
737    }
738
739    /// Coammand transfer is in progress
740    #[inline]
741    fn cmd_active() -> bool {
742        let regs = T::regs();
743
744        let status = regs.star().read();
745        #[cfg(sdmmc_v1)]
746        return status.cmdact();
747        #[cfg(sdmmc_v2)]
748        return status.cpsmact();
749    }
750
751    /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2)
752    #[inline]
753    fn wait_idle() {
754        while Self::data_active() || Self::cmd_active() {}
755    }
756
757    /// # Safety
758    ///
759    /// `buffer` must be valid for the whole transfer and word aligned
760    #[allow(unused_variables)]
761    fn prepare_datapath_read<'a>(
762        config: &Config,
763        #[cfg(sdmmc_v1)] dma: &'a mut ChannelAndRequest<'d>,
764        buffer: &'a mut [u32],
765        length_bytes: u32,
766        block_size: u8,
767    ) -> Transfer<'a> {
768        assert!(block_size <= 14, "Block size up to 2^14 bytes");
769        let regs = T::regs();
770
771        // Command AND Data state machines must be idle
772        Self::wait_idle();
773        Self::clear_interrupt_flags();
774
775        regs.dlenr().write(|w| w.set_datalength(length_bytes));
776
777        #[cfg(sdmmc_v1)]
778        let transfer = unsafe { dma.read(regs.fifor().as_ptr() as *mut u32, buffer, DMA_TRANSFER_OPTIONS) };
779        #[cfg(sdmmc_v2)]
780        let transfer = {
781            regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32));
782            regs.idmactrlr().modify(|w| w.set_idmaen(true));
783            Transfer {
784                _dummy: core::marker::PhantomData,
785            }
786        };
787
788        regs.dctrl().modify(|w| {
789            w.set_dblocksize(block_size);
790            w.set_dtdir(true);
791            #[cfg(sdmmc_v1)]
792            {
793                w.set_dmaen(true);
794                w.set_dten(true);
795            }
796        });
797
798        transfer
799    }
800
801    /// # Safety
802    ///
803    /// `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> {
805        assert!(block_size <= 14, "Block size up to 2^14 bytes");
806        let regs = T::regs();
807
808        // Command AND Data state machines must be idle
809        Self::wait_idle();
810        Self::clear_interrupt_flags();
811
812        regs.dlenr().write(|w| w.set_datalength(length_bytes));
813
814        #[cfg(sdmmc_v1)]
815        let transfer = unsafe {
816            self.dma
817                .write(buffer, regs.fifor().as_ptr() as *mut u32, DMA_TRANSFER_OPTIONS)
818        };
819        #[cfg(sdmmc_v2)]
820        let transfer = {
821            regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_ptr() as u32));
822            regs.idmactrlr().modify(|w| w.set_idmaen(true));
823            Transfer {
824                _dummy: core::marker::PhantomData,
825            }
826        };
827
828        regs.dctrl().modify(|w| {
829            w.set_dblocksize(block_size);
830            w.set_dtdir(false);
831            #[cfg(sdmmc_v1)]
832            {
833                w.set_dmaen(true);
834                w.set_dten(true);
835            }
836        });
837
838        transfer
839    }
840
841    /// Stops the DMA datapath
842    fn stop_datapath() {
843        let regs = T::regs();
844
845        #[cfg(sdmmc_v1)]
846        regs.dctrl().modify(|w| {
847            w.set_dmaen(false);
848            w.set_dten(false);
849        });
850        #[cfg(sdmmc_v2)]
851        regs.idmactrlr().modify(|w| w.set_idmaen(false));
852    }
853
854    /// Sets the CLKDIV field in CLKCR. Updates clock field in self
855    fn clkcr_set_clkdiv(&mut self, freq: u32, width: BusWidth) -> Result<(), Error> {
856        let regs = T::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
865        let ker_ck = T::frequency();
866        let (_bypass, clkdiv, new_clock) = clk_div(ker_ck, freq)?;
867
868        // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7
869        // Section 55.5.8
870        let sdmmc_bus_bandwidth = new_clock.0 * width_u32;
871        assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32);
872        self.clock = new_clock;
873
874        // CPSMACT and DPSMACT must be 0 to set CLKDIV
875        Self::wait_idle();
876        regs.clkcr().modify(|w| {
877            w.set_clkdiv(clkdiv);
878            #[cfg(sdmmc_v1)]
879            w.set_bypass(_bypass);
880        });
881
882        Ok(())
883    }
884
885    /// Query the card status (CMD13, returns R1)
886    fn read_status<Ext>(&self, card: &SdmmcPeripheral) -> Result<CardStatus<Ext>, Error>
887    where
888        CardStatus<Ext>: From<u32>,
889    {
890        let regs = T::regs();
891        let rca = card.get_address();
892
893        Self::cmd(common_cmd::card_status(rca, false), false)?; // CMD13
894
895        let r1 = regs.respr(0).read().cardstatus();
896        Ok(r1.into())
897    }
898
899    /// Select one card and place it into the _Tranfer State_
900    ///
901    /// If `None` is specifed for `card`, all cards are put back into
902    /// _Stand-by State_
903    fn select_card(&self, rca: Option<u16>) -> Result<(), Error> {
904        // Determine Relative Card Address (RCA) of given card
905        let rca = rca.unwrap_or(0);
906
907        let r = Self::cmd(common_cmd::select_card(rca), false);
908        match (r, rca) {
909            (Err(Error::Timeout), 0) => Ok(()),
910            _ => r,
911        }
912    }
913
914    /// Clear flags in interrupt clear register
915    #[inline]
916    fn clear_interrupt_flags() {
917        let regs = T::regs();
918        regs.icr().write(|w| {
919            w.set_ccrcfailc(true);
920            w.set_dcrcfailc(true);
921            w.set_ctimeoutc(true);
922            w.set_dtimeoutc(true);
923            w.set_txunderrc(true);
924            w.set_rxoverrc(true);
925            w.set_cmdrendc(true);
926            w.set_cmdsentc(true);
927            w.set_dataendc(true);
928            w.set_dbckendc(true);
929            w.set_sdioitc(true);
930            #[cfg(sdmmc_v1)]
931            w.set_stbiterrc(true);
932
933            #[cfg(sdmmc_v2)]
934            {
935                w.set_dholdc(true);
936                w.set_dabortc(true);
937                w.set_busyd0endc(true);
938                w.set_ackfailc(true);
939                w.set_acktimeoutc(true);
940                w.set_vswendc(true);
941                w.set_ckstopc(true);
942                w.set_idmatec(true);
943                w.set_idmabtcc(true);
944            }
945        });
946    }
947
948    /// Send command to card
949    #[allow(unused_variables)]
950    fn cmd<R: Resp>(cmd: Cmd<R>, data: bool) -> Result<(), Error> {
951        let regs = T::regs();
952
953        Self::clear_interrupt_flags();
954        // CP state machine must be idle
955        while Self::cmd_active() {}
956
957        // Command arg
958        regs.argr().write(|w| w.set_cmdarg(cmd.arg));
959
960        // Command index and start CP State Machine
961        regs.cmdr().write(|w| {
962            w.set_waitint(false);
963            w.set_waitresp(get_waitresp_val(cmd.response_len()));
964            w.set_cmdindex(cmd.cmd);
965            w.set_cpsmen(true);
966
967            #[cfg(sdmmc_v2)]
968            {
969                // Special mode in CP State Machine
970                // CMD12: Stop Transmission
971                let cpsm_stop_transmission = cmd.cmd == 12;
972                w.set_cmdstop(cpsm_stop_transmission);
973                w.set_cmdtrans(data);
974            }
975        });
976
977        let mut status;
978        if cmd.response_len() == ResponseLen::Zero {
979            // Wait for CMDSENT or a timeout
980            while {
981                status = regs.star().read();
982                !(status.ctimeout() || status.cmdsent())
983            } {}
984        } else {
985            // Wait for CMDREND or CCRCFAIL or a timeout
986            while {
987                status = regs.star().read();
988                !(status.ctimeout() || status.cmdrend() || status.ccrcfail())
989            } {}
990        }
991
992        if status.ctimeout() {
993            return Err(Error::Timeout);
994        } else if status.ccrcfail() {
995            return Err(Error::Crc);
996        }
997        Ok(())
998    }
999
1000    fn on_drop() {
1001        let regs = T::regs();
1002        if Self::data_active() {
1003            Self::clear_interrupt_flags();
1004            // Send abort
1005            // CP state machine must be idle
1006            while Self::cmd_active() {}
1007
1008            // Command arg
1009            regs.argr().write(|w| w.set_cmdarg(0));
1010
1011            // Command index and start CP State Machine
1012            regs.cmdr().write(|w| {
1013                w.set_waitint(false);
1014                w.set_waitresp(get_waitresp_val(ResponseLen::R48));
1015                w.set_cmdindex(12);
1016                w.set_cpsmen(true);
1017
1018                #[cfg(sdmmc_v2)]
1019                {
1020                    w.set_cmdstop(true);
1021                    w.set_cmdtrans(false);
1022                }
1023            });
1024
1025            // Wait for the abort
1026            while Self::data_active() {}
1027        }
1028        regs.maskr().write(|_| ()); // disable irqs
1029        Self::clear_interrupt_flags();
1030        Self::stop_datapath();
1031    }
1032
1033    /// Wait for a previously started datapath transfer to complete from an interrupt.
1034    #[inline]
1035    async fn complete_datapath_transfer(block: bool) -> Result<(), Error> {
1036        let regs = T::regs();
1037
1038        let res = poll_fn(|cx| {
1039            T::state().register(cx.waker());
1040            let status = regs.star().read();
1041
1042            if status.dcrcfail() {
1043                return Poll::Ready(Err(Error::Crc));
1044            }
1045            if status.dtimeout() {
1046                return Poll::Ready(Err(Error::Timeout));
1047            }
1048            if status.txunderr() {
1049                return Poll::Ready(Err(Error::Underrun));
1050            }
1051            #[cfg(sdmmc_v1)]
1052            if status.stbiterr() {
1053                return Poll::Ready(Err(Error::StBitErr));
1054            }
1055            let done = match block {
1056                true => status.dbckend(),
1057                false => status.dataend(),
1058            };
1059            if done {
1060                return Poll::Ready(Ok(()));
1061            }
1062            Poll::Pending
1063        })
1064        .await;
1065
1066        Self::clear_interrupt_flags();
1067
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
1079        // Always read 1 block of 512 bytes
1080        // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
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
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
1108    }
1109
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
1288    pub fn clock(&self) -> Hertz {
1289        self.clock
1290    }
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}
1753
1754impl<'d, T: Instance> Drop for Sdmmc<'d, T> {
1755    fn drop(&mut self) {
1756        T::Interrupt::disable();
1757        Self::on_drop();
1758
1759        critical_section::with(|_| {
1760            self.clk.set_as_disconnected();
1761            self.cmd.set_as_disconnected();
1762            self.d0.set_as_disconnected();
1763            if let Some(x) = &mut self.d1 {
1764                x.set_as_disconnected();
1765            }
1766            if let Some(x) = &mut self.d2 {
1767                x.set_as_disconnected();
1768            }
1769            if let Some(x) = &mut self.d3 {
1770                x.set_as_disconnected();
1771            }
1772            if let Some(x) = &mut self.d4 {
1773                x.set_as_disconnected();
1774            }
1775            if let Some(x) = &mut self.d5 {
1776                x.set_as_disconnected();
1777            }
1778            if let Some(x) = &mut self.d6 {
1779                x.set_as_disconnected();
1780            }
1781            if let Some(x) = &mut self.d7 {
1782                x.set_as_disconnected();
1783            }
1784        });
1785    }
1786}
1787
1788//////////////////////////////////////////////////////
1789
1790trait SealedInstance {
1791    fn regs() -> RegBlock;
1792    fn state() -> &'static AtomicWaker;
1793}
1794
1795/// SDMMC instance trait.
1796#[allow(private_bounds)]
1797pub trait Instance: SealedInstance + PeripheralType + RccPeripheral + 'static {
1798    /// Interrupt for this instance.
1799    type Interrupt: interrupt::typelevel::Interrupt;
1800}
1801
1802pin_trait!(CkPin, Instance);
1803pin_trait!(CmdPin, Instance);
1804pin_trait!(D0Pin, Instance);
1805pin_trait!(D1Pin, Instance);
1806pin_trait!(D2Pin, Instance);
1807pin_trait!(D3Pin, Instance);
1808pin_trait!(D4Pin, Instance);
1809pin_trait!(D5Pin, Instance);
1810pin_trait!(D6Pin, Instance);
1811pin_trait!(D7Pin, Instance);
1812
1813#[cfg(sdmmc_v1)]
1814dma_trait!(SdmmcDma, Instance);
1815
1816foreach_peripheral!(
1817    (sdmmc, $inst:ident) => {
1818        impl SealedInstance for peripherals::$inst {
1819            fn regs() -> RegBlock {
1820                crate::pac::$inst
1821            }
1822
1823            fn state() -> &'static ::embassy_sync::waitqueue::AtomicWaker {
1824                static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new();
1825                &WAKER
1826            }
1827        }
1828
1829        impl Instance for peripherals::$inst {
1830            type Interrupt = crate::interrupt::typelevel::$inst;
1831        }
1832    };
1833);
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}