sdmmc/bus/spi/
read.rs

1#[cfg(all(feature = "async", feature = "async-trait"))]
2use alloc::boxed::Box;
3use core::time::Duration;
4use core::{convert::TryFrom, slice};
5
6use embedded_hal::digital::OutputPin;
7use embedded_timers::{clock::Clock, instant::Instant};
8
9use crate::{
10    bus::Read,
11    sd::{
12        command::Command,
13        registers::CSD,
14        transfer::{Token, TokenError},
15        BLOCK_SIZE,
16    },
17};
18
19use super::bus::{BUSError, Bus, Error, Transfer};
20
21impl<E, F, SPI, CS, C, I> Bus<SPI, CS, C>
22where
23    SPI: Transfer<Error = E> + Send,
24    CS: OutputPin<Error = F> + Send,
25    C: Clock<Instant = I> + Send,
26    I: Instant,
27{
28    #[cfg_attr(not(feature = "async"), deasync::deasync)]
29    pub(crate) async fn read_block(&mut self, block: &mut [u8]) -> Result<(), BUSError<E, F>> {
30        let deadline = self.clock.now() + Duration::from_millis(100);
31        let token = loop {
32            if self.clock.now() > deadline {
33                return Err(BUSError::Timeout);
34            }
35            let mut byte = 0u8;
36            self.rx(slice::from_mut(&mut byte)).await?;
37            if byte == 0xFF {
38                continue;
39            }
40            match Token::try_from(byte) {
41                Ok(token) => break token,
42                Err(TokenError::NotToken) => continue,
43                Err(e) => return Err(BUSError::Transfer(e)),
44            }
45        };
46        if token != Token::Start {
47            return Err(BUSError::Generic);
48        }
49        self.rx(block).await?;
50        let mut crc = [0u8; 2];
51        self.rx(&mut crc).await
52    }
53}
54
55#[cfg_attr(all(feature = "async", feature = "async-trait"), async_trait::async_trait)]
56#[cfg_attr(not(feature = "async"), deasync::deasync)]
57impl<E, F, SPI, CS, C, I> Read for Bus<SPI, CS, C>
58where
59    SPI: Transfer<Error = E> + Send,
60    CS: OutputPin<Error = F> + Send,
61    C: Clock<Instant = I> + Send,
62    I: Instant,
63{
64    type Error = Error<E, F>;
65
66    async fn read_csd(&mut self) -> Result<CSD, BUSError<E, F>> {
67        self.tx(&[0xFF; 5]).await?;
68        self.select()?;
69        self.send_command(Command::SendCSD(0)).await?;
70        let mut buffer = [0u8; 16];
71        self.read_block(&mut buffer).await?;
72        self.deselect()?;
73        self.tx(&[0xFF]).await?; // Extra byte to release MISO
74        CSD::try_from(u128::from_be_bytes(buffer)).ok_or(BUSError::Generic)
75    }
76
77    async fn read<'a, B>(&mut self, address: u32, blocks: B) -> Result<(), BUSError<E, F>>
78    where
79        B: core::iter::ExactSizeIterator<Item = &'a mut [u8; BLOCK_SIZE]> + Send,
80    {
81        self.tx(&[0xFF; 5]).await?;
82        self.select()?;
83        let num_blocks = blocks.len();
84        let cmd = match num_blocks {
85            1 => Command::ReadSingleBlock(address),
86            _ => Command::ReadMultipleBlock(address),
87        };
88        self.send_command(cmd).await?;
89        for block in blocks {
90            self.read_block(block).await?;
91        }
92        if num_blocks > 1 {
93            self.send_command(Command::StopTransmission).await?;
94            self.wait(Duration::from_millis(100)).await?;
95        }
96        self.deselect()?;
97        self.tx(&[0xFF]).await // Extra byte to release MISO
98    }
99}