ESP32 loading .bin from SPIFFS

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

ESP32 loading .bin from SPIFFS

Postby zazas321 » Thu Jan 20, 2022 10:33 am

Hello. In my program, I need to update device from SPIFFS. I have found an older forum post:
viewtopic.php?t=22441

There is described how to do it and a code snippet is attached.
I have some questions:

1. In the same post, a guy shared his partition table:

Code: Select all

nvs,data,nvs,0x9000,200K,
otadata,data,ota,0x3b000,8K,
phy_init,data,phy,0x3d000,4K,
factory,app,factory,0x40000,1200K,
ota_0,app,ota_0,0x170000,1200K,
ota_1,app,ota_1,0x2a0000,1200K,
Could someone help me understand what is the point of having 3 partitions for app? We have a factory partition, ota_0 and ota_1. Why we need all three?

Just for the experimentation sake, I have tried to completely remove factory and just leave ota_0 and ota_1. My partition table looks :

Code: Select all

nvs,      data, nvs,     0x9000,  0x4000,
otadata,  data, ota,     0xd000,  0x2000,
phy_init, data, phy,     0xf000,  0x1000,
ota_0,    app,  ota_0,   0x10000,  0x200000,
ota_1,    app,  ota_1,           , 0x200000,
storage,  data, spiffs,          , 0x100000,
Now when I flash the device, I think it automatically uses the ota_0 instead of factory, the rest is seems to be working exactly the same as with 3 partition tables. So what is the point of having 3 partition tables for the app? (factory, app_0, app_1)



2. I would like to understand what exactly is happening when I update the firmware over the SPIFFS. From what I understand, by default, my whole program sits in ota_0. When I initiate firmware update over the SPIFFS, all data from my spiffs storage is being written to ota_1.

What exactly happens next? Is ota_1 being automatically chosen as a default partition that the device boots from? How does the program know which partition to choose?

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

Re: ESP32 loading .bin from SPIFFS

Postby ESP_Sprite » Fri Jan 21, 2022 1:54 am

zazas321 wrote:
Thu Jan 20, 2022 10:33 am
Now when I flash the device, I think it automatically uses the ota_0 instead of factory, the rest is seems to be working exactly the same as with 3 partition tables. So what is the point of having 3 partition tables for the app? (factory, app_0, app_1)
It depends on your bootloader. You can configure the bootloader to always boot to the factory app when e.g. a button on your device is pressed while it is powered on. This means that if e.g. your device gets 'bricked' because of e.g. some bug in the current OTA image (that is not caught by a rollback mechanism), you can tell the user to do that to boot to a 'known-good' image that can retry the OTA.
2. I would like to understand what exactly is happening when I update the firmware over the SPIFFS. From what I understand, by default, my whole program sits in ota_0. When I initiate firmware update over the SPIFFS, all data from my spiffs storage is being written to ota_1.
SPIFFS normally is not part of an OTA update. SPIFFS data is kept in the storage partition, not in the ota* partitions.
What exactly happens next? Is ota_1 being automatically chosen as a default partition that the device boots from? How does the program know which partition to choose?
Normally, the bootloader uses some flags in the otadata partition to figure out where to boot from.

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Re: ESP32 loading .bin from SPIFFS

Postby zazas321 » Fri Jan 21, 2022 5:49 am

Thank you very much for the response! Just a few clarifications:
ESP_Sprite wrote: Thu Jan 20, 2022 12:33 pm
Now when I flash the device, I think it automatically uses the ota_0 instead of factory, the rest is seems to be working exactly the same as with 3 partition tables. So what is the point of having 3 partition tables for the app? (factory, app_0, app_1)
It depends on your bootloader. You can configure the bootloader to always boot to the factory app when e.g. a button on your device is pressed while it is powered on. This means that if e.g. your device gets 'bricked' because of e.g. some bug in the current OTA image (that is not caught by a rollback mechanism), you can tell the user to do that to boot to a 'known-good' image that can retry the OTA.
So this can be another safety layer for my program? How about when I only have 2 partitions ota_0 and ota_1? Lets say my program is on ota_0 at the moment. When I initiate the OTA, I write all the data from SPIFFS (The binary file is uploaded to SPIFFS first) to ota_1 partition. When all the data is transferred from SPIFFS to ota_1, I think the ota functions internally perform some integrity check and if everything is fine my firmware will be updated. Now my concern is what exactly happens next? In the default bootloader configuration:
1.Does ota_0 (The partition where I had my "old" program before firmware update) still keep the old program data or it is cleared? Can I rollback to the old app if I only have ota_0 and ota_1 or I must have three partitions (factory, app_0, app_1) to perform rollback?
2.Is the ota_1 chosen as default partition (I mean whenever I restart the device or power cycle it is going to start the program from ota_1?

ESP_Sprite wrote: 2. I would like to understand what exactly is happening when I update the firmware over the SPIFFS. From what I understand, by default, my whole program sits in ota_0. When I initiate firmware update over the SPIFFS, all data from my spiffs storage is being written to ota_1.
SPIFFS normally is not part of an OTA update. SPIFFS data is kept in the storage partition, not in the ota* partitions.
Yes I meant that I save my binary files to the SPIFFS (at the moment I just save the file there manually) but for the final product it will be saved to spiffs via the WEB server or BLE). After I have my binary saved to SPIFFS I just write this data to the empty partition. Is that correct way to do this?


Additional questions:

1.When I have 3 partitions (factory, ota_0, ota_1). I have my app on factory partition. When I perform an OTA, does this factory app gets erased? If not, can I load it at any time I want? Lets say I have been running my app and I did OTA once. The new firmware was written to ota_0 (from SPIFFS because thats where I keep my .bin file that I want to update). Now the device is running ota_0 application. When I update the device again, I am now writing to ota_1 because ota_0 is currently running app. When a second OTA is completed, now the app runs ota_1 application. Is my understanding correct? What happens to the factory app in the meantime?

2. If I have 3 partitions (factory, ota_0, ota_1) does that mean that in theory I can have 3 seperate applications saved in flash and I can choose which one to run?

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

Re: ESP32 loading .bin from SPIFFS

Postby ESP_Sprite » Fri Jan 21, 2022 8:15 am

zazas321 wrote:
Fri Jan 21, 2022 5:49 am
So this can be another safety layer for my program? How about when I only have 2 partitions ota_0 and ota_1? Lets say my program is on ota_0 at the moment. When I initiate the OTA, I write all the data from SPIFFS (The binary file is uploaded to SPIFFS first) to ota_1 partition. When all the data is transferred from SPIFFS to ota_1, I think the ota functions internally perform some integrity check and if everything is fine my firmware will be updated. Now my concern is what exactly happens next? In the default bootloader configuration:
1.Does ota_0 (The partition where I had my "old" program before firmware update) still keep the old program data or it is cleared? Can I rollback to the old app if I only have ota_0 and ota_1 or I must have three partitions (factory, app_0, app_1) to perform rollback?
2.Is the ota_1 chosen as default partition (I mean whenever I restart the device or power cycle it is going to start the program from ota_1?
Yes, the OTA logic verifies the hash of the image (to make sure it's not corrupted) and will flip a bit in the otadata partition to make the next boot boot from ota_1. The old ota_0 program is not cleared unless you either clear it yourself or perform another ota (which will then get written to ota_0)
Yes I meant that I save my binary files to the SPIFFS (at the moment I just save the file there manually) but for the final product it will be saved to spiffs via the WEB server or BLE). After I have my binary saved to SPIFFS I just write this data to the empty partition. Is that correct way to do this?
I'd personally write it directly to the OTA partition using esp_ota_begin/write/end in your http server handler or ble handlers, but there's nothing technically wrong with storing it on a spiffs partition first.

1.When I have 3 partitions (factory, ota_0, ota_1). I have my app on factory partition. When I perform an OTA, does this factory app gets erased? If not, can I load it at any time I want? Lets say I have been running my app and I did OTA once. The new firmware was written to ota_0 (from SPIFFS because thats where I keep my .bin file that I want to update). Now the device is running ota_0 application. When I update the device again, I am now writing to ota_1 because ota_0 is currently running app. When a second OTA is completed, now the app runs ota_1 application. Is my understanding correct? What happens to the factory app in the meantime?
The idea of a factory app is that, in a scenario of mass-produced widgets, the app is programmed in the factory with a known-good 'gold' image that will never ever change during the lifetime of the device, so it's always a fallback. As such, you can load it any time you please (given you configure the bootloader to give you a way to do so).
2. If I have 3 partitions (factory, ota_0, ota_1) does that mean that in theory I can have 3 seperate applications saved in flash and I can choose which one to run?
Technically yes, however the OTA partitions in particular are more intended for (as the name implies) OTA upgrades, so you'd probably need to write images directly to the partitions without using the appfs, and you probably also need to hack the bootloader to allow you to select the partition you want to boot from.

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Re: ESP32 loading .bin from SPIFFS

Postby zazas321 » Fri Jan 21, 2022 8:19 am

Thank you very much for great explanation regarding the OTA. I really like the idea of having one "golden" app as you have mentioned saved in the factory app partition. However, lets say after a year or so we have improved our device a lot and now we have a new "golden" app that contains all the improvements and is fully tested and working better than the old "factory" app. During the next OTA, we want the new firmware to rewrite the factory partition and from now on, we use this as a "golden" app.

I have read through
https://docs.espressif.com/projects/esp ... m/ota.html
and eso_ota_ops.c but couldnt find how can this be done

In the documentation I have found the following:
currently selected OTA partition slot. The “factory” app partition slot (if it exists) is never updated via OTA, so resetting to this allows reverting to a “known good” firmware application.
Does that mean that we wont be able to rewrite the factory app via the OTA? Does that mean that the only way to rewrite the "factory" app is by flashing the device via the serial

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

Re: ESP32 loading .bin from SPIFFS

Postby ESP_Sprite » Fri Jan 21, 2022 12:14 pm

No, you could. The factory partition is simply another partition (not an OTA one that needs to keep track of the ping-pong between to OTA partitions, so you can use the spi partition API to simply write a new image in there. In general, there's no need to update the factory partition, though: you don't want it to have the latest features or anything, you simply want it to be good enough to be able to recover from a bad OTA. (And yes, there are exceptions, for instance if you lose control over the URL that the factory image uses for OTA.)

Who is online

Users browsing this forum: No registered users and 84 guests