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