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" fmtSize (SD_MMC.cardSize ()));
46+     LOG_INF (" SD card type %s, Size: %s, using %d bit mode @ %uMHz " 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" 
457+   return  res != FR_OK ? false  : true ;
458+ }
0 commit comments