sdmmc/
lib.rs

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