From 201c097bb7c21743b20c0bf9bdb9ed48f9e0e2cc Mon Sep 17 00:00:00 2001 From: almir-okato <66885489+almir-okato@users.noreply.github.com> Date: Thu, 16 Jan 2025 16:29:12 -0300 Subject: [PATCH] article: How to migrate from IDF Bootloader to MCUboot using ESP Self-Reflasher (#363) This article shows how to use the ESP Self-Reflasher component can be used to migrate an ESP32 embedded with an IDF-based application (OTA capable) + IDF bootloader to MCUboot compatible application + MCUboot bootloader Signed-off-by: Almir Okato --- assets/img/authors/almir-okato.webp | Bin 0 -> 6962 bytes content/authors/almir-okato/_index.md | 3 + .../featured-reflasher-idf-mcuboot.webp | Bin 0 -> 13164 bytes .../index.md | 600 ++++++++++++++++++ data/authors/almir-okato.json | 9 + 5 files changed, 612 insertions(+) create mode 100644 assets/img/authors/almir-okato.webp create mode 100644 content/authors/almir-okato/_index.md create mode 100644 content/blog/2025/01/how-to-migrate-from-idf-bootloader-to-mcuboot-using-esp-self-reflasher/featured-reflasher-idf-mcuboot.webp create mode 100644 content/blog/2025/01/how-to-migrate-from-idf-bootloader-to-mcuboot-using-esp-self-reflasher/index.md create mode 100644 data/authors/almir-okato.json diff --git a/assets/img/authors/almir-okato.webp b/assets/img/authors/almir-okato.webp new file mode 100644 index 0000000000000000000000000000000000000000..89d75c20293a6baebc2aad8e15a86fd9abbaa8bd GIT binary patch literal 6962 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 D`znEp literal 0 HcmV?d00001 diff --git a/content/blog/2025/01/how-to-migrate-from-idf-bootloader-to-mcuboot-using-esp-self-reflasher/index.md b/content/blog/2025/01/how-to-migrate-from-idf-bootloader-to-mcuboot-using-esp-self-reflasher/index.md new file mode 100644 index 00000000..891eb362 --- /dev/null +++ b/content/blog/2025/01/how-to-migrate-from-idf-bootloader-to-mcuboot-using-esp-self-reflasher/index.md @@ -0,0 +1,600 @@ +--- +title: "How to migrate from IDF Bootloader to MCUboot using ESP Self-Reflasher" +date: 2025-01-16 +showAuthor: false +authors: + - "almir-okato" +tags: ["Component", "ESP-IDF", "Bootloader", "MCUboot", "ESP Self Reflasher", "NuttX"] +--- + +Migration is a word that carries a weighty importance in many contexts. It means relocation, resettling or, in case of the tech area, it could mean upgrade or replacement. + +A variety of reasons may motivate the big decision of migrating an entire piece of hardware or software from a production running system. They may range from technical to strategic purposes, frequently: + +- Update deprecated part of the system; +- Better performance; +- Scalability; +- Specific desirable features; +- Licensing restrictions; +- Cost reductions; +- Industry standards compliance; +- Better support from vendor or community; +- Security; + +Also it is not uncommon to migrate to another platform out of necessity driven by constraints or issues that appear after implementation, thus choosing a flexible platform is often a good consideration when designing a solution. + +In Embedded Systems, migration is quite an important subject that may emerge as a result of an ongoing production decision, or serve as a factor contributing to design choices at the project stage. Hardware-wise or firmware-wise, any change of that kind is risky, so it requires good planning, controlled testing, and careful execution. + +On the firmware area, the same reasons motivate choosing a flexible platform for a project or actually migrating from a production running RTOS (Real Time Operating System) to another one. + +Relatively, changing an RTOS may not be as straight forward as a firmware update. One of the concerns that needs to be addressed beforehand is the bootloader compatibility. + +Besides initializing the system, the bootloader may be responsible for handling safe and secure firmware updates. However, it typically cannot update itself, either by design (usually due to security and safety reasons) or due to device restrictions, such as flash bootloader region protection. Also in most of the scenarios, the device is not physically accessible, thus a direct serial flashing is not practical. + +Support for Espressif chips on platforms other than [**ESP-IDF**](https://idf.espressif.com/), like [**NuttX RTOS**](https://nuttx.apache.org/) and [**Zephyr RTOS**](https://zephyrproject.org/) keeps improving. It brings more interesting options to the table, such as offering a more flexible platform that provides more design choices or offering more flexibility in firmware migration. + +However there is no standard support for **ESP-IDF** bootloader on the mentioned RTOS, so in the case of an eventual migration from **ESP-IDF** to one of them, the bootloader would need to be replaced with [**MCUboot**](https://docs.mcuboot.com/) bootloader, for example, that is one of the options available for booting either **NuttX RTOS** or **Zephyr RTOS** on Espressif chips. + +**MCUboot** bootloader is an open source secure bootloader that handles fault-tolerant updates and image verification for authenticity and integrity. **MCUboot** was designed to provide good coverage of bootloader capabilities so it could be attractive to be ported to and used with more platforms. + +However, as said before, migration is driven by variable reasons according to each project, thus it is not the goal of this article to discuss or compare each platform. + +This tutorial aims to demonstrate how **ESP Self-Reflasher** component can be used to migrate an ESP-IDF-bootloader-based application (OTA capable) to an MCUboot-based-bootloader application in case of an eventual need. The **ESP Self-Reflasher** component is used as a middle step application for enabling the device to "reflash" its own firmware. + +{{< alert icon="eye" >}} +The MCUboot-compatible application in this guide is a **NuttX RTOS** application but could also be a **Zephyr RTOS** application. +{{< /alert >}} + +The overall process described in this guide can be illustrated as: + +```mermaid +flowchart LR + A[ESP-IDF bootloader + ESP-IDF application with OTA capabilities] -->|OTA
process| B[Reflashing application with ESP Self-Reflasher component] + B -->|Reflashing
process| C(MCUboot bootloader + NuttX application) +``` + +## ESP Self-Reflasher component + +The [**ESP Self-Reflasher**](https://components.espressif.com/components/espressif/esp-self-reflasher) is an **ESP-IDF** component that allows the device to be "reflashed" with new firmware. This is achieved through one of the following ways of operation: + +- Downloading the reflashing image +- Embedding the reflashing image + +The component has examples for each way of operation. Both will be used in this guide. + +## Environment prerequisites + +Besides **ESP-IDF** (see [ESP-IDF Getting Started](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/index.html)), the following is required: + +- **ESP Self-Reflasher**: clone it to `/components` using Git: + + ```bash + cd /components + git clone https://github.com/espressif/esp-self-reflasher.git + ``` + +- **NuttX**: in order to build the application that will be migrated to, set the **NuttX** workspace. See [NuttX Getting Started](https://developer.espressif.com/blog/nuttx-getting-started/). + +- **MCUboot**: in the case of building the bootloader standalone, follow the instructions [here](https://docs.mcuboot.com/readme-espressif.html). + +## Step-by-step guide + +### Build the reflashing images (MCUboot and NuttX application) + +1. With the **NuttX** workspace ready, prepare the NSH (NuttShell) configuration with **MCUboot** compatibility, which is available under the `mcuboot_nsh` defconfig (premade application configuration for a board, more information [here](https://nuttx.apache.org/docs/latest/quickstart/configuring.html)). This is the build that will be used as the *final target* of the reflashing process. + + ```bash + cd + ./tools/configure.sh esp32-devkitc:mcuboot_nsh + ``` + + You can also manually configure other **NuttX** applications to be built with **MCUboot** compatibility: + + - In your **NuttX** workspace, enter the menuconfig: + ```bash + make menuconfig + ``` + - In the menu `System Type -> Bootloader and Image Configuration`, enable the option `Enable MCUboot-bootable format` + +2. Ensure that the flash image map (organization of image slots in flash) is properly configured in menuconfig -> `System Type -> SPI Flash Configuration` from menuconfig. For this example using the ESP32, the following flash image map is considered (note that the Bootloader offset may differ among other Espressif chip families): + + | REGION | OFFSET | SIZE | + | -------------------------------- | --------- | -------- | + | Bootloader | 0x001000 | 0x00F000 | + | Application primary slot | 0x010000 | 0x100000 | + | Application secondary slot | 0x110000 | 0x100000 | + | Scratch | 0x210000 | 0x040000 | + + {{< alert icon="eye" >}} + If **MCUboot** is built separately from the **NuttX** build, make sure that both have a matching flash image map. + {{< /alert >}} + +3. Navigate to the menuconfig `Exit` and, when prompted, save the current settings. + +4. Build the **MCUboot** bootloader: + + ```bash + make -j bootloader + ``` + +5. Now build the **NuttX** application: + + ```bash + make ESPTOOL_BINDIR=./ -s -j + ``` + +### Build the reflashing application + +#### Example 1: Download the target reflashing image + +The **ESP Self-Reflasher** component provides the example `boot_swap_download_example`. This can be used as a starting point for the reflashing application. + +1. Navigate to the example directory. + + ```bash + cd /components/esp-self-reflasher/examples/boot_swap_download_example/ + ``` + +2. First, copy the *final target images* (**NuttX** and **MCUboot** binaries) to the directory that will be served for HTTP download. + + ```bash + cp /nuttx.bin /components/esp-self-reflasher/examples/boot_swap_download_example/example_bin_dir/app_upd.bin + cp /mcuboot-esp32.bin /components/esp-self-reflasher/examples/boot_swap_download_example/example_bin_dir/mcuboot-esp32.bin + ``` + +3. Configure the example: + + ```bash + idf.py menuconfig + ``` + +4. Enter menu `Example Configuration -> Bootloader reflash configuration` and set the `Bootloader bin url endpoint` with the host IP, port and the bootloader binary name (e.g. `http://192.168.0.100:8070/mcuboot-esp32.bin`): + + ```text + http://:/mcuboot-esp32.bin + ``` + +5. Then configure the similar parameters on the `Example Configuration -> Application reflash configuration` menu, set the `Application upgrade url endpoint` (e.g. `http://192.168.0.100:8070/app_upd.bin`): + + ```text + http://:/app_upd.bin + ``` + +6. Also configure the `Bootloader region address` (the Bootloader offset mentioned above) and the `Bootloader region size`. + +7. Set the `Application region address` and `Application region size`. Note that if the `boot_swap_download_example` is flashed standalone directly as is, these must match the image Secondary Slot from the target **MCUboot** image organization as the example expects **MCUboot** to do the swapping to the Primary Slot later, otherwise, if the example is OTA upgraded which this tutorial walk through, these configs must match Primary Slot. It will depend on where the reflashing application is running from (Factory partition or OTA partition), as it should not overwrite itself on the process. + +8. Configure the preferred network connection settings on the menu `Example Connection Configuration`, such as Wi-Fi SSID and Password. + +9. Navigate to the menuconfig `Exit` and, when prompted, save the current settings. + +10. Build the example: + + ```bash + idf.py build + ``` + +#### Example 2: Embed the target reflashing image + +Alternatively, **ESP Self-Reflasher** component can be used without network connection and download step, however as using this way the "bootloader + target reflashing image" will be embedded on the reflashing application, it must not exceed the total size that the first OTA supports. + +If the constraint is not a problem, `boot_swap_embedded_example` can be used as start point for the reflashing application. Note that for this guide, the size of the OTA partitions on the partition table may be changed (see next section). + +1. Navigate to the example directory. + + ```bash + cd /components/esp-self-reflasher/examples/boot_swap_embedded_example/ + ``` + +2. In this example, the **MCUboot** bootloader and target reflashing image needs to be merged in one binary as it goes embedded to the application. + + ```bash + esptool.py -c esp32 merge_bin --output /components/esp-self-reflasher/examples/boot_swap_embedded_example/example_bin_dir/app_upd.merged.bin 0x0000 /mcuboot-esp32.bin 0xF000 /nuttx.bin + ``` + + >**Note:** + In ESP32 case, the offsets on the merge step are shifted minus 0x1000 because of its bootloader offset 0x1000. + +3. Configure the example: + + ```bash + idf.py menuconfig + ``` + +4. Enter menu `Example Configuration` and set the directory where the merged binary is placed and its name. Set the `Destination address`, that for this example will be the Bootloader offset, and the `Destination region size`, that must be the image slot size from the target flash organization plus the bootloader region size. + +5. Navigate to the menuconfig `Exit` and, when prompted, save the current settings. + +6. Build the example: + + ```bash + idf.py build + ``` + +### Build and flash the ESP-IDF application + +The **ESP-IDF**'s `simple_ota_example` will be used as the hypothetical **ESP-IDF** application that will OTA to the reflashing application. The steps are basically the same as described on its [documentation](https://github.com/espressif/esp-idf/tree/v5.1.4/examples/system/ota), with few changes. + +1. Navigate to the example directory. + + ```bash + cd /examples/system/ota/simple_ota_example/ + ``` + +2. Set the target chip: + + ```bash + idf.py set-target esp32 + ``` + +3. Set the configurations for the example: + + ```bash + idf.py menuconfig + ``` + +4. In the `Example Configuration` menu, set the `firmware upgrade url endpoint` with the host IP, port and the Reflasher application binary name (e.g. `http://192.168.0.100:8070/boot_swap_download.bin`): + + ```text + http://:/.bin + ``` + +5. In the `Example Connection Configuration` menu, again set the preferred network connection settings, such as Wi-Fi SSID and Password. + +6. Only for illustration purposes, this guide is using simple HTTP requests, so enable the `Allow HTTP for OTA` option in the `Component config -> ESP HTTPS OTA`. + + >**Note:** + If the `boot_swap_embedded_example` was used, define a custom partition table in `Partition table` menu. Create the `partitions.csv` file with the following content: + + ```text + # Name, Type, SubType, Offset, Size, Flags + nvs, data, nvs, , 0x4000, + otadata, data, ota, , 0x2000, + phy_init, data, phy, , 0x1000, + factory, app, factory, 0x10000, 0x180000, + ota_0, app, ota_0, , 0x180000, + ``` + +7. Navigate to the menuconfig `Exit` and, when prompted, save the current settings. + +8. Copy the reflashing application binary that was build in the previous section to the directory where the HTTP server will run: + + ```bash + cp /components/esp-self-reflasher/examples/boot_swap__example/build/boot_swap__example.bin + ``` + +9. Open a new bash and start the HTTP server for the OTA application. Here is a suggestion for creating the HTTP server using Python: + + ```bash + cd + sudo python -m http.server -b + # e.g. sudo python -m http.server -b 192.168.0.100 8070 + ``` + + >**Note:** + If the `boot_swap_download_example` was used, copy the target reflashing images to the or open another bash and start the HTTP server from where the reflashing images will be downloaded (watch for the that cannot be the same): + + ```bash + cd /components/esp-self-reflasher/examples/boot_swap_download_example/example_bin_dir/ + sudo python -m http.server -b + # e.g. sudo python -m http.server -b 192.168.0.100 8071 + ``` + +10. Finally build and flash the OTA application: + + ```bash + idf.py -p flash monitor + # e.g. idf.py -p /dev/ttyUSB0 flash monitor + ``` + +### Execution output + +Now that everything is properly build and set, after flashing the OTA application the console output will be similar as the following (check the section related to the example you chose to build): + +#### `boot_swap_download_example` + + >**Note:** + Some Wifi and other common console log outputs are ommited. + +
+ Click here to view + +```text +I (29) boot: ESP-IDF v5.1.4 2nd stage bootloader +I (29) boot: compile time Jan 14 2025 01:06:52 +I (29) boot: Multicore bootloader +I (34) boot: chip revision: v3.0 +I (37) boot.esp32: SPI Speed : 40MHz +I (42) boot.esp32: SPI Mode : DIO +I (47) boot.esp32: SPI Flash Size : 4MB +I (51) boot: Enabling RNG early entropy source... +I (57) boot: Partition Table: +I (60) boot: ## Label Usage Type ST Offset Length +I (67) boot: 0 nvs WiFi data 01 02 00009000 00004000 +I (75) boot: 1 otadata OTA data 01 00 0000d000 00002000 +I (82) boot: 2 phy_init RF data 01 01 0000f000 00001000 +I (90) boot: 3 factory factory app 00 00 00010000 00100000 +I (97) boot: 4 ota_0 OTA app 00 10 00110000 00100000 +I (105) boot: 5 ota_1 OTA app 00 11 00210000 00100000 +I (112) boot: End of partition table +... + +I (505) cpu_start: Application information: +I (510) cpu_start: Project name: simple_ota +... + +I (613) main_task: Calling app_main() +I (613) simple_ota_example: OTA example app_main start +... + +I (863) example_connect: Start example_connect. +... + +I (1053) example_connect: Connecting to Home... +I (1063) example_connect: Waiting for IP(s) +... + +I (4863) example_connect: Got IPv6 event: Interface "example_netif_sta" address: fe80:0000:0000:0000:c6dd:57ff:fe5f:2b04, type: ESP_IP6_ADDR_IS_LINK_LOCAL +I (6763) esp_netif_handlers: example_netif_sta ip: 192.168.100.100, mask: 255.255.255.0, gw: 192.168.100.1 +I (6763) example_connect: Got IPv4 event: Interface "example_netif_sta" address: 192.168.100.100 +I (6773) example_common: Connected to example_netif_sta +I (6773) example_common: - IPv4 address: 192.168.100.100, +I (6783) example_common: - IPv6 address: fe80:0000:0000:0000:c6dd:57ff:fe5f:2b04, type: ESP_IP6_ADDR_IS_LINK_LOCAL +... + +I (6793) simple_ota_example: Starting OTA example task +I (6803) simple_ota_example: Attempting to download update from http://192.168.100.101:8070/boot_swap_download.bin +I (6823) main_task: Returned from app_main() +I (6943) esp_https_ota: Starting OTA... +I (6943) esp_https_ota: Writing to partition subtype 16 at offset 0x110000 +... + +I (22823) simple_ota_example: OTA Succeed, Rebooting... +... + +ets Jul 29 2019 12:21:46 +rst:0xc (SW_CPU_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT) +configsip: 0, SPIWP:0xee +clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 +mode:DIO, clock div:2 +load:0x3fff0030,len:7112 +load:0x40078000,len:15624 +load:0x40080400,len:4 +load:0x40080404,len:3876 +entry 0x4008064c +I (29) boot: ESP-IDF v5.1.4 2nd stage bootloader +I (29) boot: compile time Jan 14 2025 01:06:52 +I (29) boot: Multicore bootloader +I (33) boot: chip revision: v3.0 +I (37) boot.esp32: SPI Speed : 40MHz +I (42) boot.esp32: SPI Mode : DIO +I (46) boot.esp32: SPI Flash Size : 4MB +I (51) boot: Enabling RNG early entropy source... +I (56) boot: Partition Table: +I (60) boot: ## Label Usage Type ST Offset Length +I (67) boot: 0 nvs WiFi data 01 02 00009000 00004000 +I (75) boot: 1 otadata OTA data 01 00 0000d000 00002000 +I (82) boot: 2 phy_init RF data 01 01 0000f000 00001000 +I (90) boot: 3 factory factory app 00 00 00010000 00100000 +I (97) boot: 4 ota_0 OTA app 00 10 00110000 00100000 +I (105) boot: 5 ota_1 OTA app 00 11 00210000 00100000 +I (112) boot: End of partition table +... + +I (498) cpu_start: Application information: +I (502) cpu_start: Project name: boot_swap_download +... + +I (607) main_task: Calling app_main() +I (607) boot_swap_download_example: Self Reflasher example app_main start +I (627) example_connect: Start example_connect. +... + +I (797) example_connect: Connecting to Home... +I (807) example_connect: Waiting for IP(s) +... + +I (4627) example_connect: Got IPv6 event: Interface "example_netif_sta" address: fe80:0000:0000:0000:c6dd:57ff:fe5f:2b04, type: ESP_IP6_ADDR_IS_LINK_LOCAL +I (6497) esp_netif_handlers: example_netif_sta ip: 192.168.100.100, mask: 255.255.255.0, gw: 192.168.100.1 +I (6497) example_connect: Got IPv4 event: Interface "example_netif_sta" address: 192.168.100.100 +I (6507) example_common: Connected to example_netif_sta +I (6507) example_common: - IPv4 address: 192.168.100.100, +I (6517) example_common: - IPv6 address: fe80:0000:0000:0000:c6dd:57ff:fe5f:2b04, type: ESP_IP6_ADDR_IS_LINK_LOCAL +... + +I (6527) boot_swap_download_example: Starting Self Reflasher example task +I (6537) self_reflasher: src_start 0x00210000 src_end 0x00310000 dest_start 0x00010000 dest_end 0x00110000 +I (6787) main_task: Returned from app_main() +I (10497) self_reflasher: Partition erased successfully +I (15327) self_reflasher: Connection closed +I (15327) self_reflasher: Total downloaded binary length: 1048576 (0x100000) +I (15327) self_reflasher: File downloaded successfully +I (15337) self_reflasher: Starting copy 0x00100000 bytes from address 0x00210000 to address 0x00010000 +I (19137) self_reflasher: Flash destination region erased successfully +I (21677) self_reflasher: Data copied from partition address 0x00210000 offset 0x00000000 to region: 0x00010000 +I (21677) self_reflasher: Updating configuration for next download +I (21687) self_reflasher: Current selected partition for download placement will be erased +I (25617) self_reflasher: Partition erased successfully +I (25807) self_reflasher: Connection closed +I (25807) self_reflasher: Total downloaded binary length: 27376 (0x6af0) +I (25807) self_reflasher: File downloaded successfully +I (25817) self_reflasher: Starting copy 0x00006af0 bytes from address 0x00210000 to address 0x00001000 +I (26417) self_reflasher: Flash destination region erased successfully +I (26527) self_reflasher: Data copied from partition address 0x00210000 offset 0x00000000 to region: 0x00001000 +I (26527) boot_swap_download_example: MCUboot+Image overwritting succeed, Rebooting... +... + +ets Jul 29 2019 12:21:46 +rst:0xc (SW_CPU_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT) +configsip: 0, SPIWP:0xee +clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 +mode:DIO, clock div:2 +load:0x3fff7c98,len:6176 +load:0x40078000,len:13312 +load:0x40090000,len:7804 +entry 0x4007b3b0 +[esp32] [INF] *** Booting MCUboot build v1.10.0-131-gb206b99b *** +[esp32] [INF] [boot] chip revision: v3.0 +[esp32] [INF] [boot.esp32] SPI Speed : 40MHz +[esp32] [INF] [boot.esp32] SPI Mode : DIO +[esp32] [INF] [boot.esp32] SPI Flash Size : 4MB +[esp32] [INF] [boot] Enabling RNG early entropy source... +[esp32] [INF] Primary image: magic=good, swap_type=0x1, copy_done=0x3, image_ok=0x1 +[esp32] [INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 +[esp32] [INF] Boot source: primary slot +[esp32] [INF] Image index: 0, Swap type: none +[esp32] [INF] Disabling RNG early entropy source... +[esp32] [INF] br_image_off = 0x10000 +[esp32] [INF] ih_hdr_size = 0x20 +[esp32] [INF] Loading image 0 - slot 0 from flash, area id: 1 +[esp32] [INF] DRAM segment: start=0x146dc, size=0x2e4, vaddr=0x3ffb1ee0 +[esp32] [INF] IRAM segment: start=0x129f8, size=0x1ce4, vaddr=0x40080000 +[esp32] [INF] start=0x400818ec +IROM segment aligned lma 0x00020000 vma 0x400d0000 len 0x011b18 (72472) +DROM segment aligned lma 0x00010000 vma 0x3f400000 len 0x0029b8 (10680) + +NuttShell (NSH) NuttX-10.4.0 +nsh> +``` + +
+ +#### `boot_swap_embedded_example` + + >**Note:** + Some Wifi and other common console log outputs are ommited. + +
+ Click here to view + +```text +I (29) boot: ESP-IDF v5.1.4 2nd stage bootloader +I (29) boot: compile time Jan 14 2025 00:49:05 +I (29) boot: Multicore bootloader +I (34) boot: chip revision: v3.0 +I (37) boot.esp32: SPI Speed : 40MHz +I (42) boot.esp32: SPI Mode : DIO +I (47) boot.esp32: SPI Flash Size : 4MB +I (51) boot: Enabling RNG early entropy source... +I (57) boot: Partition Table: +I (60) boot: ## Label Usage Type ST Offset Length +I (67) boot: 0 nvs WiFi data 01 02 00009000 00004000 +I (75) boot: 1 otadata OTA data 01 00 0000d000 00002000 +I (82) boot: 2 phy_init RF data 01 01 0000f000 00001000 +I (90) boot: 3 factory factory app 00 00 00010000 00180000 +I (97) boot: 4 ota_0 OTA app 00 10 00190000 00180000 +I (105) boot: End of partition table +... + +I (606) simple_ota_example: OTA example app_main start +... + +I (866) example_connect: Start example_connect. +... + +I (1046) example_connect: Connecting to Home... +I (1046) example_connect: Waiting for IP(s) +... + +I (4866) example_connect: Got IPv6 event: Interface "example_netif_sta" address: fe80:0000:0000:0000:c6dd:57ff:fe5f:2b04, type: ESP_IP6_ADDR_IS_LINK_LOCAL +I (6736) esp_netif_handlers: example_netif_sta ip: 192.168.100.100, mask: 255.255.255.0, gw: 192.168.100.1 +I (6736) example_connect: Got IPv4 event: Interface "example_netif_sta" address: 192.168.100.100 +I (6746) example_common: Connected to example_netif_sta +I (6746) example_common: - IPv4 address: 192.168.100.100, +I (6756) example_common: - IPv6 address: fe80:0000:0000:0000:c6dd:57ff:fe5f:2b04, type: ESP_IP6_ADDR_IS_LINK_LOCAL +... + +I (6766) simple_ota_example: Starting OTA example task +I (6776) simple_ota_example: Attempting to download update from http://192.168.100.101:8070/boot_swap_embedded.bin +I (6796) main_task: Returned from app_main() +I (6886) esp_https_ota: Starting OTA... +I (6896) esp_https_ota: Writing to partition subtype 16 at offset 0x190000 +I (26356) esp_image: segment 0: paddr=00190020 vaddr=3f400020 size=1174b8h (1143992) map +I (26696) esp_image: segment 1: paddr=002a74e0 vaddr=3ffb0000 size=036e8h ( 14056) +I (26706) esp_image: segment 2: paddr=002aabd0 vaddr=40080000 size=05448h ( 21576) +I (26706) esp_image: segment 3: paddr=002b0020 vaddr=400d0020 size=12ab0h ( 76464) map +I (26736) esp_image: segment 4: paddr=002c2ad8 vaddr=40085448 size=0805ch ( 32860) +I (26756) esp_image: segment 0: paddr=00190020 vaddr=3f400020 size=1174b8h (1143992) map +I (27096) esp_image: segment 1: paddr=002a74e0 vaddr=3ffb0000 size=036e8h ( 14056) +I (27106) esp_image: segment 2: paddr=002aabd0 vaddr=40080000 size=05448h ( 21576) +I (27116) esp_image: segment 3: paddr=002b0020 vaddr=400d0020 size=12ab0h ( 76464) map +I (27136) esp_image: segment 4: paddr=002c2ad8 vaddr=40085448 size=0805ch ( 32860) +I (27196) simple_ota_example: OTA Succeed, Rebooting... +... + +ets Jul 29 2019 12:21:46 +rst:0xc (SW_CPU_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT) +configsip: 0, SPIWP:0xee +clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 +mode:DIO, clock div:2 +load:0x3fff0030,len:7112 +load:0x40078000,len:15624 +load:0x40080400,len:4 +load:0x40080404,len:3876 +entry 0x4008064c +I (29) boot: ESP-IDF v5.1.4 2nd stage bootloader +I (29) boot: compile time Jan 14 2025 00:49:05 +I (29) boot: Multicore bootloader +I (33) boot: chip revision: v3.0 +I (37) boot.esp32: SPI Speed : 40MHz +I (42) boot.esp32: SPI Mode : DIO +I (46) boot.esp32: SPI Flash Size : 4MB +I (51) boot: Enabling RNG early entropy source... +I (56) boot: Partition Table: +I (60) boot: ## Label Usage Type ST Offset Length +I (67) boot: 0 nvs WiFi data 01 02 00009000 00004000 +I (75) boot: 1 otadata OTA data 01 00 0000d000 00002000 +I (82) boot: 2 phy_init RF data 01 01 0000f000 00001000 +I (90) boot: 3 factory factory app 00 00 00010000 00180000 +I (97) boot: 4 ota_0 OTA app 00 10 00190000 00180000 +I (105) boot: End of partition table +... + +I (625) cpu_start: Application information: +I (629) cpu_start: Project name: boot_swap_embedded +... + +I (734) boot_swap_embedded_example: Boot swap embedded bin example start +I (744) self_reflasher: Starting copy 0x0010f000 bytes from address 0x001941bc to address 0x00001000 +I (12934) self_reflasher: Data copied from address 0x001941bc to region: 0x00001000 +I (12934) boot_swap_embedded_example: Overwritting succeed, Rebooting... +ets Jul 29 2019 12:21:46 +rst:0xc (SW_CPU_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT) +configsip: 0, SPIWP:0xee +clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 +mode:DIO, clock div:2 +load:0x3fff7c98,len:6176 +load:0x40078000,len:13312 +load:0x40090000,len:7804 +entry 0x4007b3b0 +[esp32] [INF] *** Booting MCUboot build v1.10.0-131-gb206b99b *** +[esp32] [INF] [boot] chip revision: v3.0 +[esp32] [INF] [boot.esp32] SPI Speed : 40MHz +[esp32] [INF] [boot.esp32] SPI Mode : DIO +[esp32] [INF] [boot.esp32] SPI Flash Size : 4MB +[esp32] [INF] [boot] Enabling RNG early entropy source... +[esp32] [INF] Primary image: magic=good, swap_type=0x1, copy_done=0x3, image_ok=0x1 +[esp32] [INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 +[esp32] [INF] Boot source: primary slot +[esp32] [INF] Image index: 0, Swap type: none +[esp32] [INF] Disabling RNG early entropy source... +[esp32] [INF] br_image_off = 0x10000 +[esp32] [INF] ih_hdr_size = 0x20 +[esp32] [INF] Loading image 0 - slot 0 from flash, area id: 1 +[esp32] [INF] DRAM segment: start=0x146dc, size=0x2e4, vaddr=0x3ffb1ee0 +[esp32] [INF] IRAM segment: start=0x129f8, size=0x1ce4, vaddr=0x40080000 +[esp32] [INF] start=0x400818ec +IROM segment aligned lma 0x00020000 vma 0x400d0000 len 0x011b18 (72472) +DROM segment aligned lma 0x00010000 vma 0x3f400000 len 0x0029b8 (10680) + +NuttShell (NSH) NuttX-10.4.0 +nsh> +``` + +
+ +## Conclusion + +This article demonstrated how to configure and build the **ESP Self-Reflasher** examples and walked through their use, starting from an **ESP-IDF** OTA application, updating to one of the examples, replacing **ESP-IDF**'s bootloader and application with **MCUboot** bootloader and **NuttX** application respectively and finally reaching the **NuttX** application execution. + +The **ESP Self-Reflasher** component may help on the process of migrating an ESP32-xx device from an **ESP-IDF** application to other **MCUboot** compatible platform, however it is strongly recommended to observe the already enabled constraints of a device beforehand and also to plan carefully as it uses risky flash operations. diff --git a/data/authors/almir-okato.json b/data/authors/almir-okato.json new file mode 100644 index 00000000..31b0c5eb --- /dev/null +++ b/data/authors/almir-okato.json @@ -0,0 +1,9 @@ +{ + "name": "Almir Okato", + "image" : "img/authors/almir-okato.webp", + "bio": "Embedded Software Engineer at Espressif", + "social": [ + { "linkedin": "https://www.linkedin.com/in/almir-okato" }, + { "github": "https://github.com/almir-okato" } + ] +}