sdmmc/bus/spi/
bus.rs

1#[cfg(feature = "async")]
2use alloc::boxed::Box;
3use core::slice;
4#[cfg(not(feature = "fugit"))]
5use core::time::Duration;
6
7#[cfg(not(feature = "async"))]
8use embedded_hal::blocking::spi;
9use embedded_hal::{digital::v2::OutputPin, timer::CountDown};
10#[cfg(feature = "fugit")]
11use fugit::NanosDurationU32 as Duration;
12
13use crate::sd::{
14    command::{AppCommand, Command},
15    response::{self, Response},
16};
17
18use crate::bus;
19
20#[derive(Debug)]
21pub enum Error<SPI, CS> {
22    SPI(SPI),
23    CS(CS),
24}
25
26pub type BUSError<SPI, CS> = bus::Error<Error<SPI, CS>>;
27
28#[cfg_attr(feature = "async", async_trait::async_trait)]
29#[cfg_attr(not(feature = "async"), deasync::deasync)]
30pub trait Transfer {
31    type Error;
32    async fn transfer(&mut self, tx: &[u8], rx: &mut [u8]) -> Result<(), Self::Error>;
33}
34
35#[cfg(not(feature = "async"))]
36impl<E, T: spi::Transfer<u8, Error = E>> Transfer for T {
37    type Error = E;
38
39    fn transfer(&mut self, tx: &[u8], rx: &mut [u8]) -> Result<(), Self::Error> {
40        rx.copy_from_slice(tx);
41        self.transfer(rx).map(|_| ())
42    }
43}
44
45pub struct Bus<SPI, CS, C> {
46    spi: SPI,
47    cs: CS,
48    pub(crate) countdown: C,
49}
50
51impl<E, SPI, CS, C> Bus<SPI, CS, C>
52where
53    CS: OutputPin<Error = E>,
54    C: CountDown<Time = Duration>,
55{
56    pub fn new(spi: SPI, cs: CS, countdown: C) -> Self {
57        Self { spi, cs, countdown }
58    }
59
60    pub fn spi<R>(&mut self, f: impl Fn(&mut SPI) -> R) -> R {
61        f(&mut self.spi)
62    }
63
64    pub(crate) fn select<T>(&mut self) -> Result<(), BUSError<T, E>> {
65        self.cs.set_low().map_err(|e| BUSError::BUS(Error::CS(e)))
66    }
67
68    pub(crate) fn deselect<T>(&mut self) -> Result<(), BUSError<T, E>> {
69        self.cs.set_high().map_err(|e| BUSError::BUS(Error::CS(e)))
70    }
71}
72
73#[cfg_attr(not(feature = "async"), deasync::deasync)]
74impl<E, F, SPI, CS, C> Bus<SPI, CS, C>
75where
76    SPI: Transfer<Error = E>,
77    CS: OutputPin<Error = F>,
78    C: CountDown<Time = Duration>,
79{
80    pub(crate) async fn tx(&mut self, bytes: &[u8]) -> Result<(), BUSError<E, F>> {
81        self.spi.transfer(bytes, &mut []).await.map_err(|e| BUSError::BUS(Error::SPI(e)))
82    }
83
84    pub(crate) async fn rx(&mut self, buffer: &mut [u8]) -> Result<(), BUSError<E, F>> {
85        self.spi.transfer(&[], buffer).await.map_err(|e| BUSError::BUS(Error::SPI(e)))
86    }
87
88    pub(crate) async fn wait(&mut self, timeout: Duration) -> Result<(), BUSError<E, F>> {
89        self.countdown.start(timeout);
90        let mut byte = 0u8;
91        while byte != 0xFFu8 {
92            if self.countdown.wait().is_ok() {
93                return Err(BUSError::Timeout);
94            }
95            self.rx(slice::from_mut(&mut byte)).await?;
96        }
97        Ok(())
98    }
99
100    pub(crate) async fn send_command(&mut self, cmd: Command) -> Result<Response, BUSError<E, F>> {
101        let bytes: [u8; 6] = cmd.into();
102        trace!("Send CMD {:?} bytes {:X?}", cmd, &bytes);
103        self.tx(&bytes[..]).await?;
104
105        if cmd == Command::StopTransmission {
106            self.rx(&mut [0u8]).await?; // Skip stuff byte
107        }
108
109        // Skip Ncr, 0~8 bytes for SDC, 1~8 bytes for MMC
110        let mut r1 = response::R1::default();
111        for _ in 0..=8 {
112            self.rx(slice::from_mut(&mut r1.0)).await?;
113            if r1.valid() {
114                break;
115            }
116        }
117        if !r1.valid() {
118            return Err(BUSError::NoResponse);
119        }
120
121        if let Some(e) = r1.error() {
122            return Err(BUSError::Command(e));
123        }
124        let mut response = Response { r1, ..Default::default() };
125
126        let size = cmd.expected_response_ex_size();
127        if size > 0 {
128            let mut buffer = [0u8; 4];
129            self.rx(&mut buffer[4 - size..]).await?;
130            response.ex = u32::from_be_bytes(buffer);
131        }
132        Ok(response)
133    }
134
135    pub(crate) async fn send_app_command(
136        &mut self,
137        cmd: AppCommand,
138    ) -> Result<Response, BUSError<E, F>> {
139        self.send_command(Command::AppCommand(0)).await?;
140        self.send_command(Command::App(cmd)).await
141    }
142}
143
144impl<E, F, SPI, CS, C> bus::Bus for Bus<SPI, CS, C>
145where
146    SPI: Transfer<Error = E>,
147    CS: OutputPin<Error = F>,
148    C: CountDown<Time = Duration>,
149{
150    type Error = Error<E, F>;
151
152    fn before(&mut self) -> Result<(), BUSError<E, F>> {
153        Ok(())
154    }
155
156    fn after(&mut self) -> Result<(), BUSError<E, F>> {
157        self.deselect()
158    }
159}
160
161pub(crate) fn millis(millis: u32) -> Duration {
162    match () {
163        #[cfg(not(feature = "fugit"))]
164        () => Duration::from_millis(millis as u64),
165        #[cfg(feature = "fugit")]
166        () => Duration::millis(millis),
167    }
168}