aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-04-06 22:04:18 +0000
committerGitHub <[email protected]>2025-04-06 22:04:18 +0000
commit717fbc1cd9a038d6601721a6e84f58be264ee624 (patch)
tree2339ba2d2dc7584817b906055d545fb656548ac6
parent5bd610b0de35cc95009f790141885fe80fc84a27 (diff)
parentdc31bfd8295c3626794e0b1b38804af2acc59053 (diff)
Merge pull request #4016 from antonok-edm/emmc
Support eMMC devices via SDMMC (STM32)
-rw-r--r--embassy-stm32/Cargo.toml2
-rw-r--r--embassy-stm32/build.rs2
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs1274
-rw-r--r--examples/stm32f4/src/bin/sdmmc.rs2
-rw-r--r--examples/stm32f7/src/bin/sdmmc.rs2
-rw-r--r--examples/stm32h7/src/bin/sdmmc.rs2
-rw-r--r--tests/stm32/src/bin/sdmmc.rs4
7 files changed, 742 insertions, 546 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 4d0555d4a..d15ac4823 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -70,7 +70,7 @@ cortex-m-rt = ">=0.6.15,<0.8"
70cortex-m = "0.7.6" 70cortex-m = "0.7.6"
71futures-util = { version = "0.3.30", default-features = false } 71futures-util = { version = "0.3.30", default-features = false }
72rand_core = "0.6.3" 72rand_core = "0.6.3"
73sdio-host = "0.5.0" 73sdio-host = "0.9.0"
74critical-section = "1.1" 74critical-section = "1.1"
75#stm32-metapac = { version = "16" } 75#stm32-metapac = { version = "16" }
76stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a7a30c9d54e7415709c463a537501691784672db" } 76stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a7a30c9d54e7415709c463a537501691784672db" }
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index b4e61878c..d965d8732 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -1056,7 +1056,7 @@ fn main() {
1056 (("sdmmc", "D4"), quote!(crate::sdmmc::D4Pin)), 1056 (("sdmmc", "D4"), quote!(crate::sdmmc::D4Pin)),
1057 (("sdmmc", "D5"), quote!(crate::sdmmc::D5Pin)), 1057 (("sdmmc", "D5"), quote!(crate::sdmmc::D5Pin)),
1058 (("sdmmc", "D6"), quote!(crate::sdmmc::D6Pin)), 1058 (("sdmmc", "D6"), quote!(crate::sdmmc::D6Pin)),
1059 (("sdmmc", "D6"), quote!(crate::sdmmc::D7Pin)), 1059 (("sdmmc", "D7"), quote!(crate::sdmmc::D7Pin)),
1060 (("sdmmc", "D8"), quote!(crate::sdmmc::D8Pin)), 1060 (("sdmmc", "D8"), quote!(crate::sdmmc::D8Pin)),
1061 (("quadspi", "BK1_IO0"), quote!(crate::qspi::BK1D0Pin)), 1061 (("quadspi", "BK1_IO0"), quote!(crate::qspi::BK1D0Pin)),
1062 (("quadspi", "BK1_IO1"), quote!(crate::qspi::BK1D1Pin)), 1062 (("quadspi", "BK1_IO1"), quote!(crate::qspi::BK1D1Pin)),
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 8f3c45f50..63868e5ae 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -10,7 +10,10 @@ use core::task::Poll;
10use embassy_hal_internal::drop::OnDrop; 10use embassy_hal_internal::drop::OnDrop;
11use embassy_hal_internal::{Peri, PeripheralType}; 11use embassy_hal_internal::{Peri, PeripheralType};
12use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; 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};
14 17
15#[cfg(sdmmc_v1)] 18#[cfg(sdmmc_v1)]
16use crate::dma::ChannelAndRequest; 19use crate::dma::ChannelAndRequest;
@@ -136,10 +139,14 @@ pub enum Error {
136 UnsupportedCardVersion, 139 UnsupportedCardVersion,
137 /// Unsupported card type. 140 /// Unsupported card type.
138 UnsupportedCardType, 141 UnsupportedCardType,
142 /// Unsupported voltage.
143 UnsupportedVoltage,
139 /// CRC error. 144 /// CRC error.
140 Crc, 145 Crc,
141 /// No card inserted. 146 /// No card inserted.
142 NoCard, 147 NoCard,
148 /// 8-lane buses are not supported for SD cards.
149 BusWidth,
143 /// Bad clock supplied to the SDMMC peripheral. 150 /// Bad clock supplied to the SDMMC peripheral.
144 BadClock, 151 BadClock,
145 /// Signaling switch failed. 152 /// Signaling switch failed.
@@ -149,38 +156,40 @@ pub enum Error {
149 StBitErr, 156 StBitErr,
150} 157}
151 158
152/// A SD command
153struct Cmd {
154 cmd: u8,
155 arg: u32,
156 resp: Response,
157}
158
159#[derive(Clone, Copy, Debug, Default)] 159#[derive(Clone, Copy, Debug, Default)]
160/// SD Card 160/// SD Card
161pub struct Card { 161pub struct Card {
162 /// The type of this card 162 /// The type of this card
163 pub card_type: CardCapacity, 163 pub card_type: CardCapacity,
164 /// Operation Conditions Register 164 /// Operation Conditions Register
165 pub ocr: OCR, 165 pub ocr: OCR<SD>,
166 /// Relative Card Address 166 /// Relative Card Address
167 pub rca: u32, 167 pub rca: u16,
168 /// Card ID 168 /// Card ID
169 pub cid: CID, 169 pub cid: CID<SD>,
170 /// Card Specific Data 170 /// Card Specific Data
171 pub csd: CSD, 171 pub csd: CSD<SD>,
172 /// SD CARD Configuration Register 172 /// SD CARD Configuration Register
173 pub scr: SCR, 173 pub scr: SCR,
174 /// SD Status 174 /// SD Status
175 pub status: SDStatus, 175 pub status: SDStatus,
176} 176}
177 177
178impl Card { 178#[derive(Clone, Copy, Debug, Default)]
179 /// Size in bytes 179/// eMMC storage
180 pub fn size(&self) -> u64 { 180pub struct Emmc {
181 // SDHC / SDXC / SDUC 181 /// The capacity of this card
182 u64::from(self.csd.block_count()) * 512 182 pub capacity: CardCapacity,
183 } 183 /// Operation Conditions Register
184 pub ocr: OCR<EMMC>,
185 /// Relative Card Address
186 pub rca: u16,
187 /// Card ID
188 pub cid: CID<EMMC>,
189 /// Card Specific Data
190 pub csd: CSD<EMMC>,
191 /// Extended Card Specific Data
192 pub ext_csd: ExtCSD,
184} 193}
185 194
186#[repr(u8)] 195#[repr(u8)]
@@ -189,22 +198,12 @@ enum PowerCtrl {
189 On = 0b11, 198 On = 0b11,
190} 199}
191 200
192#[repr(u32)] 201fn get_waitresp_val(rlen: ResponseLen) -> u8 {
193#[allow(dead_code)] 202 match rlen {
194#[allow(non_camel_case_types)] 203 common_cmd::ResponseLen::Zero => 0,
195enum CmdAppOper { 204 common_cmd::ResponseLen::R48 => 1,
196 VOLTAGE_WINDOW_SD = 0x8010_0000, 205 common_cmd::ResponseLen::R136 => 3,
197 HIGH_CAPACITY = 0x4000_0000, 206 }
198 SDMMC_STD_CAPACITY = 0x0000_0000,
199 SDMMC_CHECK_PATTERN = 0x0000_01AA,
200 SD_SWITCH_1_8V_CAPACITY = 0x0100_0000,
201}
202
203#[derive(Eq, PartialEq, Copy, Clone)]
204enum Response {
205 None = 0,
206 Short = 1,
207 Long = 3,
208} 207}
209 208
210/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to 209/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to
@@ -301,6 +300,61 @@ impl Default for Config {
301 } 300 }
302} 301}
303 302
303/// Peripheral that can be operated over SDMMC
304#[derive(Clone, Copy, Debug)]
305pub enum SdmmcPeripheral {
306 /// SD Card
307 SdCard(Card),
308 /// eMMC memory
309 Emmc(Emmc),
310}
311
312impl SdmmcPeripheral {
313 /// Get this peripheral's address on the SDMMC bus
314 fn get_address(&self) -> u16 {
315 match self {
316 Self::SdCard(c) => c.rca,
317 Self::Emmc(e) => e.rca,
318 }
319 }
320 /// Is this a standard or high capacity peripheral?
321 fn get_capacity(&self) -> CardCapacity {
322 match self {
323 Self::SdCard(c) => c.card_type,
324 Self::Emmc(e) => e.capacity,
325 }
326 }
327 /// Size in bytes
328 fn size(&self) -> u64 {
329 match self {
330 // SDHC / SDXC / SDUC
331 Self::SdCard(c) => u64::from(c.csd.block_count()) * 512,
332 // capacity > 2GB
333 Self::Emmc(e) => u64::from(e.ext_csd.sector_count()) * 512,
334 }
335 }
336
337 /// Get a mutable reference to the SD Card.
338 ///
339 /// Panics if there is another peripheral instead.
340 fn get_sd_card(&mut self) -> &mut Card {
341 match *self {
342 Self::SdCard(ref mut c) => c,
343 _ => unreachable!("SD only"),
344 }
345 }
346
347 /// Get a mutable reference to the eMMC.
348 ///
349 /// Panics if there is another peripheral instead.
350 fn get_emmc(&mut self) -> &mut Emmc {
351 match *self {
352 Self::Emmc(ref mut e) => e,
353 _ => unreachable!("eMMC only"),
354 }
355 }
356}
357
304/// Sdmmc device 358/// Sdmmc device
305pub struct Sdmmc<'d, T: Instance> { 359pub struct Sdmmc<'d, T: Instance> {
306 _peri: Peri<'d, T>, 360 _peri: Peri<'d, T>,
@@ -313,6 +367,10 @@ pub struct Sdmmc<'d, T: Instance> {
313 d1: Option<Peri<'d, AnyPin>>, 367 d1: Option<Peri<'d, AnyPin>>,
314 d2: Option<Peri<'d, AnyPin>>, 368 d2: Option<Peri<'d, AnyPin>>,
315 d3: Option<Peri<'d, AnyPin>>, 369 d3: Option<Peri<'d, AnyPin>>,
370 d4: Option<Peri<'d, AnyPin>>,
371 d5: Option<Peri<'d, AnyPin>>,
372 d6: Option<Peri<'d, AnyPin>>,
373 d7: Option<Peri<'d, AnyPin>>,
316 374
317 config: Config, 375 config: Config,
318 /// Current clock to card 376 /// Current clock to card
@@ -320,7 +378,7 @@ pub struct Sdmmc<'d, T: Instance> {
320 /// Current signalling scheme to card 378 /// Current signalling scheme to card
321 signalling: Signalling, 379 signalling: Signalling,
322 /// Card 380 /// Card
323 card: Option<Card>, 381 card: Option<SdmmcPeripheral>,
324 382
325 /// An optional buffer to be used for commands 383 /// An optional buffer to be used for commands
326 /// This should be used if there are special memory location requirements for dma 384 /// This should be used if there are special memory location requirements for dma
@@ -361,6 +419,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
361 None, 419 None,
362 None, 420 None,
363 None, 421 None,
422 None,
423 None,
424 None,
425 None,
364 config, 426 config,
365 ) 427 )
366 } 428 }
@@ -396,6 +458,60 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
396 Some(d1.into()), 458 Some(d1.into()),
397 Some(d2.into()), 459 Some(d2.into()),
398 Some(d3.into()), 460 Some(d3.into()),
461 None,
462 None,
463 None,
464 None,
465 config,
466 )
467 }
468}
469
470#[cfg(sdmmc_v1)]
471impl<'d, T: Instance> Sdmmc<'d, T> {
472 /// Create a new SDMMC driver, with 8 data lanes.
473 pub fn new_8bit(
474 sdmmc: Peri<'d, T>,
475 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
476 dma: Peri<'d, impl SdmmcDma<T>>,
477 clk: Peri<'d, impl CkPin<T>>,
478 cmd: Peri<'d, impl CmdPin<T>>,
479 d0: Peri<'d, impl D0Pin<T>>,
480 d1: Peri<'d, impl D1Pin<T>>,
481 d2: Peri<'d, impl D2Pin<T>>,
482 d3: Peri<'d, impl D3Pin<T>>,
483 d4: Peri<'d, impl D4Pin<T>>,
484 d5: Peri<'d, impl D5Pin<T>>,
485 d6: Peri<'d, impl D6Pin<T>>,
486 d7: Peri<'d, impl D7Pin<T>>,
487 config: Config,
488 ) -> Self {
489 critical_section::with(|_| {
490 clk.set_as_af(clk.af_num(), CLK_AF);
491 cmd.set_as_af(cmd.af_num(), CMD_AF);
492 d0.set_as_af(d0.af_num(), DATA_AF);
493 d1.set_as_af(d1.af_num(), DATA_AF);
494 d2.set_as_af(d2.af_num(), DATA_AF);
495 d3.set_as_af(d3.af_num(), DATA_AF);
496 d4.set_as_af(d4.af_num(), DATA_AF);
497 d5.set_as_af(d5.af_num(), DATA_AF);
498 d6.set_as_af(d6.af_num(), DATA_AF);
499 d7.set_as_af(d7.af_num(), DATA_AF);
500 });
501
502 Self::new_inner(
503 sdmmc,
504 new_dma_nonopt!(dma),
505 clk.into(),
506 cmd.into(),
507 d0.into(),
508 Some(d1.into()),
509 Some(d2.into()),
510 Some(d3.into()),
511 Some(d4.into()),
512 Some(d5.into()),
513 Some(d6.into()),
514 Some(d7.into()),
399 config, 515 config,
400 ) 516 )
401 } 517 }
@@ -418,7 +534,20 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
418 d0.set_as_af(d0.af_num(), DATA_AF); 534 d0.set_as_af(d0.af_num(), DATA_AF);
419 }); 535 });
420 536
421 Self::new_inner(sdmmc, clk.into(), cmd.into(), d0.into(), None, None, None, config) 537 Self::new_inner(
538 sdmmc,
539 clk.into(),
540 cmd.into(),
541 d0.into(),
542 None,
543 None,
544 None,
545 None,
546 None,
547 None,
548 None,
549 config,
550 )
422 } 551 }
423 552
424 /// Create a new SDMMC driver, with 4 data lanes. 553 /// Create a new SDMMC driver, with 4 data lanes.
@@ -450,6 +579,58 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
450 Some(d1.into()), 579 Some(d1.into()),
451 Some(d2.into()), 580 Some(d2.into()),
452 Some(d3.into()), 581 Some(d3.into()),
582 None,
583 None,
584 None,
585 None,
586 config,
587 )
588 }
589}
590
591#[cfg(sdmmc_v2)]
592impl<'d, T: Instance> Sdmmc<'d, T> {
593 /// Create a new SDMMC driver, with 8 data lanes.
594 pub fn new_8bit(
595 sdmmc: Peri<'d, T>,
596 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
597 clk: Peri<'d, impl CkPin<T>>,
598 cmd: Peri<'d, impl CmdPin<T>>,
599 d0: Peri<'d, impl D0Pin<T>>,
600 d1: Peri<'d, impl D1Pin<T>>,
601 d2: Peri<'d, impl D2Pin<T>>,
602 d3: Peri<'d, impl D3Pin<T>>,
603 d4: Peri<'d, impl D4Pin<T>>,
604 d5: Peri<'d, impl D5Pin<T>>,
605 d6: Peri<'d, impl D6Pin<T>>,
606 d7: Peri<'d, impl D7Pin<T>>,
607 config: Config,
608 ) -> Self {
609 critical_section::with(|_| {
610 clk.set_as_af(clk.af_num(), CLK_AF);
611 cmd.set_as_af(cmd.af_num(), CMD_AF);
612 d0.set_as_af(d0.af_num(), DATA_AF);
613 d1.set_as_af(d1.af_num(), DATA_AF);
614 d2.set_as_af(d2.af_num(), DATA_AF);
615 d3.set_as_af(d3.af_num(), DATA_AF);
616 d4.set_as_af(d4.af_num(), DATA_AF);
617 d5.set_as_af(d5.af_num(), DATA_AF);
618 d6.set_as_af(d6.af_num(), DATA_AF);
619 d7.set_as_af(d7.af_num(), DATA_AF);
620 });
621
622 Self::new_inner(
623 sdmmc,
624 clk.into(),
625 cmd.into(),
626 d0.into(),
627 Some(d1.into()),
628 Some(d2.into()),
629 Some(d3.into()),
630 Some(d4.into()),
631 Some(d5.into()),
632 Some(d6.into()),
633 Some(d7.into()),
453 config, 634 config,
454 ) 635 )
455 } 636 }
@@ -465,6 +646,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
465 d1: Option<Peri<'d, AnyPin>>, 646 d1: Option<Peri<'d, AnyPin>>,
466 d2: Option<Peri<'d, AnyPin>>, 647 d2: Option<Peri<'d, AnyPin>>,
467 d3: Option<Peri<'d, AnyPin>>, 648 d3: Option<Peri<'d, AnyPin>>,
649 d4: Option<Peri<'d, AnyPin>>,
650 d5: Option<Peri<'d, AnyPin>>,
651 d6: Option<Peri<'d, AnyPin>>,
652 d7: Option<Peri<'d, AnyPin>>,
468 config: Config, 653 config: Config,
469 ) -> Self { 654 ) -> Self {
470 rcc::enable_and_reset::<T>(); 655 rcc::enable_and_reset::<T>();
@@ -503,6 +688,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
503 d1, 688 d1,
504 d2, 689 d2,
505 d3, 690 d3,
691 d4,
692 d5,
693 d6,
694 d7,
506 695
507 config, 696 config,
508 clock: SD_INIT_FREQ, 697 clock: SD_INIT_FREQ,
@@ -673,182 +862,29 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
673 Ok(()) 862 Ok(())
674 } 863 }
675 864
676 /// Switch mode using CMD6.
677 ///
678 /// Attempt to set a new signalling mode. The selected
679 /// signalling mode is returned. Expects the current clock
680 /// frequency to be > 12.5MHz.
681 async fn switch_signalling_mode(&mut self, signalling: Signalling) -> Result<Signalling, Error> {
682 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
683 // necessary"
684
685 let set_function = 0x8000_0000
686 | match signalling {
687 // See PLSS v7_10 Table 4-11
688 Signalling::DDR50 => 0xFF_FF04,
689 Signalling::SDR104 => 0xFF_1F03,
690 Signalling::SDR50 => 0xFF_1F02,
691 Signalling::SDR25 => 0xFF_FF01,
692 Signalling::SDR12 => 0xFF_FF00,
693 };
694
695 let status = match self.cmd_block.as_deref_mut() {
696 Some(x) => x,
697 None => &mut CmdBlock::new(),
698 };
699
700 // Arm `OnDrop` after the buffer, so it will be dropped first
701 let regs = T::regs();
702 let on_drop = OnDrop::new(|| Self::on_drop());
703
704 let transfer = Self::prepare_datapath_read(
705 &self.config,
706 #[cfg(sdmmc_v1)]
707 &mut self.dma,
708 status.as_mut(),
709 64,
710 6,
711 );
712 InterruptHandler::<T>::data_interrupts(true);
713 Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6
714
715 let res = poll_fn(|cx| {
716 T::state().register(cx.waker());
717 let status = regs.star().read();
718
719 if status.dcrcfail() {
720 return Poll::Ready(Err(Error::Crc));
721 }
722 if status.dtimeout() {
723 return Poll::Ready(Err(Error::Timeout));
724 }
725 #[cfg(sdmmc_v1)]
726 if status.stbiterr() {
727 return Poll::Ready(Err(Error::StBitErr));
728 }
729 if status.dataend() {
730 return Poll::Ready(Ok(()));
731 }
732 Poll::Pending
733 })
734 .await;
735 Self::clear_interrupt_flags();
736
737 // Host is allowed to use the new functions at least 8
738 // clocks after the end of the switch command
739 // transaction. We know the current clock period is < 80ns,
740 // so a total delay of 640ns is required here
741 for _ in 0..300 {
742 cortex_m::asm::nop();
743 }
744
745 match res {
746 Ok(_) => {
747 on_drop.defuse();
748 Self::stop_datapath();
749 drop(transfer);
750
751 // Function Selection of Function Group 1
752 let selection = (u32::from_be(status[4]) >> 24) & 0xF;
753
754 match selection {
755 0 => Ok(Signalling::SDR12),
756 1 => Ok(Signalling::SDR25),
757 2 => Ok(Signalling::SDR50),
758 3 => Ok(Signalling::SDR104),
759 4 => Ok(Signalling::DDR50),
760 _ => Err(Error::UnsupportedCardType),
761 }
762 }
763 Err(e) => Err(e),
764 }
765 }
766
767 /// Query the card status (CMD13, returns R1) 865 /// Query the card status (CMD13, returns R1)
768 fn read_status(&self, card: &Card) -> Result<CardStatus, Error> { 866 fn read_status<Ext>(&self, card: &SdmmcPeripheral) -> Result<CardStatus<Ext>, Error>
867 where
868 CardStatus<Ext>: From<u32>,
869 {
769 let regs = T::regs(); 870 let regs = T::regs();
770 let rca = card.rca; 871 let rca = card.get_address();
771 872
772 Self::cmd(Cmd::card_status(rca << 16), false)?; // CMD13 873 Self::cmd(common_cmd::card_status(rca, false), false)?; // CMD13
773 874
774 let r1 = regs.respr(0).read().cardstatus(); 875 let r1 = regs.respr(0).read().cardstatus();
775 Ok(r1.into()) 876 Ok(r1.into())
776 } 877 }
777 878
778 /// Reads the SD Status (ACMD13)
779 async fn read_sd_status(&mut self) -> Result<(), Error> {
780 let card = self.card.as_mut().ok_or(Error::NoCard)?;
781 let rca = card.rca;
782
783 let cmd_block = match self.cmd_block.as_deref_mut() {
784 Some(x) => x,
785 None => &mut CmdBlock::new(),
786 };
787
788 Self::cmd(Cmd::set_block_length(64), false)?; // CMD16
789 Self::cmd(Cmd::app_cmd(rca << 16), false)?; // APP
790
791 let status = cmd_block;
792
793 // Arm `OnDrop` after the buffer, so it will be dropped first
794 let regs = T::regs();
795 let on_drop = OnDrop::new(|| Self::on_drop());
796
797 let transfer = Self::prepare_datapath_read(
798 &self.config,
799 #[cfg(sdmmc_v1)]
800 &mut self.dma,
801 status.as_mut(),
802 64,
803 6,
804 );
805 InterruptHandler::<T>::data_interrupts(true);
806 Self::cmd(Cmd::card_status(0), true)?;
807
808 let res = poll_fn(|cx| {
809 T::state().register(cx.waker());
810 let status = regs.star().read();
811
812 if status.dcrcfail() {
813 return Poll::Ready(Err(Error::Crc));
814 }
815 if status.dtimeout() {
816 return Poll::Ready(Err(Error::Timeout));
817 }
818 #[cfg(sdmmc_v1)]
819 if status.stbiterr() {
820 return Poll::Ready(Err(Error::StBitErr));
821 }
822 if status.dataend() {
823 return Poll::Ready(Ok(()));
824 }
825 Poll::Pending
826 })
827 .await;
828 Self::clear_interrupt_flags();
829
830 if res.is_ok() {
831 on_drop.defuse();
832 Self::stop_datapath();
833 drop(transfer);
834
835 for byte in status.iter_mut() {
836 *byte = u32::from_be(*byte);
837 }
838 self.card.as_mut().unwrap().status = status.0.into();
839 }
840 res
841 }
842
843 /// Select one card and place it into the _Tranfer State_ 879 /// Select one card and place it into the _Tranfer State_
844 /// 880 ///
845 /// If `None` is specifed for `card`, all cards are put back into 881 /// If `None` is specifed for `card`, all cards are put back into
846 /// _Stand-by State_ 882 /// _Stand-by State_
847 fn select_card(&self, card: Option<&Card>) -> Result<(), Error> { 883 fn select_card(&self, rca: Option<u16>) -> Result<(), Error> {
848 // Determine Relative Card Address (RCA) of given card 884 // Determine Relative Card Address (RCA) of given card
849 let rca = card.map(|c| c.rca << 16).unwrap_or(0); 885 let rca = rca.unwrap_or(0);
850 886
851 let r = Self::cmd(Cmd::sel_desel_card(rca), false); 887 let r = Self::cmd(common_cmd::select_card(rca), false);
852 match (r, rca) { 888 match (r, rca) {
853 (Err(Error::Timeout), 0) => Ok(()), 889 (Err(Error::Timeout), 0) => Ok(()),
854 _ => r, 890 _ => r,
@@ -889,70 +925,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
889 }); 925 });
890 } 926 }
891 927
892 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
893 // Read the 64-bit SCR register
894 Self::cmd(Cmd::set_block_length(8), false)?; // CMD16
895 Self::cmd(Cmd::app_cmd(card.rca << 16), false)?;
896
897 let cmd_block = match self.cmd_block.as_deref_mut() {
898 Some(x) => x,
899 None => &mut CmdBlock::new(),
900 };
901 let scr = &mut cmd_block.0[..2];
902
903 // Arm `OnDrop` after the buffer, so it will be dropped first
904 let regs = T::regs();
905 let on_drop = OnDrop::new(|| Self::on_drop());
906
907 let transfer = Self::prepare_datapath_read(
908 &self.config,
909 #[cfg(sdmmc_v1)]
910 &mut self.dma,
911 scr,
912 8,
913 3,
914 );
915 InterruptHandler::<T>::data_interrupts(true);
916 Self::cmd(Cmd::cmd51(), true)?;
917
918 let res = poll_fn(|cx| {
919 T::state().register(cx.waker());
920 let status = regs.star().read();
921
922 if status.dcrcfail() {
923 return Poll::Ready(Err(Error::Crc));
924 }
925 if status.dtimeout() {
926 return Poll::Ready(Err(Error::Timeout));
927 }
928 #[cfg(sdmmc_v1)]
929 if status.stbiterr() {
930 return Poll::Ready(Err(Error::StBitErr));
931 }
932 if status.dataend() {
933 return Poll::Ready(Ok(()));
934 }
935 Poll::Pending
936 })
937 .await;
938 Self::clear_interrupt_flags();
939
940 if res.is_ok() {
941 on_drop.defuse();
942 Self::stop_datapath();
943 drop(transfer);
944
945 unsafe {
946 let scr_bytes = &*(&scr as *const _ as *const [u8; 8]);
947 card.scr = SCR(u64::from_be_bytes(*scr_bytes));
948 }
949 }
950 res
951 }
952
953 /// Send command to card 928 /// Send command to card
954 #[allow(unused_variables)] 929 #[allow(unused_variables)]
955 fn cmd(cmd: Cmd, data: bool) -> Result<(), Error> { 930 fn cmd<R: Resp>(cmd: Cmd<R>, data: bool) -> Result<(), Error> {
956 let regs = T::regs(); 931 let regs = T::regs();
957 932
958 Self::clear_interrupt_flags(); 933 Self::clear_interrupt_flags();
@@ -965,7 +940,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
965 // Command index and start CP State Machine 940 // Command index and start CP State Machine
966 regs.cmdr().write(|w| { 941 regs.cmdr().write(|w| {
967 w.set_waitint(false); 942 w.set_waitint(false);
968 w.set_waitresp(cmd.resp as u8); 943 w.set_waitresp(get_waitresp_val(cmd.response_len()));
969 w.set_cmdindex(cmd.cmd); 944 w.set_cmdindex(cmd.cmd);
970 w.set_cpsmen(true); 945 w.set_cpsmen(true);
971 946
@@ -980,7 +955,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
980 }); 955 });
981 956
982 let mut status; 957 let mut status;
983 if cmd.resp == Response::None { 958 if cmd.response_len() == ResponseLen::Zero {
984 // Wait for CMDSENT or a timeout 959 // Wait for CMDSENT or a timeout
985 while { 960 while {
986 status = regs.star().read(); 961 status = regs.star().read();
@@ -1016,7 +991,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1016 // Command index and start CP State Machine 991 // Command index and start CP State Machine
1017 regs.cmdr().write(|w| { 992 regs.cmdr().write(|w| {
1018 w.set_waitint(false); 993 w.set_waitint(false);
1019 w.set_waitresp(Response::Short as u8); 994 w.set_waitresp(get_waitresp_val(ResponseLen::R48));
1020 w.set_cmdindex(12); 995 w.set_cmdindex(12);
1021 w.set_cpsmen(true); 996 w.set_cpsmen(true);
1022 997
@@ -1035,14 +1010,169 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1035 Self::stop_datapath(); 1010 Self::stop_datapath();
1036 } 1011 }
1037 1012
1038 /// Initializes card (if present) and sets the bus at the specified frequency. 1013 /// Wait for a previously started datapath transfer to complete from an interrupt.
1039 pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> { 1014 #[inline]
1015 async fn complete_datapath_transfer() -> Result<(), Error> {
1016 let regs = T::regs();
1017
1018 let res = poll_fn(|cx| {
1019 T::state().register(cx.waker());
1020 let status = regs.star().read();
1021
1022 if status.dcrcfail() {
1023 return Poll::Ready(Err(Error::Crc));
1024 }
1025 if status.dtimeout() {
1026 return Poll::Ready(Err(Error::Timeout));
1027 }
1028 #[cfg(sdmmc_v1)]
1029 if status.stbiterr() {
1030 return Poll::Ready(Err(Error::StBitErr));
1031 }
1032 if status.dataend() {
1033 return Poll::Ready(Ok(()));
1034 }
1035 Poll::Pending
1036 })
1037 .await;
1038
1039 Self::clear_interrupt_flags();
1040
1041 res
1042 }
1043
1044 /// Read a data block.
1045 #[inline]
1046 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
1047 let card_capacity = self.card()?.get_capacity();
1048
1049 // NOTE(unsafe) DataBlock uses align 4
1050 let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) };
1051
1052 // Always read 1 block of 512 bytes
1053 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1054 let address = match card_capacity {
1055 CardCapacity::StandardCapacity => block_idx * 512,
1056 _ => block_idx,
1057 };
1058 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1059
1060 let on_drop = OnDrop::new(|| Self::on_drop());
1061
1062 let transfer = Self::prepare_datapath_read(
1063 &self.config,
1064 #[cfg(sdmmc_v1)]
1065 &mut self.dma,
1066 buffer,
1067 512,
1068 9,
1069 );
1070 InterruptHandler::<T>::data_interrupts(true);
1071 Self::cmd(common_cmd::read_single_block(address), true)?;
1072
1073 let res = Self::complete_datapath_transfer().await;
1074
1075 if res.is_ok() {
1076 on_drop.defuse();
1077 Self::stop_datapath();
1078 drop(transfer);
1079 }
1080 res
1081 }
1082
1083 /// Write a data block.
1084 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> {
1085 let card = self.card.as_mut().ok_or(Error::NoCard)?;
1086
1087 // NOTE(unsafe) DataBlock uses align 4
1088 let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) };
1089
1090 // Always read 1 block of 512 bytes
1091 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1092 let address = match card.get_capacity() {
1093 CardCapacity::StandardCapacity => block_idx * 512,
1094 _ => block_idx,
1095 };
1096 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1097
1098 let on_drop = OnDrop::new(|| Self::on_drop());
1099
1100 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
1101 #[cfg(sdmmc_v1)]
1102 Self::cmd(common_cmd::write_single_block(address), true)?;
1103
1104 let transfer = self.prepare_datapath_write(buffer, 512, 9);
1105 InterruptHandler::<T>::data_interrupts(true);
1106
1107 #[cfg(sdmmc_v2)]
1108 Self::cmd(common_cmd::write_single_block(address), true)?;
1109
1110 let res = Self::complete_datapath_transfer().await;
1111
1112 match res {
1113 Ok(_) => {
1114 on_drop.defuse();
1115 Self::stop_datapath();
1116 drop(transfer);
1117
1118 // TODO: Make this configurable
1119 let mut timeout: u32 = 0x00FF_FFFF;
1120
1121 let card = self.card.as_ref().unwrap();
1122 while timeout > 0 {
1123 let ready_for_data = match card {
1124 SdmmcPeripheral::Emmc(_) => self.read_status::<EMMC>(card)?.ready_for_data(),
1125 SdmmcPeripheral::SdCard(_) => self.read_status::<SD>(card)?.ready_for_data(),
1126 };
1127
1128 if ready_for_data {
1129 return Ok(());
1130 }
1131 timeout -= 1;
1132 }
1133 Err(Error::SoftwareTimeout)
1134 }
1135 Err(e) => Err(e),
1136 }
1137 }
1138
1139 /// Get a reference to the initialized card
1140 ///
1141 /// # Errors
1142 ///
1143 /// Returns Error::NoCard if [`init_sd_card`](#method.init_sd_card) or
1144 /// [`init_emmc`](#method.init_emmc) has not previously succeeded
1145 #[inline]
1146 pub fn card(&self) -> Result<&SdmmcPeripheral, Error> {
1147 self.card.as_ref().ok_or(Error::NoCard)
1148 }
1149
1150 /// Get the current SDMMC bus clock
1151 pub fn clock(&self) -> Hertz {
1152 self.clock
1153 }
1154
1155 /// Set a specific cmd buffer rather than using the default stack allocated one.
1156 /// This is required if stack RAM cannot be used with DMA and usually manifests
1157 /// itself as an indefinite wait on a dma transfer because the dma peripheral
1158 /// cannot access the memory.
1159 pub fn set_cmd_block(&mut self, cmd_block: &'d mut CmdBlock) {
1160 self.cmd_block = Some(cmd_block)
1161 }
1162
1163 async fn init_internal(&mut self, freq: Hertz, mut card: SdmmcPeripheral) -> Result<(), Error> {
1040 let regs = T::regs(); 1164 let regs = T::regs();
1041 let ker_ck = T::frequency(); 1165 let ker_ck = T::frequency();
1042 1166
1043 let bus_width = match self.d3.is_some() { 1167 let bus_width = match (self.d3.is_some(), self.d7.is_some()) {
1044 true => BusWidth::Four, 1168 (true, true) => {
1045 false => BusWidth::One, 1169 if matches!(card, SdmmcPeripheral::SdCard(_)) {
1170 return Err(Error::BusWidth);
1171 }
1172 BusWidth::Eight
1173 }
1174 (true, false) => BusWidth::Four,
1175 _ => BusWidth::One,
1046 }; 1176 };
1047 1177
1048 // While the SD/SDIO card or eMMC is in identification mode, 1178 // While the SD/SDIO card or eMMC is in identification mode,
@@ -1061,283 +1191,424 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1061 }); 1191 });
1062 1192
1063 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); 1193 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
1064 Self::cmd(Cmd::idle(), false)?; 1194 Self::cmd(common_cmd::idle(), false)?;
1065 1195
1066 // Check if cards supports CMD8 (with pattern) 1196 match card {
1067 Self::cmd(Cmd::hs_send_ext_csd(0x1AA), false)?; 1197 SdmmcPeripheral::SdCard(ref mut card) => {
1068 let r1 = regs.respr(0).read().cardstatus(); 1198 // Check if cards supports CMD8 (with pattern)
1199 Self::cmd(sd_cmd::send_if_cond(1, 0xAA), false)?;
1200 let cic = CIC::from(regs.respr(0).read().cardstatus());
1069 1201
1070 let mut card = if r1 == 0x1AA { 1202 if cic.pattern() != 0xAA {
1071 // Card echoed back the pattern. Must be at least v2 1203 return Err(Error::UnsupportedCardVersion);
1072 Card::default() 1204 }
1073 } else {
1074 return Err(Error::UnsupportedCardVersion);
1075 };
1076 1205
1077 let ocr = loop { 1206 if cic.voltage_accepted() & 1 == 0 {
1078 // Signal that next command is a app command 1207 return Err(Error::UnsupportedVoltage);
1079 Self::cmd(Cmd::app_cmd(0), false)?; // CMD55 1208 }
1080 1209
1081 let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32 1210 let ocr = loop {
1082 | CmdAppOper::HIGH_CAPACITY as u32 1211 // Signal that next command is a app command
1083 | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32; 1212 Self::cmd(common_cmd::app_cmd(0), false)?; // CMD55
1213
1214 // 3.2-3.3V
1215 let voltage_window = 1 << 5;
1216 // Initialize card
1217 match Self::cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window), false) {
1218 // ACMD41
1219 Ok(_) => (),
1220 Err(Error::Crc) => (),
1221 Err(err) => return Err(err),
1222 }
1223 let ocr: OCR<SD> = regs.respr(0).read().cardstatus().into();
1224 if !ocr.is_busy() {
1225 // Power up done
1226 break ocr;
1227 }
1228 };
1084 1229
1085 // Initialize card 1230 if ocr.high_capacity() {
1086 match Self::cmd(Cmd::app_op_cmd(arg), false) { 1231 // Card is SDHC or SDXC or SDUC
1087 // ACMD41 1232 card.card_type = CardCapacity::HighCapacity;
1088 Ok(_) => (), 1233 } else {
1089 Err(Error::Crc) => (), 1234 card.card_type = CardCapacity::StandardCapacity;
1090 Err(err) => return Err(err), 1235 }
1236 card.ocr = ocr;
1091 } 1237 }
1092 let ocr: OCR = regs.respr(0).read().cardstatus().into(); 1238 SdmmcPeripheral::Emmc(ref mut emmc) => {
1093 if !ocr.is_busy() { 1239 let ocr = loop {
1094 // Power up done 1240 let high_voltage = 0b0 << 7;
1095 break ocr; 1241 let access_mode = 0b10 << 29;
1242 let op_cond = high_voltage | access_mode | 0b1_1111_1111 << 15;
1243 // Initialize card
1244 match Self::cmd(emmc_cmd::send_op_cond(op_cond), false) {
1245 Ok(_) => (),
1246 Err(Error::Crc) => (),
1247 Err(err) => return Err(err),
1248 }
1249 let ocr: OCR<EMMC> = regs.respr(0).read().cardstatus().into();
1250 if !ocr.is_busy() {
1251 // Power up done
1252 break ocr;
1253 }
1254 };
1255
1256 emmc.capacity = if ocr.access_mode() == 0b10 {
1257 // Card is SDHC or SDXC or SDUC
1258 CardCapacity::HighCapacity
1259 } else {
1260 CardCapacity::StandardCapacity
1261 };
1262 emmc.ocr = ocr;
1096 } 1263 }
1097 };
1098
1099 if ocr.high_capacity() {
1100 // Card is SDHC or SDXC or SDUC
1101 card.card_type = CardCapacity::SDHC;
1102 } else {
1103 card.card_type = CardCapacity::SDSC;
1104 } 1264 }
1105 card.ocr = ocr;
1106 1265
1107 Self::cmd(Cmd::all_send_cid(), false)?; // CMD2 1266 Self::cmd(common_cmd::all_send_cid(), false)?; // CMD2
1108 let cid0 = regs.respr(0).read().cardstatus() as u128; 1267 let cid0 = regs.respr(0).read().cardstatus() as u128;
1109 let cid1 = regs.respr(1).read().cardstatus() as u128; 1268 let cid1 = regs.respr(1).read().cardstatus() as u128;
1110 let cid2 = regs.respr(2).read().cardstatus() as u128; 1269 let cid2 = regs.respr(2).read().cardstatus() as u128;
1111 let cid3 = regs.respr(3).read().cardstatus() as u128; 1270 let cid3 = regs.respr(3).read().cardstatus() as u128;
1112 let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3); 1271 let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3);
1113 card.cid = cid.into();
1114 1272
1115 Self::cmd(Cmd::send_rel_addr(), false)?; 1273 match card {
1116 card.rca = regs.respr(0).read().cardstatus() >> 16; 1274 SdmmcPeripheral::SdCard(ref mut card) => {
1275 card.cid = cid.into();
1117 1276
1118 Self::cmd(Cmd::send_csd(card.rca << 16), false)?; 1277 Self::cmd(sd_cmd::send_relative_address(), false)?;
1278 let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus());
1279 card.rca = rca.address();
1280 }
1281 SdmmcPeripheral::Emmc(ref mut emmc) => {
1282 emmc.cid = cid.into();
1283
1284 emmc.rca = 1u16.into();
1285 Self::cmd(emmc_cmd::assign_relative_address(emmc.rca), false)?;
1286 }
1287 }
1288
1289 Self::cmd(common_cmd::send_csd(card.get_address()), false)?;
1119 let csd0 = regs.respr(0).read().cardstatus() as u128; 1290 let csd0 = regs.respr(0).read().cardstatus() as u128;
1120 let csd1 = regs.respr(1).read().cardstatus() as u128; 1291 let csd1 = regs.respr(1).read().cardstatus() as u128;
1121 let csd2 = regs.respr(2).read().cardstatus() as u128; 1292 let csd2 = regs.respr(2).read().cardstatus() as u128;
1122 let csd3 = regs.respr(3).read().cardstatus() as u128; 1293 let csd3 = regs.respr(3).read().cardstatus() as u128;
1123 let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3); 1294 let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3);
1124 card.csd = csd.into();
1125 1295
1126 self.select_card(Some(&card))?; 1296 self.select_card(Some(card.get_address()))?;
1297
1298 let bus_width = match card {
1299 SdmmcPeripheral::SdCard(ref mut card) => {
1300 card.csd = csd.into();
1127 1301
1128 self.get_scr(&mut card).await?; 1302 self.get_scr(card).await?;
1303
1304 if !card.scr.bus_width_four() {
1305 BusWidth::One
1306 } else {
1307 BusWidth::Four
1308 }
1309 }
1310 SdmmcPeripheral::Emmc(ref mut emmc) => {
1311 emmc.csd = csd.into();
1312
1313 bus_width
1314 }
1315 };
1129 1316
1130 // Set bus width 1317 // Set bus width
1131 let (width, acmd_arg) = match bus_width { 1318 let widbus = match bus_width {
1132 BusWidth::Eight => unimplemented!(), 1319 BusWidth::Eight => 2,
1133 BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2), 1320 BusWidth::Four => 1,
1134 _ => (BusWidth::One, 0), 1321 BusWidth::One => 0,
1322 _ => unreachable!(),
1135 }; 1323 };
1136 Self::cmd(Cmd::app_cmd(card.rca << 16), false)?; 1324
1137 Self::cmd(Cmd::cmd6(acmd_arg), false)?; 1325 match card {
1326 SdmmcPeripheral::SdCard(ref mut card) => {
1327 let acmd_arg = match bus_width {
1328 BusWidth::Four if card.scr.bus_width_four() => 2,
1329 _ => 0,
1330 };
1331 Self::cmd(common_cmd::app_cmd(card.rca), false)?;
1332 Self::cmd(sd_cmd::cmd6(acmd_arg), false)?;
1333 }
1334 SdmmcPeripheral::Emmc(_) => {
1335 // Write bus width to ExtCSD byte 183
1336 Self::cmd(
1337 emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus),
1338 false,
1339 )?;
1340
1341 // Wait for ready after R1b response
1342 loop {
1343 let status = self.read_status::<EMMC>(&card)?;
1344
1345 if status.ready_for_data() {
1346 break;
1347 }
1348 }
1349 }
1350 }
1138 1351
1139 // CPSMACT and DPSMACT must be 0 to set WIDBUS 1352 // CPSMACT and DPSMACT must be 0 to set WIDBUS
1140 Self::wait_idle(); 1353 Self::wait_idle();
1141 1354
1142 regs.clkcr().modify(|w| { 1355 regs.clkcr().modify(|w| w.set_widbus(widbus));
1143 w.set_widbus(match width {
1144 BusWidth::One => 0,
1145 BusWidth::Four => 1,
1146 BusWidth::Eight => 2,
1147 _ => panic!("Invalid Bus Width"),
1148 })
1149 });
1150 1356
1151 // Set Clock 1357 // Set Clock
1152 if freq.0 <= 25_000_000 { 1358 if freq.0 <= 25_000_000 {
1153 // Final clock frequency 1359 // Final clock frequency
1154 self.clkcr_set_clkdiv(freq.0, width)?; 1360 self.clkcr_set_clkdiv(freq.0, bus_width)?;
1155 } else { 1361 } else {
1156 // Switch to max clock for SDR12 1362 // Switch to max clock for SDR12
1157 self.clkcr_set_clkdiv(25_000_000, width)?; 1363 self.clkcr_set_clkdiv(25_000_000, bus_width)?;
1158 } 1364 }
1159 1365
1160 self.card = Some(card); 1366 self.card = Some(card);
1161 1367
1162 // Read status 1368 match card {
1163 self.read_sd_status().await?; 1369 SdmmcPeripheral::SdCard(_) => {
1370 // Read status
1371 self.read_sd_status().await?;
1164 1372
1165 if freq.0 > 25_000_000 { 1373 if freq.0 > 25_000_000 {
1166 // Switch to SDR25 1374 // Switch to SDR25
1167 self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?; 1375 self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?;
1168 1376
1169 if self.signalling == Signalling::SDR25 { 1377 if self.signalling == Signalling::SDR25 {
1170 // Set final clock frequency 1378 // Set final clock frequency
1171 self.clkcr_set_clkdiv(freq.0, width)?; 1379 self.clkcr_set_clkdiv(freq.0, bus_width)?;
1172 1380
1173 if self.read_status(&card)?.state() != CurrentState::Transfer { 1381 if self.read_status::<SD>(self.card.as_ref().unwrap())?.state() != CurrentState::Transfer {
1174 return Err(Error::SignalingSwitchFailed); 1382 return Err(Error::SignalingSwitchFailed);
1383 }
1384 }
1175 } 1385 }
1386
1387 // Read status after signalling change
1388 self.read_sd_status().await?;
1389 }
1390 SdmmcPeripheral::Emmc(_) => {
1391 self.read_ext_csd().await?;
1176 } 1392 }
1177 } 1393 }
1178 1394
1179 // Read status after signalling change
1180 self.read_sd_status().await?;
1181
1182 Ok(()) 1395 Ok(())
1183 } 1396 }
1184 1397
1185 /// Read a data block. 1398 /// Initializes card (if present) and sets the bus at the specified frequency.
1186 #[inline] 1399 ///
1187 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> { 1400 /// SD only.
1188 let card_capacity = self.card()?.card_type; 1401 pub async fn init_sd_card(&mut self, freq: Hertz) -> Result<(), Error> {
1402 self.init_internal(freq, SdmmcPeripheral::SdCard(Card::default())).await
1403 }
1189 1404
1190 // NOTE(unsafe) DataBlock uses align 4 1405 /// Switch mode using CMD6.
1191 let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) }; 1406 ///
1407 /// Attempt to set a new signalling mode. The selected
1408 /// signalling mode is returned. Expects the current clock
1409 /// frequency to be > 12.5MHz.
1410 ///
1411 /// SD only.
1412 async fn switch_signalling_mode(&mut self, signalling: Signalling) -> Result<Signalling, Error> {
1413 let _ = self.card.as_mut().ok_or(Error::NoCard)?.get_sd_card();
1414 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
1415 // necessary"
1192 1416
1193 // Always read 1 block of 512 bytes 1417 let set_function = 0x8000_0000
1194 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes 1418 | match signalling {
1195 let address = match card_capacity { 1419 // See PLSS v7_10 Table 4-11
1196 CardCapacity::SDSC => block_idx * 512, 1420 Signalling::DDR50 => 0xFF_FF04,
1197 _ => block_idx, 1421 Signalling::SDR104 => 0xFF_1F03,
1422 Signalling::SDR50 => 0xFF_1F02,
1423 Signalling::SDR25 => 0xFF_FF01,
1424 Signalling::SDR12 => 0xFF_FF00,
1425 };
1426
1427 let status = match self.cmd_block.as_deref_mut() {
1428 Some(x) => x,
1429 None => &mut CmdBlock::new(),
1198 }; 1430 };
1199 Self::cmd(Cmd::set_block_length(512), false)?; // CMD16
1200 1431
1201 let regs = T::regs(); 1432 // Arm `OnDrop` after the buffer, so it will be dropped first
1202 let on_drop = OnDrop::new(|| Self::on_drop()); 1433 let on_drop = OnDrop::new(|| Self::on_drop());
1203 1434
1204 let transfer = Self::prepare_datapath_read( 1435 let transfer = Self::prepare_datapath_read(
1205 &self.config, 1436 &self.config,
1206 #[cfg(sdmmc_v1)] 1437 #[cfg(sdmmc_v1)]
1207 &mut self.dma, 1438 &mut self.dma,
1208 buffer, 1439 status.as_mut(),
1209 512, 1440 64,
1210 9, 1441 6,
1211 ); 1442 );
1212 InterruptHandler::<T>::data_interrupts(true); 1443 InterruptHandler::<T>::data_interrupts(true);
1213 Self::cmd(Cmd::read_single_block(address), true)?; 1444 Self::cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
1214 1445
1215 let res = poll_fn(|cx| { 1446 let res = Self::complete_datapath_transfer().await;
1216 T::state().register(cx.waker());
1217 let status = regs.star().read();
1218 1447
1219 if status.dcrcfail() { 1448 // Host is allowed to use the new functions at least 8
1220 return Poll::Ready(Err(Error::Crc)); 1449 // clocks after the end of the switch command
1221 } 1450 // transaction. We know the current clock period is < 80ns,
1222 if status.dtimeout() { 1451 // so a total delay of 640ns is required here
1223 return Poll::Ready(Err(Error::Timeout)); 1452 for _ in 0..300 {
1453 cortex_m::asm::nop();
1454 }
1455
1456 match res {
1457 Ok(_) => {
1458 on_drop.defuse();
1459 Self::stop_datapath();
1460 drop(transfer);
1461
1462 // Function Selection of Function Group 1
1463 let selection = (u32::from_be(status[4]) >> 24) & 0xF;
1464
1465 match selection {
1466 0 => Ok(Signalling::SDR12),
1467 1 => Ok(Signalling::SDR25),
1468 2 => Ok(Signalling::SDR50),
1469 3 => Ok(Signalling::SDR104),
1470 4 => Ok(Signalling::DDR50),
1471 _ => Err(Error::UnsupportedCardType),
1472 }
1224 } 1473 }
1474 Err(e) => Err(e),
1475 }
1476 }
1477
1478 /// Reads the SCR register.
1479 ///
1480 /// SD only.
1481 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
1482 // Read the 64-bit SCR register
1483 Self::cmd(common_cmd::set_block_length(8), false)?; // CMD16
1484 Self::cmd(common_cmd::app_cmd(card.rca), false)?;
1485
1486 let cmd_block = match self.cmd_block.as_deref_mut() {
1487 Some(x) => x,
1488 None => &mut CmdBlock::new(),
1489 };
1490 let scr = &mut cmd_block.0[..2];
1491
1492 // Arm `OnDrop` after the buffer, so it will be dropped first
1493 let on_drop = OnDrop::new(|| Self::on_drop());
1494
1495 let transfer = Self::prepare_datapath_read(
1496 &self.config,
1225 #[cfg(sdmmc_v1)] 1497 #[cfg(sdmmc_v1)]
1226 if status.stbiterr() { 1498 &mut self.dma,
1227 return Poll::Ready(Err(Error::StBitErr)); 1499 scr,
1228 } 1500 8,
1229 if status.dataend() { 1501 3,
1230 return Poll::Ready(Ok(())); 1502 );
1231 } 1503 InterruptHandler::<T>::data_interrupts(true);
1232 Poll::Pending 1504 Self::cmd(sd_cmd::send_scr(), true)?;
1233 }) 1505
1234 .await; 1506 let res = Self::complete_datapath_transfer().await;
1235 Self::clear_interrupt_flags();
1236 1507
1237 if res.is_ok() { 1508 if res.is_ok() {
1238 on_drop.defuse(); 1509 on_drop.defuse();
1239 Self::stop_datapath(); 1510 Self::stop_datapath();
1240 drop(transfer); 1511 drop(transfer);
1512
1513 unsafe {
1514 let scr_bytes = &*(&scr as *const _ as *const [u8; 8]);
1515 card.scr = SCR(u64::from_be_bytes(*scr_bytes));
1516 }
1241 } 1517 }
1242 res 1518 res
1243 } 1519 }
1244 1520
1245 /// Write a data block. 1521 /// Reads the SD Status (ACMD13)
1246 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> { 1522 ///
1247 let card = self.card.as_mut().ok_or(Error::NoCard)?; 1523 /// SD only.
1248 1524 async fn read_sd_status(&mut self) -> Result<(), Error> {
1249 // NOTE(unsafe) DataBlock uses align 4 1525 let card = self.card.as_mut().ok_or(Error::NoCard)?.get_sd_card();
1250 let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) }; 1526 let rca = card.rca;
1251 1527
1252 // Always read 1 block of 512 bytes 1528 let cmd_block = match self.cmd_block.as_deref_mut() {
1253 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes 1529 Some(x) => x,
1254 let address = match card.card_type { 1530 None => &mut CmdBlock::new(),
1255 CardCapacity::SDSC => block_idx * 512,
1256 _ => block_idx,
1257 }; 1531 };
1258 Self::cmd(Cmd::set_block_length(512), false)?; // CMD16
1259
1260 let regs = T::regs();
1261 let on_drop = OnDrop::new(|| Self::on_drop());
1262
1263 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
1264 #[cfg(sdmmc_v1)]
1265 Self::cmd(Cmd::write_single_block(address), true)?;
1266 1532
1267 let transfer = self.prepare_datapath_write(buffer, 512, 9); 1533 Self::cmd(common_cmd::set_block_length(64), false)?; // CMD16
1268 InterruptHandler::<T>::data_interrupts(true); 1534 Self::cmd(common_cmd::app_cmd(rca), false)?; // APP
1269 1535
1270 #[cfg(sdmmc_v2)] 1536 let status = cmd_block;
1271 Self::cmd(Cmd::write_single_block(address), true)?;
1272 1537
1273 let res = poll_fn(|cx| { 1538 // Arm `OnDrop` after the buffer, so it will be dropped first
1274 T::state().register(cx.waker()); 1539 let on_drop = OnDrop::new(|| Self::on_drop());
1275 let status = regs.star().read();
1276 1540
1277 if status.dcrcfail() { 1541 let transfer = Self::prepare_datapath_read(
1278 return Poll::Ready(Err(Error::Crc)); 1542 &self.config,
1279 }
1280 if status.dtimeout() {
1281 return Poll::Ready(Err(Error::Timeout));
1282 }
1283 #[cfg(sdmmc_v1)] 1543 #[cfg(sdmmc_v1)]
1284 if status.stbiterr() { 1544 &mut self.dma,
1285 return Poll::Ready(Err(Error::StBitErr)); 1545 status.as_mut(),
1286 } 1546 64,
1287 if status.dataend() { 1547 6,
1288 return Poll::Ready(Ok(())); 1548 );
1289 } 1549 InterruptHandler::<T>::data_interrupts(true);
1290 Poll::Pending 1550 Self::cmd(sd_cmd::sd_status(), true)?;
1291 })
1292 .await;
1293 Self::clear_interrupt_flags();
1294 1551
1295 match res { 1552 let res = Self::complete_datapath_transfer().await;
1296 Ok(_) => {
1297 on_drop.defuse();
1298 Self::stop_datapath();
1299 drop(transfer);
1300 1553
1301 // TODO: Make this configurable 1554 if res.is_ok() {
1302 let mut timeout: u32 = 0x00FF_FFFF; 1555 on_drop.defuse();
1556 Self::stop_datapath();
1557 drop(transfer);
1303 1558
1304 // Try to read card status (ACMD13) 1559 for byte in status.iter_mut() {
1305 while timeout > 0 { 1560 *byte = u32::from_be(*byte);
1306 match self.read_sd_status().await {
1307 Ok(_) => return Ok(()),
1308 Err(Error::Timeout) => (), // Try again
1309 Err(e) => return Err(e),
1310 }
1311 timeout -= 1;
1312 }
1313 Err(Error::SoftwareTimeout)
1314 } 1561 }
1315 Err(e) => Err(e), 1562 card.status = status.0.into();
1316 } 1563 }
1564 res
1317 } 1565 }
1318 1566
1319 /// Get a reference to the initialized card 1567 /// Initializes eMMC and sets the bus at the specified frequency.
1320 /// 1568 ///
1321 /// # Errors 1569 /// eMMC only.
1322 /// 1570 pub async fn init_emmc(&mut self, freq: Hertz) -> Result<(), Error> {
1323 /// Returns Error::NoCard if [`init_card`](#method.init_card) 1571 self.init_internal(freq, SdmmcPeripheral::Emmc(Emmc::default())).await
1324 /// has not previously succeeded
1325 #[inline]
1326 pub fn card(&self) -> Result<&Card, Error> {
1327 self.card.as_ref().ok_or(Error::NoCard)
1328 } 1572 }
1329 1573
1330 /// Get the current SDMMC bus clock 1574 /// Gets the EXT_CSD register.
1331 pub fn clock(&self) -> Hertz { 1575 ///
1332 self.clock 1576 /// eMMC only.
1333 } 1577 async fn read_ext_csd(&mut self) -> Result<(), Error> {
1578 let card = self.card.as_mut().ok_or(Error::NoCard)?.get_emmc();
1334 1579
1335 /// Set a specific cmd buffer rather than using the default stack allocated one. 1580 // Note: cmd_block can't be used because ExtCSD is too long to fit.
1336 /// This is required if stack RAM cannot be used with DMA and usually manifests 1581 let mut data_block = DataBlock([0u8; 512]);
1337 /// itself as an indefinite wait on a dma transfer because the dma peripheral 1582
1338 /// cannot access the memory. 1583 // NOTE(unsafe) DataBlock uses align 4
1339 pub fn set_cmd_block(&mut self, cmd_block: &'d mut CmdBlock) { 1584 let buffer = unsafe { &mut *((&mut data_block.0) as *mut [u8; 512] as *mut [u32; 128]) };
1340 self.cmd_block = Some(cmd_block) 1585
1586 Self::cmd(common_cmd::set_block_length(512), false).unwrap(); // CMD16
1587
1588 // Arm `OnDrop` after the buffer, so it will be dropped first
1589 let on_drop = OnDrop::new(|| Self::on_drop());
1590
1591 let transfer = Self::prepare_datapath_read(
1592 &self.config,
1593 #[cfg(sdmmc_v1)]
1594 &mut self.dma,
1595 buffer,
1596 512,
1597 9,
1598 );
1599 InterruptHandler::<T>::data_interrupts(true);
1600 Self::cmd(emmc_cmd::send_ext_csd(), true)?;
1601
1602 let res = Self::complete_datapath_transfer().await;
1603
1604 if res.is_ok() {
1605 on_drop.defuse();
1606 Self::stop_datapath();
1607 drop(transfer);
1608
1609 card.ext_csd = unsafe { core::mem::transmute::<_, [u32; 128]>(data_block.0) }.into();
1610 }
1611 res
1341 } 1612 }
1342} 1613}
1343 1614
@@ -1359,97 +1630,22 @@ impl<'d, T: Instance> Drop for Sdmmc<'d, T> {
1359 if let Some(x) = &mut self.d3 { 1630 if let Some(x) = &mut self.d3 {
1360 x.set_as_disconnected(); 1631 x.set_as_disconnected();
1361 } 1632 }
1633 if let Some(x) = &mut self.d4 {
1634 x.set_as_disconnected();
1635 }
1636 if let Some(x) = &mut self.d5 {
1637 x.set_as_disconnected();
1638 }
1639 if let Some(x) = &mut self.d6 {
1640 x.set_as_disconnected();
1641 }
1642 if let Some(x) = &mut self.d7 {
1643 x.set_as_disconnected();
1644 }
1362 }); 1645 });
1363 } 1646 }
1364} 1647}
1365 1648
1366/// SD card Commands
1367impl Cmd {
1368 const fn new(cmd: u8, arg: u32, resp: Response) -> Cmd {
1369 Cmd { cmd, arg, resp }
1370 }
1371
1372 /// CMD0: Idle
1373 const fn idle() -> Cmd {
1374 Cmd::new(0, 0, Response::None)
1375 }
1376
1377 /// CMD2: Send CID
1378 const fn all_send_cid() -> Cmd {
1379 Cmd::new(2, 0, Response::Long)
1380 }
1381
1382 /// CMD3: Send Relative Address
1383 const fn send_rel_addr() -> Cmd {
1384 Cmd::new(3, 0, Response::Short)
1385 }
1386
1387 /// CMD6: Switch Function Command
1388 /// ACMD6: Bus Width
1389 const fn cmd6(arg: u32) -> Cmd {
1390 Cmd::new(6, arg, Response::Short)
1391 }
1392
1393 /// CMD7: Select one card and put it into the _Tranfer State_
1394 const fn sel_desel_card(rca: u32) -> Cmd {
1395 Cmd::new(7, rca, Response::Short)
1396 }
1397
1398 /// CMD8:
1399 const fn hs_send_ext_csd(arg: u32) -> Cmd {
1400 Cmd::new(8, arg, Response::Short)
1401 }
1402
1403 /// CMD9:
1404 const fn send_csd(rca: u32) -> Cmd {
1405 Cmd::new(9, rca, Response::Long)
1406 }
1407
1408 /// CMD12:
1409 //const fn stop_transmission() -> Cmd {
1410 // Cmd::new(12, 0, Response::Short)
1411 //}
1412
1413 /// CMD13: Ask card to send status register
1414 /// ACMD13: SD Status
1415 const fn card_status(rca: u32) -> Cmd {
1416 Cmd::new(13, rca, Response::Short)
1417 }
1418
1419 /// CMD16:
1420 const fn set_block_length(blocklen: u32) -> Cmd {
1421 Cmd::new(16, blocklen, Response::Short)
1422 }
1423
1424 /// CMD17: Block Read
1425 const fn read_single_block(addr: u32) -> Cmd {
1426 Cmd::new(17, addr, Response::Short)
1427 }
1428
1429 /// CMD18: Multiple Block Read
1430 //const fn read_multiple_blocks(addr: u32) -> Cmd {
1431 // Cmd::new(18, addr, Response::Short)
1432 //}
1433
1434 /// CMD24: Block Write
1435 const fn write_single_block(addr: u32) -> Cmd {
1436 Cmd::new(24, addr, Response::Short)
1437 }
1438
1439 const fn app_op_cmd(arg: u32) -> Cmd {
1440 Cmd::new(41, arg, Response::Short)
1441 }
1442
1443 const fn cmd51() -> Cmd {
1444 Cmd::new(51, 0, Response::Short)
1445 }
1446
1447 /// App Command. Indicates that next command will be a app command
1448 const fn app_cmd(rca: u32) -> Cmd {
1449 Cmd::new(55, rca, Response::Short)
1450 }
1451}
1452
1453////////////////////////////////////////////////////// 1649//////////////////////////////////////////////////////
1454 1650
1455trait SealedInstance { 1651trait SealedInstance {
diff --git a/examples/stm32f4/src/bin/sdmmc.rs b/examples/stm32f4/src/bin/sdmmc.rs
index 66e4e527c..e97b63925 100644
--- a/examples/stm32f4/src/bin/sdmmc.rs
+++ b/examples/stm32f4/src/bin/sdmmc.rs
@@ -59,7 +59,7 @@ async fn main(_spawner: Spawner) {
59 59
60 let mut err = None; 60 let mut err = None;
61 loop { 61 loop {
62 match sdmmc.init_card(mhz(24)).await { 62 match sdmmc.init_sd_card(mhz(24)).await {
63 Ok(_) => break, 63 Ok(_) => break,
64 Err(e) => { 64 Err(e) => {
65 if err != Some(e) { 65 if err != Some(e) {
diff --git a/examples/stm32f7/src/bin/sdmmc.rs b/examples/stm32f7/src/bin/sdmmc.rs
index 6d36ef518..787bef25e 100644
--- a/examples/stm32f7/src/bin/sdmmc.rs
+++ b/examples/stm32f7/src/bin/sdmmc.rs
@@ -54,7 +54,7 @@ async fn main(_spawner: Spawner) {
54 // Should print 400kHz for initialization 54 // Should print 400kHz for initialization
55 info!("Configured clock: {}", sdmmc.clock().0); 55 info!("Configured clock: {}", sdmmc.clock().0);
56 56
57 unwrap!(sdmmc.init_card(mhz(25)).await); 57 unwrap!(sdmmc.init_sd_card(mhz(25)).await);
58 58
59 let card = unwrap!(sdmmc.card()); 59 let card = unwrap!(sdmmc.card());
60 60
diff --git a/examples/stm32h7/src/bin/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs
index abe2d4ba7..96840d8ff 100644
--- a/examples/stm32h7/src/bin/sdmmc.rs
+++ b/examples/stm32h7/src/bin/sdmmc.rs
@@ -53,7 +53,7 @@ async fn main(_spawner: Spawner) -> ! {
53 // Should print 400kHz for initialization 53 // Should print 400kHz for initialization
54 info!("Configured clock: {}", sdmmc.clock().0); 54 info!("Configured clock: {}", sdmmc.clock().0);
55 55
56 unwrap!(sdmmc.init_card(mhz(25)).await); 56 unwrap!(sdmmc.init_sd_card(mhz(25)).await);
57 57
58 let card = unwrap!(sdmmc.card()); 58 let card = unwrap!(sdmmc.card());
59 59
diff --git a/tests/stm32/src/bin/sdmmc.rs b/tests/stm32/src/bin/sdmmc.rs
index 07f17b569..c1ed45588 100644
--- a/tests/stm32/src/bin/sdmmc.rs
+++ b/tests/stm32/src/bin/sdmmc.rs
@@ -54,7 +54,7 @@ async fn main(_spawner: Spawner) {
54 54
55 let mut err = None; 55 let mut err = None;
56 loop { 56 loop {
57 match s.init_card(mhz(24)).await { 57 match s.init_sd_card(mhz(24)).await {
58 Ok(_) => break, 58 Ok(_) => break,
59 Err(e) => { 59 Err(e) => {
60 if err != Some(e) { 60 if err != Some(e) {
@@ -100,7 +100,7 @@ async fn main(_spawner: Spawner) {
100 100
101 let mut err = None; 101 let mut err = None;
102 loop { 102 loop {
103 match s.init_card(mhz(24)).await { 103 match s.init_sd_card(mhz(24)).await {
104 Ok(_) => break, 104 Ok(_) => break,
105 Err(e) => { 105 Err(e) => {
106 if err != Some(e) { 106 if err != Some(e) {