stm32h7_sdmmc/
sdmmc.rs

1//! # SD MultiMediaCard interface (SDMMC)
2//!
3//! For HDHC / SDXC / SDUC cards. SDSC cards are not supported.
4//!
5//! Adapted from stm32f4xx-hal
6//! https://github.com/stm32-rs/stm32f4xx-hal/blob/master/src/sdio.rs
7
8use core::fmt;
9
10use crate::sd_registers::*;
11
12use stm32h7xx_hal::gpio::gpioa::PA0;
13use stm32h7xx_hal::gpio::gpiob::{PB14, PB15, PB3, PB4, PB8, PB9};
14use stm32h7xx_hal::gpio::gpioc::{PC1, PC10, PC11, PC12, PC6, PC7, PC8, PC9};
15use stm32h7xx_hal::gpio::gpiod::{PD2, PD6, PD7};
16use stm32h7xx_hal::gpio::gpiog::PG11;
17use stm32h7xx_hal::time::Hertz;
18
19use stm32h7xx_hal::gpio::{Alternate, AF10, AF11, AF12, AF9};
20//use stm32h7xx_hal::gpio:::{AF7, AF8};
21use stm32h7xx_hal::rcc::rec::{ResetEnable, SdmmcClkSelGetter};
22use stm32h7xx_hal::rcc::{rec, CoreClocks};
23use stm32h7xx_hal::stm32::{SDMMC1, SDMMC2};
24
25pub trait PinClk<SDMMC> {}
26pub trait PinCmd<SDMMC> {}
27pub trait PinD0<SDMMC> {}
28pub trait PinD1<SDMMC> {}
29pub trait PinD2<SDMMC> {}
30pub trait PinD3<SDMMC> {}
31pub trait PinD4<SDMMC> {}
32pub trait PinD5<SDMMC> {}
33pub trait PinD6<SDMMC> {}
34pub trait PinD7<SDMMC> {}
35
36pub trait Pins<SDMMC> {
37    const BUSWIDTH: BusWidth;
38}
39
40impl<SDMMC, CLK, CMD, D0, D1, D2, D3, D4, D5, D6, D7> Pins<SDMMC>
41    for (CLK, CMD, D0, D1, D2, D3, D4, D5, D6, D7)
42where
43    CLK: PinClk<SDMMC>,
44    CMD: PinCmd<SDMMC>,
45    D0: PinD0<SDMMC>,
46    D1: PinD1<SDMMC>,
47    D2: PinD2<SDMMC>,
48    D3: PinD3<SDMMC>,
49    D4: PinD4<SDMMC>,
50    D5: PinD5<SDMMC>,
51    D6: PinD6<SDMMC>,
52    D7: PinD7<SDMMC>,
53{
54    const BUSWIDTH: BusWidth = BusWidth::Eight;
55}
56
57impl<SDMMC, CLK, CMD, D0, D1, D2, D3> Pins<SDMMC> for (CLK, CMD, D0, D1, D2, D3)
58where
59    CLK: PinClk<SDMMC>,
60    CMD: PinCmd<SDMMC>,
61    D0: PinD0<SDMMC>,
62    D1: PinD1<SDMMC>,
63    D2: PinD2<SDMMC>,
64    D3: PinD3<SDMMC>,
65{
66    const BUSWIDTH: BusWidth = BusWidth::Four;
67}
68
69impl<SDMMC, CLK, CMD, D0> Pins<SDMMC> for (CLK, CMD, D0)
70where
71    CLK: PinClk<SDMMC>,
72    CMD: PinCmd<SDMMC>,
73    D0: PinD0<SDMMC>,
74{
75    const BUSWIDTH: BusWidth = BusWidth::One;
76}
77
78macro_rules! pins {
79    ($($SDMMCX:ty: CLK: [$($CLK:ty),*] CMD: [$($CMD:ty),*]
80       D0: [$($D0:ty),*] D1: [$($D1:ty),*] D2: [$($D2:ty),*] D3: [$($D3:ty),*]
81       D4: [$($D4:ty),*] D5: [$($D5:ty),*] D6: [$($D6:ty),*] D7: [$($D7:ty),*]
82       CKIN: [$($CKIN:ty),*] CDIR: [$($CDIR:ty),*]
83       D0DIR: [$($D0DIR:ty),*] D123DIR: [$($D123DIR:ty),*]
84    )+) => {
85        $(
86            $(
87                impl PinClk<$SDMMCX> for $CLK {}
88            )*
89                $(
90                    impl PinCmd<$SDMMCX> for $CMD {}
91                )*
92                $(
93                    impl PinD0<$SDMMCX> for $D0 {}
94                )*
95                $(
96                    impl PinD1<$SDMMCX> for $D1 {}
97                )*
98                $(
99                    impl PinD2<$SDMMCX> for $D2 {}
100                )*
101                $(
102                    impl PinD3<$SDMMCX> for $D3 {}
103                )*
104                $(
105                    impl PinD4<$SDMMCX> for $D4 {}
106                )*
107                $(
108                    impl PinD5<$SDMMCX> for $D5 {}
109                )*
110                $(
111                    impl PinD6<$SDMMCX> for $D6 {}
112                )*
113                $(
114                    impl PinD7<$SDMMCX> for $D7 {}
115                )*
116        )+
117    }
118}
119
120pins! {
121    SDMMC1:
122    CLK: [PC12<Alternate<AF12>>]
123        CMD: [PD2<Alternate<AF12>>]
124        D0: [PC8<Alternate<AF12>>]
125        D1: [PC9<Alternate<AF12>>]
126        D2: [PC10<Alternate<AF12>>]
127        D3: [PC11<Alternate<AF12>>]
128        D4: [PB8<Alternate<AF12>>]
129        D5: [PB9<Alternate<AF12>>]
130        D6: [PC6<Alternate<AF12>>]
131        D7: [PC7<Alternate<AF12>>]
132        CKIN: [PB8<Alternate<AF7>>]
133        CDIR: [PB9<Alternate<AF7>>]
134        D0DIR: [PC6<Alternate<AF8>>]
135        D123DIR: [PC7<Alternate<AF8>>]
136        SDMMC2:
137    CLK: [PC1<Alternate<AF9>>, PD6<Alternate<AF11>>]
138        CMD: [PA0<Alternate<AF9>>, PD7<Alternate<AF11>>]
139        D0: [PB14<Alternate<AF9>>]
140        D1: [PB15<Alternate<AF9>>]
141        D2: [PB3<Alternate<AF9>>, PG11<Alternate<AF10>>]
142        D3: [PB4<Alternate<AF9>>]
143        D4: [PB8<Alternate<AF10>>]
144        D5: [PB9<Alternate<AF10>>]
145        D6: [PC6<Alternate<AF10>>]
146        D7: [PC7<Alternate<AF10>>]
147        CKIN: []
148        CDIR: []
149        D0DIR: []
150        D123DIR: []
151}
152
153/// The number of lines used on the SDMMC bus
154#[derive(Copy, Clone, Debug)]
155#[allow(missing_docs)]
156pub enum BusWidth {
157    One = 1,
158    Four = 4,
159    Eight = 8,
160}
161
162/// Types of SD Card
163#[derive(Debug, Copy, Clone)]
164#[non_exhaustive]
165pub enum CardType {
166    /// Standard Capacity (< 2Gb)
167    SDSC,
168    /// High capacity (< 32Gb)
169    SDHC,
170}
171impl Default for CardType {
172    fn default() -> Self {
173        CardType::SDSC
174    }
175}
176
177/// The signalling scheme used on the SDMMC bus
178#[non_exhaustive]
179#[derive(Debug, Copy, Clone, PartialEq, Eq)]
180#[allow(missing_docs)]
181pub enum Signalling {
182    SDR12,
183    SDR25,
184    SDR50,
185    SDR104,
186    DDR50,
187}
188impl Default for Signalling {
189    fn default() -> Self {
190        Signalling::SDR12
191    }
192}
193
194/// Errors
195#[non_exhaustive]
196#[allow(missing_docs)]
197#[derive(Debug, Copy, Clone)]
198pub enum Error {
199    Timeout,
200    SoftwareTimeout,
201    UnsupportedCardVersion,
202    UnsupportedCardType,
203    Crc,
204    DataCrcFail,
205    RxOverFlow,
206    NoCard,
207    BadClock,
208    SignalingSwitchFailed,
209}
210
211/// A SD command
212struct Cmd {
213    cmd: u8,
214    arg: u32,
215    resp: Response,
216}
217
218#[derive(Clone, Copy, Debug, Default)]
219/// SD Card
220pub struct Card {
221    /// The type of this card
222    pub card_type: CardType,
223    /// Operation Conditions Register
224    pub ocr: OCR,
225    /// Relative Card Address
226    pub rca: u32,
227    /// Card ID
228    pub cid: CID,
229    /// Card Specific Data
230    pub csd: CSD,
231    /// SD CARD Configuration Register
232    pub scr: SCR,
233    /// SD Status
234    pub status: SDStatus,
235}
236impl Card {
237    /// Size in bytes
238    pub fn size(&self) -> u64 {
239        // SDHC / SDXC / SDUC
240        u64::from(self.csd.block_count()) * 512 * 1024
241    }
242}
243
244macro_rules! err_from_datapath_sm {
245    ($status:ident) => {
246        if $status.dcrcfail().bit() {
247            return Err(Error::DataCrcFail);
248        } else if $status.rxoverr().bit() {
249            return Err(Error::RxOverFlow);
250        } else if $status.dtimeout().bit() {
251            return Err(Error::Timeout);
252        }
253    };
254}
255
256/// Indicates transfer direction
257enum Dir {
258    CardToHost,
259    HostToCard,
260}
261
262enum PowerCtrl {
263    Off = 0b00,
264    On = 0b11,
265}
266
267#[repr(u32)]
268#[allow(dead_code)]
269#[allow(non_camel_case_types)]
270enum CmdAppOper {
271    VOLTAGE_WINDOW_SD = 0x8010_0000,
272    HIGH_CAPACITY = 0x4000_0000,
273    SDMMC_STD_CAPACITY = 0x0000_0000,
274    SDMMC_CHECK_PATTERN = 0x0000_01AA,
275    SD_SWITCH_1_8V_CAPACITY = 0x0100_0000,
276}
277
278#[derive(Eq, PartialEq, Copy, Clone)]
279enum Response {
280    None = 0,
281    Short = 1,
282    Long = 3,
283}
284
285#[derive(Eq, PartialEq, Copy, Clone)]
286#[allow(dead_code)]
287enum CardStatus {
288    /// Card state is ready
289    Ready = 1,
290    /// Card is in identification state
291    Identification = 2,
292    /// Card is in standby state
293    Standby = 3,
294    /// Card is in transfer state
295    Transfer = 4,
296    /// Card is sending an operation
297    Sending = 5,
298    /// Card is receiving operation information
299    Receiving = 6,
300    /// Card is in programming state
301    Programming = 7,
302    /// Card is disconnected
303    Disconnected = 8,
304    /// Error
305    Error,
306}
307impl From<u8> for CardStatus {
308    fn from(n: u8) -> Self {
309        match n {
310            1 => Self::Ready,
311            2 => Self::Identification,
312            3 => Self::Standby,
313            4 => Self::Transfer,
314            5 => Self::Sending,
315            6 => Self::Receiving,
316            7 => Self::Programming,
317            8 => Self::Disconnected,
318            _ => Self::Error,
319        }
320    }
321}
322
323/// Sdmmc device
324pub struct Sdmmc<SDMMC> {
325    sdmmc: SDMMC,
326    /// SDMMC kernel clock
327    ker_ck: Hertz,
328    /// AHB clock
329    hclk: Hertz,
330    /// Data bus width
331    bus_width: BusWidth,
332    /// Current clock to card
333    clock: Hertz,
334    /// Current signalling scheme to card
335    signalling: Signalling,
336    /// Card
337    card: Option<Card>,
338}
339impl<SDMMC> fmt::Debug for Sdmmc<SDMMC> {
340    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341        f.debug_struct("SDMMC Peripheral")
342            .field("Card detected", &self.card.is_some())
343            .field("Bus Width (bits)", &self.bus_width)
344            .field("Signalling", &self.signalling)
345            .field("Bus Clock", &self.clock)
346            .finish()
347    }
348}
349
350/// Extension trait for SDMMC peripherals
351pub trait SdmmcExt<SDMMC>: Sized {
352    /// The `ResetEnable` singleton for this peripheral
353    type Rec: ResetEnable;
354
355    /// Create and enable the Sdmmc device. Initially the bus is clocked at
356    /// <400kHz, so that SD cards can be initialised.
357    fn sdmmc<PINS>(
358        self,
359        _pins: PINS,
360        prec: Self::Rec,
361        clocks: &CoreClocks,
362    ) -> Sdmmc<SDMMC>
363    where
364        PINS: Pins<SDMMC>;
365
366    /// Create and enable the Sdmmc device. Initially the bus is clocked
367    /// <400kHz, so that SD cards can be initialised. `bus_width` is the bus
368    /// width to configure on this interface.
369    fn sdmmc_unchecked(
370        self,
371        bus_width: BusWidth,
372        prec: Self::Rec,
373        clocks: &CoreClocks,
374    ) -> Sdmmc<SDMMC>;
375}
376
377impl<S> Sdmmc<S> {
378    /// Calculate clock divisor. Returns a SDMMC_CK less than or equal to
379    /// `sdmmc_ck` in Hertz.
380    ///
381    /// Returns `(clk_div, clk_f)`, where `clk_div` is the divisor register
382    /// value and `clk_f` is the resulting new clock frequency.
383    fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(u16, Hertz), Error> {
384        match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck {
385            0 | 1 => Ok((0, ker_ck)),
386            x @ 2..=2046 => {
387                let clk_div = ((x + 1) / 2) as u16;
388                let clk = Hertz(ker_ck.0 / (clk_div as u32 * 2));
389
390                Ok((clk_div, clk))
391            }
392            _ => Err(Error::BadClock),
393        }
394    }
395}
396
397macro_rules! sdmmc {
398    ($($SDMMCX:ident: ($sdmmcX:ident, $Rec:ident),)+) => {
399        $(
400            impl SdmmcExt<$SDMMCX> for $SDMMCX {
401                type Rec = rec::$Rec;
402
403                fn sdmmc<PINS>(self, _pins: PINS,
404                               prec: rec::$Rec,
405                               clocks: &CoreClocks) -> Sdmmc<$SDMMCX>
406                where
407                    PINS: Pins<$SDMMCX>,
408                {
409                    Sdmmc::$sdmmcX(self, PINS::BUSWIDTH, prec, clocks)
410                }
411
412                fn sdmmc_unchecked(self, bus_width: BusWidth,
413                                   prec: rec::$Rec,
414                                   clocks: &CoreClocks) -> Sdmmc<$SDMMCX>
415                {
416                    Sdmmc::$sdmmcX(self, bus_width, prec, clocks)
417                }
418            }
419
420            impl Sdmmc<$SDMMCX> {
421                /// Sets the CLKDIV field in CLKCR. Updates clock field in self
422                fn clkcr_set_clkdiv(
423                    &mut self,
424                    freq: u32,
425                    width: BusWidth,
426                ) -> Result<(), Error> {
427                    let (clkdiv, new_clock) = Self::clk_div(self.ker_ck, freq)?;
428                    // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7
429                    // Section 55.5.8
430                    let sdmmc_bus_bandwidth = new_clock.0 * (width as u32);
431                    debug_assert!(self.hclk.0 > 3 * sdmmc_bus_bandwidth / 32);
432                    self.clock = new_clock;
433
434                    // CPSMACT and DPSMACT must be 0 to set CLKDIV
435                    while self.sdmmc.star.read().dpsmact().bit_is_set()
436                        || self.sdmmc.star.read().cpsmact().bit_is_set()
437                    {}
438
439                    self.sdmmc
440                        .clkcr
441                        .modify(|_, w| unsafe { w.clkdiv().bits(clkdiv) });
442
443                    Ok(())
444                }
445
446                /// Initialise SDMMC peripheral
447                pub fn $sdmmcX(
448                    sdmmc: $SDMMCX,
449                    bus_width: BusWidth,
450                    prec: rec::$Rec,
451                    clocks: &CoreClocks,
452                ) -> Self {
453                    // Enable and reset peripheral
454                    let prec = prec.enable().reset();
455
456                    let hclk = clocks.hclk();
457                    let ker_ck = match prec.get_kernel_clk_mux() {
458                        rec::SdmmcClkSel::PLL1_Q => clocks.pll1_q_ck(),
459                        rec::SdmmcClkSel::PLL2_R => clocks.pll2_r_ck(),
460                    }
461                    .expect("sdmmc_ker_ck not running!");
462
463                    // For tuning the phase of the receive sampling clock, a
464                    // DLYB block can be connected between sdmmc_io_in_ck and
465                    // sdmmc_fb_ck
466
467                    // While the SD/SDIO card or eMMC is in identification mode,
468                    // the SDMMC_CK frequency must be less than 400 kHz.
469                    let (clkdiv, clock) = Self::clk_div(ker_ck, 400_000)
470                        .expect("SDMMC too slow. Cannot be generated from ker_ck");
471
472                    // Configure clock
473                    sdmmc.clkcr.write(|w| unsafe {
474                        w.widbus()
475                            .bits(0) // 1-bit wide bus
476                            .clkdiv()
477                            .bits(clkdiv)
478                            .pwrsav() // power saving
479                            .clear_bit()
480                            .negedge() // dephasing selection bit
481                            .clear_bit()
482                            .hwfc_en() // hardware flow control
483                            .set_bit()
484                    });
485
486                    // Power off, writen 00: Clock to the card is stopped;
487                    // D[7:0], CMD, and CK are driven high.
488                    sdmmc
489                        .power
490                        .modify(|_, w| unsafe { w.pwrctrl().bits(PowerCtrl::Off as u8) });
491
492                    Sdmmc {
493                        sdmmc,
494                        ker_ck,
495                        hclk,
496                        bus_width,
497                        card: None,
498                        clock,
499                        signalling: Default::default(),
500                    }
501
502                    // drop prec: ker_ck can no longer be modified
503                }
504
505                /// Initializes card (if present) and sets the bus at the
506                /// specified frequency.
507                pub fn init_card(&mut self, freq: impl Into<Hertz>) -> Result<(), Error> {
508                    let freq = freq.into();
509
510                    // Enable power to card
511                    self.sdmmc
512                        .power
513                        .modify(|_, w| unsafe { w.pwrctrl().bits(PowerCtrl::On as u8) });
514
515                    self.cmd(Cmd::idle())?;
516
517                    // Check if cards supports CMD8 (with pattern)
518                    self.cmd(Cmd::hs_send_ext_csd(0x1AA))?;
519                    let r1 = self.sdmmc.resp1r.read().bits();
520
521                    let mut card = if r1 == 0x1AA {
522                        // Card echoed back the pattern. Must be at least v2
523                        Card::default()
524                    } else {
525                        return Err(Error::UnsupportedCardVersion);
526                    };
527
528                    let ocr = loop {
529                        // Signal that next command is a app command
530                        self.cmd(Cmd::app_cmd(0))?; // CMD55
531
532                        let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32
533                            | CmdAppOper::HIGH_CAPACITY as u32
534                            | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32;
535
536                        // Initialize card
537                        match self.cmd(Cmd::app_op_cmd(arg)) {
538                            // ACMD41
539                            Ok(_) => (),
540                            Err(Error::Crc) => (),
541                            Err(err) => return Err(err),
542                        }
543                        let ocr = OCR(self.sdmmc.resp1r.read().bits());
544                        if !ocr.is_busy() {
545                            // Power up done
546                            break ocr;
547                        }
548                    };
549
550                    if ocr.ccs() {
551                        // Card is SDHC or SDXC or SDUC
552                        card.card_type = CardType::SDHC;
553                    } else {
554                        return Err(Error::UnsupportedCardType);
555                    }
556                    card.ocr = ocr;
557
558                    // Get CID
559                    self.cmd(Cmd::all_send_cid())?; // CMD2
560                    let cid = ((self.sdmmc.resp1r.read().bits() as u128) << 96)
561                        | ((self.sdmmc.resp2r.read().bits() as u128) << 64)
562                        | ((self.sdmmc.resp3r.read().bits() as u128) << 32)
563                        | self.sdmmc.resp4r.read().bits() as u128;
564                    card.cid = CID::new(cid);
565
566                    // Get RCA
567                    self.cmd(Cmd::send_rel_addr())?;
568                    card.rca = self.sdmmc.resp1r.read().bits() >> 16;
569
570                    // Get CSD
571                    self.cmd(Cmd::send_csd(card.rca << 16))?;
572                    let csd = ((self.sdmmc.resp1r.read().bits() as u128) << 96)
573                        | ((self.sdmmc.resp2r.read().bits() as u128) << 64)
574                        | ((self.sdmmc.resp3r.read().bits() as u128) << 32)
575                        | self.sdmmc.resp4r.read().bits() as u128;
576                    card.csd = CSD(csd);
577
578                    self.select_card(Some(&card))?;
579
580                    self.get_scr(&mut card)?;
581
582                    // Set bus width
583                    let (width, acmd_arg) = match self.bus_width {
584                        BusWidth::Eight => unimplemented!(),
585                        BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2),
586                        _ => (BusWidth::One, 0),
587                    };
588                    self.cmd(Cmd::app_cmd(card.rca << 16))?;
589                    self.cmd(Cmd::cmd6(acmd_arg))?; // ACMD6: Bus Width
590
591                    // CPSMACT and DPSMACT must be 0 to set WIDBUS
592                    while self.sdmmc.star.read().dpsmact().bit_is_set()
593                        || self.sdmmc.star.read().cpsmact().bit_is_set()
594                    {}
595                    self.sdmmc.clkcr.modify(|_, w| unsafe {
596                        w.widbus().bits(match width {
597                            BusWidth::One => 0,
598                            BusWidth::Four => 1,
599                            BusWidth::Eight => 2,
600                        })
601                    });
602
603                    // Set Clock
604                    if freq.0 <= 25_000_000 {
605                        // Final clock frequency
606                        self.clkcr_set_clkdiv(freq.0, width)?;
607                    } else {
608                        // Switch to max clock for SDR12
609                        self.clkcr_set_clkdiv(25_000_000, width)?;
610
611                        sdmmc_trace!("Set intermediate clock frequency of 25MHz (SDR12 signalling");
612                    }
613
614                    // Read status
615                    let _old = self.card.replace(card);
616                    self.read_sd_status()?;
617
618                    if freq.0 > 25_000_000 {
619                        // Switch to SDR25
620                        self.signalling = self.switch_signalling_mode(Signalling::SDR25)?;
621
622                        if self.signalling == Signalling::SDR25 {
623                            self.clkcr_set_clkdiv(freq.0, width)?;
624
625                            if self.send_status()? != CardStatus::Transfer {
626                                return Err(Error::SignalingSwitchFailed);
627                            }
628                        }
629
630                        sdmmc_trace!("Set final clock frequency of {}", freq.0);
631                    }
632
633                    Ok(())
634                }
635
636                /// Get a reference to the initialized card
637                ///
638                /// # Errors
639                ///
640                /// Returns Error::NoCard if [`init_card`](#method.init_card)
641                /// has not previously succeeded
642                pub fn card(&self) -> Result<&Card, Error> {
643                    self.card.as_ref().ok_or(Error::NoCard)
644                }
645
646                /// Get the current SDMMC bus clock
647                ///
648                pub fn clock(&self) -> Hertz {
649                    self.clock
650                }
651
652                /// Start a transfer
653                fn start_datapath_transfer(
654                    &self,
655                    length_bytes: u32,
656                    block_size: u8,
657                    direction: Dir,
658                ) {
659                    // Block Size up to 2^14 bytes
660                    assert!(block_size <= 14);
661
662                    // Block Size must be greater than 0 ( != 1 byte) in DDR mode
663                    let ddr = self.sdmmc.clkcr.read().ddr().bit_is_set();
664                    assert!(
665                        !ddr || block_size != 0,
666                        "Block size must be >= 1, or >= 2 is DDR mode"
667                    );
668
669                    let dtdir = match direction {
670                        Dir::CardToHost => true,
671                        _ => false,
672                    };
673
674                    // Command AND Data state machines must be idle
675                    while self.sdmmc.star.read().dpsmact().bit_is_set()
676                        || self.sdmmc.star.read().cpsmact().bit_is_set()
677                    {}
678
679                    // Data timeout, in bus cycles
680                    self.sdmmc
681                        .dtimer
682                        .write(|w| unsafe { w.datatime().bits(5_000_000) });
683                    // Data length, in bytes
684                    self.sdmmc
685                        .dlenr
686                        .write(|w| unsafe { w.datalength().bits(length_bytes) });
687                    // Transfer
688                    self.sdmmc.dctrl.write(|w| unsafe {
689                        w.dblocksize()
690                            .bits(block_size) // 2^n bytes block size
691                            .dtdir()
692                            .bit(dtdir)
693                            .dten()
694                            .set_bit() // Enable transfer
695                    });
696                }
697
698                /// Read block from card.
699                ///
700                /// `address` is the block address.
701                pub fn read_block(
702                    &mut self,
703                    address: u32,
704                    buffer: &mut [u8; 512],
705                ) -> Result<(), Error> {
706                    let _card = self.card()?;
707
708                    self.cmd(Cmd::set_block_length(512))?; // CMD16
709
710                    // Setup read command
711                    self.start_datapath_transfer(512, 9, Dir::CardToHost);
712                    self.cmd(Cmd::read_single_block(address))?;
713
714                    let mut i = 0;
715                    let mut status;
716                    while {
717                        status = self.sdmmc.star.read();
718                        !(status.rxoverr().bit()
719                          || status.dcrcfail().bit()
720                          || status.dtimeout().bit()
721                          || status.dataend().bit())
722                    } {
723                        if status.rxfifohf().bit() {
724                            for _ in 0..8 {
725                                let bytes = self.sdmmc.fifor.read().bits().to_le_bytes();
726                                buffer[i..i + 4].copy_from_slice(&bytes);
727                                i += 4;
728                            }
729                        }
730
731                        if i >= buffer.len() {
732                            break;
733                        }
734                    }
735
736                    err_from_datapath_sm!(status);
737
738                    Ok(())
739                }
740
741                /// Read mutliple blocks from card. The length of the buffer
742                /// must be multiple of 512.
743                ///
744                /// `address` is the block address.
745                pub fn read_blocks(
746                    &mut self,
747                    address: u32,
748                    buffer: &mut [u8],
749                ) -> Result<(), Error> {
750                    let _card = self.card()?;
751
752                    assert!(buffer.len() % 512 == 0);
753                    let n_blocks = buffer.len() / 512;
754                    self.cmd(Cmd::set_block_length(512))?; // CMD16
755
756                    // Setup read command
757                    self.start_datapath_transfer(512 * n_blocks as u32, 9, Dir::CardToHost);
758                    self.cmd(Cmd::read_multiple_blocks(address))?;
759
760                    let mut i = 0;
761                    let mut status;
762                    while {
763                        status = self.sdmmc.star.read();
764                        !(status.rxoverr().bit()
765                          || status.dcrcfail().bit()
766                          || status.dtimeout().bit()
767                          || status.dataend().bit())
768                    } {
769                        if status.rxfifohf().bit() {
770                            for _ in 0..8 {
771                                let bytes = self.sdmmc.fifor.read().bits().to_le_bytes();
772                                buffer[i..i + 4].copy_from_slice(&bytes);
773                                i += 4;
774                            }
775                        }
776
777                        if i >= buffer.len() {
778                            break;
779                        }
780                    }
781
782                    self.cmd(Cmd::stop_transmission())?; // CMD12
783
784                    err_from_datapath_sm!(status);
785
786                    Ok(())
787                }
788
789                /// Write block to card. Buffer must be 512 bytes
790                pub fn write_block(
791                    &mut self,
792                    address: u32,
793                    buffer: &[u8; 512]
794                ) -> Result<(), Error> {
795                    let _card = self.card()?;
796
797                    self.cmd(Cmd::set_block_length(512))?; // CMD16
798
799                    // Setup write command
800                    self.start_datapath_transfer(512, 9, Dir::HostToCard);
801                    self.cmd(Cmd::write_single_block(address))?; // CMD24
802
803                    let mut i = 0;
804                    let mut status;
805                    while {
806                        status = self.sdmmc.star.read();
807                        !(status.txunderr().bit()
808                          || status.dcrcfail().bit()
809                          || status.dtimeout().bit()
810                          || status.dataend().bit())
811                    } {
812                        if status.txfifohe().bit() {
813                            for _ in 0..8 {
814                                let mut wb = [0u8; 4];
815                                wb.copy_from_slice(&buffer[i..i + 4]);
816                                let word = u32::from_le_bytes(wb);
817                                self.sdmmc.fifor.write(|w| unsafe { w.bits(word) });
818                                i += 4;
819                            }
820                        }
821
822                        if i >= buffer.len() {
823                            break;
824                        }
825                    }
826
827                    err_from_datapath_sm!(status);
828                    self.clear_static_interrupt_flags();
829
830                    let mut timeout: u32 = 0xFFFF_FFFF;
831
832                    // Try to read card status (ACMD13)
833                    while timeout > 0 {
834                        match self.read_sd_status() {
835                            Ok(_) => return Ok(()),
836                            Err(Error::Timeout) => (), // Try again
837                            Err(e) => return Err(e),
838                        }
839
840                        timeout -= 1;
841                    }
842                    Err(Error::SoftwareTimeout)
843                }
844
845                /// Query the card's status register (CMD13).
846                ///
847                /// Returns the 'card state' bits
848                fn send_status(&self) -> Result<CardStatus, Error> {
849                    let card = self.card()?;
850
851                    // SEND_STATUS
852                    self.cmd(Cmd::card_status(card.rca << 16))?; // CMD13
853                    let r1 = self.sdmmc.resp1r.read().bits();
854
855                    let cardstate = (r1 >> 9) as u8 & 0xF;
856
857                    Ok(cardstate.into())
858                }
859
860                /// Reads the SD Status (ACMD13)
861                ///
862                fn read_sd_status(&mut self) -> Result<(), Error> {
863                    let card = self.card()?;
864
865                    self.cmd(Cmd::set_block_length(64))?; // CMD16
866                    self.cmd(Cmd::app_cmd(card.rca << 16))?; // APP
867
868                    // Prepare the transfer
869                    self.start_datapath_transfer(64, 6, Dir::CardToHost);
870                    self.cmd(Cmd::card_status(0))?; // ACMD13
871
872                    let mut status = [0u32; 16];
873                    let mut idx = 0;
874                    let mut sta_reg;
875                    while {
876                        sta_reg = self.sdmmc.star.read();
877                        !(sta_reg.rxoverr().bit()
878                          || sta_reg.dcrcfail().bit()
879                          || sta_reg.dtimeout().bit()
880                          || sta_reg.dbckend().bit())
881                    } {
882                        if sta_reg.rxfifohf().bit() {
883                            for _ in 0..8 {
884                                status[idx] = self.sdmmc.fifor.read().bits();
885                                idx += 1;
886                            }
887                        }
888
889                        if idx == status.len() {
890                            break;
891                        }
892                    }
893
894                    err_from_datapath_sm!(sta_reg);
895
896                    let card = self.card.as_mut().ok_or(Error::NoCard)?;
897                    card.status = SDStatus::new(status);
898
899                    Ok(())
900                }
901
902                /// Get SD CARD Configuration Register (SCR)
903                fn get_scr(&self, card: &mut Card) -> Result<(), Error> {
904                    // Read the the 64-bit SCR register
905                    self.cmd(Cmd::set_block_length(8))?; // CMD16
906                    self.cmd(Cmd::app_cmd(card.rca << 16))?;
907
908                    self.start_datapath_transfer(8, 3, Dir::CardToHost);
909                    self.cmd(Cmd::cmd51())?;
910
911                    let mut scr = [0; 2];
912                    let mut i = 0;
913                    let mut status;
914                    while {
915                        status = self.sdmmc.star.read();
916
917                        !(status.rxoverr().bit()
918                          || status.dcrcfail().bit()
919                          || status.dtimeout().bit()
920                          || status.dbckend().bit())
921                    } {
922                        if status.rxfifoe().bit_is_clear() {
923                            // FIFO not empty
924                            scr[i] = self.sdmmc.fifor.read().bits();
925                            i += 1;
926                        }
927
928                        if i == 2 {
929                            break;
930                        }
931                    }
932
933                    err_from_datapath_sm!(status);
934
935                    // Bytes from wire are Big Endian
936                    let scr = ((scr[1] as u64) << 32) | scr[0] as u64;
937                    card.scr = SCR(u64::from_be(scr));
938
939                    Ok(())
940                }
941
942                /// Switch mode using CMD6.
943                ///
944                /// Attempt to set a new signalling mode. The selected
945                /// signalling mode is returned. Expects the current clock
946                /// frequency to be > 12.5MHz.
947                fn switch_signalling_mode(
948                    &self,
949                    signalling: Signalling,
950                ) -> Result<Signalling, Error> {
951                    // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
952                    // necessary"
953
954                    let set_function = 0x8000_0000
955                        | match signalling {
956                            // See PLSS v7_10 Table 4-11
957                            Signalling::DDR50 => 0xFF_FF04,
958                            Signalling::SDR104 => 0xFF_1F03,
959                            Signalling::SDR50 => 0xFF_1F02,
960                            Signalling::SDR25 => 0xFF_FF01,
961                            Signalling::SDR12 => 0xFF_FF00,
962                        };
963
964                    // Prepare the transfer
965                    self.start_datapath_transfer(64, 6, Dir::CardToHost);
966                    self.cmd(Cmd::cmd6(set_function))?; // CMD6
967
968                    let mut status = [0u32; 16];
969                    let mut idx = 0;
970                    let mut sta_reg;
971                    while {
972                        sta_reg = self.sdmmc.star.read();
973                        !(sta_reg.rxoverr().bit()
974                          || sta_reg.dcrcfail().bit()
975                          || sta_reg.dtimeout().bit()
976                          || sta_reg.dbckend().bit())
977                    } {
978                        if sta_reg.rxfifohf().bit() {
979                            for _ in 0..8 {
980                                status[idx] = self.sdmmc.fifor.read().bits();
981                                idx += 1;
982                            }
983                        }
984
985                        if idx == status.len() {
986                            break;
987                        }
988                    }
989
990                    err_from_datapath_sm!(sta_reg);
991
992                    // Host is allowed to use the new functions at least 8
993                    // clocks after the end of the switch command
994                    // transaction. We know the current clock period is < 80ns,
995                    // so a total delay of 640ns is required here
996                    for _ in 0..300 {
997                        cortex_m::asm::nop();
998                    }
999
1000                    // Support Bits of Functions in Function Group 1
1001                    let _support_bits = u32::from_be(status[3]) >> 16;
1002                    // Function Selection of Function Group 1
1003                    let selection = (u32::from_be(status[4]) >> 24) & 0xF;
1004
1005                    match selection {
1006                        0 => Ok(Signalling::SDR12),
1007                        1 => Ok(Signalling::SDR25),
1008                        2 => Ok(Signalling::SDR50),
1009                        3 => Ok(Signalling::SDR104),
1010                        4 => Ok(Signalling::DDR50),
1011                        _ => Err(Error::UnsupportedCardType),
1012                    }
1013                }
1014
1015                /// Select one card and place it into the _Tranfer State_
1016                ///
1017                /// If `None` is specifed for `card`, all cards are put back into
1018                /// _Stand-by State_
1019                fn select_card(&self, card: Option<&Card>) -> Result<(), Error> {
1020                    // Determine Relative Card Address (RCA) of given card
1021                    let rca = card.map(|c| c.rca << 16).unwrap_or(0);
1022
1023                    let r = self.cmd(Cmd::sel_desel_card(rca));
1024                    match (r, rca) {
1025                        (Err(Error::Timeout), 0) => Ok(()),
1026                        _ => r,
1027                    }
1028                }
1029
1030                /// Clear "static flags" in interrupt clear register
1031                fn clear_static_interrupt_flags(&self) {
1032                    self.sdmmc.icr.modify(|_, w| {
1033                        w.dcrcfailc()
1034                            .set_bit()
1035                            .dtimeoutc()
1036                            .set_bit()
1037                            .txunderrc()
1038                            .set_bit()
1039                            .rxoverrc()
1040                            .set_bit()
1041                            .dataendc()
1042                            .set_bit()
1043                            .dholdc()
1044                            .set_bit()
1045                            .dbckendc()
1046                            .set_bit()
1047                            .dabortc()
1048                            .set_bit()
1049                            .idmatec()
1050                            .set_bit()
1051                            .idmabtcc()
1052                            .set_bit()
1053                    });
1054                }
1055
1056                /// Send command to card
1057                fn cmd(&self, cmd: Cmd) -> Result<(), Error> {
1058                    // Clear interrupts
1059                    self.sdmmc.icr.modify(|_, w| {
1060                        w.ccrcfailc() // CRC FAIL
1061                            .set_bit()
1062                            .ctimeoutc() // TIMEOUT
1063                            .set_bit()
1064                            .cmdrendc() // CMD R END
1065                            .set_bit()
1066                            .cmdsentc() // CMD SENT
1067                            .set_bit()
1068                            .dataendc()
1069                            .set_bit()
1070                            .dbckendc()
1071                            .set_bit()
1072                            .dcrcfailc()
1073                            .set_bit()
1074                            .dtimeoutc()
1075                            .set_bit()
1076                            .sdioitc() // SDIO IT
1077                            .set_bit()
1078                            .rxoverrc()
1079                            .set_bit()
1080                            .txunderrc()
1081                            .set_bit()
1082                    });
1083
1084                    // CP state machine must be idle
1085                    while self.sdmmc.star.read().cpsmact().bit_is_set() {}
1086
1087                    // Command arg
1088                    self.sdmmc
1089                        .argr
1090                        .write(|w| unsafe { w.cmdarg().bits(cmd.arg) });
1091
1092                    // Special mode in CP State Machine
1093                    // CMD12: Stop Transmission
1094                    let cpsm_stop_transmission = (cmd.cmd == 12);
1095
1096                    // Command index and start CP State Machine
1097                    self.sdmmc.cmdr.write(|w| unsafe {
1098                        w.waitint()
1099                            .clear_bit()
1100                            .waitresp() // No / Short / Long
1101                            .bits(cmd.resp as u8)
1102                            .cmdstop() // CPSM Stop Transmission
1103                            .bit(cpsm_stop_transmission)
1104                            .cmdindex()
1105                            .bits(cmd.cmd)
1106                            .cpsmen()
1107                            .set_bit()
1108                    });
1109
1110                    let mut timeout: u32 = 0xFFFF_FFFF;
1111
1112                    let mut status;
1113                    if cmd.resp == Response::None {
1114                        // Wait for CMDSENT or a timeout
1115                        while {
1116                            status = self.sdmmc.star.read();
1117                            !(status.ctimeout().bit() || status.cmdsent().bit())
1118                                && timeout > 0
1119                        } {
1120                            timeout -= 1;
1121                        }
1122                    } else {
1123                        // Wait for CMDREND or CCRCFAIL or a timeout
1124                        while {
1125                            status = self.sdmmc.star.read();
1126                            !(status.ctimeout().bit()
1127                              || status.cmdrend().bit()
1128                              || status.ccrcfail().bit())
1129                                && timeout > 0
1130                        } {
1131                            timeout -= 1;
1132                        }
1133                    }
1134
1135                    if status.ctimeout().bit_is_set() {
1136                        return Err(Error::Timeout);
1137                    } else if timeout == 0 {
1138                        return Err(Error::SoftwareTimeout);
1139                    } else if status.ccrcfail().bit() {
1140                        return Err(Error::Crc);
1141                    }
1142
1143                    Ok(())
1144                }
1145
1146            }
1147        )+
1148    };
1149}
1150
1151sdmmc! {
1152    SDMMC1: (sdmmc1, Sdmmc1),
1153    SDMMC2: (sdmmc2, Sdmmc2),
1154}
1155
1156/// SD card Commands
1157impl Cmd {
1158    const fn new(cmd: u8, arg: u32, resp: Response) -> Cmd {
1159        Cmd { cmd, arg, resp }
1160    }
1161
1162    /// CMD0: Idle
1163    const fn idle() -> Cmd {
1164        Cmd::new(0, 0, Response::None)
1165    }
1166
1167    /// CMD2: Send CID
1168    const fn all_send_cid() -> Cmd {
1169        Cmd::new(2, 0, Response::Long)
1170    }
1171
1172    /// CMD3: Send Relative Address
1173    const fn send_rel_addr() -> Cmd {
1174        Cmd::new(3, 0, Response::Short)
1175    }
1176
1177    /// CMD6: Switch Function Command
1178    /// ACMD6: Bus Width
1179    const fn cmd6(arg: u32) -> Cmd {
1180        Cmd::new(6, arg, Response::Short)
1181    }
1182
1183    /// CMD7: Select one card and put it into the _Tranfer State_
1184    const fn sel_desel_card(rca: u32) -> Cmd {
1185        Cmd::new(7, rca, Response::Short)
1186    }
1187
1188    /// CMD8:
1189    const fn hs_send_ext_csd(arg: u32) -> Cmd {
1190        Cmd::new(8, arg, Response::Short)
1191    }
1192
1193    /// CMD9:
1194    const fn send_csd(rca: u32) -> Cmd {
1195        Cmd::new(9, rca, Response::Long)
1196    }
1197
1198    /// CMD12:
1199    const fn stop_transmission() -> Cmd {
1200        Cmd::new(12, 0, Response::Short)
1201    }
1202
1203    /// CMD13: Ask card to send status register
1204    /// ACMD13: SD Status
1205    const fn card_status(rca: u32) -> Cmd {
1206        Cmd::new(13, rca, Response::Short)
1207    }
1208
1209    /// CMD16:
1210    const fn set_block_length(blocklen: u32) -> Cmd {
1211        Cmd::new(16, blocklen, Response::Short)
1212    }
1213
1214    /// CMD17: Block Read
1215    const fn read_single_block(addr: u32) -> Cmd {
1216        Cmd::new(17, addr, Response::Short)
1217    }
1218
1219    /// CMD18: Multiple Block Read
1220    const fn read_multiple_blocks(addr: u32) -> Cmd {
1221        Cmd::new(18, addr, Response::Short)
1222    }
1223
1224    /// CMD24: Block Write
1225    const fn write_single_block(addr: u32) -> Cmd {
1226        Cmd::new(24, addr, Response::Short)
1227    }
1228
1229    const fn app_op_cmd(arg: u32) -> Cmd {
1230        Cmd::new(41, arg, Response::Short)
1231    }
1232
1233    const fn cmd51() -> Cmd {
1234        Cmd::new(51, 0, Response::Short)
1235    }
1236
1237    /// App Command. Indicates that next command will be a app command
1238    const fn app_cmd(rca: u32) -> Cmd {
1239        Cmd::new(55, rca, Response::Short)
1240    }
1241}