My problem is the following:
I have three OTA related partitions on my ESP32 (app0, app1 and OTA data). By default app0 is the boot partition; it contains a firmware that can receive a firmware.bin file and install it on the app1 partition. When app0 received the complete firmware.bin file, it sets app1 as the boot partition (in the OTA data partition) and reboots the system. The bootloader looks in the OTA data partition and sees that it has to start app1. Suppose the app1 that is now running crashes, so the system will reboot. But since the OTA data partition still points to app1, the bootloader will start app1 again. This will cause a app1 bootloop.
I can prevent this by setting the boot partition to app0 in the app1 code. But I don't want to have to assume that app1 contains such code, it should be any firmware.
The best solution would be if the bootloader looks in the OTA data partition and remembers what it has to start (lets call this app_to_start), then writes into the OTA data partition that the next time app0 has to be started, and then starts app_to_start.
Is it possible to modify the bootloader in such a way?
Is it possible to modify the OTA data partition with a custom bootloader?
Is it possible to modify the OTA data partition with a custom bootloader?
Last edited by t23319222 on Wed Mar 05, 2025 9:09 pm, edited 1 time in total.
Re: Is it possible to modify the OTA data partition with a custom bootloader?
Have you looked at app rollback? It seems to at least overlap with what you're trying to do.
Re: Is it possible to modify the OTA data partition with a custom bootloader?
Yes I am currently trying to make it work.
My platformio.ini file looks like this:
Right before I reboot after the OTA update, the app1 partition is marked as ESP_OTA_IMG_NEW. Then the ESP32 reboots into app1, and when I check the state of the running partition, it is ESP_OTA_IMG_VALID. Some time ago I had a custom bootloader on this ESP32, where the only modification was that it logged "Custom bootloader initialized". Before I tested this OTA update, I flashed the original bootloader back onto the ESP32.
app0 code:
app1 code:
My platformio.ini file looks like this:
Code: Select all
[env:m5stack-stamps3]
platform = espressif32
board = m5stack-stamps3
framework = arduino
monitor_speed = 9600
lib_deps =
https://github.com/arduino-libraries/Arduino_ESP32_OTA.git
https://github.com/bakercp/CRC32.git
https://github.com/bblanchon/ArduinoJson.git
build_flags = -D CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=1
app0 code:
Code: Select all
#include <Arduino.h>
#include <FS.h>
#include <SPIFFS.h>
#include <Update.h>
#include "esp_ota_ops.h"
#define Serial USBSerial
void PrintApp1State()
{
const esp_partition_t *app1_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1, NULL);
// ESP_OTA_IMG_VALID
esp_ota_img_states_t ota_state;
if (esp_ota_get_state_partition(app1_partition, &ota_state) == ESP_OK) {
switch (ota_state) {
case ESP_OTA_IMG_NEW:
Serial.println("ESP_OTA_IMG_NEW");
break;
case ESP_OTA_IMG_PENDING_VERIFY:
Serial.println("ESP_OTA_IMG_PENDING_VERIFY");
break;
case ESP_OTA_IMG_VALID:
Serial.println("ESP_OTA_IMG_VALID");
break;
case ESP_OTA_IMG_INVALID:
Serial.println("ESP_OTA_IMG_INVALID");
break;
default:
Serial.println("Unknown OTA state.");
break;
}
}
}
void CheckBootPartition()
{
const esp_partition_t *boot_partition { esp_ota_get_boot_partition() };
if (boot_partition)
{
Serial.printf("Boot partition: %s\n", boot_partition->label);
}
else
{
Serial.println("Failed to get boot partition.");
}
}
void otaUpdateApp1() {
// make sure that spiffs is initialized
if (!SPIFFS.begin()) {
Serial.println("Error initializing SPIFFS");
return;
}
// open firmware file from spiffs
File firmwareFile = SPIFFS.open("/1679363019.bin", "r");
if (!firmwareFile) {
Serial.println("Error opening the firmware file");
return;
}
// determine if enough storage is on app1
size_t firmwareSize = firmwareFile.size();
if (firmwareSize > ESP.getFreeSketchSpace()) {
Serial.println("not enough storage on app1 partition");
firmwareFile.close();
return;
}
// start ota process
if (!Update.begin(firmwareSize, U_FLASH)) {
Serial.println("error starting ota update");
firmwareFile.close();
return;
}
// copy firmware from spiffs to app1
size_t written = Update.writeStream(firmwareFile);
if (written != firmwareSize) {
Serial.printf("error writing firmware: written: %d, expected: %d\n", written, firmwareSize);
Update.abort();
firmwareFile.close();
return;
}
// end update and reboot
if (!Update.end(true)) {
Serial.println("error finalizing ota update");
} else {
PrintApp1State();
Serial.println("ota update success. restarting...");
delay(100);
ESP.restart(); // restart after update
}
// close file
firmwareFile.close();
}
void setup() {
Serial.begin(9600);
delay(2000);
Serial.println("This is:");
CheckBootPartition();
Serial.println("Updating...");
otaUpdateApp1();
}
void loop() {
}
Code: Select all
#include <Arduino.h>
#include "esp_ota_ops.h"
#define Serial USBSerial
void PrintAppState()
{
const esp_partition_t *running = esp_ota_get_running_partition();
// ESP_OTA_IMG_VALID
esp_ota_img_states_t ota_state;
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
switch (ota_state) {
case ESP_OTA_IMG_NEW:
USBSerial.println("ESP_OTA_IMG_NEW");
break;
case ESP_OTA_IMG_PENDING_VERIFY:
USBSerial.println("ESP_OTA_IMG_PENDING_VERIFY");
break;
case ESP_OTA_IMG_VALID:
USBSerial.println("ESP_OTA_IMG_VALID");
break;
case ESP_OTA_IMG_INVALID:
USBSerial.println("ESP_OTA_IMG_INVALID");
break;
default:
USBSerial.println("Unknown OTA state.");
break;
}
}
}
void CheckBootPartition()
{
const esp_partition_t *boot_partition { esp_ota_get_boot_partition() };
if (boot_partition)
{
Serial.printf("Boot partition: %s\n", boot_partition->label);
}
else
{
Serial.println("Failed to get boot partition.");
}
}
void setup() {
Serial.begin(9600);
delay(2000);
Serial.println("This is:");
// CheckBootPartition();
PrintAppState();
delay(2000);
Serial.println("Rebooting...");
delay(2000);
ESP.restart();
delay(2000);
}
void loop() {
}
Re: Is it possible to modify the OTA data partition with a custom bootloader?
Not sure what your question is, but note you need to set CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE in menuconfig (or whatever platformio's equivalent is) in order to get the rollback-when-app-resets functionality.
Who is online
Users browsing this forum: Bing [Bot], PetalBot and 5 guests
