sdmmc/bus/spi/
read.rs

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