Updating ESP32 firmware over the internet

Updating a board on your desk is one command. Updating a hundred of them in other people's buildings needs three things in place before the first one ships.

1. Two application slots

The running firmware cannot overwrite itself, so the new image is written to a second slot and the bootloader switches to it. That is decided by the partition table, and it cannot be changed over the air later. For 4 MB of flash:

# Name,   Type, SubType, Offset,   Size
nvs,      data, nvs,     0x9000,   0x6000
otadata,  data, ota,     0xf000,   0x2000
phy_init, data, phy,     0x11000,  0x1000
ota_0,    app,  ota_0,   0x20000,  0x1E0000
ota_1,    app,  ota_1,   0x200000, 0x1E0000

Each slot is 1.9 MB here. If your application is larger than half the flash, there is no room for a second copy, and that is a decision to make before the hardware is ordered.

2. A way to get the image onto the device

The common way is for the device to fetch it. ESP-IDF's esp_https_ota does the download and the writing:

esp_http_client_config_t http = {
    .url = "https://example.com/firmware.bin",
    .crt_bundle_attach = esp_crt_bundle_attach,
};
esp_https_ota_config_t ota = { .http_config = &http };

if (esp_https_ota(&ota) == ESP_OK) {
    esp_restart();
}

What it leaves to you is everything around it: a server that hosts the images, a way for the device to learn that a newer one exists, a way to update one device and not the other ninety-nine, and the memory for a TLS session while the download runs.

The other way is to push. If the device already holds a connection open to a server, the image can travel down it when you decide, to the device you chose. That is how Pinscope does it: you upload the .bin, press Update firmware on a device, and watch the progress. The component writes it with the same esp_ota functions.

3. A rollback

Sooner or later an update will be wrong: bad WiFi settings, a crash at start, a build for the wrong board. Without a rollback that device is lost until someone visits it. Switch on

CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y

and the bootloader treats a new image as on trial. The firmware has to call esp_ota_mark_app_valid_cancel_rollback() to keep it; if it restarts before doing so, the bootloader goes back to the previous image.

The question is when to make that call. Calling it at the top of app_main confirms an image that may never connect again. The useful test is the one that matters to you: the new firmware reached the server. Pinscope confirms the image on its first successful connection, and restarts the device if that has not happened within five minutes, so an update that cannot phone home undoes itself.

Before the first device ships

Try it

Three devices are free with every feature, and no card is needed. Create an account, or read the five-minute guide first.

More