1use 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};
20use 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#[derive(Copy, Clone, Debug)]
155#[allow(missing_docs)]
156pub enum BusWidth {
157 One = 1,
158 Four = 4,
159 Eight = 8,
160}
161
162#[derive(Debug, Copy, Clone)]
164#[non_exhaustive]
165pub enum CardType {
166 SDSC,
168 SDHC,
170}
171impl Default for CardType {
172 fn default() -> Self {
173 CardType::SDSC
174 }
175}
176
177#[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#[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
211struct Cmd {
213 cmd: u8,
214 arg: u32,
215 resp: Response,
216}
217
218#[derive(Clone, Copy, Debug, Default)]
219pub struct Card {
221 pub card_type: CardType,
223 pub ocr: OCR,
225 pub rca: u32,
227 pub cid: CID,
229 pub csd: CSD,
231 pub scr: SCR,
233 pub status: SDStatus,
235}
236impl Card {
237 pub fn size(&self) -> u64 {
239 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
256enum 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 Ready = 1,
290 Identification = 2,
292 Standby = 3,
294 Transfer = 4,
296 Sending = 5,
298 Receiving = 6,
300 Programming = 7,
302 Disconnected = 8,
304 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
323pub struct Sdmmc<SDMMC> {
325 sdmmc: SDMMC,
326 ker_ck: Hertz,
328 hclk: Hertz,
330 bus_width: BusWidth,
332 clock: Hertz,
334 signalling: Signalling,
336 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
350pub trait SdmmcExt<SDMMC>: Sized {
352 type Rec: ResetEnable;
354
355 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 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 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 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 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 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 pub fn $sdmmcX(
448 sdmmc: $SDMMCX,
449 bus_width: BusWidth,
450 prec: rec::$Rec,
451 clocks: &CoreClocks,
452 ) -> Self {
453 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 let (clkdiv, clock) = Self::clk_div(ker_ck, 400_000)
470 .expect("SDMMC too slow. Cannot be generated from ker_ck");
471
472 sdmmc.clkcr.write(|w| unsafe {
474 w.widbus()
475 .bits(0) .clkdiv()
477 .bits(clkdiv)
478 .pwrsav() .clear_bit()
480 .negedge() .clear_bit()
482 .hwfc_en() .set_bit()
484 });
485
486 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 }
504
505 pub fn init_card(&mut self, freq: impl Into<Hertz>) -> Result<(), Error> {
508 let freq = freq.into();
509
510 self.sdmmc
512 .power
513 .modify(|_, w| unsafe { w.pwrctrl().bits(PowerCtrl::On as u8) });
514
515 self.cmd(Cmd::idle())?;
516
517 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::default()
524 } else {
525 return Err(Error::UnsupportedCardVersion);
526 };
527
528 let ocr = loop {
529 self.cmd(Cmd::app_cmd(0))?; 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 match self.cmd(Cmd::app_op_cmd(arg)) {
538 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 break ocr;
547 }
548 };
549
550 if ocr.ccs() {
551 card.card_type = CardType::SDHC;
553 } else {
554 return Err(Error::UnsupportedCardType);
555 }
556 card.ocr = ocr;
557
558 self.cmd(Cmd::all_send_cid())?; 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 self.cmd(Cmd::send_rel_addr())?;
568 card.rca = self.sdmmc.resp1r.read().bits() >> 16;
569
570 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 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))?; 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 if freq.0 <= 25_000_000 {
605 self.clkcr_set_clkdiv(freq.0, width)?;
607 } else {
608 self.clkcr_set_clkdiv(25_000_000, width)?;
610
611 sdmmc_trace!("Set intermediate clock frequency of 25MHz (SDR12 signalling");
612 }
613
614 let _old = self.card.replace(card);
616 self.read_sd_status()?;
617
618 if freq.0 > 25_000_000 {
619 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 pub fn card(&self) -> Result<&Card, Error> {
643 self.card.as_ref().ok_or(Error::NoCard)
644 }
645
646 pub fn clock(&self) -> Hertz {
649 self.clock
650 }
651
652 fn start_datapath_transfer(
654 &self,
655 length_bytes: u32,
656 block_size: u8,
657 direction: Dir,
658 ) {
659 assert!(block_size <= 14);
661
662 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 while self.sdmmc.star.read().dpsmact().bit_is_set()
676 || self.sdmmc.star.read().cpsmact().bit_is_set()
677 {}
678
679 self.sdmmc
681 .dtimer
682 .write(|w| unsafe { w.datatime().bits(5_000_000) });
683 self.sdmmc
685 .dlenr
686 .write(|w| unsafe { w.datalength().bits(length_bytes) });
687 self.sdmmc.dctrl.write(|w| unsafe {
689 w.dblocksize()
690 .bits(block_size) .dtdir()
692 .bit(dtdir)
693 .dten()
694 .set_bit() });
696 }
697
698 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))?; 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 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))?; 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())?; err_from_datapath_sm!(status);
785
786 Ok(())
787 }
788
789 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))?; self.start_datapath_transfer(512, 9, Dir::HostToCard);
801 self.cmd(Cmd::write_single_block(address))?; 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 while timeout > 0 {
834 match self.read_sd_status() {
835 Ok(_) => return Ok(()),
836 Err(Error::Timeout) => (), Err(e) => return Err(e),
838 }
839
840 timeout -= 1;
841 }
842 Err(Error::SoftwareTimeout)
843 }
844
845 fn send_status(&self) -> Result<CardStatus, Error> {
849 let card = self.card()?;
850
851 self.cmd(Cmd::card_status(card.rca << 16))?; let r1 = self.sdmmc.resp1r.read().bits();
854
855 let cardstate = (r1 >> 9) as u8 & 0xF;
856
857 Ok(cardstate.into())
858 }
859
860 fn read_sd_status(&mut self) -> Result<(), Error> {
863 let card = self.card()?;
864
865 self.cmd(Cmd::set_block_length(64))?; self.cmd(Cmd::app_cmd(card.rca << 16))?; self.start_datapath_transfer(64, 6, Dir::CardToHost);
870 self.cmd(Cmd::card_status(0))?; 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 fn get_scr(&self, card: &mut Card) -> Result<(), Error> {
904 self.cmd(Cmd::set_block_length(8))?; 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 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 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 fn switch_signalling_mode(
948 &self,
949 signalling: Signalling,
950 ) -> Result<Signalling, Error> {
951 let set_function = 0x8000_0000
955 | match signalling {
956 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 self.start_datapath_transfer(64, 6, Dir::CardToHost);
966 self.cmd(Cmd::cmd6(set_function))?; 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 for _ in 0..300 {
997 cortex_m::asm::nop();
998 }
999
1000 let _support_bits = u32::from_be(status[3]) >> 16;
1002 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 fn select_card(&self, card: Option<&Card>) -> Result<(), Error> {
1020 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 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 fn cmd(&self, cmd: Cmd) -> Result<(), Error> {
1058 self.sdmmc.icr.modify(|_, w| {
1060 w.ccrcfailc() .set_bit()
1062 .ctimeoutc() .set_bit()
1064 .cmdrendc() .set_bit()
1066 .cmdsentc() .set_bit()
1068 .dataendc()
1069 .set_bit()
1070 .dbckendc()
1071 .set_bit()
1072 .dcrcfailc()
1073 .set_bit()
1074 .dtimeoutc()
1075 .set_bit()
1076 .sdioitc() .set_bit()
1078 .rxoverrc()
1079 .set_bit()
1080 .txunderrc()
1081 .set_bit()
1082 });
1083
1084 while self.sdmmc.star.read().cpsmact().bit_is_set() {}
1086
1087 self.sdmmc
1089 .argr
1090 .write(|w| unsafe { w.cmdarg().bits(cmd.arg) });
1091
1092 let cpsm_stop_transmission = (cmd.cmd == 12);
1095
1096 self.sdmmc.cmdr.write(|w| unsafe {
1098 w.waitint()
1099 .clear_bit()
1100 .waitresp() .bits(cmd.resp as u8)
1102 .cmdstop() .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 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 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
1156impl Cmd {
1158 const fn new(cmd: u8, arg: u32, resp: Response) -> Cmd {
1159 Cmd { cmd, arg, resp }
1160 }
1161
1162 const fn idle() -> Cmd {
1164 Cmd::new(0, 0, Response::None)
1165 }
1166
1167 const fn all_send_cid() -> Cmd {
1169 Cmd::new(2, 0, Response::Long)
1170 }
1171
1172 const fn send_rel_addr() -> Cmd {
1174 Cmd::new(3, 0, Response::Short)
1175 }
1176
1177 const fn cmd6(arg: u32) -> Cmd {
1180 Cmd::new(6, arg, Response::Short)
1181 }
1182
1183 const fn sel_desel_card(rca: u32) -> Cmd {
1185 Cmd::new(7, rca, Response::Short)
1186 }
1187
1188 const fn hs_send_ext_csd(arg: u32) -> Cmd {
1190 Cmd::new(8, arg, Response::Short)
1191 }
1192
1193 const fn send_csd(rca: u32) -> Cmd {
1195 Cmd::new(9, rca, Response::Long)
1196 }
1197
1198 const fn stop_transmission() -> Cmd {
1200 Cmd::new(12, 0, Response::Short)
1201 }
1202
1203 const fn card_status(rca: u32) -> Cmd {
1206 Cmd::new(13, rca, Response::Short)
1207 }
1208
1209 const fn set_block_length(blocklen: u32) -> Cmd {
1211 Cmd::new(16, blocklen, Response::Short)
1212 }
1213
1214 const fn read_single_block(addr: u32) -> Cmd {
1216 Cmd::new(17, addr, Response::Short)
1217 }
1218
1219 const fn read_multiple_blocks(addr: u32) -> Cmd {
1221 Cmd::new(18, addr, Response::Short)
1222 }
1223
1224 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 const fn app_cmd(rca: u32) -> Cmd {
1239 Cmd::new(55, rca, Response::Short)
1240 }
1241}