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