1#![macro_use]
3
4use core::default::Default;
5use core::future::poll_fn;
6use core::marker::PhantomData;
7use core::ops::{Deref, DerefMut};
8use core::task::Poll;
9
10use embassy_hal_internal::drop::OnDrop;
11use embassy_hal_internal::{into_ref, PeripheralRef};
12use embassy_sync::waitqueue::AtomicWaker;
13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};
14
15use crate::dma::NoDma;
16#[cfg(gpio_v2)]
17use crate::gpio::Pull;
18use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed};
19use crate::interrupt::typelevel::Interrupt;
20use crate::pac::sdmmc::Sdmmc as RegBlock;
21use crate::rcc::{self, RccPeripheral};
22use crate::time::Hertz;
23use crate::{interrupt, peripherals, Peripheral};
24
25pub struct InterruptHandler<T: Instance> {
27 _phantom: PhantomData<T>,
28}
29
30impl<T: Instance> InterruptHandler<T> {
31 fn data_interrupts(enable: bool) {
32 let regs = T::regs();
33 regs.maskr().write(|w| {
34 w.set_dcrcfailie(enable);
35 w.set_dtimeoutie(enable);
36 w.set_dataendie(enable);
37
38 #[cfg(sdmmc_v1)]
39 w.set_stbiterre(enable);
40 #[cfg(sdmmc_v2)]
41 w.set_dabortie(enable);
42 });
43 }
44}
45
46impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
47 unsafe fn on_interrupt() {
48 Self::data_interrupts(false);
49 T::state().wake();
50 }
51}
52
53const SD_INIT_FREQ: Hertz = Hertz(400_000);
55
56#[non_exhaustive]
58#[allow(missing_docs)]
59#[derive(Debug, Copy, Clone, PartialEq, Eq)]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61pub enum Signalling {
62 SDR12,
63 SDR25,
64 SDR50,
65 SDR104,
66 DDR50,
67}
68
69impl Default for Signalling {
70 fn default() -> Self {
71 Signalling::SDR12
72 }
73}
74
75#[repr(align(4))]
79#[derive(Debug, Clone, PartialEq, Eq)]
80#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81pub struct DataBlock(pub [u8; 512]);
82
83impl Deref for DataBlock {
84 type Target = [u8; 512];
85
86 fn deref(&self) -> &Self::Target {
87 &self.0
88 }
89}
90
91impl DerefMut for DataBlock {
92 fn deref_mut(&mut self) -> &mut Self::Target {
93 &mut self.0
94 }
95}
96
97#[derive(Debug, Clone, PartialEq, Eq)]
101#[cfg_attr(feature = "defmt", derive(defmt::Format))]
102pub struct CmdBlock(pub [u32; 16]);
103
104impl CmdBlock {
105 pub const fn new() -> Self {
107 Self([0u32; 16])
108 }
109}
110
111impl Deref for CmdBlock {
112 type Target = [u32; 16];
113
114 fn deref(&self) -> &Self::Target {
115 &self.0
116 }
117}
118
119impl DerefMut for CmdBlock {
120 fn deref_mut(&mut self) -> &mut Self::Target {
121 &mut self.0
122 }
123}
124
125#[non_exhaustive]
127#[derive(Debug, Copy, Clone, PartialEq, Eq)]
128#[cfg_attr(feature = "defmt", derive(defmt::Format))]
129pub enum Error {
130 Timeout,
132 SoftwareTimeout,
134 UnsupportedCardVersion,
136 UnsupportedCardType,
138 Crc,
140 NoCard,
142 BadClock,
144 SignalingSwitchFailed,
146 #[cfg(sdmmc_v1)]
148 StBitErr,
149}
150
151struct Cmd {
153 cmd: u8,
154 arg: u32,
155 resp: Response,
156}
157
158#[derive(Clone, Copy, Debug, Default)]
159pub struct Card {
161 pub card_type: CardCapacity,
163 pub ocr: OCR,
165 pub rca: u32,
167 pub cid: CID,
169 pub csd: CSD,
171 pub scr: SCR,
173 pub status: SDStatus,
175}
176
177impl Card {
178 pub fn size(&self) -> u64 {
180 u64::from(self.csd.block_count()) * 512
182 }
183}
184
185#[repr(u8)]
186enum PowerCtrl {
187 Off = 0b00,
188 On = 0b11,
189}
190
191#[repr(u32)]
192#[allow(dead_code)]
193#[allow(non_camel_case_types)]
194enum CmdAppOper {
195 VOLTAGE_WINDOW_SD = 0x8010_0000,
196 HIGH_CAPACITY = 0x4000_0000,
197 SDMMC_STD_CAPACITY = 0x0000_0000,
198 SDMMC_CHECK_PATTERN = 0x0000_01AA,
199 SD_SWITCH_1_8V_CAPACITY = 0x0100_0000,
200}
201
202#[derive(Eq, PartialEq, Copy, Clone)]
203enum Response {
204 None = 0,
205 Short = 1,
206 Long = 3,
207}
208
209#[cfg(sdmmc_v1)]
215fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u8, Hertz), Error> {
216 if sdmmc_ck > 50_000_000 {
218 return Err(Error::BadClock);
219 }
220
221 if ker_ck.0 <= sdmmc_ck {
223 return Ok((true, 0, ker_ck));
224 }
225
226 let clk_div = match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck {
228 0 | 1 => Ok(0),
229 x @ 2..=258 => Ok((x - 2) as u8),
230 _ => Err(Error::BadClock),
231 }?;
232
233 let clk_f = Hertz(ker_ck.0 / (clk_div as u32 + 2));
235 Ok((false, clk_div, clk_f))
236}
237
238#[cfg(sdmmc_v2)]
244fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u16, Hertz), Error> {
245 match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck {
247 0 | 1 => Ok((false, 0, ker_ck)),
248 x @ 2..=2046 => {
249 let clk_div = ((x + 1) / 2) as u16;
251 let clk = Hertz(ker_ck.0 / (clk_div as u32 * 2));
252
253 Ok((false, clk_div, clk))
254 }
255 _ => Err(Error::BadClock),
256 }
257}
258
259#[cfg(sdmmc_v1)]
260type Transfer<'a> = crate::dma::Transfer<'a>;
261#[cfg(sdmmc_v2)]
262struct Transfer<'a> {
263 _dummy: PhantomData<&'a ()>,
264}
265
266#[cfg(all(sdmmc_v1, dma))]
267const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions {
268 pburst: crate::dma::Burst::Incr4,
269 mburst: crate::dma::Burst::Incr4,
270 flow_ctrl: crate::dma::FlowControl::Peripheral,
271 fifo_threshold: Some(crate::dma::FifoThreshold::Full),
272 priority: crate::dma::Priority::VeryHigh,
273 circular: false,
274 half_transfer_ir: false,
275 complete_transfer_ir: true,
276};
277#[cfg(all(sdmmc_v1, not(dma)))]
278const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions {
279 priority: crate::dma::Priority::VeryHigh,
280 circular: false,
281 half_transfer_ir: false,
282 complete_transfer_ir: true,
283};
284
285#[non_exhaustive]
290pub struct Config {
291 pub data_transfer_timeout: u32,
293}
294
295impl Default for Config {
296 fn default() -> Self {
297 Self {
298 data_transfer_timeout: 5_000_000,
299 }
300 }
301}
302
303pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> {
305 _peri: PeripheralRef<'d, T>,
306 #[allow(unused)]
307 dma: PeripheralRef<'d, Dma>,
308
309 clk: PeripheralRef<'d, AnyPin>,
310 cmd: PeripheralRef<'d, AnyPin>,
311 d0: PeripheralRef<'d, AnyPin>,
312 d1: Option<PeripheralRef<'d, AnyPin>>,
313 d2: Option<PeripheralRef<'d, AnyPin>>,
314 d3: Option<PeripheralRef<'d, AnyPin>>,
315
316 config: Config,
317 clock: Hertz,
319 signalling: Signalling,
321 card: Option<Card>,
323
324 cmd_block: Option<&'d mut CmdBlock>,
327}
328
329const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh);
330#[cfg(gpio_v1)]
331const CMD_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh);
332#[cfg(gpio_v2)]
333const CMD_AF: AfType = AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up);
334const DATA_AF: AfType = CMD_AF;
335
336#[cfg(sdmmc_v1)]
337impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
338 pub fn new_1bit(
340 sdmmc: impl Peripheral<P = T> + 'd,
341 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
342 dma: impl Peripheral<P = Dma> + 'd,
343 clk: impl Peripheral<P = impl CkPin<T>> + 'd,
344 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
345 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
346 config: Config,
347 ) -> Self {
348 into_ref!(clk, cmd, d0);
349
350 critical_section::with(|_| {
351 clk.set_as_af(clk.af_num(), CLK_AF);
352 cmd.set_as_af(cmd.af_num(), CMD_AF);
353 d0.set_as_af(d0.af_num(), DATA_AF);
354 });
355
356 Self::new_inner(
357 sdmmc,
358 dma,
359 clk.map_into(),
360 cmd.map_into(),
361 d0.map_into(),
362 None,
363 None,
364 None,
365 config,
366 )
367 }
368
369 pub fn new_4bit(
371 sdmmc: impl Peripheral<P = T> + 'd,
372 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
373 dma: impl Peripheral<P = Dma> + 'd,
374 clk: impl Peripheral<P = impl CkPin<T>> + 'd,
375 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
376 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
377 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
378 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
379 d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
380 config: Config,
381 ) -> Self {
382 into_ref!(clk, cmd, d0, d1, d2, d3);
383
384 critical_section::with(|_| {
385 clk.set_as_af(clk.af_num(), CLK_AF);
386 cmd.set_as_af(cmd.af_num(), CMD_AF);
387 d0.set_as_af(d0.af_num(), DATA_AF);
388 d1.set_as_af(d1.af_num(), DATA_AF);
389 d2.set_as_af(d2.af_num(), DATA_AF);
390 d3.set_as_af(d3.af_num(), DATA_AF);
391 });
392
393 Self::new_inner(
394 sdmmc,
395 dma,
396 clk.map_into(),
397 cmd.map_into(),
398 d0.map_into(),
399 Some(d1.map_into()),
400 Some(d2.map_into()),
401 Some(d3.map_into()),
402 config,
403 )
404 }
405}
406
407#[cfg(sdmmc_v2)]
408impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
409 pub fn new_1bit(
411 sdmmc: impl Peripheral<P = T> + 'd,
412 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
413 clk: impl Peripheral<P = impl CkPin<T>> + 'd,
414 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
415 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
416 config: Config,
417 ) -> Self {
418 into_ref!(clk, cmd, d0);
419
420 critical_section::with(|_| {
421 clk.set_as_af(clk.af_num(), CLK_AF);
422 cmd.set_as_af(cmd.af_num(), CMD_AF);
423 d0.set_as_af(d0.af_num(), DATA_AF);
424 });
425
426 Self::new_inner(
427 sdmmc,
428 NoDma.into_ref(),
429 clk.map_into(),
430 cmd.map_into(),
431 d0.map_into(),
432 None,
433 None,
434 None,
435 config,
436 )
437 }
438
439 pub fn new_4bit(
441 sdmmc: impl Peripheral<P = T> + 'd,
442 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
443 clk: impl Peripheral<P = impl CkPin<T>> + 'd,
444 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
445 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
446 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
447 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
448 d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
449 config: Config,
450 ) -> Self {
451 into_ref!(clk, cmd, d0, d1, d2, d3);
452
453 critical_section::with(|_| {
454 clk.set_as_af(clk.af_num(), CLK_AF);
455 cmd.set_as_af(cmd.af_num(), CMD_AF);
456 d0.set_as_af(d0.af_num(), DATA_AF);
457 d1.set_as_af(d1.af_num(), DATA_AF);
458 d2.set_as_af(d2.af_num(), DATA_AF);
459 d3.set_as_af(d3.af_num(), DATA_AF);
460 });
461
462 Self::new_inner(
463 sdmmc,
464 NoDma.into_ref(),
465 clk.map_into(),
466 cmd.map_into(),
467 d0.map_into(),
468 Some(d1.map_into()),
469 Some(d2.map_into()),
470 Some(d3.map_into()),
471 config,
472 )
473 }
474}
475
476impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
477 fn new_inner(
478 sdmmc: impl Peripheral<P = T> + 'd,
479 dma: impl Peripheral<P = Dma> + 'd,
480 clk: PeripheralRef<'d, AnyPin>,
481 cmd: PeripheralRef<'d, AnyPin>,
482 d0: PeripheralRef<'d, AnyPin>,
483 d1: Option<PeripheralRef<'d, AnyPin>>,
484 d2: Option<PeripheralRef<'d, AnyPin>>,
485 d3: Option<PeripheralRef<'d, AnyPin>>,
486 config: Config,
487 ) -> Self {
488 into_ref!(sdmmc, dma);
489
490 rcc::enable_and_reset::<T>();
491
492 T::Interrupt::unpend();
493 unsafe { T::Interrupt::enable() };
494
495 let regs = T::regs();
496 regs.clkcr().write(|w| {
497 w.set_pwrsav(false);
498 w.set_negedge(false);
499
500 #[cfg(sdmmc_v1)]
503 w.set_hwfc_en(false);
504 #[cfg(sdmmc_v2)]
505 w.set_hwfc_en(true);
506
507 #[cfg(sdmmc_v1)]
508 w.set_clken(true);
509 });
510
511 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8));
514
515 Self {
516 _peri: sdmmc,
517 dma,
518
519 clk,
520 cmd,
521 d0,
522 d1,
523 d2,
524 d3,
525
526 config,
527 clock: SD_INIT_FREQ,
528 signalling: Default::default(),
529 card: None,
530 cmd_block: None,
531 }
532 }
533
534 #[inline]
536 fn data_active() -> bool {
537 let regs = T::regs();
538
539 let status = regs.star().read();
540 #[cfg(sdmmc_v1)]
541 return status.rxact() || status.txact();
542 #[cfg(sdmmc_v2)]
543 return status.dpsmact();
544 }
545
546 #[inline]
548 fn cmd_active() -> bool {
549 let regs = T::regs();
550
551 let status = regs.star().read();
552 #[cfg(sdmmc_v1)]
553 return status.cmdact();
554 #[cfg(sdmmc_v2)]
555 return status.cpsmact();
556 }
557
558 #[inline]
560 fn wait_idle() {
561 while Self::data_active() || Self::cmd_active() {}
562 }
563
564 #[allow(unused_variables)]
568 fn prepare_datapath_read<'a>(
569 config: &Config,
570 dma: &'a mut PeripheralRef<'d, Dma>,
571 buffer: &'a mut [u32],
572 length_bytes: u32,
573 block_size: u8,
574 ) -> Transfer<'a> {
575 assert!(block_size <= 14, "Block size up to 2^14 bytes");
576 let regs = T::regs();
577
578 Self::wait_idle();
580 Self::clear_interrupt_flags();
581
582 regs.dtimer().write(|w| w.set_datatime(config.data_transfer_timeout));
583 regs.dlenr().write(|w| w.set_datalength(length_bytes));
584
585 #[cfg(sdmmc_v1)]
586 let transfer = unsafe {
587 let request = dma.request();
588 Transfer::new_read(
589 dma,
590 request,
591 regs.fifor().as_ptr() as *mut u32,
592 buffer,
593 DMA_TRANSFER_OPTIONS,
594 )
595 };
596 #[cfg(sdmmc_v2)]
597 let transfer = {
598 regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32));
599 regs.idmactrlr().modify(|w| w.set_idmaen(true));
600 Transfer {
601 _dummy: core::marker::PhantomData,
602 }
603 };
604
605 regs.dctrl().modify(|w| {
606 w.set_dblocksize(block_size);
607 w.set_dtdir(true);
608 #[cfg(sdmmc_v1)]
609 {
610 w.set_dmaen(true);
611 w.set_dten(true);
612 }
613 });
614
615 transfer
616 }
617
618 fn prepare_datapath_write<'a>(&'a mut self, buffer: &'a [u32], length_bytes: u32, block_size: u8) -> Transfer<'a> {
622 assert!(block_size <= 14, "Block size up to 2^14 bytes");
623 let regs = T::regs();
624
625 Self::wait_idle();
627 Self::clear_interrupt_flags();
628
629 regs.dtimer()
630 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
631 regs.dlenr().write(|w| w.set_datalength(length_bytes));
632
633 #[cfg(sdmmc_v1)]
634 let transfer = unsafe {
635 let request = self.dma.request();
636 Transfer::new_write(
637 &mut self.dma,
638 request,
639 buffer,
640 regs.fifor().as_ptr() as *mut u32,
641 DMA_TRANSFER_OPTIONS,
642 )
643 };
644 #[cfg(sdmmc_v2)]
645 let transfer = {
646 regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_ptr() as u32));
647 regs.idmactrlr().modify(|w| w.set_idmaen(true));
648 Transfer {
649 _dummy: core::marker::PhantomData,
650 }
651 };
652
653 regs.dctrl().modify(|w| {
654 w.set_dblocksize(block_size);
655 w.set_dtdir(false);
656 #[cfg(sdmmc_v1)]
657 {
658 w.set_dmaen(true);
659 w.set_dten(true);
660 }
661 });
662
663 transfer
664 }
665
666 fn stop_datapath() {
668 let regs = T::regs();
669
670 #[cfg(sdmmc_v1)]
671 regs.dctrl().modify(|w| {
672 w.set_dmaen(false);
673 w.set_dten(false);
674 });
675 #[cfg(sdmmc_v2)]
676 regs.idmactrlr().modify(|w| w.set_idmaen(false));
677 }
678
679 fn clkcr_set_clkdiv(&mut self, freq: u32, width: BusWidth) -> Result<(), Error> {
681 let regs = T::regs();
682
683 let width_u32 = match width {
684 BusWidth::One => 1u32,
685 BusWidth::Four => 4u32,
686 BusWidth::Eight => 8u32,
687 _ => panic!("Invalid Bus Width"),
688 };
689
690 let ker_ck = T::frequency();
691 let (_bypass, clkdiv, new_clock) = clk_div(ker_ck, freq)?;
692
693 let sdmmc_bus_bandwidth = new_clock.0 * width_u32;
696 assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32);
697 self.clock = new_clock;
698
699 Self::wait_idle();
701 regs.clkcr().modify(|w| {
702 w.set_clkdiv(clkdiv);
703 #[cfg(sdmmc_v1)]
704 w.set_bypass(_bypass);
705 });
706
707 Ok(())
708 }
709
710 async fn switch_signalling_mode(&mut self, signalling: Signalling) -> Result<Signalling, Error> {
716 let set_function = 0x8000_0000
720 | match signalling {
721 Signalling::DDR50 => 0xFF_FF04,
723 Signalling::SDR104 => 0xFF_1F03,
724 Signalling::SDR50 => 0xFF_1F02,
725 Signalling::SDR25 => 0xFF_FF01,
726 Signalling::SDR12 => 0xFF_FF00,
727 };
728
729 let status = match self.cmd_block.as_deref_mut() {
730 Some(x) => x,
731 None => &mut CmdBlock::new(),
732 };
733
734 let regs = T::regs();
736 let on_drop = OnDrop::new(|| Self::on_drop());
737
738 let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6);
739 InterruptHandler::<T>::data_interrupts(true);
740 Self::cmd(Cmd::cmd6(set_function), true)?; let res = poll_fn(|cx| {
743 T::state().register(cx.waker());
744 let status = regs.star().read();
745
746 if status.dcrcfail() {
747 return Poll::Ready(Err(Error::Crc));
748 }
749 if status.dtimeout() {
750 return Poll::Ready(Err(Error::Timeout));
751 }
752 #[cfg(sdmmc_v1)]
753 if status.stbiterr() {
754 return Poll::Ready(Err(Error::StBitErr));
755 }
756 if status.dataend() {
757 return Poll::Ready(Ok(()));
758 }
759 Poll::Pending
760 })
761 .await;
762 Self::clear_interrupt_flags();
763
764 for _ in 0..300 {
769 cortex_m::asm::nop();
770 }
771
772 match res {
773 Ok(_) => {
774 on_drop.defuse();
775 Self::stop_datapath();
776 drop(transfer);
777
778 let selection = (u32::from_be(status[4]) >> 24) & 0xF;
780
781 match selection {
782 0 => Ok(Signalling::SDR12),
783 1 => Ok(Signalling::SDR25),
784 2 => Ok(Signalling::SDR50),
785 3 => Ok(Signalling::SDR104),
786 4 => Ok(Signalling::DDR50),
787 _ => Err(Error::UnsupportedCardType),
788 }
789 }
790 Err(e) => Err(e),
791 }
792 }
793
794 fn read_status(&self, card: &Card) -> Result<CardStatus, Error> {
796 let regs = T::regs();
797 let rca = card.rca;
798
799 Self::cmd(Cmd::card_status(rca << 16), false)?; let r1 = regs.respr(0).read().cardstatus();
802 Ok(r1.into())
803 }
804
805 async fn read_sd_status(&mut self) -> Result<(), Error> {
807 let card = self.card.as_mut().ok_or(Error::NoCard)?;
808 let rca = card.rca;
809
810 let cmd_block = match self.cmd_block.as_deref_mut() {
811 Some(x) => x,
812 None => &mut CmdBlock::new(),
813 };
814
815 Self::cmd(Cmd::set_block_length(64), false)?; Self::cmd(Cmd::app_cmd(rca << 16), false)?; let status = cmd_block;
819
820 let regs = T::regs();
822 let on_drop = OnDrop::new(|| Self::on_drop());
823
824 let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6);
825 InterruptHandler::<T>::data_interrupts(true);
826 Self::cmd(Cmd::card_status(0), true)?;
827
828 let res = poll_fn(|cx| {
829 T::state().register(cx.waker());
830 let status = regs.star().read();
831
832 if status.dcrcfail() {
833 return Poll::Ready(Err(Error::Crc));
834 }
835 if status.dtimeout() {
836 return Poll::Ready(Err(Error::Timeout));
837 }
838 #[cfg(sdmmc_v1)]
839 if status.stbiterr() {
840 return Poll::Ready(Err(Error::StBitErr));
841 }
842 if status.dataend() {
843 return Poll::Ready(Ok(()));
844 }
845 Poll::Pending
846 })
847 .await;
848 Self::clear_interrupt_flags();
849
850 if res.is_ok() {
851 on_drop.defuse();
852 Self::stop_datapath();
853 drop(transfer);
854
855 for byte in status.iter_mut() {
856 *byte = u32::from_be(*byte);
857 }
858 self.card.as_mut().unwrap().status = status.0.into();
859 }
860 res
861 }
862
863 fn select_card(&self, card: Option<&Card>) -> Result<(), Error> {
868 let rca = card.map(|c| c.rca << 16).unwrap_or(0);
870
871 let r = Self::cmd(Cmd::sel_desel_card(rca), false);
872 match (r, rca) {
873 (Err(Error::Timeout), 0) => Ok(()),
874 _ => r,
875 }
876 }
877
878 #[inline]
880 fn clear_interrupt_flags() {
881 let regs = T::regs();
882 regs.icr().write(|w| {
883 w.set_ccrcfailc(true);
884 w.set_dcrcfailc(true);
885 w.set_ctimeoutc(true);
886 w.set_dtimeoutc(true);
887 w.set_txunderrc(true);
888 w.set_rxoverrc(true);
889 w.set_cmdrendc(true);
890 w.set_cmdsentc(true);
891 w.set_dataendc(true);
892 w.set_dbckendc(true);
893 w.set_sdioitc(true);
894 #[cfg(sdmmc_v1)]
895 w.set_stbiterrc(true);
896
897 #[cfg(sdmmc_v2)]
898 {
899 w.set_dholdc(true);
900 w.set_dabortc(true);
901 w.set_busyd0endc(true);
902 w.set_ackfailc(true);
903 w.set_acktimeoutc(true);
904 w.set_vswendc(true);
905 w.set_ckstopc(true);
906 w.set_idmatec(true);
907 w.set_idmabtcc(true);
908 }
909 });
910 }
911
912 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
913 Self::cmd(Cmd::set_block_length(8), false)?; Self::cmd(Cmd::app_cmd(card.rca << 16), false)?;
916
917 let cmd_block = match self.cmd_block.as_deref_mut() {
918 Some(x) => x,
919 None => &mut CmdBlock::new(),
920 };
921 let scr = &mut cmd_block.0[..2];
922
923 let regs = T::regs();
925 let on_drop = OnDrop::new(|| Self::on_drop());
926
927 let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, scr, 8, 3);
928 InterruptHandler::<T>::data_interrupts(true);
929 Self::cmd(Cmd::cmd51(), true)?;
930
931 let res = poll_fn(|cx| {
932 T::state().register(cx.waker());
933 let status = regs.star().read();
934
935 if status.dcrcfail() {
936 return Poll::Ready(Err(Error::Crc));
937 }
938 if status.dtimeout() {
939 return Poll::Ready(Err(Error::Timeout));
940 }
941 #[cfg(sdmmc_v1)]
942 if status.stbiterr() {
943 return Poll::Ready(Err(Error::StBitErr));
944 }
945 if status.dataend() {
946 return Poll::Ready(Ok(()));
947 }
948 Poll::Pending
949 })
950 .await;
951 Self::clear_interrupt_flags();
952
953 if res.is_ok() {
954 on_drop.defuse();
955 Self::stop_datapath();
956 drop(transfer);
957
958 unsafe {
959 let scr_bytes = &*(&scr as *const _ as *const [u8; 8]);
960 card.scr = SCR(u64::from_be_bytes(*scr_bytes));
961 }
962 }
963 res
964 }
965
966 #[allow(unused_variables)]
968 fn cmd(cmd: Cmd, data: bool) -> Result<(), Error> {
969 let regs = T::regs();
970
971 Self::clear_interrupt_flags();
972 while Self::cmd_active() {}
974
975 regs.argr().write(|w| w.set_cmdarg(cmd.arg));
977
978 regs.cmdr().write(|w| {
980 w.set_waitint(false);
981 w.set_waitresp(cmd.resp as u8);
982 w.set_cmdindex(cmd.cmd);
983 w.set_cpsmen(true);
984
985 #[cfg(sdmmc_v2)]
986 {
987 let cpsm_stop_transmission = cmd.cmd == 12;
990 w.set_cmdstop(cpsm_stop_transmission);
991 w.set_cmdtrans(data);
992 }
993 });
994
995 let mut status;
996 if cmd.resp == Response::None {
997 while {
999 status = regs.star().read();
1000 !(status.ctimeout() || status.cmdsent())
1001 } {}
1002 } else {
1003 while {
1005 status = regs.star().read();
1006 !(status.ctimeout() || status.cmdrend() || status.ccrcfail())
1007 } {}
1008 }
1009
1010 if status.ctimeout() {
1011 return Err(Error::Timeout);
1012 } else if status.ccrcfail() {
1013 return Err(Error::Crc);
1014 }
1015 Ok(())
1016 }
1017
1018 fn on_drop() {
1019 let regs = T::regs();
1020 if Self::data_active() {
1021 Self::clear_interrupt_flags();
1022 while Self::cmd_active() {}
1025
1026 regs.argr().write(|w| w.set_cmdarg(0));
1028
1029 regs.cmdr().write(|w| {
1031 w.set_waitint(false);
1032 w.set_waitresp(Response::Short as u8);
1033 w.set_cmdindex(12);
1034 w.set_cpsmen(true);
1035
1036 #[cfg(sdmmc_v2)]
1037 {
1038 w.set_cmdstop(true);
1039 w.set_cmdtrans(false);
1040 }
1041 });
1042
1043 while Self::data_active() {}
1045 }
1046 InterruptHandler::<T>::data_interrupts(false);
1047 Self::clear_interrupt_flags();
1048 Self::stop_datapath();
1049 }
1050
1051 pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> {
1053 let regs = T::regs();
1054 let ker_ck = T::frequency();
1055
1056 let bus_width = match self.d3.is_some() {
1057 true => BusWidth::Four,
1058 false => BusWidth::One,
1059 };
1060
1061 let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0));
1064 self.clock = init_clock;
1065
1066 Self::wait_idle();
1068
1069 regs.clkcr().modify(|w| {
1070 w.set_widbus(0);
1071 w.set_clkdiv(clkdiv);
1072 #[cfg(sdmmc_v1)]
1073 w.set_bypass(_bypass);
1074 });
1075
1076 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
1077 Self::cmd(Cmd::idle(), false)?;
1078
1079 Self::cmd(Cmd::hs_send_ext_csd(0x1AA), false)?;
1081 let r1 = regs.respr(0).read().cardstatus();
1082
1083 let mut card = if r1 == 0x1AA {
1084 Card::default()
1086 } else {
1087 return Err(Error::UnsupportedCardVersion);
1088 };
1089
1090 let ocr = loop {
1091 Self::cmd(Cmd::app_cmd(0), false)?; let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32
1095 | CmdAppOper::HIGH_CAPACITY as u32
1096 | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32;
1097
1098 match Self::cmd(Cmd::app_op_cmd(arg), false) {
1100 Ok(_) => (),
1102 Err(Error::Crc) => (),
1103 Err(err) => return Err(err),
1104 }
1105 let ocr: OCR = regs.respr(0).read().cardstatus().into();
1106 if !ocr.is_busy() {
1107 break ocr;
1109 }
1110 };
1111
1112 if ocr.high_capacity() {
1113 card.card_type = CardCapacity::SDHC;
1115 } else {
1116 card.card_type = CardCapacity::SDSC;
1117 }
1118 card.ocr = ocr;
1119
1120 Self::cmd(Cmd::all_send_cid(), false)?; let cid0 = regs.respr(0).read().cardstatus() as u128;
1122 let cid1 = regs.respr(1).read().cardstatus() as u128;
1123 let cid2 = regs.respr(2).read().cardstatus() as u128;
1124 let cid3 = regs.respr(3).read().cardstatus() as u128;
1125 let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3);
1126 card.cid = cid.into();
1127
1128 Self::cmd(Cmd::send_rel_addr(), false)?;
1129 card.rca = regs.respr(0).read().cardstatus() >> 16;
1130
1131 Self::cmd(Cmd::send_csd(card.rca << 16), false)?;
1132 let csd0 = regs.respr(0).read().cardstatus() as u128;
1133 let csd1 = regs.respr(1).read().cardstatus() as u128;
1134 let csd2 = regs.respr(2).read().cardstatus() as u128;
1135 let csd3 = regs.respr(3).read().cardstatus() as u128;
1136 let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3);
1137 card.csd = csd.into();
1138
1139 self.select_card(Some(&card))?;
1140
1141 self.get_scr(&mut card).await?;
1142
1143 let (width, acmd_arg) = match bus_width {
1145 BusWidth::Eight => unimplemented!(),
1146 BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2),
1147 _ => (BusWidth::One, 0),
1148 };
1149 Self::cmd(Cmd::app_cmd(card.rca << 16), false)?;
1150 Self::cmd(Cmd::cmd6(acmd_arg), false)?;
1151
1152 Self::wait_idle();
1154
1155 regs.clkcr().modify(|w| {
1156 w.set_widbus(match width {
1157 BusWidth::One => 0,
1158 BusWidth::Four => 1,
1159 BusWidth::Eight => 2,
1160 _ => panic!("Invalid Bus Width"),
1161 })
1162 });
1163
1164 if freq.0 <= 25_000_000 {
1166 self.clkcr_set_clkdiv(freq.0, width)?;
1168 } else {
1169 self.clkcr_set_clkdiv(25_000_000, width)?;
1171 }
1172
1173 self.card = Some(card);
1174
1175 self.read_sd_status().await?;
1177
1178 if freq.0 > 25_000_000 {
1179 self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?;
1181
1182 if self.signalling == Signalling::SDR25 {
1183 self.clkcr_set_clkdiv(freq.0, width)?;
1185
1186 if self.read_status(&card)?.state() != CurrentState::Transfer {
1187 return Err(Error::SignalingSwitchFailed);
1188 }
1189 }
1190 }
1191
1192 self.read_sd_status().await?;
1194
1195 Ok(())
1196 }
1197
1198 #[inline]
1200 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
1201 let card_capacity = self.card()?.card_type;
1202
1203 let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) };
1205
1206 let address = match card_capacity {
1209 CardCapacity::SDSC => block_idx * 512,
1210 _ => block_idx,
1211 };
1212 Self::cmd(Cmd::set_block_length(512), false)?; let regs = T::regs();
1215 let on_drop = OnDrop::new(|| Self::on_drop());
1216
1217 let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, buffer, 512, 9);
1218 InterruptHandler::<T>::data_interrupts(true);
1219 Self::cmd(Cmd::read_single_block(address), true)?;
1220
1221 let res = poll_fn(|cx| {
1222 T::state().register(cx.waker());
1223 let status = regs.star().read();
1224
1225 if status.dcrcfail() {
1226 return Poll::Ready(Err(Error::Crc));
1227 }
1228 if status.dtimeout() {
1229 return Poll::Ready(Err(Error::Timeout));
1230 }
1231 #[cfg(sdmmc_v1)]
1232 if status.stbiterr() {
1233 return Poll::Ready(Err(Error::StBitErr));
1234 }
1235 if status.dataend() {
1236 return Poll::Ready(Ok(()));
1237 }
1238 Poll::Pending
1239 })
1240 .await;
1241 Self::clear_interrupt_flags();
1242
1243 if res.is_ok() {
1244 on_drop.defuse();
1245 Self::stop_datapath();
1246 drop(transfer);
1247 }
1248 res
1249 }
1250
1251 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> {
1253 let card = self.card.as_mut().ok_or(Error::NoCard)?;
1254
1255 let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) };
1257
1258 let address = match card.card_type {
1261 CardCapacity::SDSC => block_idx * 512,
1262 _ => block_idx,
1263 };
1264 Self::cmd(Cmd::set_block_length(512), false)?; let regs = T::regs();
1267 let on_drop = OnDrop::new(|| Self::on_drop());
1268
1269 #[cfg(sdmmc_v1)]
1271 Self::cmd(Cmd::write_single_block(address), true)?;
1272
1273 let transfer = self.prepare_datapath_write(buffer, 512, 9);
1274 InterruptHandler::<T>::data_interrupts(true);
1275
1276 #[cfg(sdmmc_v2)]
1277 Self::cmd(Cmd::write_single_block(address), true)?;
1278
1279 let res = poll_fn(|cx| {
1280 T::state().register(cx.waker());
1281 let status = regs.star().read();
1282
1283 if status.dcrcfail() {
1284 return Poll::Ready(Err(Error::Crc));
1285 }
1286 if status.dtimeout() {
1287 return Poll::Ready(Err(Error::Timeout));
1288 }
1289 #[cfg(sdmmc_v1)]
1290 if status.stbiterr() {
1291 return Poll::Ready(Err(Error::StBitErr));
1292 }
1293 if status.dataend() {
1294 return Poll::Ready(Ok(()));
1295 }
1296 Poll::Pending
1297 })
1298 .await;
1299 Self::clear_interrupt_flags();
1300
1301 match res {
1302 Ok(_) => {
1303 on_drop.defuse();
1304 Self::stop_datapath();
1305 drop(transfer);
1306
1307 let mut timeout: u32 = 0x00FF_FFFF;
1309
1310 while timeout > 0 {
1312 match self.read_sd_status().await {
1313 Ok(_) => return Ok(()),
1314 Err(Error::Timeout) => (), Err(e) => return Err(e),
1316 }
1317 timeout -= 1;
1318 }
1319 Err(Error::SoftwareTimeout)
1320 }
1321 Err(e) => Err(e),
1322 }
1323 }
1324
1325 #[inline]
1332 pub fn card(&self) -> Result<&Card, Error> {
1333 self.card.as_ref().ok_or(Error::NoCard)
1334 }
1335
1336 pub fn clock(&self) -> Hertz {
1338 self.clock
1339 }
1340
1341 pub fn set_cmd_block(&mut self, cmd_block: &'d mut CmdBlock) {
1346 self.cmd_block = Some(cmd_block)
1347 }
1348}
1349
1350impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> {
1351 fn drop(&mut self) {
1352 T::Interrupt::disable();
1353 Self::on_drop();
1354
1355 critical_section::with(|_| {
1356 self.clk.set_as_disconnected();
1357 self.cmd.set_as_disconnected();
1358 self.d0.set_as_disconnected();
1359 if let Some(x) = &mut self.d1 {
1360 x.set_as_disconnected();
1361 }
1362 if let Some(x) = &mut self.d2 {
1363 x.set_as_disconnected();
1364 }
1365 if let Some(x) = &mut self.d3 {
1366 x.set_as_disconnected();
1367 }
1368 });
1369 }
1370}
1371
1372impl Cmd {
1374 const fn new(cmd: u8, arg: u32, resp: Response) -> Cmd {
1375 Cmd { cmd, arg, resp }
1376 }
1377
1378 const fn idle() -> Cmd {
1380 Cmd::new(0, 0, Response::None)
1381 }
1382
1383 const fn all_send_cid() -> Cmd {
1385 Cmd::new(2, 0, Response::Long)
1386 }
1387
1388 const fn send_rel_addr() -> Cmd {
1390 Cmd::new(3, 0, Response::Short)
1391 }
1392
1393 const fn cmd6(arg: u32) -> Cmd {
1396 Cmd::new(6, arg, Response::Short)
1397 }
1398
1399 const fn sel_desel_card(rca: u32) -> Cmd {
1401 Cmd::new(7, rca, Response::Short)
1402 }
1403
1404 const fn hs_send_ext_csd(arg: u32) -> Cmd {
1406 Cmd::new(8, arg, Response::Short)
1407 }
1408
1409 const fn send_csd(rca: u32) -> Cmd {
1411 Cmd::new(9, rca, Response::Long)
1412 }
1413
1414 const fn card_status(rca: u32) -> Cmd {
1422 Cmd::new(13, rca, Response::Short)
1423 }
1424
1425 const fn set_block_length(blocklen: u32) -> Cmd {
1427 Cmd::new(16, blocklen, Response::Short)
1428 }
1429
1430 const fn read_single_block(addr: u32) -> Cmd {
1432 Cmd::new(17, addr, Response::Short)
1433 }
1434
1435 const fn write_single_block(addr: u32) -> Cmd {
1442 Cmd::new(24, addr, Response::Short)
1443 }
1444
1445 const fn app_op_cmd(arg: u32) -> Cmd {
1446 Cmd::new(41, arg, Response::Short)
1447 }
1448
1449 const fn cmd51() -> Cmd {
1450 Cmd::new(51, 0, Response::Short)
1451 }
1452
1453 const fn app_cmd(rca: u32) -> Cmd {
1455 Cmd::new(55, rca, Response::Short)
1456 }
1457}
1458
1459trait SealedInstance {
1462 fn regs() -> RegBlock;
1463 fn state() -> &'static AtomicWaker;
1464}
1465
1466#[allow(private_bounds)]
1468pub trait Instance: SealedInstance + RccPeripheral + 'static {
1469 type Interrupt: interrupt::typelevel::Interrupt;
1471}
1472
1473pin_trait!(CkPin, Instance);
1474pin_trait!(CmdPin, Instance);
1475pin_trait!(D0Pin, Instance);
1476pin_trait!(D1Pin, Instance);
1477pin_trait!(D2Pin, Instance);
1478pin_trait!(D3Pin, Instance);
1479pin_trait!(D4Pin, Instance);
1480pin_trait!(D5Pin, Instance);
1481pin_trait!(D6Pin, Instance);
1482pin_trait!(D7Pin, Instance);
1483
1484#[cfg(sdmmc_v1)]
1485dma_trait!(SdmmcDma, Instance);
1486
1487#[cfg(sdmmc_v2)]
1492pub trait SdmmcDma<T: Instance> {}
1493#[cfg(sdmmc_v2)]
1494impl<T: Instance> SdmmcDma<T> for NoDma {}
1495
1496foreach_peripheral!(
1497 (sdmmc, $inst:ident) => {
1498 impl SealedInstance for peripherals::$inst {
1499 fn regs() -> RegBlock {
1500 crate::pac::$inst
1501 }
1502
1503 fn state() -> &'static ::embassy_sync::waitqueue::AtomicWaker {
1504 static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new();
1505 &WAKER
1506 }
1507 }
1508
1509 impl Instance for peripherals::$inst {
1510 type Interrupt = crate::interrupt::typelevel::$inst;
1511 }
1512 };
1513);
1514
1515impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> block_device_driver::BlockDevice<512> for Sdmmc<'d, T, Dma> {
1516 type Error = Error;
1517 type Align = aligned::A4;
1518
1519 async fn read(
1520 &mut self,
1521 mut block_address: u32,
1522 buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>],
1523 ) -> Result<(), Self::Error> {
1524 for block in buf.iter_mut() {
1526 let block = unsafe { &mut *(block as *mut _ as *mut crate::sdmmc::DataBlock) };
1528 self.read_block(block_address, block).await?;
1529 block_address += 1;
1530 }
1531
1532 Ok(())
1533 }
1534
1535 async fn write(
1536 &mut self,
1537 mut block_address: u32,
1538 buf: &[aligned::Aligned<Self::Align, [u8; 512]>],
1539 ) -> Result<(), Self::Error> {
1540 for block in buf.iter() {
1542 let block = unsafe { &*(block as *const _ as *const crate::sdmmc::DataBlock) };
1544 self.write_block(block_address, block).await?;
1545 block_address += 1;
1546 }
1547
1548 Ok(())
1549 }
1550
1551 async fn size(&mut self) -> Result<u64, Self::Error> {
1552 Ok(self.card()?.size())
1553 }
1554}