aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-07-04 00:25:00 +0200
committerDario Nieuwenhuis <[email protected]>2025-07-04 00:25:00 +0200
commitc8a4a4995844be1b61d1a1479a6009eeb69b1117 (patch)
treeef85911ac543599b227884c2cb242468487ee11d
parent3127e1c50b2ea2efddba199ae780cb5ebb571c00 (diff)
stm32/sdmmc: misc improvements
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs124
1 files changed, 53 insertions, 71 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index c82407334..6e5d735d7 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -32,25 +32,48 @@ pub struct InterruptHandler<T: Instance> {
32} 32}
33 33
34impl<T: Instance> InterruptHandler<T> { 34impl<T: Instance> InterruptHandler<T> {
35 fn data_interrupts(enable: bool) { 35 fn enable_interrupts() {
36 let regs = T::regs(); 36 let regs = T::regs();
37 regs.maskr().write(|w| { 37 regs.maskr().write(|w| {
38 w.set_dcrcfailie(enable); 38 w.set_dcrcfailie(true);
39 w.set_dtimeoutie(enable); 39 w.set_dtimeoutie(true);
40 w.set_dataendie(enable); 40 w.set_dataendie(true);
41 w.set_dbckendie(true);
41 42
42 #[cfg(sdmmc_v1)] 43 #[cfg(sdmmc_v1)]
43 w.set_stbiterre(enable); 44 w.set_stbiterre(true);
44 #[cfg(sdmmc_v2)] 45 #[cfg(sdmmc_v2)]
45 w.set_dabortie(enable); 46 w.set_dabortie(true);
46 }); 47 });
47 } 48 }
48} 49}
49 50
50impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { 51impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
51 unsafe fn on_interrupt() { 52 unsafe fn on_interrupt() {
52 Self::data_interrupts(false);
53 T::state().wake(); 53 T::state().wake();
54 let status = T::regs().star().read();
55 T::regs().maskr().modify(|w| {
56 if status.dcrcfail() {
57 w.set_dcrcfailie(false)
58 }
59 if status.dtimeout() {
60 w.set_dtimeoutie(false)
61 }
62 if status.dataend() {
63 w.set_dataendie(false)
64 }
65 if status.dbckend() {
66 w.set_dbckendie(false)
67 }
68 #[cfg(sdmmc_v1)]
69 if status.stbiterr() {
70 w.set_stbiterre(false)
71 }
72 #[cfg(sdmmc_v2)]
73 if status.dabort() {
74 w.set_dabortie(false)
75 }
76 });
54 } 77 }
55} 78}
56 79
@@ -1002,14 +1025,14 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1002 // Wait for the abort 1025 // Wait for the abort
1003 while Self::data_active() {} 1026 while Self::data_active() {}
1004 } 1027 }
1005 InterruptHandler::<T>::data_interrupts(false); 1028 regs.maskr().write(|_| ()); // disable irqs
1006 Self::clear_interrupt_flags(); 1029 Self::clear_interrupt_flags();
1007 Self::stop_datapath(); 1030 Self::stop_datapath();
1008 } 1031 }
1009 1032
1010 /// Wait for a previously started datapath transfer to complete from an interrupt. 1033 /// Wait for a previously started datapath transfer to complete from an interrupt.
1011 #[inline] 1034 #[inline]
1012 async fn complete_datapath_transfer() -> Result<(), Error> { 1035 async fn complete_datapath_transfer(block: bool) -> Result<(), Error> {
1013 let regs = T::regs(); 1036 let regs = T::regs();
1014 1037
1015 let res = poll_fn(|cx| { 1038 let res = poll_fn(|cx| {
@@ -1029,7 +1052,11 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1029 if status.stbiterr() { 1052 if status.stbiterr() {
1030 return Poll::Ready(Err(Error::StBitErr)); 1053 return Poll::Ready(Err(Error::StBitErr));
1031 } 1054 }
1032 if status.dataend() { 1055 let done = match block {
1056 true => status.dbckend(),
1057 false => status.dataend(),
1058 };
1059 if done {
1033 return Poll::Ready(Ok(())); 1060 return Poll::Ready(Ok(()));
1034 } 1061 }
1035 Poll::Pending 1062 Poll::Pending
@@ -1067,10 +1094,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1067 512, 1094 512,
1068 9, 1095 9,
1069 ); 1096 );
1070 InterruptHandler::<T>::data_interrupts(true); 1097 InterruptHandler::<T>::enable_interrupts();
1071 Self::cmd(common_cmd::read_single_block(address), true)?; 1098 Self::cmd(common_cmd::read_single_block(address), true)?;
1072 1099
1073 let res = Self::complete_datapath_transfer().await; 1100 let res = Self::complete_datapath_transfer(true).await;
1074 1101
1075 if res.is_ok() { 1102 if res.is_ok() {
1076 on_drop.defuse(); 1103 on_drop.defuse();
@@ -1100,7 +1127,6 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1100 }; 1127 };
1101 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16 1128 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1102 1129
1103 let regs = T::regs();
1104 let on_drop = OnDrop::new(|| Self::on_drop()); 1130 let on_drop = OnDrop::new(|| Self::on_drop());
1105 1131
1106 let transfer = Self::prepare_datapath_read( 1132 let transfer = Self::prepare_datapath_read(
@@ -1111,30 +1137,11 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1111 512 * blocks.len() as u32, 1137 512 * blocks.len() as u32,
1112 9, 1138 9,
1113 ); 1139 );
1114 InterruptHandler::<T>::data_interrupts(true); 1140 InterruptHandler::<T>::enable_interrupts();
1115 1141
1116 Self::cmd(common_cmd::read_multiple_blocks(address), true)?; 1142 Self::cmd(common_cmd::read_multiple_blocks(address), true)?;
1117 1143
1118 let res = poll_fn(|cx| { 1144 let res = Self::complete_datapath_transfer(false).await;
1119 T::state().register(cx.waker());
1120 let status = regs.star().read();
1121
1122 if status.dcrcfail() {
1123 return Poll::Ready(Err(Error::Crc));
1124 }
1125 if status.dtimeout() {
1126 return Poll::Ready(Err(Error::Timeout));
1127 }
1128 #[cfg(sdmmc_v1)]
1129 if status.stbiterr() {
1130 return Poll::Ready(Err(Error::StBitErr));
1131 }
1132 if status.dataend() {
1133 return Poll::Ready(Ok(()));
1134 }
1135 Poll::Pending
1136 })
1137 .await;
1138 1145
1139 Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12 1146 Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12
1140 Self::clear_interrupt_flags(); 1147 Self::clear_interrupt_flags();
@@ -1169,12 +1176,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1169 Self::cmd(common_cmd::write_single_block(address), true)?; 1176 Self::cmd(common_cmd::write_single_block(address), true)?;
1170 1177
1171 let transfer = self.prepare_datapath_write(buffer, 512, 9); 1178 let transfer = self.prepare_datapath_write(buffer, 512, 9);
1172 InterruptHandler::<T>::data_interrupts(true); 1179 InterruptHandler::<T>::enable_interrupts();
1173 1180
1174 #[cfg(sdmmc_v2)] 1181 #[cfg(sdmmc_v2)]
1175 Self::cmd(common_cmd::write_single_block(address), true)?; 1182 Self::cmd(common_cmd::write_single_block(address), true)?;
1176 1183
1177 let res = Self::complete_datapath_transfer().await; 1184 let res = Self::complete_datapath_transfer(true).await;
1178 1185
1179 match res { 1186 match res {
1180 Ok(_) => { 1187 Ok(_) => {
@@ -1225,7 +1232,6 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1225 1232
1226 let block_count = blocks.len(); 1233 let block_count = blocks.len();
1227 1234
1228 let regs = T::regs();
1229 let on_drop = OnDrop::new(|| Self::on_drop()); 1235 let on_drop = OnDrop::new(|| Self::on_drop());
1230 1236
1231 #[cfg(sdmmc_v1)] 1237 #[cfg(sdmmc_v1)]
@@ -1233,36 +1239,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1233 1239
1234 // Setup write command 1240 // Setup write command
1235 let transfer = self.prepare_datapath_write(buffer, 512 * block_count as u32, 9); 1241 let transfer = self.prepare_datapath_write(buffer, 512 * block_count as u32, 9);
1236 InterruptHandler::<T>::data_interrupts(true); 1242 InterruptHandler::<T>::enable_interrupts();
1237 1243
1238 #[cfg(sdmmc_v2)] 1244 #[cfg(sdmmc_v2)]
1239 Self::cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25 1245 Self::cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
1240 1246
1241 let res = poll_fn(|cx| { 1247 let res = Self::complete_datapath_transfer(false).await;
1242 T::state().register(cx.waker());
1243
1244 let status = regs.star().read();
1245
1246 if status.dcrcfail() {
1247 return Poll::Ready(Err(Error::Crc));
1248 }
1249 if status.dtimeout() {
1250 return Poll::Ready(Err(Error::Timeout));
1251 }
1252 if status.txunderr() {
1253 return Poll::Ready(Err(Error::Underrun));
1254 }
1255 #[cfg(sdmmc_v1)]
1256 if status.stbiterr() {
1257 return Poll::Ready(Err(Error::StBitErr));
1258 }
1259 if status.dataend() {
1260 return Poll::Ready(Ok(()));
1261 }
1262
1263 Poll::Pending
1264 })
1265 .await;
1266 1248
1267 Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12 1249 Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12
1268 Self::clear_interrupt_flags(); 1250 Self::clear_interrupt_flags();
@@ -1597,10 +1579,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1597 64, 1579 64,
1598 6, 1580 6,
1599 ); 1581 );
1600 InterruptHandler::<T>::data_interrupts(true); 1582 InterruptHandler::<T>::enable_interrupts();
1601 Self::cmd(sd_cmd::cmd6(set_function), true)?; // CMD6 1583 Self::cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
1602 1584
1603 let res = Self::complete_datapath_transfer().await; 1585 let res = Self::complete_datapath_transfer(true).await;
1604 1586
1605 // Host is allowed to use the new functions at least 8 1587 // Host is allowed to use the new functions at least 8
1606 // clocks after the end of the switch command 1588 // clocks after the end of the switch command
@@ -1657,10 +1639,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1657 8, 1639 8,
1658 3, 1640 3,
1659 ); 1641 );
1660 InterruptHandler::<T>::data_interrupts(true); 1642 InterruptHandler::<T>::enable_interrupts();
1661 Self::cmd(sd_cmd::send_scr(), true)?; 1643 Self::cmd(sd_cmd::send_scr(), true)?;
1662 1644
1663 let res = Self::complete_datapath_transfer().await; 1645 let res = Self::complete_datapath_transfer(true).await;
1664 1646
1665 if res.is_ok() { 1647 if res.is_ok() {
1666 on_drop.defuse(); 1648 on_drop.defuse();
@@ -1703,10 +1685,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1703 64, 1685 64,
1704 6, 1686 6,
1705 ); 1687 );
1706 InterruptHandler::<T>::data_interrupts(true); 1688 InterruptHandler::<T>::enable_interrupts();
1707 Self::cmd(sd_cmd::sd_status(), true)?; 1689 Self::cmd(sd_cmd::sd_status(), true)?;
1708 1690
1709 let res = Self::complete_datapath_transfer().await; 1691 let res = Self::complete_datapath_transfer(true).await;
1710 1692
1711 if res.is_ok() { 1693 if res.is_ok() {
1712 on_drop.defuse(); 1694 on_drop.defuse();
@@ -1753,10 +1735,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1753 512, 1735 512,
1754 9, 1736 9,
1755 ); 1737 );
1756 InterruptHandler::<T>::data_interrupts(true); 1738 InterruptHandler::<T>::enable_interrupts();
1757 Self::cmd(emmc_cmd::send_ext_csd(), true)?; 1739 Self::cmd(emmc_cmd::send_ext_csd(), true)?;
1758 1740
1759 let res = Self::complete_datapath_transfer().await; 1741 let res = Self::complete_datapath_transfer(true).await;
1760 1742
1761 if res.is_ok() { 1743 if res.is_ok() {
1762 on_drop.defuse(); 1744 on_drop.defuse();