[SOLVED] ESP32 firmware update from SPIFFS partition

filo_gr
Posts: 109
Joined: Wed Jul 28, 2021 12:25 pm
Location: Italy

[SOLVED] ESP32 firmware update from SPIFFS partition

Postby filo_gr » Wed Jul 28, 2021 1:01 pm

Hello community,

I'm a ESP32 newby and I'm studying how the potentialities of the ESP microcontrollers.

I'm trying to create an automatic firmware update that happens when I insert a particular URL. The ESP32 is configured as an access point, while my PC is connected to it.
If I insert: 192.168.2.1/update in my PC browser I activate an handler.
  1. httpd_uri_t do_update = {
  2.         .uri       = "/update",
  3.         .method    = HTTP_GET,
  4.         .handler   = update_handler,
  5.         .user_ctx  = server_data
  6.     };
  7.     httpd_register_uri_handler(server, &do_update);
It opens the following portion of code. Here as you can see I have firmware.bin in a SPIFFS partition.
I took the .bin file from the build project folder and put it into the SPIFFS folder.
I confirm it works.
  1. #define CONFIG_FIRMWARE_UPGRADE_URL "/spiffs/firmware.bin"
  2. static esp_err_t update_handler(httpd_req_t *req){
  3.     int file_size = 0;
  4.     esp_err_t ret;
  5.     const esp_partition_t *update_partition;
  6.     const esp_partition_t *configured = esp_ota_get_boot_partition();
  7.     const esp_partition_t *running  = esp_ota_get_running_partition();
  8.     esp_ota_handle_t well_done_handle = 0;
  9.  
  10.     ESP_LOGI(TAG, "firmware.bin");
  11.     // Open for reading firmware.bin
  12.     FILE* f = fopen(CONFIG_FIRMWARE_UPGRADE_URL, "r");
  13.     if (f == NULL) {
  14.         ESP_LOGE(TAG, "Failed to open firmware.bin");
  15.         return ESP_FAIL;
  16.     }
  17.     // I calculate the length of the file firmware.bin
  18.     fseek(f, 0L, SEEK_END);
  19.     file_size = ftell(f);
  20.     rewind(f);
  21.     ESP_LOGI(TAG, "Starting OTA example");
  22.     // OTA partition
  23.     update_partition = esp_ota_get_next_update_partition(NULL);
  24.     ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x",
  25.                     update_partition->subtype, update_partition->address);
  26.     assert(update_partition != NULL);
  27.     // Reset and begin.
  28.     ESP_ERROR_CHECK(esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &well_done_handle));
  29.     ret = esp_ota_write(well_done_handle, f, file_size);// **** HERE THE PROBLEM!!!! ****
  30.     if (ret == ESP_OK) {
  31.         ESP_ERROR_CHECK(esp_ota_end(well_done_handle));
  32.         // I select a new boot partition
  33.         ESP_ERROR_CHECK(esp_ota_set_boot_partition(update_partition));
  34.         ESP_LOGI(TAG, "Restarting...");
  35.         esp_restart();
  36.     }
  37.     else {
  38.         ESP_LOGE(TAG, "Firmware upgrade failed");
  39.     }
  40.     while (1) {
  41.         vTaskDelay(1000 / portTICK_PERIOD_MS);
  42.     }
  43.     fclose(f);
  44.     return ESP_OK;
  45. }
After executing line 28, on line 29 the terminal shows me:
OTA image has invalid magic byte (expected 0xE9, saw 0xa8)

However my .bin file starts with E9!

Here I show you my partition table (if it can help):
  1. nvs,        data,   nvs,        0x9000,     0x6000,
  2. phy_init,   data,   phy,        0xf000,     0x1000,
  3. factory,    app,    factory,    0x10000,    0x100000,
  4. ota_0,      app,    ota_0,      0x110000,   0x100000,
  5. ota_1,      app,    ota_1,      0x210000,   0x100000,
  6. storage,    data,   spiffs,     0x310000,   0xEE000,
  7. otadata,    data,   ota,        0x3FE000,   0x2000,
I'm really stuck, I can't find a solution for this problem. I hope I gave you all the elements to describe my issue.
Regards,
Filippo
Last edited by filo_gr on Wed Aug 04, 2021 7:12 am, edited 1 time in total.

ESP_Sprite
Posts: 8921
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32 firmware update from SPIFFS partition

Postby ESP_Sprite » Thu Jul 29, 2021 2:06 am

esp_ota_write needs a pointer to the data to be written in memory. You hand it a file pointer instead. Read the data from the file first, then hand the data to esp_ota_write. (You probably need to do this in chunks; ota files generally don't fit in RAM fully.)

filo_gr
Posts: 109
Joined: Wed Jul 28, 2021 12:25 pm
Location: Italy

Re: ESP32 firmware update from SPIFFS partition

Postby filo_gr » Thu Jul 29, 2021 7:37 am

Thank you very much for your advice. I admit that I was a bit confused about what I had to do. :D
Now it seems to work. I'm not 100% sure so I'd like to share my solution in order to clarify what I changed from the previous snippet of code. :!:
  1. #define SEND_DATA   100
  2. static esp_err_t update_handler(httpd_req_t *req){
  3.     int data_read = 0;
  4.     esp_err_t ret;
  5.     const esp_partition_t *update_partition;
  6.     const esp_partition_t *configured = esp_ota_get_boot_partition();
  7.     const esp_partition_t *running  = esp_ota_get_running_partition();
  8.     esp_ota_handle_t well_done_handle = 0;  /* Handler for OTA update. */
  9.     if (configured != running) {
  10.         ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x",
  11.                         configured->address, running->address);
  12.         ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)"
  13.                         );
  14.     }
  15.     ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
  16.                     running->type, running->subtype, running->address);
  17.     ESP_LOGI(TAG, "firmware.bin");
  18.     // Open for reading firmware.bin
  19.     FILE* f = fopen(CONFIG_FIRMWARE_UPGRADE_URL, "r");
  20.     if (f == NULL) {
  21.         ESP_LOGE(TAG, "Failed to open firmware.bin");
  22.         return ESP_FAIL;
  23.     }
  24.     ESP_LOGI(TAG, "Starting OTA example");
  25.     // It finds the partition where it should write the firmware
  26.     update_partition = esp_ota_get_next_update_partition(NULL);
  27.     ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x",
  28.                     update_partition->subtype, update_partition->address);
  29.     assert(update_partition != NULL);
  30.     // Reset of this partition
  31.     ESP_ERROR_CHECK(esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &well_done_handle));
  32.     // Temporary buffer where I write the chunks of file read from the file firmware.bin.
  33.     char buf[SEND_DATA];
  34.     // Init of the buffer
  35.     memset(buf, 0, sizeof(buf));
  36.     /* Loop */
  37.     do{
  38.         // Put the data read from the file inside buf.
  39.         data_read = fread(buf, 1, SEND_DATA, f);
  40.         // I write data from buffer to the partition
  41.         ret = esp_ota_write(well_done_handle, buf, data_read);
  42.         // In case of failure it sends a log and exits.
  43.         if(ret != ESP_OK){
  44.             ESP_LOGE(TAG, "Firmware upgrade failed");
  45.             fclose(f);
  46.             while (1) {
  47.                 vTaskDelay(1000 / portTICK_PERIOD_MS);
  48.             }
  49.             return ESP_FAIL;
  50.         }
  51.     } while(data_read == SEND_DATA);
  52.     // If you are here it means there are no problems!
  53.     ESP_ERROR_CHECK(esp_ota_end(well_done_handle));
  54.     fclose(f);
  55.     // OTA partition configuration
  56.     ESP_ERROR_CHECK(esp_ota_set_boot_partition(update_partition));
  57.     ESP_LOGI(TAG, "Restarting...");
  58.     // REBOOT!!!!!
  59.     esp_restart();
  60.     return ESP_OK; // Not so useful :/
  61. }
I have a last question about OTA updates: previously I selected ota_0, indeed now the bootloader selects this partition.
What should I do to select the ota_1 partition? And what if I want to come back to factory?

Thank you again.
Regards,
Filippo
Last edited by filo_gr on Thu Jul 29, 2021 10:21 am, edited 1 time in total.
Filippo

ESP_Sprite
Posts: 8921
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32 firmware update from SPIFFS partition

Postby ESP_Sprite » Thu Jul 29, 2021 9:56 am

Your code will automatically update ota_0 if it's running from ota_1 (or factory) and ota_1 if it's running from ota_0; the call to esp_ota_get_next_update_partition will give you the correct partition to update. Returning to factory is something done in the bootloader; I think there's a Menuconfig option where you can select a GPIO which, if pulled high or low on startup, will return you to the factory image. You may also be able to manually make it active using esp_ota_set_boot_partition() but I'm not 100% sure on that.

filo_gr
Posts: 109
Joined: Wed Jul 28, 2021 12:25 pm
Location: Italy

Re: ESP32 firmware update from SPIFFS partition

Postby filo_gr » Thu Jul 29, 2021 10:20 am

ESP_Sprite wrote:
Thu Jul 29, 2021 9:56 am
Your code will automatically update ota_0 if it's running from ota_1 (or factory) and ota_1 if it's running from ota_0; the call to esp_ota_get_next_update_partition will give you the correct partition to update. Returning to factory is something done in the bootloader; I think there's a Menuconfig option where you can select a GPIO which, if pulled high or low on startup, will return you to the factory image. You may also be able to manually make it active using esp_ota_set_boot_partition() but I'm not 100% sure on that.
Thank you, your explanation has been very useful. I'll surely do some tests in the future :)

Filippo
Filippo

Who is online

Users browsing this forum: Baidu [Spider], ESP_rrtandler and 123 guests