aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs998
1 files changed, 419 insertions, 579 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 22b578dcf..23ece3a2a 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -41,7 +41,7 @@ impl Default for Signalling {
41} 41}
42 42
43#[repr(align(4))] 43#[repr(align(4))]
44#[derive(Debug, Clone)] 44#[derive(Debug, Clone, PartialEq, Eq)]
45#[cfg_attr(feature = "defmt", derive(defmt::Format))] 45#[cfg_attr(feature = "defmt", derive(defmt::Format))]
46pub struct DataBlock(pub [u8; 512]); 46pub struct DataBlock(pub [u8; 512]);
47 47
@@ -61,7 +61,7 @@ impl DerefMut for DataBlock {
61 61
62/// Errors 62/// Errors
63#[non_exhaustive] 63#[non_exhaustive]
64#[derive(Debug, Copy, Clone)] 64#[derive(Debug, Copy, Clone, PartialEq, Eq)]
65#[cfg_attr(feature = "defmt", derive(defmt::Format))] 65#[cfg_attr(feature = "defmt", derive(defmt::Format))]
66pub enum Error { 66pub enum Error {
67 Timeout, 67 Timeout,
@@ -175,7 +175,7 @@ fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u16, Hertz), Error> {
175 match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck { 175 match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck {
176 0 | 1 => Ok((false, 0, ker_ck)), 176 0 | 1 => Ok((false, 0, ker_ck)),
177 x @ 2..=2046 => { 177 x @ 2..=2046 => {
178 // SDMMC_CK frequency = SDMMCCLK / [CLKDIV + 2] 178 // SDMMC_CK frequency = SDMMCCLK / [CLKDIV * 2]
179 let clk_div = ((x + 1) / 2) as u16; 179 let clk_div = ((x + 1) / 2) as u16;
180 let clk = Hertz(ker_ck.0 / (clk_div as u32 * 2)); 180 let clk = Hertz(ker_ck.0 / (clk_div as u32 * 2));
181 181
@@ -204,9 +204,10 @@ impl Default for Config {
204} 204}
205 205
206/// Sdmmc device 206/// Sdmmc device
207pub struct Sdmmc<'d, T: Instance, Dma = NoDma> { 207pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> {
208 _peri: PeripheralRef<'d, T>, 208 _peri: PeripheralRef<'d, T>,
209 irq: PeripheralRef<'d, T::Interrupt>, 209 irq: PeripheralRef<'d, T::Interrupt>,
210 #[allow(unused)]
210 dma: PeripheralRef<'d, Dma>, 211 dma: PeripheralRef<'d, Dma>,
211 212
212 clk: PeripheralRef<'d, AnyPin>, 213 clk: PeripheralRef<'d, AnyPin>,
@@ -305,49 +306,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
305 config, 306 config,
306 ) 307 )
307 } 308 }
308
309 fn new_inner(
310 sdmmc: impl Peripheral<P = T> + 'd,
311 irq: impl Peripheral<P = T::Interrupt> + 'd,
312 dma: impl Peripheral<P = Dma> + 'd,
313 clk: PeripheralRef<'d, AnyPin>,
314 cmd: PeripheralRef<'d, AnyPin>,
315 d0: PeripheralRef<'d, AnyPin>,
316 d1: Option<PeripheralRef<'d, AnyPin>>,
317 d2: Option<PeripheralRef<'d, AnyPin>>,
318 d3: Option<PeripheralRef<'d, AnyPin>>,
319 config: Config,
320 ) -> Self {
321 into_ref!(sdmmc, irq, dma);
322
323 T::enable();
324 T::reset();
325
326 let inner = T::inner();
327 unsafe { inner.new_inner() };
328
329 irq.set_handler(Self::on_interrupt);
330 irq.unpend();
331 irq.enable();
332
333 Self {
334 _peri: sdmmc,
335 irq,
336 dma,
337
338 clk,
339 cmd,
340 d0,
341 d1,
342 d2,
343 d3,
344
345 config,
346 clock: SD_INIT_FREQ,
347 signalling: Default::default(),
348 card: None,
349 }
350 }
351} 309}
352 310
353#[cfg(sdmmc_v2)] 311#[cfg(sdmmc_v2)]
@@ -375,6 +333,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
375 Self::new_inner( 333 Self::new_inner(
376 sdmmc, 334 sdmmc,
377 irq, 335 irq,
336 NoDma.into_ref(),
378 clk.map_into(), 337 clk.map_into(),
379 cmd.map_into(), 338 cmd.map_into(),
380 d0.map_into(), 339 d0.map_into(),
@@ -417,6 +376,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
417 Self::new_inner( 376 Self::new_inner(
418 sdmmc, 377 sdmmc,
419 irq, 378 irq,
379 NoDma.into_ref(),
420 clk.map_into(), 380 clk.map_into(),
421 cmd.map_into(), 381 cmd.map_into(),
422 d0.map_into(), 382 d0.map_into(),
@@ -426,10 +386,13 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
426 config, 386 config,
427 ) 387 )
428 } 388 }
389}
429 390
391impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
430 fn new_inner( 392 fn new_inner(
431 sdmmc: impl Peripheral<P = T> + 'd, 393 sdmmc: impl Peripheral<P = T> + 'd,
432 irq: impl Peripheral<P = T::Interrupt> + 'd, 394 irq: impl Peripheral<P = T::Interrupt> + 'd,
395 dma: impl Peripheral<P = Dma> + 'd,
433 clk: PeripheralRef<'d, AnyPin>, 396 clk: PeripheralRef<'d, AnyPin>,
434 cmd: PeripheralRef<'d, AnyPin>, 397 cmd: PeripheralRef<'d, AnyPin>,
435 d0: PeripheralRef<'d, AnyPin>, 398 d0: PeripheralRef<'d, AnyPin>,
@@ -438,22 +401,41 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
438 d3: Option<PeripheralRef<'d, AnyPin>>, 401 d3: Option<PeripheralRef<'d, AnyPin>>,
439 config: Config, 402 config: Config,
440 ) -> Self { 403 ) -> Self {
441 into_ref!(sdmmc, irq); 404 into_ref!(sdmmc, irq, dma);
442 405
443 T::enable(); 406 T::enable();
444 T::reset(); 407 T::reset();
445 408
446 let inner = T::inner();
447 unsafe { inner.new_inner() };
448
449 irq.set_handler(Self::on_interrupt); 409 irq.set_handler(Self::on_interrupt);
450 irq.unpend(); 410 irq.unpend();
451 irq.enable(); 411 irq.enable();
452 412
413 let regs = T::regs();
414 unsafe {
415 regs.clkcr().write(|w| {
416 w.set_pwrsav(false);
417 w.set_negedge(false);
418
419 // Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors.
420 // See chip erratas for more details.
421 #[cfg(sdmmc_v1)]
422 w.set_hwfc_en(false);
423 #[cfg(sdmmc_v2)]
424 w.set_hwfc_en(true);
425
426 #[cfg(sdmmc_v1)]
427 w.set_clken(true);
428 });
429
430 // Power off, writen 00: Clock to the card is stopped;
431 // D[7:0], CMD, and CK are driven high.
432 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8));
433 }
434
453 Self { 435 Self {
454 _peri: sdmmc, 436 _peri: sdmmc,
455 irq, 437 irq,
456 dma: NoDma.into_ref(), 438 dma,
457 439
458 clk, 440 clk,
459 cmd, 441 cmd,
@@ -468,434 +450,11 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
468 card: None, 450 card: None,
469 } 451 }
470 } 452 }
471}
472
473impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
474 #[inline(always)]
475 pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> {
476 let inner = T::inner();
477 let freq = freq.into();
478
479 let bus_width = match self.d3.is_some() {
480 true => BusWidth::Four,
481 false => BusWidth::One,
482 };
483
484 inner
485 .init_card(
486 freq,
487 bus_width,
488 &mut self.card,
489 &mut self.signalling,
490 T::kernel_clk(),
491 &mut self.clock,
492 T::state(),
493 self.config.data_transfer_timeout,
494 &mut *self.dma,
495 )
496 .await
497 }
498
499 #[inline(always)]
500 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
501 let card_capacity = self.card()?.card_type;
502 let inner = T::inner();
503 let state = T::state();
504
505 // NOTE(unsafe) DataBlock uses align 4
506 let buf = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) };
507 inner
508 .read_block(
509 block_idx,
510 buf,
511 card_capacity,
512 state,
513 self.config.data_transfer_timeout,
514 &mut *self.dma,
515 )
516 .await
517 }
518
519 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> {
520 let card = self.card.as_mut().ok_or(Error::NoCard)?;
521 let inner = T::inner();
522 let state = T::state();
523
524 // NOTE(unsafe) DataBlock uses align 4
525 let buf = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) };
526 inner
527 .write_block(
528 block_idx,
529 buf,
530 card,
531 state,
532 self.config.data_transfer_timeout,
533 &mut *self.dma,
534 )
535 .await
536 }
537
538 /// Get a reference to the initialized card
539 ///
540 /// # Errors
541 ///
542 /// Returns Error::NoCard if [`init_card`](#method.init_card)
543 /// has not previously succeeded
544 #[inline(always)]
545 pub fn card(&self) -> Result<&Card, Error> {
546 self.card.as_ref().ok_or(Error::NoCard)
547 }
548
549 /// Get the current SDMMC bus clock
550 pub fn clock(&self) -> Hertz {
551 self.clock
552 }
553
554 #[inline(always)]
555 fn on_interrupt(_: *mut ()) {
556 let regs = T::inner();
557 let state = T::state();
558
559 regs.data_interrupts(false);
560 state.wake();
561 }
562}
563
564impl<'d, T: Instance, Dma> Drop for Sdmmc<'d, T, Dma> {
565 fn drop(&mut self) {
566 self.irq.disable();
567 let inner = T::inner();
568 unsafe { inner.on_drop() };
569
570 critical_section::with(|_| unsafe {
571 self.clk.set_as_disconnected();
572 self.cmd.set_as_disconnected();
573 self.d0.set_as_disconnected();
574 if let Some(x) = &mut self.d1 {
575 x.set_as_disconnected();
576 }
577 if let Some(x) = &mut self.d2 {
578 x.set_as_disconnected();
579 }
580 if let Some(x) = &mut self.d3 {
581 x.set_as_disconnected();
582 }
583 });
584 }
585}
586
587pub struct SdmmcInner(pub(crate) RegBlock);
588
589impl SdmmcInner {
590 /// # Safety
591 ///
592 /// Access to `regs` registers should be exclusive
593 unsafe fn new_inner(&self) {
594 let regs = self.0;
595
596 regs.clkcr().write(|w| {
597 w.set_pwrsav(false);
598 w.set_negedge(false);
599
600 // Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors.
601 // See chip erratas for more details.
602 #[cfg(sdmmc_v1)]
603 w.set_hwfc_en(false);
604 #[cfg(sdmmc_v2)]
605 w.set_hwfc_en(true);
606
607 #[cfg(sdmmc_v1)]
608 w.set_clken(true);
609 });
610
611 // Power off, writen 00: Clock to the card is stopped;
612 // D[7:0], CMD, and CK are driven high.
613 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8));
614 }
615
616 /// Initializes card (if present) and sets the bus at the
617 /// specified frequency.
618 #[allow(clippy::too_many_arguments)]
619 async fn init_card<T: Instance, Dma: SdmmcDma<T>>(
620 &self,
621 freq: Hertz,
622 bus_width: BusWidth,
623 old_card: &mut Option<Card>,
624 signalling: &mut Signalling,
625 ker_ck: Hertz,
626 clock: &mut Hertz,
627 waker_reg: &AtomicWaker,
628 data_transfer_timeout: u32,
629 dma: &mut Dma,
630 ) -> Result<(), Error> {
631 let regs = self.0;
632
633 // NOTE(unsafe) We have exclusive access to the peripheral
634 unsafe {
635 // While the SD/SDIO card or eMMC is in identification mode,
636 // the SDMMC_CK frequency must be no more than 400 kHz.
637 let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0));
638 *clock = init_clock;
639
640 // CPSMACT and DPSMACT must be 0 to set WIDBUS
641 self.wait_idle();
642
643 regs.clkcr().modify(|w| {
644 w.set_widbus(0);
645 w.set_clkdiv(clkdiv);
646 #[cfg(sdmmc_v1)]
647 w.set_bypass(_bypass);
648 });
649
650 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
651 self.cmd(Cmd::idle(), false)?;
652
653 // Check if cards supports CMD8 (with pattern)
654 self.cmd(Cmd::hs_send_ext_csd(0x1AA), false)?;
655 let r1 = regs.respr(0).read().cardstatus();
656
657 let mut card = if r1 == 0x1AA {
658 // Card echoed back the pattern. Must be at least v2
659 Card::default()
660 } else {
661 return Err(Error::UnsupportedCardVersion);
662 };
663
664 let ocr = loop {
665 // Signal that next command is a app command
666 self.cmd(Cmd::app_cmd(0), false)?; // CMD55
667
668 let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32
669 | CmdAppOper::HIGH_CAPACITY as u32
670 | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32;
671
672 // Initialize card
673 match self.cmd(Cmd::app_op_cmd(arg), false) {
674 // ACMD41
675 Ok(_) => (),
676 Err(Error::Crc) => (),
677 Err(err) => return Err(err),
678 }
679 let ocr: OCR = regs.respr(0).read().cardstatus().into();
680 if !ocr.is_busy() {
681 // Power up done
682 break ocr;
683 }
684 };
685
686 if ocr.high_capacity() {
687 // Card is SDHC or SDXC or SDUC
688 card.card_type = CardCapacity::SDHC;
689 } else {
690 card.card_type = CardCapacity::SDSC;
691 }
692 card.ocr = ocr;
693
694 self.cmd(Cmd::all_send_cid(), false)?; // CMD2
695 let cid0 = regs.respr(0).read().cardstatus() as u128;
696 let cid1 = regs.respr(1).read().cardstatus() as u128;
697 let cid2 = regs.respr(2).read().cardstatus() as u128;
698 let cid3 = regs.respr(3).read().cardstatus() as u128;
699 let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3);
700 card.cid = cid.into();
701
702 self.cmd(Cmd::send_rel_addr(), false)?;
703 card.rca = regs.respr(0).read().cardstatus() >> 16;
704
705 self.cmd(Cmd::send_csd(card.rca << 16), false)?;
706 let csd0 = regs.respr(0).read().cardstatus() as u128;
707 let csd1 = regs.respr(1).read().cardstatus() as u128;
708 let csd2 = regs.respr(2).read().cardstatus() as u128;
709 let csd3 = regs.respr(3).read().cardstatus() as u128;
710 let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3);
711 card.csd = csd.into();
712
713 self.select_card(Some(&card))?;
714
715 self.get_scr(&mut card, waker_reg, data_transfer_timeout, dma).await?;
716
717 // Set bus width
718 let (width, acmd_arg) = match bus_width {
719 BusWidth::Eight => unimplemented!(),
720 BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2),
721 _ => (BusWidth::One, 0),
722 };
723 self.cmd(Cmd::app_cmd(card.rca << 16), false)?;
724 self.cmd(Cmd::cmd6(acmd_arg), false)?;
725
726 // CPSMACT and DPSMACT must be 0 to set WIDBUS
727 self.wait_idle();
728
729 regs.clkcr().modify(|w| {
730 w.set_widbus(match width {
731 BusWidth::One => 0,
732 BusWidth::Four => 1,
733 BusWidth::Eight => 2,
734 _ => panic!("Invalid Bus Width"),
735 })
736 });
737
738 // Set Clock
739 if freq.0 <= 25_000_000 {
740 // Final clock frequency
741 self.clkcr_set_clkdiv(freq.0, width, ker_ck, clock)?;
742 } else {
743 // Switch to max clock for SDR12
744 self.clkcr_set_clkdiv(25_000_000, width, ker_ck, clock)?;
745 }
746
747 // Read status
748 self.read_sd_status(&mut card, waker_reg, data_transfer_timeout, dma)
749 .await?;
750
751 if freq.0 > 25_000_000 {
752 // Switch to SDR25
753 *signalling = self
754 .switch_signalling_mode(Signalling::SDR25, waker_reg, data_transfer_timeout, dma)
755 .await?;
756
757 if *signalling == Signalling::SDR25 {
758 // Set final clock frequency
759 self.clkcr_set_clkdiv(freq.0, width, ker_ck, clock)?;
760
761 if self.read_status(&card)?.state() != CurrentState::Transfer {
762 return Err(Error::SignalingSwitchFailed);
763 }
764 }
765 }
766 // Read status after signalling change
767 self.read_sd_status(&mut card, waker_reg, data_transfer_timeout, dma)
768 .await?;
769 old_card.replace(card);
770 }
771
772 Ok(())
773 }
774
775 async fn read_block<T: Instance, Dma: SdmmcDma<T>>(
776 &self,
777 block_idx: u32,
778 buffer: &mut [u32; 128],
779 capacity: CardCapacity,
780 waker_reg: &AtomicWaker,
781 data_transfer_timeout: u32,
782 dma: &mut Dma,
783 ) -> Result<(), Error> {
784 // Always read 1 block of 512 bytes
785 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
786 let address = match capacity {
787 CardCapacity::SDSC => block_idx * 512,
788 _ => block_idx,
789 };
790 self.cmd(Cmd::set_block_length(512), false)?; // CMD16
791
792 let regs = self.0;
793 let on_drop = OnDrop::new(|| unsafe { self.on_drop() });
794
795 unsafe {
796 self.prepare_datapath_read(buffer, 512, 9, data_transfer_timeout, dma);
797 self.data_interrupts(true);
798 }
799 self.cmd(Cmd::read_single_block(address), true)?;
800
801 let res = poll_fn(|cx| {
802 waker_reg.register(cx.waker());
803 let status = unsafe { regs.star().read() };
804
805 if status.dcrcfail() {
806 return Poll::Ready(Err(Error::Crc));
807 } else if status.dtimeout() {
808 return Poll::Ready(Err(Error::Timeout));
809 } else if status.dataend() {
810 return Poll::Ready(Ok(()));
811 }
812 Poll::Pending
813 })
814 .await;
815 self.clear_interrupt_flags();
816
817 if res.is_ok() {
818 on_drop.defuse();
819 self.stop_datapath();
820 }
821 res
822 }
823
824 async fn write_block<T: Instance, Dma: SdmmcDma<T>>(
825 &self,
826 block_idx: u32,
827 buffer: &[u32; 128],
828 card: &mut Card,
829 waker_reg: &AtomicWaker,
830 data_transfer_timeout: u32,
831 dma: &mut Dma,
832 ) -> Result<(), Error> {
833 // Always read 1 block of 512 bytes
834 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
835 let address = match card.card_type {
836 CardCapacity::SDSC => block_idx * 512,
837 _ => block_idx,
838 };
839 self.cmd(Cmd::set_block_length(512), false)?; // CMD16
840
841 let regs = self.0;
842 let on_drop = OnDrop::new(|| unsafe { self.on_drop() });
843
844 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
845 #[cfg(sdmmc_v1)]
846 self.cmd(Cmd::write_single_block(address), true)?;
847
848 unsafe {
849 self.prepare_datapath_write(buffer as *const [u32; 128], 512, 9, data_transfer_timeout, dma);
850 self.data_interrupts(true);
851 }
852
853 #[cfg(sdmmc_v2)]
854 self.cmd(Cmd::write_single_block(address), true)?;
855
856 let res = poll_fn(|cx| {
857 waker_reg.register(cx.waker());
858 let status = unsafe { regs.star().read() };
859
860 if status.dcrcfail() {
861 return Poll::Ready(Err(Error::Crc));
862 } else if status.dtimeout() {
863 return Poll::Ready(Err(Error::Timeout));
864 } else if status.dataend() {
865 return Poll::Ready(Ok(()));
866 }
867 Poll::Pending
868 })
869 .await;
870 self.clear_interrupt_flags();
871
872 match res {
873 Ok(_) => {
874 on_drop.defuse();
875 self.stop_datapath();
876
877 // TODO: Make this configurable
878 let mut timeout: u32 = 0x00FF_FFFF;
879
880 // Try to read card status (ACMD13)
881 while timeout > 0 {
882 match self.read_sd_status(card, waker_reg, data_transfer_timeout, dma).await {
883 Ok(_) => return Ok(()),
884 Err(Error::Timeout) => (), // Try again
885 Err(e) => return Err(e),
886 }
887 timeout -= 1;
888 }
889 Err(Error::SoftwareTimeout)
890 }
891 Err(e) => Err(e),
892 }
893 }
894 453
895 /// Data transfer is in progress 454 /// Data transfer is in progress
896 #[inline(always)] 455 #[inline(always)]
897 fn data_active(&self) -> bool { 456 fn data_active() -> bool {
898 let regs = self.0; 457 let regs = T::regs();
899 458
900 // NOTE(unsafe) Atomic read with no side-effects 459 // NOTE(unsafe) Atomic read with no side-effects
901 unsafe { 460 unsafe {
@@ -909,8 +468,8 @@ impl SdmmcInner {
909 468
910 /// Coammand transfer is in progress 469 /// Coammand transfer is in progress
911 #[inline(always)] 470 #[inline(always)]
912 fn cmd_active(&self) -> bool { 471 fn cmd_active() -> bool {
913 let regs = self.0; 472 let regs = T::regs();
914 473
915 // NOTE(unsafe) Atomic read with no side-effects 474 // NOTE(unsafe) Atomic read with no side-effects
916 unsafe { 475 unsafe {
@@ -924,37 +483,31 @@ impl SdmmcInner {
924 483
925 /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2) 484 /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2)
926 #[inline(always)] 485 #[inline(always)]
927 fn wait_idle(&self) { 486 fn wait_idle() {
928 while self.data_active() || self.cmd_active() {} 487 while Self::data_active() || Self::cmd_active() {}
929 } 488 }
930 489
931 /// # Safety 490 /// # Safety
932 /// 491 ///
933 /// `buffer` must be valid for the whole transfer and word aligned 492 /// `buffer` must be valid for the whole transfer and word aligned
934 unsafe fn prepare_datapath_read<T: Instance, Dma: SdmmcDma<T>>( 493 unsafe fn prepare_datapath_read(&mut self, buffer: *mut [u32], length_bytes: u32, block_size: u8) {
935 &self,
936 buffer: *mut [u32],
937 length_bytes: u32,
938 block_size: u8,
939 data_transfer_timeout: u32,
940 #[allow(unused_variables)] dma: &mut Dma,
941 ) {
942 assert!(block_size <= 14, "Block size up to 2^14 bytes"); 494 assert!(block_size <= 14, "Block size up to 2^14 bytes");
943 let regs = self.0; 495 let regs = T::regs();
944 496
945 // Command AND Data state machines must be idle 497 // Command AND Data state machines must be idle
946 self.wait_idle(); 498 Self::wait_idle();
947 self.clear_interrupt_flags(); 499 Self::clear_interrupt_flags();
948 500
949 // NOTE(unsafe) We have exclusive access to the regisers 501 // NOTE(unsafe) We have exclusive access to the regisers
950 502
951 regs.dtimer().write(|w| w.set_datatime(data_transfer_timeout)); 503 regs.dtimer()
504 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
952 regs.dlenr().write(|w| w.set_datalength(length_bytes)); 505 regs.dlenr().write(|w| w.set_datalength(length_bytes));
953 506
954 #[cfg(sdmmc_v1)] 507 #[cfg(sdmmc_v1)]
955 { 508 {
956 let request = dma.request(); 509 let request = self.dma.request();
957 dma.start_read( 510 self.dma.start_read(
958 request, 511 request,
959 regs.fifor().ptr() as *const u32, 512 regs.fifor().ptr() as *const u32,
960 buffer, 513 buffer,
@@ -987,30 +540,24 @@ impl SdmmcInner {
987 /// # Safety 540 /// # Safety
988 /// 541 ///
989 /// `buffer` must be valid for the whole transfer and word aligned 542 /// `buffer` must be valid for the whole transfer and word aligned
990 unsafe fn prepare_datapath_write<T: Instance, Dma: SdmmcDma<T>>( 543 unsafe fn prepare_datapath_write(&mut self, buffer: *const [u32], length_bytes: u32, block_size: u8) {
991 &self,
992 buffer: *const [u32],
993 length_bytes: u32,
994 block_size: u8,
995 data_transfer_timeout: u32,
996 #[allow(unused_variables)] dma: &mut Dma,
997 ) {
998 assert!(block_size <= 14, "Block size up to 2^14 bytes"); 544 assert!(block_size <= 14, "Block size up to 2^14 bytes");
999 let regs = self.0; 545 let regs = T::regs();
1000 546
1001 // Command AND Data state machines must be idle 547 // Command AND Data state machines must be idle
1002 self.wait_idle(); 548 Self::wait_idle();
1003 self.clear_interrupt_flags(); 549 Self::clear_interrupt_flags();
1004 550
1005 // NOTE(unsafe) We have exclusive access to the regisers 551 // NOTE(unsafe) We have exclusive access to the regisers
1006 552
1007 regs.dtimer().write(|w| w.set_datatime(data_transfer_timeout)); 553 regs.dtimer()
554 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
1008 regs.dlenr().write(|w| w.set_datalength(length_bytes)); 555 regs.dlenr().write(|w| w.set_datalength(length_bytes));
1009 556
1010 #[cfg(sdmmc_v1)] 557 #[cfg(sdmmc_v1)]
1011 { 558 {
1012 let request = dma.request(); 559 let request = self.dma.request();
1013 dma.start_write( 560 self.dma.start_write(
1014 request, 561 request,
1015 buffer, 562 buffer,
1016 regs.fifor().ptr() as *mut u32, 563 regs.fifor().ptr() as *mut u32,
@@ -1042,8 +589,8 @@ impl SdmmcInner {
1042 } 589 }
1043 590
1044 /// Stops the DMA datapath 591 /// Stops the DMA datapath
1045 fn stop_datapath(&self) { 592 fn stop_datapath() {
1046 let regs = self.0; 593 let regs = T::regs();
1047 594
1048 unsafe { 595 unsafe {
1049 #[cfg(sdmmc_v1)] 596 #[cfg(sdmmc_v1)]
@@ -1057,8 +604,8 @@ impl SdmmcInner {
1057 } 604 }
1058 605
1059 /// Sets the CLKDIV field in CLKCR. Updates clock field in self 606 /// Sets the CLKDIV field in CLKCR. Updates clock field in self
1060 fn clkcr_set_clkdiv(&self, freq: u32, width: BusWidth, ker_ck: Hertz, clock: &mut Hertz) -> Result<(), Error> { 607 fn clkcr_set_clkdiv(&mut self, freq: u32, width: BusWidth) -> Result<(), Error> {
1061 let regs = self.0; 608 let regs = T::regs();
1062 609
1063 let width_u32 = match width { 610 let width_u32 = match width {
1064 BusWidth::One => 1u32, 611 BusWidth::One => 1u32,
@@ -1067,18 +614,19 @@ impl SdmmcInner {
1067 _ => panic!("Invalid Bus Width"), 614 _ => panic!("Invalid Bus Width"),
1068 }; 615 };
1069 616
617 let ker_ck = T::kernel_clk();
1070 let (_bypass, clkdiv, new_clock) = clk_div(ker_ck, freq)?; 618 let (_bypass, clkdiv, new_clock) = clk_div(ker_ck, freq)?;
1071 619
1072 // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7 620 // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7
1073 // Section 55.5.8 621 // Section 55.5.8
1074 let sdmmc_bus_bandwidth = new_clock.0 * width_u32; 622 let sdmmc_bus_bandwidth = new_clock.0 * width_u32;
1075 assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32); 623 assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32);
1076 *clock = new_clock; 624 self.clock = new_clock;
1077 625
1078 // NOTE(unsafe) We have exclusive access to the regblock 626 // NOTE(unsafe) We have exclusive access to the regblock
1079 unsafe { 627 unsafe {
1080 // CPSMACT and DPSMACT must be 0 to set CLKDIV 628 // CPSMACT and DPSMACT must be 0 to set CLKDIV
1081 self.wait_idle(); 629 Self::wait_idle();
1082 regs.clkcr().modify(|w| { 630 regs.clkcr().modify(|w| {
1083 w.set_clkdiv(clkdiv); 631 w.set_clkdiv(clkdiv);
1084 #[cfg(sdmmc_v1)] 632 #[cfg(sdmmc_v1)]
@@ -1094,13 +642,7 @@ impl SdmmcInner {
1094 /// Attempt to set a new signalling mode. The selected 642 /// Attempt to set a new signalling mode. The selected
1095 /// signalling mode is returned. Expects the current clock 643 /// signalling mode is returned. Expects the current clock
1096 /// frequency to be > 12.5MHz. 644 /// frequency to be > 12.5MHz.
1097 async fn switch_signalling_mode<T: Instance, Dma: SdmmcDma<T>>( 645 async fn switch_signalling_mode(&mut self, signalling: Signalling) -> Result<Signalling, Error> {
1098 &self,
1099 signalling: Signalling,
1100 waker_reg: &AtomicWaker,
1101 data_transfer_timeout: u32,
1102 dma: &mut Dma,
1103 ) -> Result<Signalling, Error> {
1104 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not 646 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
1105 // necessary" 647 // necessary"
1106 648
@@ -1117,17 +659,17 @@ impl SdmmcInner {
1117 let mut status = [0u32; 16]; 659 let mut status = [0u32; 16];
1118 660
1119 // Arm `OnDrop` after the buffer, so it will be dropped first 661 // Arm `OnDrop` after the buffer, so it will be dropped first
1120 let regs = self.0; 662 let regs = T::regs();
1121 let on_drop = OnDrop::new(|| unsafe { self.on_drop() }); 663 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
1122 664
1123 unsafe { 665 unsafe {
1124 self.prepare_datapath_read(&mut status, 64, 6, data_transfer_timeout, dma); 666 self.prepare_datapath_read(&mut status, 64, 6);
1125 self.data_interrupts(true); 667 Self::data_interrupts(true);
1126 } 668 }
1127 self.cmd(Cmd::cmd6(set_function), true)?; // CMD6 669 self.cmd(Cmd::cmd6(set_function), true)?; // CMD6
1128 670
1129 let res = poll_fn(|cx| { 671 let res = poll_fn(|cx| {
1130 waker_reg.register(cx.waker()); 672 T::state().register(cx.waker());
1131 let status = unsafe { regs.star().read() }; 673 let status = unsafe { regs.star().read() };
1132 674
1133 if status.dcrcfail() { 675 if status.dcrcfail() {
@@ -1140,7 +682,7 @@ impl SdmmcInner {
1140 Poll::Pending 682 Poll::Pending
1141 }) 683 })
1142 .await; 684 .await;
1143 self.clear_interrupt_flags(); 685 Self::clear_interrupt_flags();
1144 686
1145 // Host is allowed to use the new functions at least 8 687 // Host is allowed to use the new functions at least 8
1146 // clocks after the end of the switch command 688 // clocks after the end of the switch command
@@ -1153,7 +695,7 @@ impl SdmmcInner {
1153 match res { 695 match res {
1154 Ok(_) => { 696 Ok(_) => {
1155 on_drop.defuse(); 697 on_drop.defuse();
1156 self.stop_datapath(); 698 Self::stop_datapath();
1157 699
1158 // Function Selection of Function Group 1 700 // Function Selection of Function Group 1
1159 let selection = (u32::from_be(status[4]) >> 24) & 0xF; 701 let selection = (u32::from_be(status[4]) >> 24) & 0xF;
@@ -1173,7 +715,7 @@ impl SdmmcInner {
1173 715
1174 /// Query the card status (CMD13, returns R1) 716 /// Query the card status (CMD13, returns R1)
1175 fn read_status(&self, card: &Card) -> Result<CardStatus, Error> { 717 fn read_status(&self, card: &Card) -> Result<CardStatus, Error> {
1176 let regs = self.0; 718 let regs = T::regs();
1177 let rca = card.rca; 719 let rca = card.rca;
1178 720
1179 self.cmd(Cmd::card_status(rca << 16), false)?; // CMD13 721 self.cmd(Cmd::card_status(rca << 16), false)?; // CMD13
@@ -1184,31 +726,27 @@ impl SdmmcInner {
1184 } 726 }
1185 727
1186 /// Reads the SD Status (ACMD13) 728 /// Reads the SD Status (ACMD13)
1187 async fn read_sd_status<T: Instance, Dma: SdmmcDma<T>>( 729 async fn read_sd_status(&mut self) -> Result<(), Error> {
1188 &self, 730 let card = self.card.as_mut().ok_or(Error::NoCard)?;
1189 card: &mut Card,
1190 waker_reg: &AtomicWaker,
1191 data_transfer_timeout: u32,
1192 dma: &mut Dma,
1193 ) -> Result<(), Error> {
1194 let rca = card.rca; 731 let rca = card.rca;
732
1195 self.cmd(Cmd::set_block_length(64), false)?; // CMD16 733 self.cmd(Cmd::set_block_length(64), false)?; // CMD16
1196 self.cmd(Cmd::app_cmd(rca << 16), false)?; // APP 734 self.cmd(Cmd::app_cmd(rca << 16), false)?; // APP
1197 735
1198 let mut status = [0u32; 16]; 736 let mut status = [0u32; 16];
1199 737
1200 // Arm `OnDrop` after the buffer, so it will be dropped first 738 // Arm `OnDrop` after the buffer, so it will be dropped first
1201 let regs = self.0; 739 let regs = T::regs();
1202 let on_drop = OnDrop::new(|| unsafe { self.on_drop() }); 740 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
1203 741
1204 unsafe { 742 unsafe {
1205 self.prepare_datapath_read(&mut status, 64, 6, data_transfer_timeout, dma); 743 self.prepare_datapath_read(&mut status, 64, 6);
1206 self.data_interrupts(true); 744 Self::data_interrupts(true);
1207 } 745 }
1208 self.cmd(Cmd::card_status(0), true)?; 746 self.cmd(Cmd::card_status(0), true)?;
1209 747
1210 let res = poll_fn(|cx| { 748 let res = poll_fn(|cx| {
1211 waker_reg.register(cx.waker()); 749 T::state().register(cx.waker());
1212 let status = unsafe { regs.star().read() }; 750 let status = unsafe { regs.star().read() };
1213 751
1214 if status.dcrcfail() { 752 if status.dcrcfail() {
@@ -1221,16 +759,16 @@ impl SdmmcInner {
1221 Poll::Pending 759 Poll::Pending
1222 }) 760 })
1223 .await; 761 .await;
1224 self.clear_interrupt_flags(); 762 Self::clear_interrupt_flags();
1225 763
1226 if res.is_ok() { 764 if res.is_ok() {
1227 on_drop.defuse(); 765 on_drop.defuse();
1228 self.stop_datapath(); 766 Self::stop_datapath();
1229 767
1230 for byte in status.iter_mut() { 768 for byte in status.iter_mut() {
1231 *byte = u32::from_be(*byte); 769 *byte = u32::from_be(*byte);
1232 } 770 }
1233 card.status = status.into(); 771 self.card.as_mut().unwrap().status = status.into();
1234 } 772 }
1235 res 773 res
1236 } 774 }
@@ -1252,8 +790,8 @@ impl SdmmcInner {
1252 790
1253 /// Clear flags in interrupt clear register 791 /// Clear flags in interrupt clear register
1254 #[inline(always)] 792 #[inline(always)]
1255 fn clear_interrupt_flags(&self) { 793 fn clear_interrupt_flags() {
1256 let regs = self.0; 794 let regs = T::regs();
1257 // NOTE(unsafe) Atomic write 795 // NOTE(unsafe) Atomic write
1258 unsafe { 796 unsafe {
1259 regs.icr().write(|w| { 797 regs.icr().write(|w| {
@@ -1287,8 +825,8 @@ impl SdmmcInner {
1287 825
1288 /// Enables the interrupts for data transfer 826 /// Enables the interrupts for data transfer
1289 #[inline(always)] 827 #[inline(always)]
1290 fn data_interrupts(&self, enable: bool) { 828 fn data_interrupts(enable: bool) {
1291 let regs = self.0; 829 let regs = T::regs();
1292 // NOTE(unsafe) Atomic write 830 // NOTE(unsafe) Atomic write
1293 unsafe { 831 unsafe {
1294 regs.maskr().write(|w| { 832 regs.maskr().write(|w| {
@@ -1302,13 +840,7 @@ impl SdmmcInner {
1302 } 840 }
1303 } 841 }
1304 842
1305 async fn get_scr<T: Instance, Dma: SdmmcDma<T>>( 843 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
1306 &self,
1307 card: &mut Card,
1308 waker_reg: &AtomicWaker,
1309 data_transfer_timeout: u32,
1310 dma: &mut Dma,
1311 ) -> Result<(), Error> {
1312 // Read the the 64-bit SCR register 844 // Read the the 64-bit SCR register
1313 self.cmd(Cmd::set_block_length(8), false)?; // CMD16 845 self.cmd(Cmd::set_block_length(8), false)?; // CMD16
1314 self.cmd(Cmd::app_cmd(card.rca << 16), false)?; 846 self.cmd(Cmd::app_cmd(card.rca << 16), false)?;
@@ -1316,17 +848,17 @@ impl SdmmcInner {
1316 let mut scr = [0u32; 2]; 848 let mut scr = [0u32; 2];
1317 849
1318 // Arm `OnDrop` after the buffer, so it will be dropped first 850 // Arm `OnDrop` after the buffer, so it will be dropped first
1319 let regs = self.0; 851 let regs = T::regs();
1320 let on_drop = OnDrop::new(move || unsafe { self.on_drop() }); 852 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
1321 853
1322 unsafe { 854 unsafe {
1323 self.prepare_datapath_read(&mut scr[..], 8, 3, data_transfer_timeout, dma); 855 self.prepare_datapath_read(&mut scr[..], 8, 3);
1324 self.data_interrupts(true); 856 Self::data_interrupts(true);
1325 } 857 }
1326 self.cmd(Cmd::cmd51(), true)?; 858 self.cmd(Cmd::cmd51(), true)?;
1327 859
1328 let res = poll_fn(|cx| { 860 let res = poll_fn(|cx| {
1329 waker_reg.register(cx.waker()); 861 T::state().register(cx.waker());
1330 let status = unsafe { regs.star().read() }; 862 let status = unsafe { regs.star().read() };
1331 863
1332 if status.dcrcfail() { 864 if status.dcrcfail() {
@@ -1339,11 +871,11 @@ impl SdmmcInner {
1339 Poll::Pending 871 Poll::Pending
1340 }) 872 })
1341 .await; 873 .await;
1342 self.clear_interrupt_flags(); 874 Self::clear_interrupt_flags();
1343 875
1344 if res.is_ok() { 876 if res.is_ok() {
1345 on_drop.defuse(); 877 on_drop.defuse();
1346 self.stop_datapath(); 878 Self::stop_datapath();
1347 879
1348 unsafe { 880 unsafe {
1349 let scr_bytes = &*(&scr as *const [u32; 2] as *const [u8; 8]); 881 let scr_bytes = &*(&scr as *const [u32; 2] as *const [u8; 8]);
@@ -1356,13 +888,13 @@ impl SdmmcInner {
1356 /// Send command to card 888 /// Send command to card
1357 #[allow(unused_variables)] 889 #[allow(unused_variables)]
1358 fn cmd(&self, cmd: Cmd, data: bool) -> Result<(), Error> { 890 fn cmd(&self, cmd: Cmd, data: bool) -> Result<(), Error> {
1359 let regs = self.0; 891 let regs = T::regs();
1360 892
1361 self.clear_interrupt_flags(); 893 Self::clear_interrupt_flags();
1362 // NOTE(safety) Atomic operations 894 // NOTE(safety) Atomic operations
1363 unsafe { 895 unsafe {
1364 // CP state machine must be idle 896 // CP state machine must be idle
1365 while self.cmd_active() {} 897 while Self::cmd_active() {}
1366 898
1367 // Command arg 899 // Command arg
1368 regs.argr().write(|w| w.set_cmdarg(cmd.arg)); 900 regs.argr().write(|w| w.set_cmdarg(cmd.arg));
@@ -1411,13 +943,13 @@ impl SdmmcInner {
1411 /// # Safety 943 /// # Safety
1412 /// 944 ///
1413 /// Ensure that `regs` has exclusive access to the regblocks 945 /// Ensure that `regs` has exclusive access to the regblocks
1414 unsafe fn on_drop(&self) { 946 unsafe fn on_drop() {
1415 let regs = self.0; 947 let regs = T::regs();
1416 if self.data_active() { 948 if Self::data_active() {
1417 self.clear_interrupt_flags(); 949 Self::clear_interrupt_flags();
1418 // Send abort 950 // Send abort
1419 // CP state machine must be idle 951 // CP state machine must be idle
1420 while self.cmd_active() {} 952 while Self::cmd_active() {}
1421 953
1422 // Command arg 954 // Command arg
1423 regs.argr().write(|w| w.set_cmdarg(0)); 955 regs.argr().write(|w| w.set_cmdarg(0));
@@ -1437,11 +969,320 @@ impl SdmmcInner {
1437 }); 969 });
1438 970
1439 // Wait for the abort 971 // Wait for the abort
1440 while self.data_active() {} 972 while Self::data_active() {}
1441 } 973 }
1442 self.data_interrupts(false); 974 Self::data_interrupts(false);
1443 self.clear_interrupt_flags(); 975 Self::clear_interrupt_flags();
1444 self.stop_datapath(); 976 Self::stop_datapath();
977 }
978
979 /// Initializes card (if present) and sets the bus at the
980 /// specified frequency.
981 pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> {
982 let regs = T::regs();
983 let ker_ck = T::kernel_clk();
984
985 let bus_width = match self.d3.is_some() {
986 true => BusWidth::Four,
987 false => BusWidth::One,
988 };
989
990 // NOTE(unsafe) We have exclusive access to the peripheral
991 unsafe {
992 // While the SD/SDIO card or eMMC is in identification mode,
993 // the SDMMC_CK frequency must be no more than 400 kHz.
994 let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0));
995 self.clock = init_clock;
996
997 // CPSMACT and DPSMACT must be 0 to set WIDBUS
998 Self::wait_idle();
999
1000 regs.clkcr().modify(|w| {
1001 w.set_widbus(0);
1002 w.set_clkdiv(clkdiv);
1003 #[cfg(sdmmc_v1)]
1004 w.set_bypass(_bypass);
1005 });
1006
1007 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
1008 self.cmd(Cmd::idle(), false)?;
1009
1010 // Check if cards supports CMD8 (with pattern)
1011 self.cmd(Cmd::hs_send_ext_csd(0x1AA), false)?;
1012 let r1 = regs.respr(0).read().cardstatus();
1013
1014 let mut card = if r1 == 0x1AA {
1015 // Card echoed back the pattern. Must be at least v2
1016 Card::default()
1017 } else {
1018 return Err(Error::UnsupportedCardVersion);
1019 };
1020
1021 let ocr = loop {
1022 // Signal that next command is a app command
1023 self.cmd(Cmd::app_cmd(0), false)?; // CMD55
1024
1025 let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32
1026 | CmdAppOper::HIGH_CAPACITY as u32
1027 | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32;
1028
1029 // Initialize card
1030 match self.cmd(Cmd::app_op_cmd(arg), false) {
1031 // ACMD41
1032 Ok(_) => (),
1033 Err(Error::Crc) => (),
1034 Err(err) => return Err(err),
1035 }
1036 let ocr: OCR = regs.respr(0).read().cardstatus().into();
1037 if !ocr.is_busy() {
1038 // Power up done
1039 break ocr;
1040 }
1041 };
1042
1043 if ocr.high_capacity() {
1044 // Card is SDHC or SDXC or SDUC
1045 card.card_type = CardCapacity::SDHC;
1046 } else {
1047 card.card_type = CardCapacity::SDSC;
1048 }
1049 card.ocr = ocr;
1050
1051 self.cmd(Cmd::all_send_cid(), false)?; // CMD2
1052 let cid0 = regs.respr(0).read().cardstatus() as u128;
1053 let cid1 = regs.respr(1).read().cardstatus() as u128;
1054 let cid2 = regs.respr(2).read().cardstatus() as u128;
1055 let cid3 = regs.respr(3).read().cardstatus() as u128;
1056 let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3);
1057 card.cid = cid.into();
1058
1059 self.cmd(Cmd::send_rel_addr(), false)?;
1060 card.rca = regs.respr(0).read().cardstatus() >> 16;
1061
1062 self.cmd(Cmd::send_csd(card.rca << 16), false)?;
1063 let csd0 = regs.respr(0).read().cardstatus() as u128;
1064 let csd1 = regs.respr(1).read().cardstatus() as u128;
1065 let csd2 = regs.respr(2).read().cardstatus() as u128;
1066 let csd3 = regs.respr(3).read().cardstatus() as u128;
1067 let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3);
1068 card.csd = csd.into();
1069
1070 self.select_card(Some(&card))?;
1071
1072 self.get_scr(&mut card).await?;
1073
1074 // Set bus width
1075 let (width, acmd_arg) = match bus_width {
1076 BusWidth::Eight => unimplemented!(),
1077 BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2),
1078 _ => (BusWidth::One, 0),
1079 };
1080 self.cmd(Cmd::app_cmd(card.rca << 16), false)?;
1081 self.cmd(Cmd::cmd6(acmd_arg), false)?;
1082
1083 // CPSMACT and DPSMACT must be 0 to set WIDBUS
1084 Self::wait_idle();
1085
1086 regs.clkcr().modify(|w| {
1087 w.set_widbus(match width {
1088 BusWidth::One => 0,
1089 BusWidth::Four => 1,
1090 BusWidth::Eight => 2,
1091 _ => panic!("Invalid Bus Width"),
1092 })
1093 });
1094
1095 // Set Clock
1096 if freq.0 <= 25_000_000 {
1097 // Final clock frequency
1098 self.clkcr_set_clkdiv(freq.0, width)?;
1099 } else {
1100 // Switch to max clock for SDR12
1101 self.clkcr_set_clkdiv(25_000_000, width)?;
1102 }
1103
1104 self.card = Some(card);
1105
1106 // Read status
1107 self.read_sd_status().await?;
1108
1109 if freq.0 > 25_000_000 {
1110 // Switch to SDR25
1111 self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?;
1112
1113 if self.signalling == Signalling::SDR25 {
1114 // Set final clock frequency
1115 self.clkcr_set_clkdiv(freq.0, width)?;
1116
1117 if self.read_status(&card)?.state() != CurrentState::Transfer {
1118 return Err(Error::SignalingSwitchFailed);
1119 }
1120 }
1121 }
1122 // Read status after signalling change
1123 self.read_sd_status().await?;
1124 }
1125
1126 Ok(())
1127 }
1128
1129 #[inline(always)]
1130 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
1131 let card_capacity = self.card()?.card_type;
1132
1133 // NOTE(unsafe) DataBlock uses align 4
1134 let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) };
1135
1136 // Always read 1 block of 512 bytes
1137 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1138 let address = match card_capacity {
1139 CardCapacity::SDSC => block_idx * 512,
1140 _ => block_idx,
1141 };
1142 self.cmd(Cmd::set_block_length(512), false)?; // CMD16
1143
1144 let regs = T::regs();
1145 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
1146
1147 unsafe {
1148 self.prepare_datapath_read(buffer, 512, 9);
1149 Self::data_interrupts(true);
1150 }
1151 self.cmd(Cmd::read_single_block(address), true)?;
1152
1153 let res = poll_fn(|cx| {
1154 T::state().register(cx.waker());
1155 let status = unsafe { regs.star().read() };
1156
1157 if status.dcrcfail() {
1158 return Poll::Ready(Err(Error::Crc));
1159 } else if status.dtimeout() {
1160 return Poll::Ready(Err(Error::Timeout));
1161 } else if status.dataend() {
1162 return Poll::Ready(Ok(()));
1163 }
1164 Poll::Pending
1165 })
1166 .await;
1167 Self::clear_interrupt_flags();
1168
1169 if res.is_ok() {
1170 on_drop.defuse();
1171 Self::stop_datapath();
1172 }
1173 res
1174 }
1175
1176 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> {
1177 let card = self.card.as_mut().ok_or(Error::NoCard)?;
1178
1179 // NOTE(unsafe) DataBlock uses align 4
1180 let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) };
1181
1182 // Always read 1 block of 512 bytes
1183 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1184 let address = match card.card_type {
1185 CardCapacity::SDSC => block_idx * 512,
1186 _ => block_idx,
1187 };
1188 self.cmd(Cmd::set_block_length(512), false)?; // CMD16
1189
1190 let regs = T::regs();
1191 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
1192
1193 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
1194 #[cfg(sdmmc_v1)]
1195 self.cmd(Cmd::write_single_block(address), true)?;
1196
1197 unsafe {
1198 self.prepare_datapath_write(buffer as *const [u32; 128], 512, 9);
1199 Self::data_interrupts(true);
1200 }
1201
1202 #[cfg(sdmmc_v2)]
1203 self.cmd(Cmd::write_single_block(address), true)?;
1204
1205 let res = poll_fn(|cx| {
1206 T::state().register(cx.waker());
1207 let status = unsafe { regs.star().read() };
1208
1209 if status.dcrcfail() {
1210 return Poll::Ready(Err(Error::Crc));
1211 } else if status.dtimeout() {
1212 return Poll::Ready(Err(Error::Timeout));
1213 } else if status.dataend() {
1214 return Poll::Ready(Ok(()));
1215 }
1216 Poll::Pending
1217 })
1218 .await;
1219 Self::clear_interrupt_flags();
1220
1221 match res {
1222 Ok(_) => {
1223 on_drop.defuse();
1224 Self::stop_datapath();
1225
1226 // TODO: Make this configurable
1227 let mut timeout: u32 = 0x00FF_FFFF;
1228
1229 // Try to read card status (ACMD13)
1230 while timeout > 0 {
1231 match self.read_sd_status().await {
1232 Ok(_) => return Ok(()),
1233 Err(Error::Timeout) => (), // Try again
1234 Err(e) => return Err(e),
1235 }
1236 timeout -= 1;
1237 }
1238 Err(Error::SoftwareTimeout)
1239 }
1240 Err(e) => Err(e),
1241 }
1242 }
1243
1244 /// Get a reference to the initialized card
1245 ///
1246 /// # Errors
1247 ///
1248 /// Returns Error::NoCard if [`init_card`](#method.init_card)
1249 /// has not previously succeeded
1250 #[inline(always)]
1251 pub fn card(&self) -> Result<&Card, Error> {
1252 self.card.as_ref().ok_or(Error::NoCard)
1253 }
1254
1255 /// Get the current SDMMC bus clock
1256 pub fn clock(&self) -> Hertz {
1257 self.clock
1258 }
1259
1260 #[inline(always)]
1261 fn on_interrupt(_: *mut ()) {
1262 Self::data_interrupts(false);
1263 T::state().wake();
1264 }
1265}
1266
1267impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> {
1268 fn drop(&mut self) {
1269 self.irq.disable();
1270 unsafe { Self::on_drop() };
1271
1272 critical_section::with(|_| unsafe {
1273 self.clk.set_as_disconnected();
1274 self.cmd.set_as_disconnected();
1275 self.d0.set_as_disconnected();
1276 if let Some(x) = &mut self.d1 {
1277 x.set_as_disconnected();
1278 }
1279 if let Some(x) = &mut self.d2 {
1280 x.set_as_disconnected();
1281 }
1282 if let Some(x) = &mut self.d3 {
1283 x.set_as_disconnected();
1284 }
1285 });
1445 } 1286 }
1446} 1287}
1447 1288
@@ -1540,7 +1381,7 @@ pub(crate) mod sealed {
1540 pub trait Instance { 1381 pub trait Instance {
1541 type Interrupt: Interrupt; 1382 type Interrupt: Interrupt;
1542 1383
1543 fn inner() -> SdmmcInner; 1384 fn regs() -> RegBlock;
1544 fn state() -> &'static AtomicWaker; 1385 fn state() -> &'static AtomicWaker;
1545 fn kernel_clk() -> Hertz; 1386 fn kernel_clk() -> Hertz;
1546 } 1387 }
@@ -1629,9 +1470,8 @@ foreach_peripheral!(
1629 impl sealed::Instance for peripherals::$inst { 1470 impl sealed::Instance for peripherals::$inst {
1630 type Interrupt = crate::interrupt::$inst; 1471 type Interrupt = crate::interrupt::$inst;
1631 1472
1632 fn inner() -> SdmmcInner { 1473 fn regs() -> RegBlock {
1633 const INNER: SdmmcInner = SdmmcInner(crate::pac::$inst); 1474 crate::pac::$inst
1634 INNER
1635 } 1475 }
1636 1476
1637 fn state() -> &'static ::embassy_sync::waitqueue::AtomicWaker { 1477 fn state() -> &'static ::embassy_sync::waitqueue::AtomicWaker {