aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Lazarev <[email protected]>2025-03-25 06:29:16 -0700
committerAnton Lazarev <[email protected]>2025-03-31 12:47:41 -0700
commit5325f1d911753e76a6b56d7747b816d24a7eb172 (patch)
tree3a29c25230e88c1f301a83d781e70dc03074160e
parent14bb4ee9e414137f318f64e82d808d4012e30680 (diff)
scaffold eMMC support
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs710
1 files changed, 395 insertions, 315 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index a28fd51e8..6dbb524b7 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -10,11 +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::{ 13use sdio_host::common_cmd::{self, Resp, ResponseLen};
14 common_cmd::{self, Resp, ResponseLen}, 14use sdio_host::emmc::{ExtCSD, EMMC};
15 sd::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CIC, CID, CSD, OCR, RCA, SCR, SD}, 15use sdio_host::sd::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CIC, CID, CSD, OCR, RCA, SCR, SD};
16 sd_cmd, Cmd, 16use sdio_host::{sd_cmd, Cmd};
17};
18 17
19#[cfg(sdmmc_v1)] 18#[cfg(sdmmc_v1)]
20use crate::dma::ChannelAndRequest; 19use crate::dma::ChannelAndRequest;
@@ -174,12 +173,21 @@ pub struct Card {
174 pub status: SDStatus, 173 pub status: SDStatus,
175} 174}
176 175
177impl Card { 176#[derive(Clone, Copy, Debug, Default)]
178 /// Size in bytes 177/// eMMC storage
179 pub fn size(&self) -> u64 { 178pub struct Emmc {
180 // SDHC / SDXC / SDUC 179 /// The capacity of this card
181 u64::from(self.csd.block_count()) * 512 180 pub capacity: CardCapacity,
182 } 181 /// Operation Conditions Register
182 pub ocr: OCR<EMMC>,
183 /// Relative Card Address
184 pub rca: u16,
185 /// Card ID
186 pub cid: CID<EMMC>,
187 /// Card Specific Data
188 pub csd: CSD<EMMC>,
189 /// Extended Card Specific Data
190 pub ext_csd: ExtCSD,
183} 191}
184 192
185#[repr(u8)] 193#[repr(u8)]
@@ -290,6 +298,61 @@ impl Default for Config {
290 } 298 }
291} 299}
292 300
301/// Peripheral that can be operated over SDMMC
302#[derive(Clone, Copy, Debug)]
303pub enum SdmmcPeripheral {
304 /// SD Card
305 SdCard(Card),
306 /// eMMC memory
307 Emmc(Emmc),
308}
309
310impl SdmmcPeripheral {
311 /// Get this peripheral's address on the SDMMC bus
312 fn get_address(&self) -> u16 {
313 match self {
314 Self::SdCard(c) => c.rca,
315 Self::Emmc(e) => e.rca,
316 }
317 }
318 /// Is this a standard or high capacity peripheral?
319 fn get_capacity(&self) -> CardCapacity {
320 match self {
321 Self::SdCard(c) => c.card_type,
322 Self::Emmc(e) => e.capacity,
323 }
324 }
325 /// Size in bytes
326 fn size(&self) -> u64 {
327 match self {
328 // SDHC / SDXC / SDUC
329 Self::SdCard(c) => u64::from(c.csd.block_count()) * 512,
330 // capacity > 2GB
331 Self::Emmc(e) => u64::from(e.ext_csd.sector_count()) * 512,
332 }
333 }
334
335 /// Get a mutable reference to the SD Card.
336 ///
337 /// Panics if there is another peripheral instead.
338 fn get_sd_card(&mut self) -> &mut Card {
339 match *self {
340 Self::SdCard(ref mut c) => c,
341 _ => unreachable!("SD only"),
342 }
343 }
344
345 /// Get a mutable reference to the eMMC.
346 ///
347 /// Panics if there is another peripheral instead.
348 fn get_emmc(&mut self) -> &mut Emmc {
349 match *self {
350 Self::Emmc(ref mut e) => e,
351 _ => unreachable!("eMMC only"),
352 }
353 }
354}
355
293/// Sdmmc device 356/// Sdmmc device
294pub struct Sdmmc<'d, T: Instance> { 357pub struct Sdmmc<'d, T: Instance> {
295 _peri: Peri<'d, T>, 358 _peri: Peri<'d, T>,
@@ -309,7 +372,7 @@ pub struct Sdmmc<'d, T: Instance> {
309 /// Current signalling scheme to card 372 /// Current signalling scheme to card
310 signalling: Signalling, 373 signalling: Signalling,
311 /// Card 374 /// Card
312 card: Option<Card>, 375 card: Option<SdmmcPeripheral>,
313 376
314 /// An optional buffer to be used for commands 377 /// An optional buffer to be used for commands
315 /// This should be used if there are special memory location requirements for dma 378 /// This should be used if there are special memory location requirements for dma
@@ -662,101 +725,13 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
662 Ok(()) 725 Ok(())
663 } 726 }
664 727
665 /// Switch mode using CMD6.
666 ///
667 /// Attempt to set a new signalling mode. The selected
668 /// signalling mode is returned. Expects the current clock
669 /// frequency to be > 12.5MHz.
670 async fn switch_signalling_mode(&mut self, signalling: Signalling) -> Result<Signalling, Error> {
671 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
672 // necessary"
673
674 let set_function = 0x8000_0000
675 | match signalling {
676 // See PLSS v7_10 Table 4-11
677 Signalling::DDR50 => 0xFF_FF04,
678 Signalling::SDR104 => 0xFF_1F03,
679 Signalling::SDR50 => 0xFF_1F02,
680 Signalling::SDR25 => 0xFF_FF01,
681 Signalling::SDR12 => 0xFF_FF00,
682 };
683
684 let status = match self.cmd_block.as_deref_mut() {
685 Some(x) => x,
686 None => &mut CmdBlock::new(),
687 };
688
689 // Arm `OnDrop` after the buffer, so it will be dropped first
690 let regs = T::regs();
691 let on_drop = OnDrop::new(|| Self::on_drop());
692
693 let transfer = Self::prepare_datapath_read(
694 &self.config,
695 #[cfg(sdmmc_v1)]
696 &mut self.dma,
697 status.as_mut(),
698 64,
699 6,
700 );
701 InterruptHandler::<T>::data_interrupts(true);
702 Self::cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
703
704 let res = poll_fn(|cx| {
705 T::state().register(cx.waker());
706 let status = regs.star().read();
707
708 if status.dcrcfail() {
709 return Poll::Ready(Err(Error::Crc));
710 }
711 if status.dtimeout() {
712 return Poll::Ready(Err(Error::Timeout));
713 }
714 #[cfg(sdmmc_v1)]
715 if status.stbiterr() {
716 return Poll::Ready(Err(Error::StBitErr));
717 }
718 if status.dataend() {
719 return Poll::Ready(Ok(()));
720 }
721 Poll::Pending
722 })
723 .await;
724 Self::clear_interrupt_flags();
725
726 // Host is allowed to use the new functions at least 8
727 // clocks after the end of the switch command
728 // transaction. We know the current clock period is < 80ns,
729 // so a total delay of 640ns is required here
730 for _ in 0..300 {
731 cortex_m::asm::nop();
732 }
733
734 match res {
735 Ok(_) => {
736 on_drop.defuse();
737 Self::stop_datapath();
738 drop(transfer);
739
740 // Function Selection of Function Group 1
741 let selection = (u32::from_be(status[4]) >> 24) & 0xF;
742
743 match selection {
744 0 => Ok(Signalling::SDR12),
745 1 => Ok(Signalling::SDR25),
746 2 => Ok(Signalling::SDR50),
747 3 => Ok(Signalling::SDR104),
748 4 => Ok(Signalling::DDR50),
749 _ => Err(Error::UnsupportedCardType),
750 }
751 }
752 Err(e) => Err(e),
753 }
754 }
755
756 /// Query the card status (CMD13, returns R1) 728 /// Query the card status (CMD13, returns R1)
757 fn read_status(&self, card: &Card) -> Result<CardStatus<SD>, Error> { 729 fn read_status<Ext>(&self, card: &SdmmcPeripheral) -> Result<CardStatus<Ext>, Error>
730 where
731 CardStatus<Ext>: From<u32>,
732 {
758 let regs = T::regs(); 733 let regs = T::regs();
759 let rca = card.rca; 734 let rca = card.get_address();
760 735
761 Self::cmd(common_cmd::card_status(rca, false), false)?; // CMD13 736 Self::cmd(common_cmd::card_status(rca, false), false)?; // CMD13
762 737
@@ -764,78 +739,13 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
764 Ok(r1.into()) 739 Ok(r1.into())
765 } 740 }
766 741
767 /// Reads the SD Status (ACMD13)
768 async fn read_sd_status(&mut self) -> Result<(), Error> {
769 let card = self.card.as_mut().ok_or(Error::NoCard)?;
770 let rca = card.rca;
771
772 let cmd_block = match self.cmd_block.as_deref_mut() {
773 Some(x) => x,
774 None => &mut CmdBlock::new(),
775 };
776
777 Self::cmd(common_cmd::set_block_length(64), false)?; // CMD16
778 Self::cmd(common_cmd::app_cmd(rca), false)?; // APP
779
780 let status = cmd_block;
781
782 // Arm `OnDrop` after the buffer, so it will be dropped first
783 let regs = T::regs();
784 let on_drop = OnDrop::new(|| Self::on_drop());
785
786 let transfer = Self::prepare_datapath_read(
787 &self.config,
788 #[cfg(sdmmc_v1)]
789 &mut self.dma,
790 status.as_mut(),
791 64,
792 6,
793 );
794 InterruptHandler::<T>::data_interrupts(true);
795 Self::cmd(sd_cmd::sd_status(), true)?;
796
797 let res = poll_fn(|cx| {
798 T::state().register(cx.waker());
799 let status = regs.star().read();
800
801 if status.dcrcfail() {
802 return Poll::Ready(Err(Error::Crc));
803 }
804 if status.dtimeout() {
805 return Poll::Ready(Err(Error::Timeout));
806 }
807 #[cfg(sdmmc_v1)]
808 if status.stbiterr() {
809 return Poll::Ready(Err(Error::StBitErr));
810 }
811 if status.dataend() {
812 return Poll::Ready(Ok(()));
813 }
814 Poll::Pending
815 })
816 .await;
817 Self::clear_interrupt_flags();
818
819 if res.is_ok() {
820 on_drop.defuse();
821 Self::stop_datapath();
822 drop(transfer);
823
824 for byte in status.iter_mut() {
825 *byte = u32::from_be(*byte);
826 }
827 self.card.as_mut().unwrap().status = status.0.into();
828 }
829 res
830 }
831
832 /// Select one card and place it into the _Tranfer State_ 742 /// Select one card and place it into the _Tranfer State_
833 /// 743 ///
834 /// If `None` is specifed for `card`, all cards are put back into 744 /// If `None` is specifed for `card`, all cards are put back into
835 /// _Stand-by State_ 745 /// _Stand-by State_
836 fn select_card(&self, card: Option<&Card>) -> Result<(), Error> { 746 fn select_card(&self, rca: Option<u16>) -> Result<(), Error> {
837 // Determine Relative Card Address (RCA) of given card 747 // Determine Relative Card Address (RCA) of given card
838 let rca = card.map(|c| c.rca).unwrap_or(0); 748 let rca = rca.unwrap_or(0);
839 749
840 let r = Self::cmd(common_cmd::select_card(rca), false); 750 let r = Self::cmd(common_cmd::select_card(rca), false);
841 match (r, rca) { 751 match (r, rca) {
@@ -878,67 +788,6 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
878 }); 788 });
879 } 789 }
880 790
881 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
882 // Read the 64-bit SCR register
883 Self::cmd(common_cmd::set_block_length(8), false)?; // CMD16
884 Self::cmd(common_cmd::app_cmd(card.rca), false)?;
885
886 let cmd_block = match self.cmd_block.as_deref_mut() {
887 Some(x) => x,
888 None => &mut CmdBlock::new(),
889 };
890 let scr = &mut cmd_block.0[..2];
891
892 // Arm `OnDrop` after the buffer, so it will be dropped first
893 let regs = T::regs();
894 let on_drop = OnDrop::new(|| Self::on_drop());
895
896 let transfer = Self::prepare_datapath_read(
897 &self.config,
898 #[cfg(sdmmc_v1)]
899 &mut self.dma,
900 scr,
901 8,
902 3,
903 );
904 InterruptHandler::<T>::data_interrupts(true);
905 Self::cmd(sd_cmd::send_scr(), true)?;
906
907 let res = poll_fn(|cx| {
908 T::state().register(cx.waker());
909 let status = regs.star().read();
910
911 if status.dcrcfail() {
912 return Poll::Ready(Err(Error::Crc));
913 }
914 if status.dtimeout() {
915 return Poll::Ready(Err(Error::Timeout));
916 }
917 #[cfg(sdmmc_v1)]
918 if status.stbiterr() {
919 return Poll::Ready(Err(Error::StBitErr));
920 }
921 if status.dataend() {
922 return Poll::Ready(Ok(()));
923 }
924 Poll::Pending
925 })
926 .await;
927 Self::clear_interrupt_flags();
928
929 if res.is_ok() {
930 on_drop.defuse();
931 Self::stop_datapath();
932 drop(transfer);
933
934 unsafe {
935 let scr_bytes = &*(&scr as *const _ as *const [u8; 8]);
936 card.scr = SCR(u64::from_be_bytes(*scr_bytes));
937 }
938 }
939 res
940 }
941
942 /// Send command to card 791 /// Send command to card
943 #[allow(unused_variables)] 792 #[allow(unused_variables)]
944 fn cmd<R: Resp>(cmd: Cmd<R>, data: bool) -> Result<(), Error> { 793 fn cmd<R: Resp>(cmd: Cmd<R>, data: bool) -> Result<(), Error> {
@@ -1024,6 +873,170 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1024 Self::stop_datapath(); 873 Self::stop_datapath();
1025 } 874 }
1026 875
876 /// Read a data block.
877 #[inline]
878 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
879 let card_capacity = self.card()?.get_capacity();
880
881 // NOTE(unsafe) DataBlock uses align 4
882 let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) };
883
884 // Always read 1 block of 512 bytes
885 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
886 let address = match card_capacity {
887 CardCapacity::StandardCapacity => block_idx * 512,
888 _ => block_idx,
889 };
890 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
891
892 let regs = T::regs();
893 let on_drop = OnDrop::new(|| Self::on_drop());
894
895 let transfer = Self::prepare_datapath_read(
896 &self.config,
897 #[cfg(sdmmc_v1)]
898 &mut self.dma,
899 buffer,
900 512,
901 9,
902 );
903 InterruptHandler::<T>::data_interrupts(true);
904 Self::cmd(common_cmd::read_single_block(address), true)?;
905
906 let res = poll_fn(|cx| {
907 T::state().register(cx.waker());
908 let status = regs.star().read();
909
910 if status.dcrcfail() {
911 return Poll::Ready(Err(Error::Crc));
912 }
913 if status.dtimeout() {
914 return Poll::Ready(Err(Error::Timeout));
915 }
916 #[cfg(sdmmc_v1)]
917 if status.stbiterr() {
918 return Poll::Ready(Err(Error::StBitErr));
919 }
920 if status.dataend() {
921 return Poll::Ready(Ok(()));
922 }
923 Poll::Pending
924 })
925 .await;
926 Self::clear_interrupt_flags();
927
928 if res.is_ok() {
929 on_drop.defuse();
930 Self::stop_datapath();
931 drop(transfer);
932 }
933 res
934 }
935
936 /// Write a data block.
937 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> {
938 let card = self.card.as_mut().ok_or(Error::NoCard)?;
939
940 // NOTE(unsafe) DataBlock uses align 4
941 let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) };
942
943 // Always read 1 block of 512 bytes
944 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
945 let address = match card.get_capacity() {
946 CardCapacity::StandardCapacity => block_idx * 512,
947 _ => block_idx,
948 };
949 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
950
951 let regs = T::regs();
952 let on_drop = OnDrop::new(|| Self::on_drop());
953
954 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
955 #[cfg(sdmmc_v1)]
956 Self::cmd(common_cmd::write_single_block(address), true)?;
957
958 let transfer = self.prepare_datapath_write(buffer, 512, 9);
959 InterruptHandler::<T>::data_interrupts(true);
960
961 #[cfg(sdmmc_v2)]
962 Self::cmd(common_cmd::write_single_block(address), true)?;
963
964 let res = poll_fn(|cx| {
965 T::state().register(cx.waker());
966 let status = regs.star().read();
967
968 if status.dcrcfail() {
969 return Poll::Ready(Err(Error::Crc));
970 }
971 if status.dtimeout() {
972 return Poll::Ready(Err(Error::Timeout));
973 }
974 #[cfg(sdmmc_v1)]
975 if status.stbiterr() {
976 return Poll::Ready(Err(Error::StBitErr));
977 }
978 if status.dataend() {
979 return Poll::Ready(Ok(()));
980 }
981 Poll::Pending
982 })
983 .await;
984 Self::clear_interrupt_flags();
985
986 match res {
987 Ok(_) => {
988 on_drop.defuse();
989 Self::stop_datapath();
990 drop(transfer);
991
992 // TODO: Make this configurable
993 let mut timeout: u32 = 0x00FF_FFFF;
994
995 let card = self.card.as_ref().unwrap();
996 while timeout > 0 {
997 let ready_for_data = match card {
998 SdmmcPeripheral::Emmc(_) => self.read_status::<EMMC>(card)?.ready_for_data(),
999 SdmmcPeripheral::SdCard(_) => self.read_status::<SD>(card)?.ready_for_data(),
1000 };
1001
1002 if ready_for_data {
1003 return Ok(());
1004 }
1005 timeout -= 1;
1006 }
1007 Err(Error::SoftwareTimeout)
1008 }
1009 Err(e) => Err(e),
1010 }
1011 }
1012
1013 /// Get a reference to the initialized card
1014 ///
1015 /// # Errors
1016 ///
1017 /// Returns Error::NoCard if [`init_card`](#method.init_card)
1018 /// has not previously succeeded
1019 #[inline]
1020 pub fn card(&self) -> Result<&SdmmcPeripheral, Error> {
1021 self.card.as_ref().ok_or(Error::NoCard)
1022 }
1023
1024 /// Get the current SDMMC bus clock
1025 pub fn clock(&self) -> Hertz {
1026 self.clock
1027 }
1028
1029 /// Set a specific cmd buffer rather than using the default stack allocated one.
1030 /// This is required if stack RAM cannot be used with DMA and usually manifests
1031 /// itself as an indefinite wait on a dma transfer because the dma peripheral
1032 /// cannot access the memory.
1033 pub fn set_cmd_block(&mut self, cmd_block: &'d mut CmdBlock) {
1034 self.cmd_block = Some(cmd_block)
1035 }
1036}
1037
1038/// SD only
1039impl<'d, T: Instance> Sdmmc<'d, T> {
1027 /// Initializes card (if present) and sets the bus at the specified frequency. 1040 /// Initializes card (if present) and sets the bus at the specified frequency.
1028 pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> { 1041 pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> {
1029 let regs = T::regs(); 1042 let regs = T::regs();
@@ -1114,7 +1127,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1114 let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3); 1127 let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3);
1115 card.csd = csd.into(); 1128 card.csd = csd.into();
1116 1129
1117 self.select_card(Some(&card))?; 1130 self.select_card(Some(card.rca))?;
1118 1131
1119 self.get_scr(&mut card).await?; 1132 self.get_scr(&mut card).await?;
1120 1133
@@ -1148,7 +1161,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1148 self.clkcr_set_clkdiv(25_000_000, width)?; 1161 self.clkcr_set_clkdiv(25_000_000, width)?;
1149 } 1162 }
1150 1163
1151 self.card = Some(card); 1164 self.card = Some(SdmmcPeripheral::SdCard(card));
1152 1165
1153 // Read status 1166 // Read status
1154 self.read_sd_status().await?; 1167 self.read_sd_status().await?;
@@ -1161,7 +1174,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1161 // Set final clock frequency 1174 // Set final clock frequency
1162 self.clkcr_set_clkdiv(freq.0, width)?; 1175 self.clkcr_set_clkdiv(freq.0, width)?;
1163 1176
1164 if self.read_status(&card)?.state() != CurrentState::Transfer { 1177 if self.read_status::<SD>(self.card.as_ref().unwrap())?.state() != CurrentState::Transfer {
1165 return Err(Error::SignalingSwitchFailed); 1178 return Err(Error::SignalingSwitchFailed);
1166 } 1179 }
1167 } 1180 }
@@ -1173,22 +1186,34 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1173 Ok(()) 1186 Ok(())
1174 } 1187 }
1175 1188
1176 /// Read a data block. 1189 /// Switch mode using CMD6.
1177 #[inline] 1190 ///
1178 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> { 1191 /// Attempt to set a new signalling mode. The selected
1179 let card_capacity = self.card()?.card_type; 1192 /// signalling mode is returned. Expects the current clock
1193 /// frequency to be > 12.5MHz.
1194 ///
1195 /// SD only.
1196 async fn switch_signalling_mode(&mut self, signalling: Signalling) -> Result<Signalling, Error> {
1197 let _ = self.card.as_mut().ok_or(Error::NoCard)?.get_sd_card();
1198 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
1199 // necessary"
1180 1200
1181 // NOTE(unsafe) DataBlock uses align 4 1201 let set_function = 0x8000_0000
1182 let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) }; 1202 | match signalling {
1203 // See PLSS v7_10 Table 4-11
1204 Signalling::DDR50 => 0xFF_FF04,
1205 Signalling::SDR104 => 0xFF_1F03,
1206 Signalling::SDR50 => 0xFF_1F02,
1207 Signalling::SDR25 => 0xFF_FF01,
1208 Signalling::SDR12 => 0xFF_FF00,
1209 };
1183 1210
1184 // Always read 1 block of 512 bytes 1211 let status = match self.cmd_block.as_deref_mut() {
1185 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes 1212 Some(x) => x,
1186 let address = match card_capacity { 1213 None => &mut CmdBlock::new(),
1187 CardCapacity::StandardCapacity => block_idx * 512,
1188 _ => block_idx,
1189 }; 1214 };
1190 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1191 1215
1216 // Arm `OnDrop` after the buffer, so it will be dropped first
1192 let regs = T::regs(); 1217 let regs = T::regs();
1193 let on_drop = OnDrop::new(|| Self::on_drop()); 1218 let on_drop = OnDrop::new(|| Self::on_drop());
1194 1219
@@ -1196,12 +1221,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1196 &self.config, 1221 &self.config,
1197 #[cfg(sdmmc_v1)] 1222 #[cfg(sdmmc_v1)]
1198 &mut self.dma, 1223 &mut self.dma,
1199 buffer, 1224 status.as_mut(),
1200 512, 1225 64,
1201 9, 1226 6,
1202 ); 1227 );
1203 InterruptHandler::<T>::data_interrupts(true); 1228 InterruptHandler::<T>::data_interrupts(true);
1204 Self::cmd(common_cmd::read_single_block(address), true)?; 1229 Self::cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
1205 1230
1206 let res = poll_fn(|cx| { 1231 let res = poll_fn(|cx| {
1207 T::state().register(cx.waker()); 1232 T::state().register(cx.waker());
@@ -1225,41 +1250,64 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1225 .await; 1250 .await;
1226 Self::clear_interrupt_flags(); 1251 Self::clear_interrupt_flags();
1227 1252
1228 if res.is_ok() { 1253 // Host is allowed to use the new functions at least 8
1229 on_drop.defuse(); 1254 // clocks after the end of the switch command
1230 Self::stop_datapath(); 1255 // transaction. We know the current clock period is < 80ns,
1231 drop(transfer); 1256 // so a total delay of 640ns is required here
1257 for _ in 0..300 {
1258 cortex_m::asm::nop();
1232 } 1259 }
1233 res
1234 }
1235 1260
1236 /// Write a data block. 1261 match res {
1237 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> { 1262 Ok(_) => {
1238 let card = self.card.as_mut().ok_or(Error::NoCard)?; 1263 on_drop.defuse();
1264 Self::stop_datapath();
1265 drop(transfer);
1239 1266
1240 // NOTE(unsafe) DataBlock uses align 4 1267 // Function Selection of Function Group 1
1241 let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) }; 1268 let selection = (u32::from_be(status[4]) >> 24) & 0xF;
1242 1269
1243 // Always read 1 block of 512 bytes 1270 match selection {
1244 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes 1271 0 => Ok(Signalling::SDR12),
1245 let address = match card.card_type { 1272 1 => Ok(Signalling::SDR25),
1246 CardCapacity::StandardCapacity => block_idx * 512, 1273 2 => Ok(Signalling::SDR50),
1247 _ => block_idx, 1274 3 => Ok(Signalling::SDR104),
1275 4 => Ok(Signalling::DDR50),
1276 _ => Err(Error::UnsupportedCardType),
1277 }
1278 }
1279 Err(e) => Err(e),
1280 }
1281 }
1282
1283 /// Reads the SCR register.
1284 ///
1285 /// SD only.
1286 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
1287 // Read the 64-bit SCR register
1288 Self::cmd(common_cmd::set_block_length(8), false)?; // CMD16
1289 Self::cmd(common_cmd::app_cmd(card.rca), false)?;
1290
1291 let cmd_block = match self.cmd_block.as_deref_mut() {
1292 Some(x) => x,
1293 None => &mut CmdBlock::new(),
1248 }; 1294 };
1249 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16 1295 let scr = &mut cmd_block.0[..2];
1250 1296
1297 // Arm `OnDrop` after the buffer, so it will be dropped first
1251 let regs = T::regs(); 1298 let regs = T::regs();
1252 let on_drop = OnDrop::new(|| Self::on_drop()); 1299 let on_drop = OnDrop::new(|| Self::on_drop());
1253 1300
1254 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes 1301 let transfer = Self::prepare_datapath_read(
1255 #[cfg(sdmmc_v1)] 1302 &self.config,
1256 Self::cmd(common_cmd::write_single_block(address), true)?; 1303 #[cfg(sdmmc_v1)]
1257 1304 &mut self.dma,
1258 let transfer = self.prepare_datapath_write(buffer, 512, 9); 1305 scr,
1306 8,
1307 3,
1308 );
1259 InterruptHandler::<T>::data_interrupts(true); 1309 InterruptHandler::<T>::data_interrupts(true);
1260 1310 Self::cmd(sd_cmd::send_scr(), true)?;
1261 #[cfg(sdmmc_v2)]
1262 Self::cmd(common_cmd::write_single_block(address), true)?;
1263 1311
1264 let res = poll_fn(|cx| { 1312 let res = poll_fn(|cx| {
1265 T::state().register(cx.waker()); 1313 T::state().register(cx.waker());
@@ -1283,52 +1331,84 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1283 .await; 1331 .await;
1284 Self::clear_interrupt_flags(); 1332 Self::clear_interrupt_flags();
1285 1333
1286 match res { 1334 if res.is_ok() {
1287 Ok(_) => { 1335 on_drop.defuse();
1288 on_drop.defuse(); 1336 Self::stop_datapath();
1289 Self::stop_datapath(); 1337 drop(transfer);
1290 drop(transfer);
1291
1292 // TODO: Make this configurable
1293 let mut timeout: u32 = 0x00FF_FFFF;
1294
1295 let card = self.card.as_ref().unwrap();
1296 while timeout > 0 {
1297 let status = self.read_status(card)?;
1298 1338
1299 if status.ready_for_data() { 1339 unsafe {
1300 return Ok(()); 1340 let scr_bytes = &*(&scr as *const _ as *const [u8; 8]);
1301 } 1341 card.scr = SCR(u64::from_be_bytes(*scr_bytes));
1302 timeout -= 1;
1303 }
1304 Err(Error::SoftwareTimeout)
1305 } 1342 }
1306 Err(e) => Err(e),
1307 } 1343 }
1344 res
1308 } 1345 }
1309 1346
1310 /// Get a reference to the initialized card 1347 /// Reads the SD Status (ACMD13)
1311 ///
1312 /// # Errors
1313 /// 1348 ///
1314 /// Returns Error::NoCard if [`init_card`](#method.init_card) 1349 /// SD only.
1315 /// has not previously succeeded 1350 async fn read_sd_status(&mut self) -> Result<(), Error> {
1316 #[inline] 1351 let card = self.card.as_mut().ok_or(Error::NoCard)?.get_sd_card();
1317 pub fn card(&self) -> Result<&Card, Error> { 1352 let rca = card.rca;
1318 self.card.as_ref().ok_or(Error::NoCard)
1319 }
1320 1353
1321 /// Get the current SDMMC bus clock 1354 let cmd_block = match self.cmd_block.as_deref_mut() {
1322 pub fn clock(&self) -> Hertz { 1355 Some(x) => x,
1323 self.clock 1356 None => &mut CmdBlock::new(),
1324 } 1357 };
1325 1358
1326 /// Set a specific cmd buffer rather than using the default stack allocated one. 1359 Self::cmd(common_cmd::set_block_length(64), false)?; // CMD16
1327 /// This is required if stack RAM cannot be used with DMA and usually manifests 1360 Self::cmd(common_cmd::app_cmd(rca), false)?; // APP
1328 /// itself as an indefinite wait on a dma transfer because the dma peripheral 1361
1329 /// cannot access the memory. 1362 let status = cmd_block;
1330 pub fn set_cmd_block(&mut self, cmd_block: &'d mut CmdBlock) { 1363
1331 self.cmd_block = Some(cmd_block) 1364 // Arm `OnDrop` after the buffer, so it will be dropped first
1365 let regs = T::regs();
1366 let on_drop = OnDrop::new(|| Self::on_drop());
1367
1368 let transfer = Self::prepare_datapath_read(
1369 &self.config,
1370 #[cfg(sdmmc_v1)]
1371 &mut self.dma,
1372 status.as_mut(),
1373 64,
1374 6,
1375 );
1376 InterruptHandler::<T>::data_interrupts(true);
1377 Self::cmd(sd_cmd::sd_status(), true)?;
1378
1379 let res = poll_fn(|cx| {
1380 T::state().register(cx.waker());
1381 let status = regs.star().read();
1382
1383 if status.dcrcfail() {
1384 return Poll::Ready(Err(Error::Crc));
1385 }
1386 if status.dtimeout() {
1387 return Poll::Ready(Err(Error::Timeout));
1388 }
1389 #[cfg(sdmmc_v1)]
1390 if status.stbiterr() {
1391 return Poll::Ready(Err(Error::StBitErr));
1392 }
1393 if status.dataend() {
1394 return Poll::Ready(Ok(()));
1395 }
1396 Poll::Pending
1397 })
1398 .await;
1399 Self::clear_interrupt_flags();
1400
1401 if res.is_ok() {
1402 on_drop.defuse();
1403 Self::stop_datapath();
1404 drop(transfer);
1405
1406 for byte in status.iter_mut() {
1407 *byte = u32::from_be(*byte);
1408 }
1409 card.status = status.0.into();
1410 }
1411 res
1332 } 1412 }
1333} 1413}
1334 1414