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 #[cfg(any(
332 esp_idf_version_at_least_6_0_1,
333 esp_idf_version_patch_at_least_5_5_5
334 ))]
335 unaligned_multi_block_rw_max_chunk_size: 0,
336 };
337
338 let mut card: alloc::boxed::Box<sdmmc_card_t> = Default::default();
339
340 esp!(unsafe { sdmmc_card_init(&configuration, &mut *card) })?;
341
342 Ok(Self { _host: host, card })
343 }
344 }
345
346 #[cfg(esp_idf_soc_sdmmc_host_supported)]
347 impl<'d> SdCardDriver<SdMmcHostDriver<'d>> {
348 pub fn new_mmc(
350 host: SdMmcHostDriver<'d>,
351 configuration: &config::Configuration,
352 ) -> Result<Self, EspError> {
353 let configuration = sdmmc_host_t {
354 flags: _SDMMC_HOST_FLAG_DEINIT_ARG
355 | _SDMMC_HOST_FLAG_DDR
356 | (1 | (host.width() - 1)) as u32,
360 slot: host.slot() as _,
361 max_freq_khz: configuration.speed_khz as _,
362 io_voltage: configuration.io_voltage.as_native(),
363 init: Some(sdmmc_host_init),
364 set_bus_width: Some(sdmmc_host_set_bus_width),
365 get_bus_width: Some(sdmmc_host_get_slot_width),
366 set_bus_ddr_mode: Some(sdmmc_host_set_bus_ddr_mode),
367 set_card_clk: Some(sdmmc_host_set_card_clk),
368 set_cclk_always_on: Some(sdmmc_host_set_cclk_always_on),
369 do_transaction: Some(sdmmc_host_do_transaction),
370 __bindgen_anon_1: sdmmc_host_t__bindgen_ty_1 {
371 deinit: Some(sdmmc_host_deinit),
372 },
373 io_int_enable: Some(sdmmc_host_io_int_enable),
374 io_int_wait: Some(sdmmc_host_io_int_wait),
375 get_real_freq: Some(sdmmc_host_get_real_freq),
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 )))] input_delay_phase: configuration.input_delay_phase as _,
382 #[cfg(not(any(
383 esp_idf_version_major = "4",
384 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
385 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
386 )))] set_input_delay: Some(sdmmc_host_set_input_delay),
388 #[cfg(esp_idf_version_at_least_6_0_0)]
389 set_input_delayline: None,
390 command_timeout_ms: configuration.command_timeout_ms as _,
391 #[cfg(not(any(
392 esp_idf_version_major = "4",
393 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
394 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
395 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
396 )))] dma_aligned_buffer: core::ptr::null_mut(),
398 #[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),
400 #[cfg(not(any(
401 esp_idf_version_major = "4",
402 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
403 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
404 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
405 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
406 all(esp_idf_version_major = "5", esp_idf_version_minor = "4"),
407 )))] check_buffer_alignment: Some(sdmmc_host_check_buffer_alignment),
409 #[cfg(not(any(
410 esp_idf_version_major = "4",
411 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
412 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
413 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
414 )))] pwr_ctrl_handle: core::ptr::null_mut() as _,
416 #[cfg(not(any(
417 esp_idf_version_major = "4",
418 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
419 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
420 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
421 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
422 )))] driver_strength: configuration.driver_strength as _,
424 #[cfg(not(any(
425 esp_idf_version_major = "4",
426 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
427 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
428 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
429 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
430 )))] current_limit: configuration.current_limit as _,
432 #[cfg(not(any(
433 esp_idf_version_major = "4",
434 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
435 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
436 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
437 all(esp_idf_version_major = "5", esp_idf_version_minor = "3"),
438 )))] is_slot_set_to_uhs1: None,
440 #[cfg(any(
442 esp_idf_version_at_least_6_0_1,
443 esp_idf_version_patch_at_least_5_5_5
444 ))]
445 unaligned_multi_block_rw_max_chunk_size: 0,
446 };
447
448 let mut card: alloc::boxed::Box<sdmmc_card_t> = Default::default();
449
450 esp!(unsafe { sdmmc_card_init(&configuration, &mut *card) })?;
451
452 Ok(Self { _host: host, card })
453 }
454 }
455}