1use crate::spi::{InnerDelay, SpiBusWrapper, SpiInitError};
2use esp_hal::gpio::{Level, Output, OutputConfig};
3use esp_hal::peripherals::GPIO16;
4
5use sdmmc;
6use embedded_timers::{clock::Clock, instant::TimespecInstant};
7
8pub struct SdDelay(pub InnerDelay);
17
18#[cfg(feature = "blocking")]
19impl embedded_hal::delay::DelayNs for SdDelay {
20 fn delay_ns(&mut self, ns: u32) {
21 self.0.delay_ns(ns)
22 }
23}
24
25#[cfg(feature = "async")]
26impl sdmmc::delay::Delay for SdDelay {
27 type Future = embassy_time::Timer;
28
29 fn delay_ms(&mut self, ms: u32) -> Self::Future {
30 let _ = &mut self.0;
31 embassy_time::Timer::after_millis(ms as u64)
32 }
33}
34
35pub struct SdClock;
43
44impl Clock for SdClock {
45 type Instant = TimespecInstant;
46
47 fn now(&self) -> Self::Instant {
48 #[cfg(feature = "async")]
49 let now = embassy_time::Instant::now().as_millis();
50 #[cfg(feature = "blocking")]
51 let now = esp_hal::time::Instant::now()
52 .duration_since_epoch()
53 .as_millis();
54 TimespecInstant::new((now / 1000) as u32, ((now % 1000) * 1_000_000) as u32)
55 }
56}
57
58pub struct SdSpi<'a>(pub &'a SpiBusWrapper);
63
64pub type SdBus<'a> = sdmmc::bus::spi::Bus<SdSpi<'a>, Output<'a>, SdClock>;
66
67pub type SDC<'a> = sdmmc::SD<SdBus<'a>>;
87pub type SdVolMgr<'a> = SDC<'a>;
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq)]
96pub enum SdInitError {
97 SpiDevice(SpiInitError),
99 CardInitFailed,
101}
102
103#[cfg(feature = "AtomicBus")]
104compile_error!("AtomicBus is not supported with async-sdmmc");
105
106impl SdInitError {
107 pub const fn as_str(self) -> &'static str {
109 match self {
110 Self::SpiDevice(err) => err.as_str(),
111 Self::CardInitFailed => "SD card init failed",
112 }
113 }
114}
115
116#[cfg(feature = "blocking")]
117impl<'a> sdmmc::bus::spi::Transfer for SdSpi<'a> {
118 type Error = SpiInitError;
119
120 fn transfer(&mut self, tx: &[u8], rx: &mut [u8]) -> Result<(), Self::Error> {
121 #[cfg(feature = "RefCellBus")]
122 {
123 let bus = &mut *self.0.borrow_mut();
124 match (!tx.is_empty(), !rx.is_empty()) {
125 (true, true) => {
126 let n = core::cmp::min(tx.len(), rx.len());
127 rx[..n].copy_from_slice(&tx[..n]);
128 embedded_hal::spi::SpiBus::transfer_in_place(bus, &mut rx[..n])
129 .map_err(|_| SpiInitError::DeviceInitFailed)?;
130 Ok(())
131 }
132 (true, false) => embedded_hal::spi::SpiBus::write(bus, tx)
133 .map_err(|_| SpiInitError::DeviceInitFailed),
134 (false, true) => embedded_hal::spi::SpiBus::read(bus, rx)
135 .map_err(|_| SpiInitError::DeviceInitFailed),
136 _ => Ok(()),
137 }
138 }
139 #[cfg(feature = "CriticalSectionBus")]
140 {
141 self.0.lock(|bus| {
142 let mut bus = bus.borrow_mut();
143 match (!tx.is_empty(), !rx.is_empty()) {
144 (true, true) => {
145 let n = core::cmp::min(tx.len(), rx.len());
146 rx[..n].copy_from_slice(&tx[..n]);
147 embedded_hal::spi::SpiBus::transfer_in_place(&mut *bus, &mut rx[..n])
148 .map_err(|_| SpiInitError::DeviceInitFailed)?;
149 Ok(())
150 }
151 (true, false) => embedded_hal::spi::SpiBus::write(&mut *bus, tx)
152 .map_err(|_| SpiInitError::DeviceInitFailed),
153 (false, true) => embedded_hal::spi::SpiBus::read(&mut *bus, rx)
154 .map_err(|_| SpiInitError::DeviceInitFailed),
155 _ => Ok(()),
156 }
157 })
158 }
159 }
160}
161
162#[cfg(feature = "async")]
163impl<'a> sdmmc::bus::spi::Transfer for SdSpi<'a> {
164 type Error = SpiInitError;
165
166 async fn transfer(&mut self, tx: &[u8], rx: &mut [u8]) -> Result<(), Self::Error> {
167 let mut guard = self.0.lock().await;
168 match (!tx.is_empty(), !rx.is_empty()) {
169 (true, true) => {
170 let n = core::cmp::min(tx.len(), rx.len());
171 rx[..n].copy_from_slice(&tx[..n]);
172 embedded_hal_async::spi::SpiBus::transfer_in_place(&mut *guard, &mut rx[..n])
173 .await
174 .map_err(|_| SpiInitError::DeviceInitFailed)?;
175 Ok(())
176 }
177 (true, false) => embedded_hal_async::spi::SpiBus::write(&mut *guard, tx)
178 .await
179 .map_err(|_| SpiInitError::DeviceInitFailed),
180 (false, true) => embedded_hal_async::spi::SpiBus::read(&mut *guard, rx)
181 .await
182 .map_err(|_| SpiInitError::DeviceInitFailed),
183 _ => Ok(()),
184 }
185 }
186}
187
188#[cfg_attr(not(feature = "async"), deasync::deasync)]
214pub async fn init_sd<'a>(
215 spi_bus: &'a SpiBusWrapper,
216 sd_cs: GPIO16<'a>,
217 delay: SdDelay,
218) -> Result<SDC<'a>, SdInitError> {
219 let sd_cs = Output::new(sd_cs, Level::Low, OutputConfig::default());
220 let mut bus = SdBus::new(SdSpi(spi_bus), sd_cs, SdClock);
221 let card = bus.init(delay).await.map_err(|_| SdInitError::CardInitFailed)?;
222 let sd = sdmmc::SD::init(bus, card)
223 .await
224 .map_err(|_| SdInitError::CardInitFailed)?;
225
226 Ok(sd)
227}