aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-12-12 11:32:47 -0600
committerxoviat <[email protected]>2025-12-12 11:32:47 -0600
commitd9c90df7578dda10d888941b8df5a2295373ca1f (patch)
tree4bae45ee7c3fa41f873d13faf7ed45b17769d91e
parent640ca72c0e33b252026191ac9bc64fa6b0c9b166 (diff)
stm32/sdio: update transfer interface
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs64
-rw-r--r--embassy-stm32/src/sdmmc/sd.rs58
-rw-r--r--embassy-stm32/src/sdmmc/sdio.rs27
3 files changed, 97 insertions, 52 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 12086cd3a..e716fc348 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -7,6 +7,7 @@ use core::marker::PhantomData;
7use core::slice; 7use core::slice;
8use core::task::Poll; 8use core::task::Poll;
9 9
10use aligned::{A4, Aligned};
10use embassy_hal_internal::{Peri, PeripheralType}; 11use embassy_hal_internal::{Peri, PeripheralType};
11use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
12use sdio_host::Cmd; 13use sdio_host::Cmd;
@@ -139,16 +140,38 @@ impl Default for Signalling {
139 } 140 }
140} 141}
141 142
143const fn aligned_mut(x: &mut [u32]) -> &mut Aligned<A4, [u8]> {
144 let len = x.len() * 4;
145 unsafe { core::mem::transmute(slice::from_raw_parts_mut(x.as_mut_ptr() as _, len)) }
146}
147
142const fn slice8_mut(x: &mut [u32]) -> &mut [u8] { 148const fn slice8_mut(x: &mut [u32]) -> &mut [u8] {
143 let len = x.len() * 4; 149 let len = x.len() * 4;
144 unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } 150 unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) }
145} 151}
146 152
153#[allow(unused)]
154const fn slice32_mut(x: &mut Aligned<A4, [u8]>) -> &mut [u32] {
155 let len = (size_of_val(x) + 4 - 1) / 4;
156 unsafe { slice::from_raw_parts_mut(x as *mut Aligned<A4, [u8]> as *mut _, len) }
157}
158
159const fn aligned_ref(x: &[u32]) -> &Aligned<A4, [u8]> {
160 let len = x.len() * 4;
161 unsafe { core::mem::transmute(slice::from_raw_parts(x.as_ptr() as _, len)) }
162}
163
147const fn slice8_ref(x: &[u32]) -> &[u8] { 164const fn slice8_ref(x: &[u32]) -> &[u8] {
148 let len = x.len() * 4; 165 let len = x.len() * 4;
149 unsafe { slice::from_raw_parts(x.as_ptr() as _, len) } 166 unsafe { slice::from_raw_parts(x.as_ptr() as _, len) }
150} 167}
151 168
169#[allow(unused)]
170const fn slice32_ref(x: &Aligned<A4, [u8]>) -> &[u32] {
171 let len = (size_of_val(x) + 4 - 1) / 4;
172 unsafe { slice::from_raw_parts(x as *const Aligned<A4, [u8]> as *const _, len) }
173}
174
152/// Errors 175/// Errors
153#[non_exhaustive] 176#[non_exhaustive]
154#[derive(Debug, Copy, Clone, PartialEq, Eq)] 177#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -187,6 +210,11 @@ enum PowerCtrl {
187 On = 0b11, 210 On = 0b11,
188} 211}
189 212
213enum DatapathMode {
214 Block(BlockSize),
215 Byte,
216}
217
190fn get_waitresp_val(rlen: ResponseLen) -> u8 { 218fn get_waitresp_val(rlen: ResponseLen) -> u8 {
191 match rlen { 219 match rlen {
192 common_cmd::ResponseLen::Zero => 0, 220 common_cmd::ResponseLen::Zero => 0,
@@ -768,12 +796,16 @@ impl<'d> Sdmmc<'d> {
768 #[allow(unused_variables)] 796 #[allow(unused_variables)]
769 fn prepare_datapath_read<'a>( 797 fn prepare_datapath_read<'a>(
770 &'a self, 798 &'a self,
771 buffer: &'a mut [u32], 799 buffer: &'a mut Aligned<A4, [u8]>,
772 block_size: BlockSize, 800 mode: DatapathMode,
773 byte_mode: bool,
774 ) -> WrappedTransfer<'a> { 801 ) -> WrappedTransfer<'a> {
775 let regs = self.info.regs; 802 let regs = self.info.regs;
776 803
804 let (byte_mode, block_size) = match mode {
805 DatapathMode::Block(block_size) => (false, block_size as u8),
806 DatapathMode::Byte => (true, 0),
807 };
808
777 // Command AND Data state machines must be idle 809 // Command AND Data state machines must be idle
778 self.wait_idle(); 810 self.wait_idle();
779 self.clear_interrupt_flags(); 811 self.clear_interrupt_flags();
@@ -783,8 +815,11 @@ impl<'d> Sdmmc<'d> {
783 // SAFETY: No other functions use the dma 815 // SAFETY: No other functions use the dma
784 #[cfg(sdmmc_v1)] 816 #[cfg(sdmmc_v1)]
785 let transfer = unsafe { 817 let transfer = unsafe {
786 self.dma 818 self.dma.read_unchecked(
787 .read_unchecked(regs.fifor().as_ptr() as *mut u32, buffer, DMA_TRANSFER_OPTIONS) 819 regs.fifor().as_ptr() as *mut u32,
820 slice32_mut(buffer),
821 DMA_TRANSFER_OPTIONS,
822 )
788 }; 823 };
789 #[cfg(sdmmc_v2)] 824 #[cfg(sdmmc_v2)]
790 let transfer = { 825 let transfer = {
@@ -817,14 +852,14 @@ impl<'d> Sdmmc<'d> {
817 /// # Safety 852 /// # Safety
818 /// 853 ///
819 /// `buffer` must be valid for the whole transfer and word aligned 854 /// `buffer` must be valid for the whole transfer and word aligned
820 fn prepare_datapath_write<'a>( 855 fn prepare_datapath_write<'a>(&'a self, buffer: &'a Aligned<A4, [u8]>, mode: DatapathMode) -> WrappedTransfer<'a> {
821 &'a self,
822 buffer: &'a [u32],
823 block_size: BlockSize,
824 byte_mode: bool,
825 ) -> WrappedTransfer<'a> {
826 let regs = self.info.regs; 856 let regs = self.info.regs;
827 857
858 let (byte_mode, block_size) = match mode {
859 DatapathMode::Block(block_size) => (false, block_size as u8),
860 DatapathMode::Byte => (true, 0),
861 };
862
828 // Command AND Data state machines must be idle 863 // Command AND Data state machines must be idle
829 self.wait_idle(); 864 self.wait_idle();
830 self.clear_interrupt_flags(); 865 self.clear_interrupt_flags();
@@ -834,8 +869,11 @@ impl<'d> Sdmmc<'d> {
834 // SAFETY: No other functions use the dma 869 // SAFETY: No other functions use the dma
835 #[cfg(sdmmc_v1)] 870 #[cfg(sdmmc_v1)]
836 let transfer = unsafe { 871 let transfer = unsafe {
837 self.dma 872 self.dma.write_unchecked(
838 .write_unchecked(buffer, regs.fifor().as_ptr() as *mut u32, DMA_TRANSFER_OPTIONS) 873 slice32_ref(buffer),
874 regs.fifor().as_ptr() as *mut u32,
875 DMA_TRANSFER_OPTIONS,
876 )
839 }; 877 };
840 #[cfg(sdmmc_v2)] 878 #[cfg(sdmmc_v2)]
841 let transfer = { 879 let transfer = {
diff --git a/embassy-stm32/src/sdmmc/sd.rs b/embassy-stm32/src/sdmmc/sd.rs
index 6190226b8..20318bbfa 100644
--- a/embassy-stm32/src/sdmmc/sd.rs
+++ b/embassy-stm32/src/sdmmc/sd.rs
@@ -5,7 +5,10 @@ use sdio_host::emmc::{EMMC, ExtCSD};
5use sdio_host::sd::{BusWidth, CIC, CID, CSD, CardCapacity, CardStatus, CurrentState, OCR, RCA, SCR, SD, SDStatus}; 5use sdio_host::sd::{BusWidth, CIC, CID, CSD, CardCapacity, CardStatus, CurrentState, OCR, RCA, SCR, SD, SDStatus};
6use sdio_host::{common_cmd, emmc_cmd, sd_cmd}; 6use sdio_host::{common_cmd, emmc_cmd, sd_cmd};
7 7
8use crate::sdmmc::{BlockSize, Error, Sdmmc, Signalling, block_size, bus_width_vals, slice8_mut, slice8_ref}; 8use crate::sdmmc::{
9 BlockSize, DatapathMode, Error, Sdmmc, Signalling, aligned_mut, aligned_ref, block_size, bus_width_vals,
10 slice8_mut, slice8_ref,
11};
9use crate::time::{Hertz, mhz}; 12use crate::time::{Hertz, mhz};
10 13
11/// Aligned data block for SDMMC transfers. 14/// Aligned data block for SDMMC transfers.
@@ -230,10 +233,8 @@ impl<'a, 'b> StorageDevice<'a, 'b, Card> {
230 }; 233 };
231 234
232 let buffer = &mut cmd_block.0[..64 / 4]; 235 let buffer = &mut cmd_block.0[..64 / 4];
233 236 let mode = DatapathMode::Block(block_size(size_of_val(buffer)));
234 let transfer = self 237 let transfer = self.sdmmc.prepare_datapath_read(aligned_mut(buffer), mode);
235 .sdmmc
236 .prepare_datapath_read(buffer, block_size(size_of_val(buffer)), false);
237 238
238 self.sdmmc.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6 239 self.sdmmc.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
239 240
@@ -272,7 +273,9 @@ impl<'a, 'b> StorageDevice<'a, 'b, Card> {
272 273
273 // Arm `OnDrop` after the buffer, so it will be dropped first 274 // Arm `OnDrop` after the buffer, so it will be dropped first
274 275
275 let transfer = self.sdmmc.prepare_datapath_read(scr, BlockSize::Size8, false); 276 let transfer = self
277 .sdmmc
278 .prepare_datapath_read(aligned_mut(scr), DatapathMode::Block(BlockSize::Size8));
276 self.sdmmc.cmd(sd_cmd::send_scr(), true)?; 279 self.sdmmc.cmd(sd_cmd::send_scr(), true)?;
277 280
278 self.sdmmc.complete_datapath_transfer(transfer, true).await?; 281 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
@@ -290,10 +293,9 @@ impl<'a, 'b> StorageDevice<'a, 'b, Card> {
290 self.sdmmc.cmd(common_cmd::app_cmd(rca), false)?; // APP 293 self.sdmmc.cmd(common_cmd::app_cmd(rca), false)?; // APP
291 294
292 let buffer = &mut cmd_block.as_mut()[..64 / 4]; 295 let buffer = &mut cmd_block.as_mut()[..64 / 4];
296 let mode = DatapathMode::Block(block_size(size_of_val(buffer)));
293 297
294 let transfer = self 298 let transfer = self.sdmmc.prepare_datapath_read(aligned_mut(buffer), mode);
295 .sdmmc
296 .prepare_datapath_read(buffer, block_size(size_of_val(buffer)), false);
297 self.sdmmc.cmd(sd_cmd::sd_status(), true)?; 299 self.sdmmc.cmd(sd_cmd::sd_status(), true)?;
298 300
299 self.sdmmc.complete_datapath_transfer(transfer, true).await?; 301 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
@@ -398,9 +400,10 @@ impl<'a, 'b> StorageDevice<'a, 'b, Emmc> {
398 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false) 400 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)
399 .unwrap(); // CMD16 401 .unwrap(); // CMD16
400 402
401 let transfer = self 403 let transfer = self.sdmmc.prepare_datapath_read(
402 .sdmmc 404 aligned_mut(&mut data_block.0),
403 .prepare_datapath_read(&mut data_block.0, block_size(size_of::<DataBlock>()), false); 405 DatapathMode::Block(block_size(size_of::<DataBlock>())),
406 );
404 self.sdmmc.cmd(emmc_cmd::send_ext_csd(), true)?; 407 self.sdmmc.cmd(emmc_cmd::send_ext_csd(), true)?;
405 408
406 self.sdmmc.complete_datapath_transfer(transfer, true).await?; 409 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
@@ -418,7 +421,7 @@ impl<'a, 'b, A: Addressable> StorageDevice<'a, 'b, A> {
418 421
419 /// Read a data block. 422 /// Read a data block.
420 #[inline] 423 #[inline]
421 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> { 424 pub async fn read_block(&mut self, block_idx: u32, data_block: &mut DataBlock) -> Result<(), Error> {
422 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop(); 425 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
423 let card_capacity = self.info.get_capacity(); 426 let card_capacity = self.info.get_capacity();
424 427
@@ -431,9 +434,10 @@ impl<'a, 'b, A: Addressable> StorageDevice<'a, 'b, A> {
431 self.sdmmc 434 self.sdmmc
432 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16 435 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
433 436
434 let transfer = self 437 let transfer = self.sdmmc.prepare_datapath_read(
435 .sdmmc 438 aligned_mut(&mut data_block.0),
436 .prepare_datapath_read(&mut buffer.0, block_size(size_of::<DataBlock>()), false); 439 DatapathMode::Block(block_size(size_of::<DataBlock>())),
440 );
437 self.sdmmc.cmd(common_cmd::read_single_block(address), true)?; 441 self.sdmmc.cmd(common_cmd::read_single_block(address), true)?;
438 442
439 self.sdmmc.complete_datapath_transfer(transfer, true).await?; 443 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
@@ -464,9 +468,10 @@ impl<'a, 'b, A: Addressable> StorageDevice<'a, 'b, A> {
464 self.sdmmc 468 self.sdmmc
465 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16 469 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
466 470
467 let transfer = self 471 let transfer = self.sdmmc.prepare_datapath_read(
468 .sdmmc 472 aligned_mut(buffer),
469 .prepare_datapath_read(buffer, block_size(size_of::<DataBlock>()), false); 473 DatapathMode::Block(block_size(size_of::<DataBlock>())),
474 );
470 self.sdmmc.cmd(common_cmd::read_multiple_blocks(address), true)?; 475 self.sdmmc.cmd(common_cmd::read_multiple_blocks(address), true)?;
471 476
472 self.sdmmc.complete_datapath_transfer(transfer, false).await?; 477 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
@@ -497,9 +502,10 @@ impl<'a, 'b, A: Addressable> StorageDevice<'a, 'b, A> {
497 #[cfg(sdmmc_v1)] 502 #[cfg(sdmmc_v1)]
498 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?; 503 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?;
499 504
500 let transfer = self 505 let transfer = self.sdmmc.prepare_datapath_write(
501 .sdmmc 506 aligned_ref(&buffer.0),
502 .prepare_datapath_write(&buffer.0, block_size(size_of::<DataBlock>()), false); 507 DatapathMode::Block(block_size(size_of::<DataBlock>())),
508 );
503 509
504 #[cfg(sdmmc_v2)] 510 #[cfg(sdmmc_v2)]
505 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?; 511 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?;
@@ -548,10 +554,10 @@ impl<'a, 'b, A: Addressable> StorageDevice<'a, 'b, A> {
548 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25 554 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
549 555
550 // Setup write command 556 // Setup write command
551 let transfer = self 557 let transfer = self.sdmmc.prepare_datapath_write(
552 .sdmmc 558 aligned_ref(buffer),
553 .prepare_datapath_write(buffer, block_size(size_of::<DataBlock>()), false); 559 DatapathMode::Block(block_size(size_of::<DataBlock>())),
554 560 );
555 #[cfg(sdmmc_v2)] 561 #[cfg(sdmmc_v2)]
556 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25 562 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
557 563
diff --git a/embassy-stm32/src/sdmmc/sdio.rs b/embassy-stm32/src/sdmmc/sdio.rs
index 1412b21fc..e436d68cb 100644
--- a/embassy-stm32/src/sdmmc/sdio.rs
+++ b/embassy-stm32/src/sdmmc/sdio.rs
@@ -1,10 +1,11 @@
1use core::ops::{Deref, DerefMut}; 1use core::ops::{Deref, DerefMut};
2 2
3use aligned::{A4, Aligned};
3use sdio_host::common_cmd::{R1, Rz, cmd}; 4use sdio_host::common_cmd::{R1, Rz, cmd};
4use sdio_host::sd::BusWidth; 5use sdio_host::sd::BusWidth;
5use sdio_host::sd_cmd; 6use sdio_host::sd_cmd;
6 7
7use crate::sdmmc::{Error, Sdmmc, block_size, slice8_mut, slice8_ref}; 8use crate::sdmmc::{DatapathMode, Error, Sdmmc, aligned_mut, aligned_ref, block_size, slice8_mut, slice8_ref};
8use crate::time::Hertz; 9use crate::time::Hertz;
9 10
10/// Aligned data block for SDMMC transfers. 11/// Aligned data block for SDMMC transfers.
@@ -39,7 +40,7 @@ impl DerefMut for DataBlock {
39/// Storage Device 40/// Storage Device
40pub struct SerialDataInterface<'a, 'b> { 41pub struct SerialDataInterface<'a, 'b> {
41 /// Inner member 42 /// Inner member
42 pub sdmmc: &'a mut Sdmmc<'b>, 43 sdmmc: &'a mut Sdmmc<'b>,
43} 44}
44 45
45/// Card Storage Device 46/// Card Storage Device
@@ -101,9 +102,10 @@ impl<'a, 'b> SerialDataInterface<'a, 'b> {
101 ) 102 )
102 }; 103 };
103 104
104 let transfer = self 105 let transfer = self.sdmmc.prepare_datapath_read(
105 .sdmmc 106 aligned_mut(buffer),
106 .prepare_datapath_read(buffer, block_size(size_of::<DataBlock>()), false); 107 DatapathMode::Block(block_size(size_of::<DataBlock>())),
108 );
107 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?; 109 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
108 110
109 self.sdmmc.complete_datapath_transfer(transfer, false).await?; 111 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
@@ -113,12 +115,10 @@ impl<'a, 'b> SerialDataInterface<'a, 'b> {
113 } 115 }
114 116
115 /// Read in multibyte mode using cmd53 117 /// Read in multibyte mode using cmd53
116 pub async fn cmd53_byte_read(&mut self, arg: u32, buffer: &mut [u32]) -> Result<(), Error> { 118 pub async fn cmd53_byte_read(&mut self, arg: u32, buffer: &mut Aligned<A4, [u8]>) -> Result<(), Error> {
117 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop(); 119 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
118 120
119 let transfer = self 121 let transfer = self.sdmmc.prepare_datapath_read(buffer, DatapathMode::Byte);
120 .sdmmc
121 .prepare_datapath_read(buffer, block_size(size_of::<DataBlock>()), true);
122 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?; 122 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
123 123
124 self.sdmmc.complete_datapath_transfer(transfer, false).await?; 124 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
@@ -142,9 +142,10 @@ impl<'a, 'b> SerialDataInterface<'a, 'b> {
142 #[cfg(sdmmc_v1)] 142 #[cfg(sdmmc_v1)]
143 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?; 143 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
144 144
145 let transfer = self 145 let transfer = self.sdmmc.prepare_datapath_write(
146 .sdmmc 146 aligned_ref(buffer),
147 .prepare_datapath_read(buffer, block_size(size_of::<DataBlock>()), false); 147 DatapathMode::Block(block_size(size_of::<DataBlock>())),
148 );
148 149
149 #[cfg(sdmmc_v2)] 150 #[cfg(sdmmc_v2)]
150 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?; 151 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
@@ -164,7 +165,7 @@ impl<'a, 'b> SerialDataInterface<'a, 'b> {
164 165
165 let transfer = self 166 let transfer = self
166 .sdmmc 167 .sdmmc
167 .prepare_datapath_write(buffer, block_size(size_of::<DataBlock>()), true); 168 .prepare_datapath_write(aligned_ref(buffer), DatapathMode::Byte);
168 169
169 #[cfg(sdmmc_v2)] 170 #[cfg(sdmmc_v2)]
170 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?; 171 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;