11// General purpose SD card and flash storage utilities
22//
3- // s60sc 2021, 2022
3+ // Card can be accessed using a 1 data bit or 4 data bits (if allowed by board)
4+ // 4 data bits is potentially faster on ESP32S3 (depending on card spec)
5+ // but requires 3 additional pins
6+ /* The following #defines must be declared under the relevant camera entry in camera_pins.h
7+ 1 bit 4 bit
8+ SD_MMC_CMD SD_MMC_CMD
9+ SD_MMC_CLK SD_MMC_CLK
10+ SD_MMC_D0 SD_MMC_D0
11+ SD_MMC_D1
12+ SD_MMC_D2
13+ SD_MMC_D3
14+ */
15+ // s60sc 2021, 2022, 2025
416
517#include " appGlobals.h"
18+ #include " ff.h"
19+ #include " vfs_fat_internal.h"
620
721// Storage settings
822int sdMinCardFreeSpace = 100 ; // Minimum amount of card free Megabytes before sdFreeSpaceMode action is enabled
923int sdFreeSpaceMode = 1 ; // 0 - No Check, 1 - Delete oldest dir, 2 - Upload oldest dir to FTP/HFS and then delete on SD
1024bool formatIfMountFailed = true ; // Auto format the file system if mount failed. Set to false to not auto format.
25+ static bool use1bitMode = true ;
1126static fs::FS fp = STORAGE;
27+ #if (!CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32S2)
28+ static int sdmmcFreq = BOARD_MAX_SDMMC_FREQ; // board specific default SD_MMC speed
29+ #endif
1230
1331// hold sorted list of filenames/folders names in order of newest first
1432static std::vector<std::string> fileVec;
@@ -17,31 +35,22 @@ static auto previousDir = "/~previous";
1735static char fsType[10 ] = {0 };
1836
1937static void infoSD () {
20- #if !( CONFIG_IDF_TARGET_ESP32C3)
38+ #if (! CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32S2 )
2139 uint8_t cardType = SD_MMC.cardType ();
2240 if (cardType == CARD_NONE) LOG_WRN (" No SD card attached" );
2341 else {
2442 char typeStr[8 ] = " UNKNOWN" ;
2543 if (cardType == CARD_MMC) strcpy (typeStr, " MMC" );
2644 else if (cardType == CARD_SD) strcpy (typeStr, " SDSC" );
2745 else if (cardType == CARD_SDHC) strcpy (typeStr, " SDHC" );
28- LOG_INF (" SD card type %s, Size: %s" , typeStr, fmtSize (SD_MMC.cardSize ()));
46+ LOG_INF (" SD card type %s, Size: %s, using %d bit mode @ %uMHz " , typeStr, fmtSize (SD_MMC.cardSize ()), use1bitMode ? 1 : 4 , sdmmcFreq / 1000 );
2947 }
3048#endif
3149}
3250
3351static bool prepSD_MMC () {
3452 bool res = false ;
35- #if !(CONFIG_IDF_TARGET_ESP32C3)
36- /* open SD card in MMC 1 bit mode
37- MMC4 MMC1 ESP32 ESP32S3
38- D2 12
39- D3 .. 13
40- CMD CMD 15 38
41- CLK CLK 14 39
42- D0 D0 2 40
43- D1 4
44- */
53+ #if (!CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32S2)
4554 if (psramFound ()) heap_caps_malloc_extmem_enable (MIN_RAM); // small number to force vector into psram
4655 fileVec.reserve (1000 );
4756 if (psramFound ()) heap_caps_malloc_extmem_enable (MAX_RAM);
@@ -50,11 +59,18 @@ static bool prepSD_MMC() {
5059 LOG_WRN (" SD card pins not defined" );
5160 return false ;
5261#else
62+ #if defined(SD_MMC_D1)
63+ // assume 4 bit mode
64+ SD_MMC.setPins (SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0, SD_MMC_D1, SD_MMC_D2, SD_MMC_D3);
65+ use1bitMode = false ;
66+ #else
67+ // assume 1 bit mode
5368 SD_MMC.setPins (SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
69+ #endif
5470#endif
5571#endif
5672
57- res = SD_MMC.begin (" /sdcard" , true , formatIfMountFailed);
73+ res = SD_MMC.begin (" /sdcard" , use1bitMode , formatIfMountFailed, sdmmcFreq );
5874#if defined(CAMERA_MODEL_AI_THINKER)
5975 pinMode (4 , OUTPUT);
6076 digitalWrite (4 , 0 ); // set lamp pin fully off as sd_mmc library still initialises pin 4 in 1 line mode
@@ -88,7 +104,7 @@ static void listFolder(const char* rootDir) {
88104bool startStorage () {
89105 // start required storage device (SD card or flash file system)
90106 bool res = false ;
91- #if !( CONFIG_IDF_TARGET_ESP32C3)
107+ #if (! CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32S2 )
92108 if ((fs::SDMMCFS*)&STORAGE == &SD_MMC) {
93109 strcpy (fsType, " SD_MMC" );
94110 res = prepSD_MMC ();
@@ -413,3 +429,30 @@ esp_err_t downloadFile(File& df, httpd_req_t* req) {
413429 } else res = sendChunks (df, req); // send AVI
414430 return res;
415431}
432+
433+ bool formatSDcard () {
434+ // format SD card, erases existing content
435+ // can take some time to complete
436+ // invoke from url: <cam ip>/control?formatSD=1
437+ LOG_INF (" Format the SD card, wait ..." );
438+ char drv[3 ] = {' 0' , ' :' , 0 };
439+ const size_t workbuf_size = 4096 ;
440+ void * workbuf = NULL ;
441+ size_t allocation_unit_size = 4 * 1024 ;
442+ int sector_size_default = 512 ;
443+
444+ workbuf = ff_memalloc (workbuf_size);
445+ if (workbuf == NULL ) {
446+ LOG_ERR (" workbuf memory not allocated" );
447+ return false ;
448+ }
449+
450+ size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size (
451+ sector_size_default, allocation_unit_size);
452+ const MKFS_PARM opt = {(BYTE)FM_ANY, 0 , 0 , 0 , alloc_unit_size};
453+ FRESULT res = f_mkfs (drv, &opt, workbuf, workbuf_size);
454+ ff_memfree (workbuf);
455+ if (res != FR_OK) LOG_ERR (" SD card format failed" );
456+ else LOG_INF (" SD card formatted with alloc unit size %d" , alloc_unit_size);
457+ return res != FR_OK ? false : true ;
458+ }
0 commit comments