sdmmc/
lib.rs

1#![doc = include_str!("../README.md")]
2#![doc(hidden)]
3#![cfg_attr(not(any(test, feature = "std")), no_std)]
4
5#[cfg(all(feature = "async", feature = "async-trait"))]
6extern crate alloc;
7#[macro_use]
8extern crate log;
9#[cfg(feature = "spidev")]
10extern crate spidev;
11
12pub mod bus;
13pub mod delay;
14mod sd;
15
16use bus::Error;
17pub use sd::registers::NumBlocks;
18use sd::{registers::CSD, BLOCK_SIZE};
19
20pub struct SD<BUS> {
21    bus: BUS,
22    card: sd::Card,
23    csd: CSD,
24}
25
26type LBA = u32;
27
28#[cfg_attr(not(feature = "async"), deasync::deasync)]
29impl<E, BUS> SD<BUS>
30where
31    BUS: bus::Read<Error = E> + bus::Write<Error = E> + bus::Bus<Error = E>,
32{
33    pub async fn init(mut bus: BUS, card: sd::Card) -> Result<Self, Error<E>> {
34        bus.before()?;
35        let result = bus.read_csd().await;
36        bus.after()?;
37        result.map(|csd| Self { bus, card, csd })
38    }
39
40    pub fn csd(&self) -> CSD {
41        self.csd
42    }
43
44    pub fn bus<R>(&mut self, f: impl Fn(&mut BUS) -> R) -> R {
45        f(&mut self.bus)
46    }
47
48    pub async fn read<'a, B>(&mut self, address: LBA, blocks: B) -> Result<(), Error<E>>
49    where
50        B: core::iter::ExactSizeIterator<Item = &'a mut [u8; BLOCK_SIZE]> + Send,
51    {
52        if blocks.len() == 0 {
53            return Ok(());
54        }
55        self.bus.before()?;
56        let address = if self.card.high_capacity() { address } else { address * BLOCK_SIZE as u32 };
57        let result = self.bus.read(address, blocks).await;
58        self.bus.after().and(result)
59    }
60
61    pub async fn write<'a, B>(&mut self, address: LBA, blocks: B) -> Result<(), Error<E>>
62    where
63        B: core::iter::ExactSizeIterator<Item = &'a [u8; BLOCK_SIZE]> + Send,
64    {
65        if blocks.len() == 0 {
66            return Ok(());
67        }
68        let address = if self.card.high_capacity() { address } else { address * BLOCK_SIZE as u32 };
69        self.bus.before()?;
70        let result = self.bus.write(address, blocks).await;
71        self.bus.after().and(result)
72    }
73
74    pub fn num_blocks(&self) -> NumBlocks {
75        self.csd.num_blocks()
76    }
77
78    pub fn block_size_shift(&self) -> u8 {
79        self.csd.block_size_shift()
80    }
81}