Arduino FatFS
Loading...
Searching...
No Matches
Esp32SdmmcIO.h
Go to the documentation of this file.
1
12#pragma once
13
14#include "BaseIO.h"
15
16#if defined(ESP32) || defined(ESP_PLATFORM)
17
18#include <driver/sdmmc_host.h>
19#include <driver/sdmmc_defs.h>
20#include <sdmmc_cmd.h>
21#include "sdcommon.h"
22
23namespace fatfs {
24
60class Esp32SdmmcIO : public BaseIO {
61 public:
65 Esp32SdmmcIO() : card(nullptr), auto_init(false) {
66 memset(&host_config, 0, sizeof(host_config));
67 memset(&slot_config, 0, sizeof(slot_config));
68 }
69
78 Esp32SdmmcIO(bool mode1bit, int max_freq_khz = SDMMC_FREQ_DEFAULT)
79 : card(nullptr), auto_init(true), init_mode1bit(mode1bit),
80 init_max_freq_khz(max_freq_khz) {
81 memset(&host_config, 0, sizeof(host_config));
82 memset(&slot_config, 0, sizeof(slot_config));
83 }
84
95 Esp32SdmmcIO(bool mode1bit, int max_freq_khz,
96 const sdmmc_host_t& host_cfg,
97 const sdmmc_slot_config_t& slot_cfg)
98 : card(nullptr), auto_init(true), init_mode1bit(mode1bit),
99 init_max_freq_khz(max_freq_khz), host_config(host_cfg),
100 slot_config(slot_cfg) {
101 }
102
107 end();
108 }
109
117 bool begin(bool mode1bit = false, int max_freq_khz = SDMMC_FREQ_DEFAULT) {
118 return begin(mode1bit, max_freq_khz,
119 SDMMC_HOST_DEFAULT(),
120 SDMMC_SLOT_CONFIG_DEFAULT());
121 }
122
132 bool begin(bool mode1bit, int max_freq_khz,
133 sdmmc_host_t host_cfg, sdmmc_slot_config_t slot_cfg) {
134
135 // Store configurations
136 host_config = host_cfg;
137 slot_config = slot_cfg;
138
139 // Set bus width
140 if (mode1bit) {
141 slot_config.width = 1;
142 } else {
143 slot_config.width = 4;
144 }
145
146 // Set maximum frequency
147 host_config.max_freq_khz = max_freq_khz;
148
149 // Initialize host
150 esp_err_t err = sdmmc_host_init();
151 if (err != ESP_OK) {
152 stat = STA_NOINIT;
153 return false;
154 }
155
156 // Initialize slot
157 err = sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config);
158 if (err != ESP_OK) {
159 sdmmc_host_deinit();
160 stat = STA_NOINIT;
161 return false;
162 }
163
164 // Allocate card structure
165 if (card == nullptr) {
166 card = (sdmmc_card_t*)malloc(sizeof(sdmmc_card_t));
167 if (card == nullptr) {
168 sdmmc_host_deinit();
169 stat = STA_NOINIT;
170 return false;
171 }
172 }
173 memset(card, 0, sizeof(sdmmc_card_t));
174
175 // Probe and initialize card
176 card->host = host_config;
177 err = sdmmc_card_init(&host_config, card);
178 if (err != ESP_OK) {
179 free(card);
180 card = nullptr;
181 sdmmc_host_deinit();
182 stat = STA_NODISK;
183 return false;
184 }
185
186 // Determine card type flags
187 CardType = 0;
188 if (card->is_mmc) {
189 CardType = CT_MMC;
190 } else {
191 // SD card
192 if (card->ocr & SD_OCR_SDHC_CAP) {
193 CardType = CT_SD2 | CT_BLOCK; // SDHC/SDXC
194 } else {
195 CardType = CT_SD2; // SDSC
196 }
197 }
198
199 stat = STA_CLEAR;
200 return true;
201 }
202
206 void end() {
207 if (card != nullptr) {
208 free(card);
209 card = nullptr;
210 }
211 sdmmc_host_deinit();
212 stat = STA_NOINIT;
213 }
214
220 DSTATUS disk_initialize(BYTE drv) override {
221 if (drv != 0) return STA_NOINIT;
222
223 // If already initialized, return current status
224 if (stat == STA_CLEAR) return stat;
225
226 // Try to initialize with stored settings or defaults
227 if (auto_init && host_config.flags == 0) {
228 // Constructor with mode1bit and freq was used
230 return STA_CLEAR;
231 }
232 } else if (auto_init && host_config.flags != 0) {
233 // Constructor with full config was used
235 return STA_CLEAR;
236 }
237 } else {
238 // Default constructor was used, try with defaults
239 if (begin()) {
240 return STA_CLEAR;
241 }
242 }
243
244 return stat;
245 }
246
252 DSTATUS disk_status(BYTE drv) override {
253 if (drv != 0) return STA_NOINIT;
254 return stat;
255 }
256
265 DRESULT disk_read(BYTE drv, BYTE* buff, LBA_t sector, UINT count) override {
266 if (drv != 0 || !count) return RES_PARERR;
267 if (stat & STA_NOINIT) return RES_NOTRDY;
268 if (card == nullptr) return RES_NOTRDY;
269
270 // Use low-level API to read sectors
271 esp_err_t err = sdmmc_read_sectors(card, buff, sector, count);
272
273 return (err == ESP_OK) ? RES_OK : RES_ERROR;
274 }
275
284#if FF_IO_USE_WRITE
285 DRESULT disk_write(BYTE drv, const BYTE* buff, LBA_t sector,
286 UINT count) override {
287 if (drv != 0 || !count) return RES_PARERR;
288 if (stat & STA_NOINIT) return RES_NOTRDY;
289 if (stat & STA_PROTECT) return RES_WRPRT;
290 if (card == nullptr) return RES_NOTRDY;
291
292 // Use low-level API to write sectors
293 esp_err_t err = sdmmc_write_sectors(card, buff, sector, count);
294
295 return (err == ESP_OK) ? RES_OK : RES_ERROR;
296 }
297#endif
298
306#if FF_IO_USE_IOCTL
307 DRESULT disk_ioctl(BYTE drv, ioctl_cmd_t cmd, void* buff) override {
308 if (drv != 0) return RES_PARERR;
309 if (stat & STA_NOINIT) return RES_NOTRDY;
310
311 DRESULT res = RES_ERROR;
312
313 switch (cmd) {
314 case CTRL_SYNC:
315 // SD_MMC handles synchronization internally
316 res = RES_OK;
317 break;
318
319 case GET_SECTOR_COUNT:
320 if (buff && card) {
321 // Get total sectors from card capacity
322 uint64_t capacity = ((uint64_t)card->csd.capacity) * card->csd.sector_size;
323 *(DWORD*)buff = (DWORD)(capacity / 512);
324 res = RES_OK;
325 }
326 break;
327
328 case GET_SECTOR_SIZE:
329 if (buff) {
330 // SD cards use 512-byte sectors for compatibility
331 *(WORD*)buff = 512;
332 res = RES_OK;
333 }
334 break;
335
336 case GET_BLOCK_SIZE:
337 if (buff && card) {
338 // Return erase block size in sectors
339 // Use the card's erase sector size if available
340 uint32_t erase_size = card->csd.sector_size;
341 if (erase_size < 512) erase_size = 512;
342 *(DWORD*)buff = erase_size / 512;
343 if (*(DWORD*)buff == 0) *(DWORD*)buff = 1;
344 res = RES_OK;
345 }
346 break;
347
348 case CTRL_TRIM:
349 // TRIM/ERASE not implemented via SD_MMC library
350 res = RES_OK; // Return OK but don't actually trim
351 break;
352
353 case MMC_GET_TYPE:
354 if (buff) {
355 *(BYTE*)buff = CardType;
356 res = RES_OK;
357 }
358 break;
359
360 case MMC_GET_CSD:
361 if (buff && card) {
362 // Copy CSD register data
363 memcpy(buff, &card->csd, sizeof(card->csd));
364 res = RES_OK;
365 }
366 break;
367
368 case MMC_GET_CID:
369 if (buff && card) {
370 // Copy CID register data
371 memcpy(buff, &card->cid, sizeof(card->cid));
372 res = RES_OK;
373 }
374 break;
375
376 case MMC_GET_OCR:
377 if (buff && card) {
378 // Copy OCR register
379 *(DWORD*)buff = card->ocr;
380 res = RES_OK;
381 }
382 break;
383
384 case MMC_GET_SDSTAT:
385 if (buff && card) {
386 // Get SD status - this requires reading from the card
387 // For simplicity, return not implemented
388 res = RES_PARERR;
389 }
390 break;
391
392 default:
393 res = RES_PARERR;
394 break;
395 }
396
397 return res;
398 }
399#endif
400
405 uint64_t cardSize() const {
406 if (card == nullptr) return 0;
407 return ((uint64_t)card->csd.capacity) * card->csd.sector_size;
408 }
409
414 uint8_t cardType() const {
415 return CardType;
416 }
417
422 uint64_t totalSectors() const {
423 if (stat & STA_NOINIT || card == nullptr) return 0;
424 return cardSize() / 512;
425 }
426
431 sdmmc_card_t* getCard() {
432 return card;
433 }
434
439 bool isMMC() const {
440 return card ? card->is_mmc : false;
441 }
442
447 uint32_t getFreqKHz() const {
448 return card ? card->max_freq_khz : 0;
449 }
450
451 protected:
452 volatile DSTATUS stat = STA_NOINIT;
453 BYTE CardType = 0;
454 sdmmc_card_t* card;
455 sdmmc_host_t host_config;
456 sdmmc_slot_config_t slot_config;
457
458 // Auto-initialization parameters (for constructor-based config)
462};
463
464} // namespace fatfs
465
466#endif // ESP32 || ESP_PLATFORM
Empty IO implementation that we can use to test the compilation.
Definition BaseIO.h:10
Accessing an SD card via the ESP32 SDMMC interface using low-level API.
Definition Esp32SdmmcIO.h:60
Esp32SdmmcIO(bool mode1bit, int max_freq_khz=SDMMC_FREQ_DEFAULT)
Constructor with bus mode and frequency.
Definition Esp32SdmmcIO.h:78
bool init_mode1bit
Stored 1-bit mode setting.
Definition Esp32SdmmcIO.h:460
uint64_t cardSize() const
Get the card size in bytes.
Definition Esp32SdmmcIO.h:405
bool isMMC() const
Check if card is MMC.
Definition Esp32SdmmcIO.h:439
BYTE CardType
Card type flags.
Definition Esp32SdmmcIO.h:453
bool auto_init
Whether to auto-init on first use.
Definition Esp32SdmmcIO.h:459
sdmmc_card_t * card
Pointer to card structure.
Definition Esp32SdmmcIO.h:454
DRESULT disk_write(BYTE drv, const BYTE *buff, LBA_t sector, UINT count) override
Write sector(s)
Definition Esp32SdmmcIO.h:285
bool begin(bool mode1bit, int max_freq_khz, sdmmc_host_t host_cfg, sdmmc_slot_config_t slot_cfg)
Initialize with custom host and slot configuration.
Definition Esp32SdmmcIO.h:132
DRESULT disk_ioctl(BYTE drv, ioctl_cmd_t cmd, void *buff) override
Miscellaneous drive controls.
Definition Esp32SdmmcIO.h:307
Esp32SdmmcIO(bool mode1bit, int max_freq_khz, const sdmmc_host_t &host_cfg, const sdmmc_slot_config_t &slot_cfg)
Constructor with custom host and slot configuration.
Definition Esp32SdmmcIO.h:95
bool begin(bool mode1bit=false, int max_freq_khz=SDMMC_FREQ_DEFAULT)
Initialize the SDMMC interface and mount the SD card.
Definition Esp32SdmmcIO.h:117
DSTATUS disk_status(BYTE drv) override
Get disk status.
Definition Esp32SdmmcIO.h:252
~Esp32SdmmcIO()
Destructor - cleanup resources.
Definition Esp32SdmmcIO.h:106
Esp32SdmmcIO()
Default constructor - card must be initialized with begin()
Definition Esp32SdmmcIO.h:65
sdmmc_card_t * getCard()
Get pointer to the card structure (for advanced use)
Definition Esp32SdmmcIO.h:431
sdmmc_host_t host_config
Host configuration.
Definition Esp32SdmmcIO.h:455
uint64_t totalSectors() const
Get the total number of sectors.
Definition Esp32SdmmcIO.h:422
DSTATUS disk_initialize(BYTE drv) override
Initialize disk drive.
Definition Esp32SdmmcIO.h:220
volatile DSTATUS stat
Physical drive status.
Definition Esp32SdmmcIO.h:452
DRESULT disk_read(BYTE drv, BYTE *buff, LBA_t sector, UINT count) override
Read sector(s)
Definition Esp32SdmmcIO.h:265
uint8_t cardType() const
Get the card type flags.
Definition Esp32SdmmcIO.h:414
sdmmc_slot_config_t slot_config
Slot configuration.
Definition Esp32SdmmcIO.h:456
void end()
End SDMMC interface and unmount SD card.
Definition Esp32SdmmcIO.h:206
uint32_t getFreqKHz() const
Get card frequency in kHz.
Definition Esp32SdmmcIO.h:447
int init_max_freq_khz
Stored max frequency setting.
Definition Esp32SdmmcIO.h:461