How to boot ota1 from ota0 partition?

shubhamm098
Posts: 6
Joined: Wed Mar 19, 2025 8:45 am

How to boot ota1 from ota0 partition?

Postby shubhamm098 » Thu Mar 20, 2025 10:51 am

I got this solution please verify if it's logically correct?

Solution: Using esp_app_desc_t and esp_image_load().

This method manually loads and jumps to the desired partition without changing the bootloader's configuration.
📌 Implementation (Modified ota0)

Code: Untitled.c Select all

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_ota_ops.h"
#include "esp_partition.h"
#include "esp_err.h"
#include "esp_image_format.h"

#define TAG "ota0"
#define FORCED_UPDATE_PIN GPIO_NUM_0 // Define the GPIO pin to trigger update mode
#define OTA1_LABEL "ota_1"
#define OTA2_LABEL "ota_2"

bool check_forced_update(void) {
gpio_pad_select_gpio(FORCED_UPDATE_PIN);
gpio_set_direction(FORCED_UPDATE_PIN, GPIO_MODE_INPUT);
return (gpio_get_level(FORCED_UPDATE_PIN) == 1);
}

// Function to directly load and execute another partition
void launch_partition(const char* partition_label) {
const esp_partition_t* partition = esp_partition_find_first(
ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, partition_label);

if (partition == NULL) {
ESP_LOGE(TAG, "Partition %s not found!", partition_label);
return;
}

ESP_LOGI(TAG, "Found partition %s at offset 0x%08X", partition->label, partition->address);

// Read the application descriptor from the partition
esp_app_desc_t app_desc;
if (esp_partition_read(partition, 0x1000, &app_desc, sizeof(app_desc)) != ESP_OK) {
ESP_LOGE(TAG, "Failed to read app descriptor from partition %s", partition->label);
return;
}

ESP_LOGI(TAG, "Application version: %s", app_desc.version);
ESP_LOGI(TAG, "Jumping to %s...", partition_label);

// Execute the partition
esp_err_t err = esp_image_load(ESP_IMAGE_LOAD, partition, &app_desc);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to load image: %s", esp_err_to_name(err));
return;
}
}

void app_main(void) {
ESP_LOGI(TAG, "Booting from ota0");

if (check_forced_update()) {
ESP_LOGI(TAG, "Forced update detected. Entering update mode...");

// Insert your USB MSC update handling code here (if needed)

while (1) {
ESP_LOGI(TAG, "Waiting for firmware update...");
vTaskDelay(pdMS_TO_TICKS(1000));
}
}

ESP_LOGI(TAG, "No forced update detected. Checking which partition to launch.");

const esp_partition_t* running_partition = esp_ota_get_running_partition();

if (strcmp(running_partition->label, OTA1_LABEL) == 0) {
ESP_LOGI(TAG, "Currently running: ota1, attempting to boot ota2 for this cycle.");
launch_partition(OTA2_LABEL);
}
else if (strcmp(running_partition->label, OTA2_LABEL) == 0) {
ESP_LOGI(TAG, "Currently running: ota2, attempting to boot ota1 for this cycle.");
launch_partition(OTA1_LABEL);
}
else {
ESP_LOGI(TAG, "Unknown partition running. Defaulting to ota1 for this cycle.");
launch_partition(OTA1_LABEL);
}
}
🔍 Explanation

launch_partition() Function:
Finds the desired partition using esp_partition_find_first().
Reads the application descriptor (esp_app_desc_t) to verify the application.
Uses esp_image_load() to load and execute the partition without modifying otadata.

Handling Forced Update:
If the FORCED_UPDATE_PIN is HIGH, you can trigger the MSC update process.
Otherwise, ota0 decides which partition (ota1 or ota2) to launch for the current boot cycle.

ahsrabrifat
Posts: 201
Joined: Sat Jan 18, 2025 2:31 pm

Re: How to boot ota1 from ota0 partition?

Postby ahsrabrifat » Sat Mar 22, 2025 12:00 pm

ESP-IDF does not provide a function called esp_image_load(). You cannot directly jump to another partition this way. ESP32 does not support manual function calls to load and jump to another partition dynamically at runtime. To switch between OTA partitions, you must use esp_ota_set_boot_partition() and then restart. Modify your code the following way and try:

Code: Select all

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_ota_ops.h"
#include "esp_partition.h"
#include "esp_err.h"

#define TAG "ota0"
#define FORCED_UPDATE_PIN GPIO_NUM_0
#define OTA1_LABEL "ota_1"
#define OTA2_LABEL "ota_2"

bool check_forced_update(void) {
    gpio_pad_select_gpio(FORCED_UPDATE_PIN);
    gpio_set_direction(FORCED_UPDATE_PIN, GPIO_MODE_INPUT);
    return (gpio_get_level(FORCED_UPDATE_PIN) == 1);
}

void switch_partition_and_reboot(const char* partition_label) {
    const esp_partition_t* partition = esp_partition_find_first(
        ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, partition_label);

    if (partition == NULL) {
        ESP_LOGE(TAG, "Partition %s not found!", partition_label);
        return;
    }

    ESP_LOGI(TAG, "Setting boot partition to %s at 0x%08X", partition->label, partition->address);

    esp_err_t err = esp_ota_set_boot_partition(partition);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to set boot partition: %s", esp_err_to_name(err));
        return;
    }

    ESP_LOGI(TAG, "Rebooting into new partition...");
    esp_restart();
}

void enter_forced_update_mode() {
    ESP_LOGI(TAG, "Forced update detected. Entering update mode...");

    int timeout = 60;
    while (timeout--) {
        ESP_LOGI(TAG, "Waiting for firmware update... (%d seconds left)", timeout);
        vTaskDelay(pdMS_TO_TICKS(1000));
        if (check_update_received()) {  // Implement this function based on your update method
            ESP_LOGI(TAG, "Firmware update received, proceeding...");
            break;
        }
    }

    if (timeout == 0) {
        ESP_LOGI(TAG, "No update received. Rebooting to normal mode.");
        esp_restart();
    }
}

void app_main(void) {
    ESP_LOGI(TAG, "Booting from ota0");

    if (check_forced_update()) {
        enter_forced_update_mode();
    }

    ESP_LOGI(TAG, "No forced update detected. Checking which partition to launch.");

    const esp_partition_t* running_partition = esp_ota_get_running_partition();

    if (strcmp(running_partition->label, OTA1_LABEL) == 0) {
        ESP_LOGI(TAG, "Currently running: ota1, switching to ota2.");
        switch_partition_and_reboot(OTA2_LABEL);
    }
    else if (strcmp(running_partition->label, OTA2_LABEL) == 0) {
        ESP_LOGI(TAG, "Currently running: ota2, switching to ota1.");
        switch_partition_and_reboot(OTA1_LABEL);
    }
    else {
        ESP_LOGI(TAG, "Unknown partition running. Defaulting to ota1.");
        switch_partition_and_reboot(OTA1_LABEL);
    }
}

Who is online

Users browsing this forum: PerplexityBot, Semrush [Bot] and 7 guests