M5Stack SD Card firmware Update

I am trying to implement firmware updates by sd card.
I’ve formatted a 32GB SD card to have a single FAT32 4GB partion and copied the firmware.bin from: .pio/build/m5stack-core-esp32 to the card and renamed it to update.bin. Then i’ve flashed the M5 by USB with the attached code.

On boot with inserted SD Card i get the following output (on the lcd):

SD card found, try update
Could not load update.bin from root

maybe someone has done something similar and could help me?
I am a beginner in ESP32 programming and therefore possible that this is an obvious and simple error on my side :wink:

#include <M5Stack.h>
#include <Update.h>

void performUpdate(Stream &updateSource, size_t updateSize) {
   if (Update.begin(updateSize)) {      
      size_t written = Update.writeStream(updateSource);
      if (written == updateSize) {
         M5.Lcd.println("Written : " + String(written) + " successfully");
      }
      else {
         M5.Lcd.println("Written only : " + String(written) + "/" + String(updateSize) + ". Retry?");
      }
      if (Update.end()) {
         M5.Lcd.println("OTA done!");
         if (Update.isFinished()) {
            M5.Lcd.println("Update successfully completed. Rebooting.");
         }
         else {
            M5.Lcd.println("Update not finished? Something went wrong!");
         }
      }
      else {
         M5.Lcd.println("Error Occurred. Error #: " + String(Update.getError()));
      }

   }
   else
   {
      M5.Lcd.println("Not enough space to begin OTA");
   }
}

void updateFromFS(fs::FS &fs) {
   File updateBin = fs.open("/update.bin");
   if (updateBin) {
      if(updateBin.isDirectory()){
         M5.Lcd.println("Error, update.bin is not a file");
         updateBin.close();
         return;
      }

      size_t updateSize = updateBin.size();

      if (updateSize > 0) {
         M5.Lcd.println("Try to start update");
         performUpdate(updateBin, updateSize);
      }
      else {
         M5.Lcd.println("Error, file is empty");
      }

      updateBin.close();
    
      // whe finished remove the binary from sd card to indicate end of the process
      fs.remove("/update.bin");      
   }
   else {
      M5.Lcd.println("Could not load update.bin from sd root");
   }
}

void setup()
{
    M5.begin();
    if (!SD.begin())
    {
        M5.Lcd.println("No SD Card");
    } else {
        M5.Lcd.println("SD Card found, try update");
        updateFromFS(SD);
    }
    M5.Lcd.println("Yay, SD Update worked!");
}

void loop()
{
}

I guess you meant that message.

Well so that means it’s failing the check

So either the path is /update.bin is wrong or no file can be seen at all.

You should try and some directory readout code like

void printDirectory(File dir, int numTabs) {
  while (true) {
    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) {
      Serial.print('\t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println("/");
      printDirectory(entry, numTabs + 1);
    } else {
      // files have sizes, directories do not
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}

And then call it as such

        M5.Lcd.println("SD Card found, try update");
        File root = SD.open("/");
        printDirectory(root, 0);
        root.close();
        updateFromFS(SD);

and observe the output via serial.

yep, sorry for the confusion about that

serial output seems to be broken (most likley another problem)

i’ve changed your code to simply output things to the integrated LCD this lists all files including /update.bin with a filesize of 367680

That is weird. Can you modify the function to

void updateFromFS(fs::FS &fs) {
   File updateBin = fs.open("/update.bin");
   M5.Lcd.println("Update file has size " + String(updateBin.size()));
   delay(1000);
   /*... */

to see if the file size is also seen correctly in the updateFromFS function? If yes, the if(..) check must be wrong, although it looks absolutely right through the overloaded bool() operator of the file object.