djuseeq / Ch376msc

Arduino library for CH376 mass storage contoller
MIT License
77 stars 17 forks source link

Enhancement request: Stream or File support #35

Closed petervanderwalt closed 4 years ago

petervanderwalt commented 4 years ago

So I can use writeStream from https://github.com/espressif/arduino-esp32/blob/master/libraries/Update/examples/SD_Update/SD_Update.ino (:

Other example: https://techtutorialsx.com/2019/07/21/esp32-arduino-updating-firmware-from-the-spiffs-file-system/

Between the examples, SD and SPIFFS covered, no if only CH376s library had a stream interface (;

[alternative, I am far to stupid to figure out hehe, is to use https://github.com/espressif/arduino-esp32/blob/master/libraries/Update/src/Update.h#L46-L50

djuseeq commented 4 years ago

I’m pretty busy lately, but I’ll see what I can do

petervanderwalt commented 4 years ago

So I tried to take a knack at it the last day or two:

    readMoreUpdates = true; 
    size_t updateSize = flashDrive.getFileSize();
    size_t writtenSize = 0;

    int runLoops = 0;

    if (Update.begin(updateSize)) {      
      interface.setCursor(145, 140);
      interface.print("Write: ");
      while(readMoreUpdates){ 
        readMoreUpdates = flashDrive.readFile(updateBuffer, sizeof(updateBuffer));

        // Credit to https://github.com/atanisoft for the type cast assistance with the following line
        size_t written = Update.write((uint8_t*)updateBuffer, sizeof(updateBuffer)-1); // -1 = remove null terminator from c string
        runLoops++;
        writtenSize = writtenSize+written;

        double perc = ((double)flashDrive.getCursorPos()/ (double)flashDrive.getFileSize())*100;
        interface.setCursor(190, 140);
        interface.print(perc);
        interface.print("%");

      }

      interface.beep(frequency);
      delay(100);
      interface.stopBeep();

      Serial.print("Wrote: ");
      Serial.print(writtenSize);
      Serial.print(" of ");
      Serial.print(updateSize);
      Serial.print(" in loops: ");
      Serial.println(runLoops);

     if (Update.end()) {
        if (Update.isFinished()) {
          interface.setCursor(145, 140);
          interface.setTextColor(ILI9341_GREEN, ILI9341_BLACK);
          interface.println("Rebooting...");
          interface.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        } else {
          interface.setCursor(145, 140);
          interface.setTextColor(ILI9341_RED, ILI9341_BLACK);
          interface.println("Error!");
          interface.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        }
      } else {
        interface.setCursor(145, 140);
        interface.setTextColor(ILI9341_RED, ILI9341_BLACK);
        interface.println(String(Update.errorString()));
        interface.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
      }
    } else {
      interface.setCursor(145, 140);
      interface.setTextColor(ILI9341_RED, ILI9341_BLACK);
      interface.println("No Space");
      interface.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
    }

Wrote: 1101598 of 1101408 in loops: 4337

4337 read * 254 bytes = 1101598 = what was written to update.h by

size_t written = Update.write((uint8_t*)updateBuffer, sizeof(updateBuffer)-1); // -1 = remove null terminator from c string

But the data on the flashdrive was 1101408 big

I chatted to a couple guys on the arduino-esp32 gitter about it, and it seems readFile is meant for ascii data, and having trouble with the Binary data I am trying to read (firmware image bin)

So might not need full on streaming support, but if you can find a couple minutes to play with the sample code and see what I am doing wrong, or if I should be using https://github.com/djuseeq/Ch376msc/blob/master/src/Read.cpp#L72 or something else (:

petervanderwalt commented 4 years ago

Just checking if if you maybe have had a chance to look at this (: Would be so cool to be able to do firmware updates to the ESP32s over USB

djuseeq commented 4 years ago

Hi, to read a binary data use readRaw() function instead. Try this branch, i wrote one extra function to be more simply to use. flashDrive.setFileName("RTOSTM32.ELF"); //set the file name flashDrive.openFile(); //open the file //read data from flash drive until we reach EOF while(!flashDrive.getEOF()){ flashDrive.readRaw(adatBuffer, sizeof(adatBuffer)); for(int i = 0; i < (int)flashDrive.getStreamLen(); i++){ Serial.write(adatBuffer[i]); }//end for loop }//end while loop flashDrive.closeFile(); //at the end, close the file

For testing purpose i read 848 Kb .elf file and send it over UART to computer, after a compare two files, the checksum s are identical, so the read is correct.
Screenshot_20201028_132525

petervanderwalt commented 4 years ago

That did the job (:


byte updateBuffer[255];       

// ... open the file etc ...

size_t updateSize = flashDrive.getFileSize();
size_t writtenSize = 0;

while(!flashDrive.getEOF()){
          flashDrive.readRaw(updateBuffer, sizeof(updateBuffer));
          size_t written = Update.write(updateBuffer, flashDrive.getStreamLen());
          writtenSize = writtenSize+written;
          double perc = ((double)flashDrive.getCursorPos()/ (double)flashDrive.getFileSize())*100;
          Serial.print(perc);
          Serial.println("%");
}
Serial.print("Wrote: ")
Serial.print(writtenSize);
Serial.print(" of ");
Serial.print(updateSize); 

I'll clean up my code after this stint of the project, and then I'll send over an Example sketch for this (: very useful

Thank you for your help!