1#[cfg(feature = "alloc")]
2pub use sdcard::*;
3
4#[cfg(esp_idf_soc_sdmmc_host_supported)]
5pub mod mmc;
6pub mod spi;
7
8#[cfg(feature = "alloc")]
9mod sdcard {
10 #[cfg(esp_idf_soc_sdmmc_host_supported)]
11 use super::mmc::SdMmcHostDriver;
12 use super::spi::SdSpiHostDriver;
13
14 use core::borrow::Borrow;
15
16 use crate::spi::SpiDriver;
17 use crate::sys::*;
18
19 extern crate alloc;
20
21 const _SDMMC_HOST_FLAG_SPI: u32 = 1 << 3;
22 const _SDMMC_HOST_FLAG_DDR: u32 = 1 << 4;
23 const _SDMMC_HOST_FLAG_DEINIT_ARG: u32 = 1 << 5;
24
25 pub type SdCardConfiguration = config::Configuration;
26
27 pub mod config {
28 #[cfg(not(any(
29 esp_idf_version_major = "4",
30 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
31 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
32 )))] use crate::sys::*;
34
35 #[cfg(not(any(
37 esp_idf_version_major = "4",
38 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
39 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
40 )))] #[non_exhaustive]
42 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
43 pub enum DelayPhase {
44 Phase0 = sdmmc_delay_phase_t_SDMMC_DELAY_PHASE_0 as isize,
45 Phase1 = sdmmc_delay_phase_t_SDMMC_DELAY_PHASE_1 as isize,
46 Phase2 = sdmmc_delay_phase_t_SDMMC_DELAY_PHASE_2 as isize,
47 Phase3 = sdmmc_delay_phase_t_SDMMC_DELAY_PHASE_3 as isize,
48 }
49
50 #[non_exhaustive]
70 #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
71 pub enum Voltage {
72 V1P8,
78 #[default]
81 V3P3,
82 }
83
84 impl Voltage {
85 pub(crate) const fn as_native(&self) -> f32 {
86 match self {
87 Self::V1P8 => 1.8,
88 Self::V3P3 => 3.3,
89 }
90 }
91 }
92
93 #[cfg(not(any(
95 esp_idf_version_major = "4",
96 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
97 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
98 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
99 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
100 )))] #[non_exhaustive]
102 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
103 pub enum DriverStrength {
104 StrengthB = sdmmc_driver_strength_t_SDMMC_DRIVER_STRENGTH_B as isize,
106 StrengthA = sdmmc_driver_strength_t_SDMMC_DRIVER_STRENGTH_A as isize,
108 StrengthC = sdmmc_driver_strength_t_SDMMC_DRIVER_STRENGTH_C as isize,
110 StrengthD = sdmmc_driver_strength_t_SDMMC_DRIVER_STRENGTH_D as isize,
112 }
113
114 #[cfg(not(any(
116 esp_idf_version_major = "4",
117 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
118 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
119 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
120 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
121 )))] #[non_exhaustive]
123 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
124 pub enum CurrentLimit {
125 Limit200mA = sdmmc_current_limit_t_SDMMC_CURRENT_LIMIT_200MA as isize,
127 Limit400mA = sdmmc_current_limit_t_SDMMC_CURRENT_LIMIT_400MA as isize,
129 Limit600mA = sdmmc_current_limit_t_SDMMC_CURRENT_LIMIT_600MA as isize,
131 Limit800mA = sdmmc_current_limit_t_SDMMC_CURRENT_LIMIT_800MA as isize,
133 }
134
135 #[non_exhaustive]
137 pub struct Configuration {
138 pub command_timeout_ms: u32,
140 pub io_voltage: Voltage,
143 pub speed_khz: u32,
147 #[cfg(not(any(
148 esp_idf_version_major = "4",
149 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
150 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
151 )))] pub input_delay_phase: DelayPhase,
153 #[cfg(not(any(
154 esp_idf_version_major = "4",
155 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
156 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
157 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
158 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
159 )))] pub driver_strength: DriverStrength,
161 #[cfg(not(any(
162 esp_idf_version_major = "4",
163 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
164 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
165 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
166 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
167 )))] pub current_limit: CurrentLimit,
169 }
170
171 impl Configuration {
172 pub const fn new() -> Self {
174 Self {
175 command_timeout_ms: 0,
176 io_voltage: Voltage::V3P3,
177 speed_khz: 20000,
178 #[cfg(not(any(
179 esp_idf_version_major = "4",
180 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
181 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
182 )))] input_delay_phase: DelayPhase::Phase0,
184 #[cfg(not(any(
185 esp_idf_version_major = "4",
186 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
187 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
188 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
189 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
190 )))] driver_strength: DriverStrength::StrengthB,
192 #[cfg(not(any(
193 esp_idf_version_major = "4",
194 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
195 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
196 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
197 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
198 )))] current_limit: CurrentLimit::Limit200mA,
200 }
201 }
202 }
203
204 impl Default for Configuration {
205 fn default() -> Self {
206 Self::new()
207 }
208 }
209 }
210
211 pub struct SdCardDriver<T> {
221 _host: T,
222 card: alloc::boxed::Box<sdmmc_card_t>,
223 }
224
225 impl<T> SdCardDriver<T> {
226 pub fn card(&self) -> &sdmmc_card_t {
228 &self.card
229 }
230
231 }
234
235 impl<'d, T> SdCardDriver<SdSpiHostDriver<'d, T>>
236 where
237 T: Borrow<SpiDriver<'d>>,
238 {
239 pub fn new_spi(
241 host: SdSpiHostDriver<'d, T>,
242 configuration: &config::Configuration,
243 ) -> Result<Self, EspError> {
244 let configuration = sdmmc_host_t {
245 flags: _SDMMC_HOST_FLAG_SPI | _SDMMC_HOST_FLAG_DEINIT_ARG,
246 slot: host.handle() as _,
247 max_freq_khz: configuration.speed_khz as _,
248 io_voltage: configuration.io_voltage.as_native(),
249 init: Some(sdspi_host_init),
250 set_bus_width: None,
251 get_bus_width: None,
252 set_bus_ddr_mode: None,
253 set_card_clk: Some(sdspi_host_set_card_clk),
254 set_cclk_always_on: None,
255 do_transaction: Some(sdspi_host_do_transaction),
256 __bindgen_anon_1: sdmmc_host_t__bindgen_ty_1 {
257 deinit_p: Some(sdspi_host_remove_device),
258 },
259 io_int_enable: Some(sdspi_host_io_int_enable),
260 io_int_wait: Some(sdspi_host_io_int_wait),
261 #[cfg(not(any(
262 esp_idf_version_major = "4",
263 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
264 )))] get_real_freq: Some(sdspi_host_get_real_freq),
266 #[cfg(not(any(
267 esp_idf_version_major = "4",
268 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
269 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
270 )))] input_delay_phase: configuration.input_delay_phase as _,
272 #[cfg(not(any(
273 esp_idf_version_major = "4",
274 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
275 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
276 )))] set_input_delay: None,
278 #[cfg(esp_idf_version_at_least_6_0_0)]
279 set_input_delayline: None,
280 command_timeout_ms: configuration.command_timeout_ms as _,
281 #[cfg(not(any(
282 esp_idf_version_major = "4",
283 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
284 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
285 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
286 )))] dma_aligned_buffer: core::ptr::null_mut(),
288 #[cfg(all(esp_idf_version_at_least_5_3_0, not(esp_idf_version_at_least_6_0_0)))] get_dma_info: Some(sdspi_host_get_dma_info),
290 #[cfg(not(any(
291 esp_idf_version_major = "4",
292 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
293 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
294 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
295 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
296 all(esp_idf_version_major = "5", esp_idf_version_minor = "4"),
297 )))] check_buffer_alignment: Some(sdspi_host_check_buffer_alignment),
299 #[cfg(not(any(
300 esp_idf_version_major = "4",
301 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
302 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
303 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
304 )))] pwr_ctrl_handle: core::ptr::null_mut() as _,
306 #[cfg(not(any(
307 esp_idf_version_major = "4",
308 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
309 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
310 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
311 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
312 )))] driver_strength: configuration.driver_strength as _,
314 #[cfg(not(any(
315 esp_idf_version_major = "4",
316 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
317 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
318 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
319 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
320 )))] current_limit: configuration.current_limit as _,
322 #[cfg(not(any(
323 esp_idf_version_major = "4",
324 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
325 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
326 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
327 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
328 )))] is_slot_set_to_uhs1: None,
330 };
331
332 let mut card: alloc::boxed::Box<sdmmc_card_t> = Default::default();
333
334 esp!(unsafe { sdmmc_card_init(&configuration, &mut *card) })?;
335
336 Ok(Self { _host: host, card })
337 }
338 }
339
340 #[cfg(esp_idf_soc_sdmmc_host_supported)]
341 impl<'d> SdCardDriver<SdMmcHostDriver<'d>> {
342 pub fn new_mmc(
344 host: SdMmcHostDriver<'d>,
345 configuration: &config::Configuration,
346 ) -> Result<Self, EspError> {
347 let configuration = sdmmc_host_t {
348 flags: _SDMMC_HOST_FLAG_DEINIT_ARG
349 | _SDMMC_HOST_FLAG_DDR
350 | (1 | (host.width() - 1)) as u32,
354 slot: host.slot() as _,
355 max_freq_khz: configuration.speed_khz as _,
356 io_voltage: configuration.io_voltage.as_native(),
357 init: Some(sdmmc_host_init),
358 set_bus_width: Some(sdmmc_host_set_bus_width),
359 get_bus_width: Some(sdmmc_host_get_slot_width),
360 set_bus_ddr_mode: Some(sdmmc_host_set_bus_ddr_mode),
361 set_card_clk: Some(sdmmc_host_set_card_clk),
362 set_cclk_always_on: Some(sdmmc_host_set_cclk_always_on),
363 do_transaction: Some(sdmmc_host_do_transaction),
364 __bindgen_anon_1: sdmmc_host_t__bindgen_ty_1 {
365 deinit: Some(sdmmc_host_deinit),
366 },
367 io_int_enable: Some(sdmmc_host_io_int_enable),
368 io_int_wait: Some(sdmmc_host_io_int_wait),
369 get_real_freq: Some(sdmmc_host_get_real_freq),
370 #[cfg(not(any(
371 esp_idf_version_major = "4",
372 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
373 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
374 )))] input_delay_phase: configuration.input_delay_phase as _,
376 #[cfg(not(any(
377 esp_idf_version_major = "4",
378 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
379 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
380 )))] set_input_delay: Some(sdmmc_host_set_input_delay),
382 #[cfg(esp_idf_version_at_least_6_0_0)]
383 set_input_delayline: None,
384 command_timeout_ms: configuration.command_timeout_ms as _,
385 #[cfg(not(any(
386 esp_idf_version_major = "4",
387 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
388 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
389 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
390 )))] dma_aligned_buffer: core::ptr::null_mut(),
392 #[cfg(all(esp_idf_version_at_least_5_3_0, not(esp_idf_version_at_least_6_0_0)))] get_dma_info: Some(sdmmc_host_get_dma_info),
394 #[cfg(not(any(
395 esp_idf_version_major = "4",
396 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
397 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
398 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
399 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
400 all(esp_idf_version_major = "5", esp_idf_version_minor = "4"),
401 )))] check_buffer_alignment: Some(sdmmc_host_check_buffer_alignment),
403 #[cfg(not(any(
404 esp_idf_version_major = "4",
405 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
406 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
407 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
408 )))] pwr_ctrl_handle: core::ptr::null_mut() as _,
410 #[cfg(not(any(
411 esp_idf_version_major = "4",
412 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
413 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
414 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
415 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
416 )))] driver_strength: configuration.driver_strength as _,
418 #[cfg(not(any(
419 esp_idf_version_major = "4",
420 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
421 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
422 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
423 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
424 )))] current_limit: configuration.current_limit as _,
426 #[cfg(not(any(
427 esp_idf_version_major = "4",
428 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
429 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
430 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
431 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
432 )))] is_slot_set_to_uhs1: None,
434 };
435
436 let mut card: alloc::boxed::Box<sdmmc_card_t> = Default::default();
437
438 esp!(unsafe { sdmmc_card_init(&configuration, &mut *card) })?;
439
440 Ok(Self { _host: host, card })
441 }
442 }
443}