aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/sdmmc/sd.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/sdmmc/sd.rs')
-rw-r--r--embassy-stm32/src/sdmmc/sd.rs699
1 files changed, 699 insertions, 0 deletions
diff --git a/embassy-stm32/src/sdmmc/sd.rs b/embassy-stm32/src/sdmmc/sd.rs
new file mode 100644
index 000000000..20318bbfa
--- /dev/null
+++ b/embassy-stm32/src/sdmmc/sd.rs
@@ -0,0 +1,699 @@
1use core::default::Default;
2use core::ops::{Deref, DerefMut};
3
4use sdio_host::emmc::{EMMC, ExtCSD};
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};
7
8use crate::sdmmc::{
9 BlockSize, DatapathMode, Error, Sdmmc, Signalling, aligned_mut, aligned_ref, block_size, bus_width_vals,
10 slice8_mut, slice8_ref,
11};
12use crate::time::{Hertz, mhz};
13
14/// Aligned data block for SDMMC transfers.
15///
16/// This is a 512-byte array, aligned to 4 bytes to satisfy DMA requirements.
17#[repr(align(4))]
18#[derive(Debug, Clone, PartialEq, Eq)]
19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20pub struct DataBlock(pub [u32; 128]);
21
22impl DataBlock {
23 /// Create a new DataBlock
24 pub const fn new() -> Self {
25 DataBlock([0u32; 128])
26 }
27}
28
29impl Deref for DataBlock {
30 type Target = [u8; 512];
31
32 fn deref(&self) -> &Self::Target {
33 unwrap!(slice8_ref(&self.0[..]).try_into())
34 }
35}
36
37impl DerefMut for DataBlock {
38 fn deref_mut(&mut self) -> &mut Self::Target {
39 unwrap!(slice8_mut(&mut self.0[..]).try_into())
40 }
41}
42
43/// Command Block buffer for SDMMC command transfers.
44///
45/// This is a 16-word array, exposed so that DMA commpatible memory can be used if required.
46#[derive(Debug, Clone, PartialEq, Eq)]
47#[cfg_attr(feature = "defmt", derive(defmt::Format))]
48pub struct CmdBlock(pub [u32; 16]);
49
50impl CmdBlock {
51 /// Creates a new instance of CmdBlock
52 pub const fn new() -> Self {
53 Self([0u32; 16])
54 }
55}
56
57impl Deref for CmdBlock {
58 type Target = [u32; 16];
59
60 fn deref(&self) -> &Self::Target {
61 &self.0
62 }
63}
64
65impl DerefMut for CmdBlock {
66 fn deref_mut(&mut self) -> &mut Self::Target {
67 &mut self.0
68 }
69}
70
71/// Represents either an SD or EMMC card
72pub trait Addressable: Sized + Clone {
73 /// Associated type
74 type Ext;
75
76 /// Get this peripheral's address on the SDMMC bus
77 fn get_address(&self) -> u16;
78
79 /// Is this a standard or high capacity peripheral?
80 fn get_capacity(&self) -> CardCapacity;
81
82 /// Size in bytes
83 fn size(&self) -> u64;
84}
85
86/// Storage Device
87pub struct StorageDevice<'a, 'b, T: Addressable> {
88 info: T,
89 /// Inner member
90 pub sdmmc: &'a mut Sdmmc<'b>,
91}
92
93/// Card Storage Device
94impl<'a, 'b> StorageDevice<'a, 'b, Card> {
95 /// Create a new SD card
96 pub async fn new_sd_card(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> {
97 let mut s = Self {
98 info: Card::default(),
99 sdmmc,
100 };
101
102 s.acquire(cmd_block, freq).await?;
103
104 Ok(s)
105 }
106
107 /// Initializes the card into a known state (or at least tries to).
108 async fn acquire(&mut self, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<(), Error> {
109 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
110 let regs = self.sdmmc.info.regs;
111
112 let _bus_width = match self.sdmmc.bus_width() {
113 BusWidth::Eight => return Err(Error::BusWidth),
114 bus_width => bus_width,
115 };
116
117 // While the SD/SDIO card or eMMC is in identification mode,
118 // the SDMMC_CK frequency must be no more than 400 kHz.
119 self.sdmmc.init_idle()?;
120
121 // Check if cards supports CMD8 (with pattern)
122 self.sdmmc.cmd(sd_cmd::send_if_cond(1, 0xAA), false)?;
123 let cic = CIC::from(regs.respr(0).read().cardstatus());
124
125 if cic.pattern() != 0xAA {
126 return Err(Error::UnsupportedCardVersion);
127 }
128
129 if cic.voltage_accepted() & 1 == 0 {
130 return Err(Error::UnsupportedVoltage);
131 }
132
133 let ocr = loop {
134 // Signal that next command is a app command
135 self.sdmmc.cmd(common_cmd::app_cmd(0), false)?; // CMD55
136
137 // 3.2-3.3V
138 let voltage_window = 1 << 5;
139 // Initialize card
140 match self
141 .sdmmc
142 .cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window), false)
143 {
144 // ACMD41
145 Ok(_) => (),
146 Err(Error::Crc) => (),
147 Err(err) => return Err(err),
148 }
149
150 let ocr: OCR<SD> = regs.respr(0).read().cardstatus().into();
151 if !ocr.is_busy() {
152 // Power up done
153 break ocr;
154 }
155 };
156
157 if ocr.high_capacity() {
158 // Card is SDHC or SDXC or SDUC
159 self.info.card_type = CardCapacity::HighCapacity;
160 } else {
161 self.info.card_type = CardCapacity::StandardCapacity;
162 }
163 self.info.ocr = ocr;
164
165 self.info.cid = self.sdmmc.get_cid()?.into();
166
167 self.sdmmc.cmd(sd_cmd::send_relative_address(), false)?;
168 let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus());
169 self.info.rca = rca.address();
170
171 self.info.csd = self.sdmmc.get_csd(self.info.get_address())?.into();
172 self.sdmmc.select_card(Some(self.info.get_address()))?;
173
174 self.info.scr = self.get_scr(cmd_block).await?;
175
176 let (bus_width, acmd_arg) = if !self.info.scr.bus_width_four() {
177 (BusWidth::One, 0)
178 } else {
179 (BusWidth::Four, 2)
180 };
181
182 self.sdmmc.cmd(common_cmd::app_cmd(self.info.rca), false)?;
183 self.sdmmc.cmd(sd_cmd::cmd6(acmd_arg), false)?;
184
185 self.sdmmc.clkcr_set_clkdiv(freq.clamp(mhz(0), mhz(25)), bus_width)?;
186
187 // Read status
188 self.info.status = self.read_sd_status(cmd_block).await?;
189
190 if freq > mhz(25) {
191 // Switch to SDR25
192 self.sdmmc.signalling = self.switch_signalling_mode(cmd_block, Signalling::SDR25).await?;
193
194 if self.sdmmc.signalling == Signalling::SDR25 {
195 // Set final clock frequency
196 self.sdmmc.clkcr_set_clkdiv(freq, bus_width)?;
197
198 if self.sdmmc.read_status(&self.info)?.state() != CurrentState::Transfer {
199 return Err(Error::SignalingSwitchFailed);
200 }
201 }
202
203 // Read status after signalling change
204 self.read_sd_status(cmd_block).await?;
205 }
206
207 Ok(())
208 }
209
210 /// Switch mode using CMD6.
211 ///
212 /// Attempt to set a new signalling mode. The selected
213 /// signalling mode is returned. Expects the current clock
214 /// frequency to be > 12.5MHz.
215 ///
216 /// SD only.
217 async fn switch_signalling_mode(
218 &self,
219 cmd_block: &mut CmdBlock,
220 signalling: Signalling,
221 ) -> Result<Signalling, Error> {
222 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
223 // necessary"
224
225 let set_function = 0x8000_0000
226 | match signalling {
227 // See PLSS v7_10 Table 4-11
228 Signalling::DDR50 => 0xFF_FF04,
229 Signalling::SDR104 => 0xFF_1F03,
230 Signalling::SDR50 => 0xFF_1F02,
231 Signalling::SDR25 => 0xFF_FF01,
232 Signalling::SDR12 => 0xFF_FF00,
233 };
234
235 let buffer = &mut cmd_block.0[..64 / 4];
236 let mode = DatapathMode::Block(block_size(size_of_val(buffer)));
237 let transfer = self.sdmmc.prepare_datapath_read(aligned_mut(buffer), mode);
238
239 self.sdmmc.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
240
241 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
242
243 // Host is allowed to use the new functions at least 8
244 // clocks after the end of the switch command
245 // transaction. We know the current clock period is < 80ns,
246 // so a total delay of 640ns is required here
247 for _ in 0..300 {
248 cortex_m::asm::nop();
249 }
250
251 // Function Selection of Function Group 1
252 let selection = (u32::from_be(cmd_block[4]) >> 24) & 0xF;
253
254 match selection {
255 0 => Ok(Signalling::SDR12),
256 1 => Ok(Signalling::SDR25),
257 2 => Ok(Signalling::SDR50),
258 3 => Ok(Signalling::SDR104),
259 4 => Ok(Signalling::DDR50),
260 _ => Err(Error::UnsupportedCardType),
261 }
262 }
263
264 /// Reads the SCR register.
265 ///
266 /// SD only.
267 async fn get_scr(&self, cmd_block: &mut CmdBlock) -> Result<SCR, Error> {
268 // Read the 64-bit SCR register
269 self.sdmmc.cmd(common_cmd::set_block_length(8), false)?; // CMD16
270 self.sdmmc.cmd(common_cmd::app_cmd(self.info.rca), false)?;
271
272 let scr = &mut cmd_block.0[..2];
273
274 // Arm `OnDrop` after the buffer, so it will be dropped first
275
276 let transfer = self
277 .sdmmc
278 .prepare_datapath_read(aligned_mut(scr), DatapathMode::Block(BlockSize::Size8));
279 self.sdmmc.cmd(sd_cmd::send_scr(), true)?;
280
281 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
282
283 Ok(SCR(u64::from_be_bytes(unwrap!(slice8_mut(scr).try_into()))))
284 }
285
286 /// Reads the SD Status (ACMD13)
287 ///
288 /// SD only.
289 async fn read_sd_status(&self, cmd_block: &mut CmdBlock) -> Result<SDStatus, Error> {
290 let rca = self.info.rca;
291
292 self.sdmmc.cmd(common_cmd::set_block_length(64), false)?; // CMD16
293 self.sdmmc.cmd(common_cmd::app_cmd(rca), false)?; // APP
294
295 let buffer = &mut cmd_block.as_mut()[..64 / 4];
296 let mode = DatapathMode::Block(block_size(size_of_val(buffer)));
297
298 let transfer = self.sdmmc.prepare_datapath_read(aligned_mut(buffer), mode);
299 self.sdmmc.cmd(sd_cmd::sd_status(), true)?;
300
301 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
302
303 for byte in cmd_block.iter_mut() {
304 *byte = u32::from_be(*byte);
305 }
306
307 Ok(cmd_block.0.into())
308 }
309}
310
311/// Emmc storage device
312impl<'a, 'b> StorageDevice<'a, 'b, Emmc> {
313 /// Create a new EMMC card
314 pub async fn new_emmc(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> {
315 let mut s = Self {
316 info: Emmc::default(),
317 sdmmc,
318 };
319
320 s.acquire(cmd_block, freq).await?;
321
322 Ok(s)
323 }
324
325 async fn acquire(&mut self, _cmd_block: &mut CmdBlock, freq: Hertz) -> Result<(), Error> {
326 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
327 let regs = self.sdmmc.info.regs;
328
329 let bus_width = self.sdmmc.bus_width();
330
331 // While the SD/SDIO card or eMMC is in identification mode,
332 // the SDMMC_CK frequency must be no more than 400 kHz.
333 self.sdmmc.init_idle()?;
334
335 let ocr = loop {
336 let high_voltage = 0b0 << 7;
337 let access_mode = 0b10 << 29;
338 let op_cond = high_voltage | access_mode | 0b1_1111_1111 << 15;
339 // Initialize card
340 match self.sdmmc.cmd(emmc_cmd::send_op_cond(op_cond), false) {
341 Ok(_) => (),
342 Err(Error::Crc) => (),
343 Err(err) => return Err(err),
344 }
345 let ocr: OCR<EMMC> = regs.respr(0).read().cardstatus().into();
346 if !ocr.is_busy() {
347 // Power up done
348 break ocr;
349 }
350 };
351
352 self.info.capacity = if ocr.access_mode() == 0b10 {
353 // Card is SDHC or SDXC or SDUC
354 CardCapacity::HighCapacity
355 } else {
356 CardCapacity::StandardCapacity
357 };
358 self.info.ocr = ocr;
359
360 self.info.cid = self.sdmmc.get_cid()?.into();
361
362 self.info.rca = 1u16.into();
363 self.sdmmc
364 .cmd(emmc_cmd::assign_relative_address(self.info.rca), false)?;
365
366 self.info.csd = self.sdmmc.get_csd(self.info.get_address())?.into();
367 self.sdmmc.select_card(Some(self.info.get_address()))?;
368
369 let (widbus, _) = bus_width_vals(bus_width);
370
371 // Write bus width to ExtCSD byte 183
372 self.sdmmc.cmd(
373 emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus),
374 false,
375 )?;
376
377 // Wait for ready after R1b response
378 loop {
379 let status = self.sdmmc.read_status(&self.info)?;
380
381 if status.ready_for_data() {
382 break;
383 }
384 }
385
386 self.sdmmc.clkcr_set_clkdiv(freq.clamp(mhz(0), mhz(25)), bus_width)?;
387 self.info.ext_csd = self.read_ext_csd().await?;
388
389 Ok(())
390 }
391
392 /// Gets the EXT_CSD register.
393 ///
394 /// eMMC only.
395 async fn read_ext_csd(&self) -> Result<ExtCSD, Error> {
396 // Note: cmd_block can't be used because ExtCSD is too long to fit.
397 let mut data_block = DataBlock::new();
398
399 self.sdmmc
400 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)
401 .unwrap(); // CMD16
402
403 let transfer = self.sdmmc.prepare_datapath_read(
404 aligned_mut(&mut data_block.0),
405 DatapathMode::Block(block_size(size_of::<DataBlock>())),
406 );
407 self.sdmmc.cmd(emmc_cmd::send_ext_csd(), true)?;
408
409 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
410
411 Ok(data_block.0.into())
412 }
413}
414
415/// Card or Emmc storage device
416impl<'a, 'b, A: Addressable> StorageDevice<'a, 'b, A> {
417 /// Write a block
418 pub fn card(&self) -> A {
419 self.info.clone()
420 }
421
422 /// Read a data block.
423 #[inline]
424 pub async fn read_block(&mut self, block_idx: u32, data_block: &mut DataBlock) -> Result<(), Error> {
425 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
426 let card_capacity = self.info.get_capacity();
427
428 // Always read 1 block of 512 bytes
429 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
430 let address = match card_capacity {
431 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
432 _ => block_idx,
433 };
434 self.sdmmc
435 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
436
437 let transfer = self.sdmmc.prepare_datapath_read(
438 aligned_mut(&mut data_block.0),
439 DatapathMode::Block(block_size(size_of::<DataBlock>())),
440 );
441 self.sdmmc.cmd(common_cmd::read_single_block(address), true)?;
442
443 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
444
445 Ok(())
446 }
447
448 /// Read multiple data blocks.
449 #[inline]
450 pub async fn read_blocks(&mut self, block_idx: u32, blocks: &mut [DataBlock]) -> Result<(), Error> {
451 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
452 let card_capacity = self.info.get_capacity();
453
454 // NOTE(unsafe) reinterpret buffer as &mut [u32]
455 let buffer = unsafe {
456 core::slice::from_raw_parts_mut(
457 blocks.as_mut_ptr() as *mut u32,
458 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
459 )
460 };
461
462 // Always read 1 block of 512 bytes
463 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
464 let address = match card_capacity {
465 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
466 _ => block_idx,
467 };
468 self.sdmmc
469 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
470
471 let transfer = self.sdmmc.prepare_datapath_read(
472 aligned_mut(buffer),
473 DatapathMode::Block(block_size(size_of::<DataBlock>())),
474 );
475 self.sdmmc.cmd(common_cmd::read_multiple_blocks(address), true)?;
476
477 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
478
479 self.sdmmc.cmd(common_cmd::stop_transmission(), false)?; // CMD12
480 self.sdmmc.clear_interrupt_flags();
481
482 Ok(())
483 }
484
485 /// Write a data block.
486 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error>
487 where
488 CardStatus<A::Ext>: From<u32>,
489 {
490 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
491
492 // Always read 1 block of 512 bytes
493 // cards are byte addressed hence the blockaddress is in multiples of 512 bytes
494 let address = match self.info.get_capacity() {
495 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
496 _ => block_idx,
497 };
498 self.sdmmc
499 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
500
501 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
502 #[cfg(sdmmc_v1)]
503 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?;
504
505 let transfer = self.sdmmc.prepare_datapath_write(
506 aligned_ref(&buffer.0),
507 DatapathMode::Block(block_size(size_of::<DataBlock>())),
508 );
509
510 #[cfg(sdmmc_v2)]
511 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?;
512
513 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
514
515 // TODO: Make this configurable
516 let mut timeout: u32 = 0x00FF_FFFF;
517
518 while timeout > 0 {
519 let ready_for_data = self.sdmmc.read_status(&self.info)?.ready_for_data();
520 if ready_for_data {
521 return Ok(());
522 }
523 timeout -= 1;
524 }
525
526 Err(Error::SoftwareTimeout)
527 }
528
529 /// Write multiple data blocks.
530 pub async fn write_blocks(&mut self, block_idx: u32, blocks: &[DataBlock]) -> Result<(), Error>
531 where
532 CardStatus<A::Ext>: From<u32>,
533 {
534 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
535
536 // NOTE(unsafe) reinterpret buffer as &[u32]
537 let buffer = unsafe {
538 core::slice::from_raw_parts(
539 blocks.as_ptr() as *const u32,
540 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
541 )
542 };
543 // Always read 1 block of 512 bytes
544 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
545 let address = match self.info.get_capacity() {
546 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
547 _ => block_idx,
548 };
549
550 self.sdmmc
551 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
552
553 #[cfg(sdmmc_v1)]
554 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
555
556 // Setup write command
557 let transfer = self.sdmmc.prepare_datapath_write(
558 aligned_ref(buffer),
559 DatapathMode::Block(block_size(size_of::<DataBlock>())),
560 );
561 #[cfg(sdmmc_v2)]
562 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
563
564 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
565
566 self.sdmmc.cmd(common_cmd::stop_transmission(), false)?; // CMD12
567 self.sdmmc.clear_interrupt_flags();
568
569 // TODO: Make this configurable
570 let mut timeout: u32 = 0x00FF_FFFF;
571
572 while timeout > 0 {
573 let ready_for_data = self.sdmmc.read_status(&self.info)?.ready_for_data();
574
575 if ready_for_data {
576 return Ok(());
577 }
578 timeout -= 1;
579 }
580 Err(Error::SoftwareTimeout)
581 }
582}
583
584#[derive(Clone, Copy, Debug, Default)]
585/// SD Card
586pub struct Card {
587 /// The type of this card
588 pub card_type: CardCapacity,
589 /// Operation Conditions Register
590 pub ocr: OCR<SD>,
591 /// Relative Card Address
592 pub rca: u16,
593 /// Card ID
594 pub cid: CID<SD>,
595 /// Card Specific Data
596 pub csd: CSD<SD>,
597 /// SD CARD Configuration Register
598 pub scr: SCR,
599 /// SD Status
600 pub status: SDStatus,
601}
602
603impl Addressable for Card {
604 type Ext = SD;
605
606 /// Get this peripheral's address on the SDMMC bus
607 fn get_address(&self) -> u16 {
608 self.rca
609 }
610
611 /// Is this a standard or high capacity peripheral?
612 fn get_capacity(&self) -> CardCapacity {
613 self.card_type
614 }
615
616 /// Size in bytes
617 fn size(&self) -> u64 {
618 u64::from(self.csd.block_count()) * 512
619 }
620}
621
622#[derive(Clone, Copy, Debug, Default)]
623/// eMMC storage
624pub struct Emmc {
625 /// The capacity of this card
626 pub capacity: CardCapacity,
627 /// Operation Conditions Register
628 pub ocr: OCR<EMMC>,
629 /// Relative Card Address
630 pub rca: u16,
631 /// Card ID
632 pub cid: CID<EMMC>,
633 /// Card Specific Data
634 pub csd: CSD<EMMC>,
635 /// Extended Card Specific Data
636 pub ext_csd: ExtCSD,
637}
638
639impl Addressable for Emmc {
640 type Ext = EMMC;
641
642 /// Get this peripheral's address on the SDMMC bus
643 fn get_address(&self) -> u16 {
644 self.rca
645 }
646
647 /// Is this a standard or high capacity peripheral?
648 fn get_capacity(&self) -> CardCapacity {
649 self.capacity
650 }
651
652 /// Size in bytes
653 fn size(&self) -> u64 {
654 u64::from(self.ext_csd.sector_count()) * 512
655 }
656}
657
658impl<'d, 'e, A: Addressable> block_device_driver::BlockDevice<512> for StorageDevice<'d, 'e, A> {
659 type Error = Error;
660 type Align = aligned::A4;
661
662 async fn read(
663 &mut self,
664 block_address: u32,
665 buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>],
666 ) -> Result<(), Self::Error> {
667 // TODO: I think block_address needs to be adjusted by the partition start offset
668 if buf.len() == 1 {
669 let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut DataBlock) };
670 self.read_block(block_address, block).await?;
671 } else {
672 let blocks: &mut [DataBlock] =
673 unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut DataBlock, buf.len()) };
674 self.read_blocks(block_address, blocks).await?;
675 }
676 Ok(())
677 }
678
679 async fn write(
680 &mut self,
681 block_address: u32,
682 buf: &[aligned::Aligned<Self::Align, [u8; 512]>],
683 ) -> Result<(), Self::Error> {
684 // TODO: I think block_address needs to be adjusted by the partition start offset
685 if buf.len() == 1 {
686 let block = unsafe { &*(&buf[0] as *const _ as *const DataBlock) };
687 self.write_block(block_address, block).await?;
688 } else {
689 let blocks: &[DataBlock] =
690 unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const DataBlock, buf.len()) };
691 self.write_blocks(block_address, blocks).await?;
692 }
693 Ok(())
694 }
695
696 async fn size(&mut self) -> Result<u64, Self::Error> {
697 Ok(self.info.size())
698 }
699}