@@ -21,34 +21,74 @@ use crate::{debug, warn};
2121// Types and Implementations
2222// ****************************************************************************
2323
24+ /// A dummy "CS pin" that does nothing when set high or low.
25+ ///
26+ /// Should be used when constructing an [`SpiDevice`] implementation for use with [`SdCard`].
27+ ///
28+ /// Let the [`SpiDevice`] use this dummy CS pin that does not actually do anything, and pass the
29+ /// card's real CS pin to [`SdCard`]'s constructor. This allows the driver to have more
30+ /// fine-grained control of how the CS pin is managed than is allowed by default using the
31+ /// [`SpiDevice`] trait, which is needed to implement the SD/MMC SPI communication spec correctly.
32+ ///
33+ /// If you're not sure how to get a [`SpiDevice`], you may use one of the implementations
34+ /// in the [`embedded-hal-bus`] crate, providing a wrapped version of your platform's HAL-provided
35+ /// [`SpiBus`] and [`DelayNs`] as well as our [`DummyCsPin`] in the constructor.
36+ ///
37+ /// [`SpiDevice`]: embedded_hal::spi::SpiDevice
38+ /// [`SpiBus`]: embedded_hal::spi::SpiBus
39+ /// [`DelayNs`]: embedded_hal::delay::DelayNs
40+ /// [`embedded-hal-bus`]: https://docs.rs/embedded-hal-bus
41+ pub struct DummyCsPin ;
42+
43+ impl embedded_hal:: digital:: ErrorType for DummyCsPin {
44+ type Error = core:: convert:: Infallible ;
45+ }
46+
47+ impl embedded_hal:: digital:: OutputPin for DummyCsPin {
48+ #[ inline( always) ]
49+ fn set_low ( & mut self ) -> Result < ( ) , Self :: Error > {
50+ Ok ( ( ) )
51+ }
52+
53+ #[ inline( always) ]
54+ fn set_high ( & mut self ) -> Result < ( ) , Self :: Error > {
55+ Ok ( ( ) )
56+ }
57+ }
58+
2459/// Represents an SD Card on an SPI bus.
2560///
26- /// Built from an SPI peripheral and a Chip Select pin. We need Chip Select to
27- /// be separate so we can clock out some bytes without Chip Select asserted
28- /// (which "flushes the SD cards registers" according to the spec).
61+ /// Built from an [`SpiDevice`] implementation and a Chip Select pin.
62+ /// Unfortunately, We need control of the chip select pin separately from the [`SpiDevice`]
63+ /// implementation so we can clock out some bytes without Chip Select asserted
64+ /// (which is necessary to make the SD card actually release the Spi bus after performing
65+ /// operations on it, according to the spec). To support this, we provide [`DummyCsPin`]
66+ /// which should be provided to your chosen [`SpiDevice`] implementation rather than the card's
67+ /// actual CS pin. Then provide the actual CS pin to [`SdCard`]'s constructor.
2968///
3069/// All the APIs take `&self` - mutability is handled using an inner `RefCell`.
70+ ///
71+ /// [`SpiDevice`]: embedded_hal::spi::SpiDevice
3172pub struct SdCard < SPI , CS , DELAYER >
3273where
33- SPI : embedded_hal:: blocking:: spi:: Transfer < u8 > + embedded_hal:: blocking:: spi:: Write < u8 > ,
34- CS : embedded_hal:: digital:: v2:: OutputPin ,
35- <SPI as embedded_hal:: blocking:: spi:: Transfer < u8 > >:: Error : core:: fmt:: Debug ,
36- <SPI as embedded_hal:: blocking:: spi:: Write < u8 > >:: Error : core:: fmt:: Debug ,
37- DELAYER : embedded_hal:: blocking:: delay:: DelayUs < u8 > ,
74+ SPI : embedded_hal:: spi:: SpiDevice < u8 > ,
75+ CS : embedded_hal:: digital:: OutputPin ,
76+ DELAYER : embedded_hal:: delay:: DelayNs ,
3877{
3978 inner : RefCell < SdCardInner < SPI , CS , DELAYER > > ,
4079}
4180
4281impl < SPI , CS , DELAYER > SdCard < SPI , CS , DELAYER >
4382where
44- SPI : embedded_hal:: blocking:: spi:: Transfer < u8 > + embedded_hal:: blocking:: spi:: Write < u8 > ,
45- CS : embedded_hal:: digital:: v2:: OutputPin ,
46- <SPI as embedded_hal:: blocking:: spi:: Transfer < u8 > >:: Error : core:: fmt:: Debug ,
47- <SPI as embedded_hal:: blocking:: spi:: Write < u8 > >:: Error : core:: fmt:: Debug ,
48- DELAYER : embedded_hal:: blocking:: delay:: DelayUs < u8 > ,
83+ SPI : embedded_hal:: spi:: SpiDevice < u8 > ,
84+ CS : embedded_hal:: digital:: OutputPin ,
85+ DELAYER : embedded_hal:: delay:: DelayNs ,
4986{
5087 /// Create a new SD/MMC Card driver using a raw SPI interface.
5188 ///
89+ /// See the docs of the [`SdCard`] struct for more information about
90+ /// how to construct the needed `SPI` and `CS` types.
91+ ///
5292 /// The card will not be initialised at this time. Initialisation is
5393 /// deferred until a method is called on the object.
5494 ///
5999
60100 /// Construct a new SD/MMC Card driver, using a raw SPI interface and the given options.
61101 ///
102+ /// See the docs of the [`SdCard`] struct for more information about
103+ /// how to construct the needed `SPI` and `CS` types.
104+ ///
62105 /// The card will not be initialised at this time. Initialisation is
63106 /// deferred until a method is called on the object.
64107 pub fn new_with_options (
@@ -152,11 +195,9 @@ where
152195
153196impl < SPI , CS , DELAYER > BlockDevice for SdCard < SPI , CS , DELAYER >
154197where
155- SPI : embedded_hal:: blocking:: spi:: Transfer < u8 > + embedded_hal:: blocking:: spi:: Write < u8 > ,
156- CS : embedded_hal:: digital:: v2:: OutputPin ,
157- <SPI as embedded_hal:: blocking:: spi:: Transfer < u8 > >:: Error : core:: fmt:: Debug ,
158- <SPI as embedded_hal:: blocking:: spi:: Write < u8 > >:: Error : core:: fmt:: Debug ,
159- DELAYER : embedded_hal:: blocking:: delay:: DelayUs < u8 > ,
198+ SPI : embedded_hal:: spi:: SpiDevice < u8 > ,
199+ CS : embedded_hal:: digital:: OutputPin ,
200+ DELAYER : embedded_hal:: delay:: DelayNs ,
160201{
161202 type Error = Error ;
162203
@@ -205,11 +246,9 @@ where
205246/// All the APIs required `&mut self`.
206247struct SdCardInner < SPI , CS , DELAYER >
207248where
208- SPI : embedded_hal:: blocking:: spi:: Transfer < u8 > + embedded_hal:: blocking:: spi:: Write < u8 > ,
209- CS : embedded_hal:: digital:: v2:: OutputPin ,
210- <SPI as embedded_hal:: blocking:: spi:: Transfer < u8 > >:: Error : core:: fmt:: Debug ,
211- <SPI as embedded_hal:: blocking:: spi:: Write < u8 > >:: Error : core:: fmt:: Debug ,
212- DELAYER : embedded_hal:: blocking:: delay:: DelayUs < u8 > ,
249+ SPI : embedded_hal:: spi:: SpiDevice < u8 > ,
250+ CS : embedded_hal:: digital:: OutputPin ,
251+ DELAYER : embedded_hal:: delay:: DelayNs ,
213252{
214253 spi : SPI ,
215254 cs : CS ,
@@ -220,11 +259,9 @@ where
220259
221260impl < SPI , CS , DELAYER > SdCardInner < SPI , CS , DELAYER >
222261where
223- SPI : embedded_hal:: blocking:: spi:: Transfer < u8 > + embedded_hal:: blocking:: spi:: Write < u8 > ,
224- CS : embedded_hal:: digital:: v2:: OutputPin ,
225- <SPI as embedded_hal:: blocking:: spi:: Transfer < u8 > >:: Error : core:: fmt:: Debug ,
226- <SPI as embedded_hal:: blocking:: spi:: Write < u8 > >:: Error : core:: fmt:: Debug ,
227- DELAYER : embedded_hal:: blocking:: delay:: DelayUs < u8 > ,
262+ SPI : embedded_hal:: spi:: SpiDevice < u8 > ,
263+ CS : embedded_hal:: digital:: OutputPin ,
264+ DELAYER : embedded_hal:: delay:: DelayNs ,
228265{
229266 /// Read one or more blocks, starting at the given block index.
230267 fn read ( & mut self , blocks : & mut [ Block ] , start_block_idx : BlockIdx ) -> Result < ( ) , Error > {
@@ -583,21 +620,24 @@ where
583620
584621 /// Send one byte and receive one byte over the SPI bus.
585622 fn transfer_byte ( & mut self , out : u8 ) -> Result < u8 , Error > {
623+ let mut read_buf = [ 0u8 ; 1 ] ;
586624 self . spi
587- . transfer ( & mut [ out] )
588- . map ( |b| b [ 0 ] )
589- . map_err ( |_e| Error :: Transport )
625+ . transfer ( & mut read_buf , & [ out] )
626+ . map_err ( |_| Error :: Transport ) ? ;
627+ Ok ( read_buf [ 0 ] )
590628 }
591629
592- /// Send mutiple bytes and ignore what comes back over the SPI bus.
630+ /// Send multiple bytes and ignore what comes back over the SPI bus.
593631 fn write_bytes ( & mut self , out : & [ u8 ] ) -> Result < ( ) , Error > {
594632 self . spi . write ( out) . map_err ( |_e| Error :: Transport ) ?;
595633 Ok ( ( ) )
596634 }
597635
598636 /// Send multiple bytes and replace them with what comes back over the SPI bus.
599637 fn transfer_bytes ( & mut self , in_out : & mut [ u8 ] ) -> Result < ( ) , Error > {
600- self . spi . transfer ( in_out) . map_err ( |_e| Error :: Transport ) ?;
638+ self . spi
639+ . transfer_in_place ( in_out)
640+ . map_err ( |_e| Error :: Transport ) ?;
601641 Ok ( ( ) )
602642 }
603643
@@ -689,7 +729,7 @@ pub enum CardType {
689729 /// Uses byte-addressing internally, so limited to 2GiB in size.
690730 SD2 ,
691731 /// An high-capacity 'SDHC' Card.
692- ///
732+ ///
693733 /// Uses block-addressing internally to support capacities above 2GiB.
694734 SDHC ,
695735}
@@ -753,7 +793,7 @@ impl Delay {
753793 /// `Ok(())`.
754794 fn delay < T > ( & mut self , delayer : & mut T , err : Error ) -> Result < ( ) , Error >
755795 where
756- T : embedded_hal:: blocking :: delay:: DelayUs < u8 > ,
796+ T : embedded_hal:: delay:: DelayNs ,
757797 {
758798 if self . retries_left == 0 {
759799 Err ( err)
0 commit comments