|
| 1 | +--- |
| 2 | +title: "MCUboot - Getting Started Guide for ESP32" |
| 3 | +date: 2025-12-16 |
| 4 | +showAuthor: false |
| 5 | +authors: |
| 6 | + - "almir-okato" |
| 7 | +tags: ["Bootloader", "MCUboot", "NuttX", "Zephyr"] |
| 8 | +--- |
| 9 | + |
| 10 | +## Introduction |
| 11 | + |
| 12 | +In the embedded world, firmware updates are essential and increasingly important. As IoT solutions grow exponentially in numbers and complexity, so does the concern to make devices secure and updatable in the field efficiently. |
| 13 | + |
| 14 | +Some years ago, **MCUboot** emerged as an open source bootloader project for small and low-cost systems, designed to simplify and standardize solutions for these challenges. It started as an Apache Mynewt subproject when developers decided to separate the bootloader from OS development. Later, it was ported to **Zephyr RTOS** and became its default bootloader. |
| 15 | + |
| 16 | +**Espressif Systems** has been expanding support for other **3rd party RTOSes** like **Zephyr** and **NuttX** as attractive options for a developer adopt within its SoCs. Since then, a port for **Espressif** SoCs has been developed in the **MCUboot** project. |
| 17 | + |
| 18 | +This guide shows how to get started with **MCUboot** on your ESP32-based project (note: this is a translated and updated version of my original article in [**Embarcados** website](https://embarcados.com.br/primeiros-passos-com-esp32-utilizando-mcuboot-como-bootloader/)). It covers environment setup, required configuration in the application side, how to build the **MCUboot Espressif Port** bootloader and how to flash it into the device. The [ESP32 DevKitC](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-devkitc.html) board was used to prepare this guide. |
| 19 | + |
| 20 | +{{< alert icon="eye" >}} |
| 21 | +The MCUboot-compatible application mentioned in this guide can be either a **NuttX RTOS** application or a **Zephyr RTOS** application built for Espressif SoCs with MCUboot compatibility configuration enable. |
| 22 | + |
| 23 | +This guide assumes that you are familiar with building and configuring the chosen RTOS. |
| 24 | +{{< /alert >}} |
| 25 | + |
| 26 | +## What is MCUboot? |
| 27 | + |
| 28 | +As previously mentioned, **MCUboot** is an open source secure bootloader for 32-bit microcontrollers. The project defines a common infrastructure for secure boot and it covers: |
| 29 | + |
| 30 | +- **Fault-tolerant updates**: the flash organization is well defined, using the concept of slots for placing the main bootable image and update image in different flash regions, with a scratch area to help the swapping process during firmware updates. This provides mechanisms for reliable firmware updates and also allows recovering and reverting if any problem during the process. |
| 31 | +- **Security**: image validation through hash checking and signature verification using asymmetric key algorithms like RSA 2048/3072, ECDSA and ed25519 ensures integrity and authenticity of firmware images. |
| 32 | + |
| 33 | +The project aims to standardize these aspects comprehensively. **MCUboot** core features are independent from any operating system and hardware, relying on hardware porting layers from the target host OS. |
| 34 | + |
| 35 | +### High-level overview of the boot process |
| 36 | + |
| 37 | +{{< figure |
| 38 | + default=true |
| 39 | + src="./assets/mcuboot-process-overview1.webp" |
| 40 | + caption="MCUboot boot process overview" |
| 41 | +>}} |
| 42 | +
|
| 43 | +{{< figure |
| 44 | + default=true |
| 45 | + src="./assets/mcuboot-process-overview2.webp" |
| 46 | + caption="MCUboot boot process overview" |
| 47 | +>}} |
| 48 | +
|
| 49 | +**Important concepts:** |
| 50 | + |
| 51 | +- **Primary slot** is where the main bootable image resides, code always runs from there. |
| 52 | +- **Secondary slot** is used for updates; it stores the incoming image and, after the swap, stores the original image to enable recovery if needed. |
| 53 | +- **Scratch region** is used to help image swap when updating. |
| 54 | +- A header and trailer are added to the image to track general information, swapping, and update states. |
| 55 | + |
| 56 | +{{< alert icon="eye" >}} |
| 57 | +The booting process and concepts presented here are related to the **Espressif Port** current support to **MCUboot**. See more at the official [MCUboot documentation](https://docs.mcuboot.com/). |
| 58 | +{{< /alert >}} |
| 59 | + |
| 60 | +## Setting the environment |
| 61 | + |
| 62 | +First, prepare the development environment. This guide assumes the use of Linux (Ubuntu 20.04.2 LTS or later). |
| 63 | + |
| 64 | +Ensure you have **Git**, **Python3**, **pip**, **CMake** and **Ninja** installed. If you don't, you can run the following (this step is optional): |
| 65 | + |
| 66 | +```bash |
| 67 | +sudo apt update |
| 68 | +sudo apt upgrade |
| 69 | +sudo apt install git python3 python3-pip cmake ninja-build |
| 70 | +``` |
| 71 | + |
| 72 | +### **MCUboot Espressif Port** HAL |
| 73 | + |
| 74 | +The **MCUboot Espressif Port** depends on HAL (Hardware Abstraction Layer) sources based on **ESP-IDF**. Then it is required to have either **ESP-IDF** itself installed, which allows building the project in a standalone way, or one of the Espressif's HAL sources used by **Zephyr RTOS** (`zephyrproject-rtos/hal_espressif/`) or **NuttX RTOS** |
| 75 | +(`espressif/esp-hal-3rdparty`). For both the later options, it is recommended using them only within their RTOS build system, since their sources revision may differ from what is currently expected. |
| 76 | + |
| 77 | +**Installing ESP-IDF v5.1.6** |
| 78 | + |
| 79 | + ```bash |
| 80 | + git clone --recursive https://github.com/espressif/esp-idf.git |
| 81 | + ``` |
| 82 | + |
| 83 | + ```bash |
| 84 | + cd <IDF_PATH> |
| 85 | + git checkout v5.1.6 |
| 86 | + ``` |
| 87 | + |
| 88 | + ```bash |
| 89 | + <IDF_PATH>/install.sh |
| 90 | + ``` |
| 91 | + |
| 92 | + ```bash |
| 93 | + . <IDF_PATH>/export.sh |
| 94 | + ``` |
| 95 | + |
| 96 | + More information about **ESP-IDF** installation can be found [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html#manual-installation). |
| 97 | + |
| 98 | +### Clone and set up MCUboot |
| 99 | + |
| 100 | +1. Clone the repository into a directory of your choice (other than **ESP-IDF** installation): |
| 101 | + |
| 102 | + ```bash |
| 103 | + git clone https://github.com/mcu-tools/mcuboot.git |
| 104 | + cd mcuboot |
| 105 | + ``` |
| 106 | + |
| 107 | +2. Install the additional dependencies needed by **MCUboot**: |
| 108 | + |
| 109 | + ```bash |
| 110 | + pip3 install -r scripts/requirements.txt |
| 111 | + ``` |
| 112 | + |
| 113 | +3. Update the **MbedTLS** submodule required by **MCUboot**: |
| 114 | + |
| 115 | + ```bash |
| 116 | + git submodule update --init --recursive ext/mbedtls |
| 117 | + ``` |
| 118 | + |
| 119 | +4. For any images you may boot with **MCUboot**, you need to sign them using `imgtool`. This tool adds the **MCUboot** expected headers and trailers to the binary, signs the firmware, and can also generate the signing keys. `imgtool` can be found at `<MCUBOOT_DIR>/scripts/imgtool.py` (where `<MCUBOOT_DIR>` is the path of the cloned repository), or you can install it as follows (optional): |
| 120 | + |
| 121 | + ```bash |
| 122 | + pip3 install imgtool |
| 123 | + ``` |
| 124 | + |
| 125 | +{{< alert icon="eye" >}} |
| 126 | +**MCUboot** repository includes some sample cryptographic keys for signing and testing the secure boot verification. It is crucial that you never use these keys in production since the private key is available in the **MCUboot** repository. |
| 127 | +See how to generate and manage cryptographic keys at the [imgtool documentation](https://docs.mcuboot.com/imgtool.html). |
| 128 | +{{< /alert >}} |
| 129 | + |
| 130 | +## Building and flashing MCUboot on ESP32 |
| 131 | + |
| 132 | +With everything set, let's configure, build and flash the **MCUboot Espressif Port** bootloader. |
| 133 | +
|
| 134 | +1. Firstly set the flash layout organization in the `<MCUBOOT_DIR>/boot/espressif/port/esp32/bootloader.conf` file, it must match the same flash organization as the chosen RTOS. For example: |
| 135 | +
|
| 136 | + ```text |
| 137 | + CONFIG_ESP_FLASH_SIZE=4MB |
| 138 | + CONFIG_ESP_BOOTLOADER_SIZE=0xF000 |
| 139 | + CONFIG_ESP_BOOTLOADER_OFFSET=0x1000 |
| 140 | + CONFIG_ESP_IMAGE0_PRIMARY_START_ADDRESS=0x20000 |
| 141 | + CONFIG_ESP_APPLICATION_SIZE=0x150000 |
| 142 | + CONFIG_ESP_IMAGE0_SECONDARY_START_ADDRESS=0x170000 |
| 143 | + CONFIG_ESP_SCRATCH_OFFSET=0x3E0000 |
| 144 | + CONFIG_ESP_SCRATCH_SIZE=0x1F000 |
| 145 | + ``` |
| 146 | +
|
| 147 | +2. Compile and generate the ELF: |
| 148 | +
|
| 149 | + ```bash |
| 150 | + cd <MCUBOOT_DIR>/boot/espressif |
| 151 | + cmake -DCMAKE_TOOLCHAIN_FILE=tools/toolchain-esp32.cmake -DMCUBOOT_TARGET=esp32 -DESP_HAL_PATH=<IDF_PATH> -DMCUBOOT_FLASH_PORT=/dev/ttyUSB0 -B build -GNinja |
| 152 | + ``` |
| 153 | +
|
| 154 | + ```bash |
| 155 | + ninja -C build/ |
| 156 | + ``` |
| 157 | +
|
| 158 | +3. Erase the device's flash: |
| 159 | + |
| 160 | + ```bash |
| 161 | + esptool.py -p <PORT> erase_flash |
| 162 | + ``` |
| 163 | + |
| 164 | +4. Flash **MCUboot Espressif Port** bootloader to your board: |
| 165 | + |
| 166 | + ```bash |
| 167 | + ninja -C build/ flash |
| 168 | + ``` |
| 169 | + |
| 170 | + Alternatively: |
| 171 | + |
| 172 | + ```bash |
| 173 | + esptool.py -p /dev/ttyUSB0 -b 921600 --before default_reset --after hard_reset --chip esp32 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x1000 build/mcuboot_esp32.bin |
| 174 | + ``` |
| 175 | + |
| 176 | + > **Note:** You may adjust the USB port (`-p /dev/ttyUSB0`) and baud rate (`-b 921600`) according to your board connection. |
| 177 | + |
| 178 | +5. Check the serial monitor on the UART port (the same port used to flash) and reset your **ESP32** board. This guide uses `picocom` tool, but any serial monitor tool can be used: |
| 179 | + |
| 180 | + ```bash |
| 181 | + picocom -b 115200 /dev/ttyUSB0 |
| 182 | + ``` |
| 183 | + |
| 184 | +Since no image has been flashed yet, you will see **MCUboot** waiting for an application image in the primary slot. |
| 185 | + |
| 186 | +```text |
| 187 | +[esp32] [INF] *** Booting MCUboot build v2.3.0-rc2-3-g234c66e6 *** |
| 188 | +[esp32] [INF] [boot] chip revision: v3.0 |
| 189 | +[esp32] [INF] [boot.esp32] SPI Speed : 40MHz |
| 190 | +[esp32] [INF] [boot.esp32] SPI Mode : DIO |
| 191 | +[esp32] [INF] [boot.esp32] SPI Flash Size : 4MB |
| 192 | +[esp32] [INF] [boot] Enabling RNG early entropy source... |
| 193 | +[esp32] [INF] Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 |
| 194 | +[esp32] [INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 |
| 195 | +[esp32] [INF] Boot source: primary slot |
| 196 | +[esp32] [INF] Image index: 0, Swap type: none |
| 197 | +[esp32] [ERR] Unable to find bootable image |
| 198 | +``` |
| 199 | + |
| 200 | +## Preparing and flashing an application |
| 201 | + |
| 202 | +You can use applications from either **Zephyr RTOS** or **NuttX RTOS**, ensuring **MCUboot** compatibility is enabled in whichever RTOS you use. |
| 203 | + |
| 204 | +This section will quickly mention the required `Kconfigs` for setting a **NuttX RTOS** and a **Zephyr RTOS** application with **MCUboot** compatibility, assuming you are familiar with how to configure and build the chosen RTOS. |
| 205 | + |
| 206 | +### NuttX RTOS |
| 207 | + |
| 208 | +Enable the `CONFIG_ESP32_APP_FORMAT_MCUBOOT` configuration and check if the following config values matches what was set in the `<MCUBOOT_DIR>/boot/espressif/port/esp32/bootloader.conf`. For the example from this guide, `menuconfig` was configured as: |
| 209 | + |
| 210 | +- System Type -> Bootloader and Image Configuration-> |
| 211 | + - Enable MCUboot-bootable format (`CONFIG_ESP32_APP_FORMAT_MCUBOOT`): y |
| 212 | +- System Type -> SPI Flash Configuration -> |
| 213 | + - Application image primary slot offset (`CONFIG_ESPRESSIF_OTA_PRIMARY_SLOT_OFFSET`): 0x20000 |
| 214 | + - Application image secondary slot offset (`CONFIG_ESPRESSIF_OTA_SECONDARY_SLOT_OFFSET`): 0x170000 |
| 215 | + - Application image slot size (in bytes) (`CONFIG_ESPRESSIF_OTA_SLOT_SIZE`): 0x150000 |
| 216 | + - Scratch partition offset (`CONFIG_ESPRESSIF_OTA_SCRATCH_OFFSET`): 0x3E0000 |
| 217 | + - Scratch partition size (`CONFIG_ESPRESSIF_OTA_SCRATCH_SIZE`): 0x1F000 |
| 218 | + |
| 219 | +### Zephyr RTOS |
| 220 | + |
| 221 | +Enable the `CONFIG_BOOTLOADER_MCUBOOT` configuration and check if the flash partitions on the `DTS` from your board matches what was set in the `<MCUBOOT_DIR>/boot/espressif/port/esp32/bootloader.conf`. For this example it is possible to set an overlay file with the following content: |
| 222 | + |
| 223 | +```text |
| 224 | +&flash0 { |
| 225 | + partitions { |
| 226 | + boot_partition: partition@0 { |
| 227 | + label = "mcuboot"; |
| 228 | + reg = <0x0 DT_SIZE_K(64)>; |
| 229 | + }; |
| 230 | +
|
| 231 | + slot0_partition: partition@20000 { |
| 232 | + label = "image-0"; |
| 233 | + reg = <0x20000 DT_SIZE_K(1344)>; |
| 234 | + }; |
| 235 | +
|
| 236 | + slot1_partition: partition@170000 { |
| 237 | + label = "image-1"; |
| 238 | + reg = <0x170000 DT_SIZE_K(1344)>; |
| 239 | + }; |
| 240 | +
|
| 241 | + storage_partition: partition@3b0000 { |
| 242 | + label = "storage"; |
| 243 | + reg = <0x3B0000 DT_SIZE_K(192)>; |
| 244 | + }; |
| 245 | +
|
| 246 | + scratch_partition: partition@3e0000 { |
| 247 | + label = "image-scratch"; |
| 248 | + reg = <0x3E0000 DT_SIZE_K(124)>; |
| 249 | + }; |
| 250 | + }; |
| 251 | +}; |
| 252 | +``` |
| 253 | + |
| 254 | +### Signing and Flashing the Application |
| 255 | + |
| 256 | +Before flashing, sign the application binary using `imgtool`. Replace `<APP_BIN>` with your application binary (e.g., `nuttx.hex` or `zephyr.bin`), and `signed.bin` will be the output signed image: |
| 257 | + |
| 258 | +```bash |
| 259 | +python3 scripts/imgtool.py sign --align 4 -v 0 -H 32 --pad-header -S 0x00150000 <APP_BIN> signed.bin |
| 260 | +``` |
| 261 | + |
| 262 | +Alternatively, if you installed **imgtool** through **pip**: |
| 263 | + |
| 264 | +```bash |
| 265 | +imgtool sign --align 4 -v 0 -H 32 --pad-header -S 0x00150000 <APP_BIN> signed.bin |
| 266 | +``` |
| 267 | + |
| 268 | +> **Note:** a **Zephyr** image with **MCUboot** compatibility doesn't need the `--pad-header` parameter. |
| 269 | +
|
| 270 | +Here is a quick look on what these `imgtool sign` parameters do: |
| 271 | +
|
| 272 | +- `--align 4`: Specify the flash device alignment as 4 bytes (32-bit word). |
| 273 | +- `-v 0`: Specify the image version (in this case, `0`). |
| 274 | +- `-H 32`: Specify the **MCUboot** header size to be added to the image binary. |
| 275 | +- `--pad-header`: Indicates to `imgtool` to add the **MCUboot** header into the beginning of the image binary, instead of overwritting it (the **Zephyr** build for some platforms already pads the binary beginning with 0s and may not need this parameter). |
| 276 | +- `-S 0x00150000`: Indicates the slot size so the tool can add the **MCUboot** trailer properly. |
| 277 | +
|
| 278 | +> **Note:** This step just adds the basic required header, however notice that we didn't add any cryptographic key for security verification yet. It will be covered in the next parts of this **MCUboot** guide series. Refer to the [imgtool documentation](https://docs.mcuboot.com/imgtool.html) for more information. |
| 279 | + |
| 280 | +Flash the signed image to the device at the primary slot address: |
| 281 | + |
| 282 | +```bash |
| 283 | +esptool.py -p /dev/ttyUSB0 -b 921600 --before default_reset --after hard_reset --chip esp32 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x20000 signed.bin |
| 284 | +``` |
| 285 | + |
| 286 | +Checking the serial monitor, **MCUboot** should now successfully load and boot the application from the primary slot. |
| 287 | + |
| 288 | +**NuttX's nsh**: |
| 289 | +
|
| 290 | +```text |
| 291 | +[esp32] [INF] *** Booting MCUboot build v2.3.0-rc2-3-g234c66e6 *** |
| 292 | +[esp32] [INF] [boot] chip revision: v3.0 |
| 293 | +[esp32] [INF] [boot.esp32] SPI Speed : 40MHz |
| 294 | +[esp32] [INF] [boot.esp32] SPI Mode : DIO |
| 295 | +[esp32] [INF] [boot.esp32] SPI Flash Size : 4MB |
| 296 | +[esp32] [INF] [boot] Enabling RNG early entropy source... |
| 297 | +[esp32] [INF] Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 |
| 298 | +[esp32] [INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 |
| 299 | +[esp32] [INF] Boot source: primary slot |
| 300 | +[esp32] [INF] Image index: 0, Swap type: none |
| 301 | +[esp32] [INF] Disabling RNG early entropy source... |
| 302 | +[esp32] [INF] br_image_off = 0x20000 |
| 303 | +[esp32] [INF] ih_hdr_size = 0x20 |
| 304 | +[esp32] [INF] Loading image 0 - slot 0 from flash, area id: 1 |
| 305 | +[esp32] [INF] DRAM segment: start=0x250a4, size=0xce4, vaddr=0x3ffb2010 |
| 306 | +[esp32] [INF] IRAM segment: start=0x20080, size=0x5024, vaddr=0x40080000 |
| 307 | +[esp32] [INF] start=0x40082048 |
| 308 | +IROM segment aligned lma 0x00040000 vma 0x400d0000 len 0x012afc (76540) |
| 309 | +DROM segment aligned lma 0x00030000 vma 0x3f410000 len 0x003060 (12384) |
| 310 | +
|
| 311 | +NuttShell (NSH) NuttX-10.4.0 |
| 312 | +nsh> |
| 313 | +``` |
| 314 | +
|
| 315 | +**Zephyr's hello world**: |
| 316 | + |
| 317 | +```text |
| 318 | +[esp32] [INF] *** Booting MCUboot build v2.3.0-rc2-3-g234c66e6 *** |
| 319 | +[esp32] [INF] [boot] chip revision: v3.0 |
| 320 | +[esp32] [INF] [boot.esp32] SPI Speed : 40MHz |
| 321 | +[esp32] [INF] [boot.esp32] SPI Mode : DIO |
| 322 | +[esp32] [INF] [boot.esp32] SPI Flash Size : 4MB |
| 323 | +[esp32] [INF] [boot] Enabling RNG early entropy source... |
| 324 | +[esp32] [INF] Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 |
| 325 | +[esp32] [INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 |
| 326 | +[esp32] [INF] Boot source: primary slot |
| 327 | +[esp32] [INF] Image index: 0, Swap type: none |
| 328 | +[esp32] [INF] Disabling RNG early entropy source... |
| 329 | +[esp32] [INF] br_image_off = 0x20000 |
| 330 | +[esp32] [INF] ih_hdr_size = 0x20 |
| 331 | +[esp32] [INF] Loading image 0 - slot 0 from flash, area id: 1 |
| 332 | +[esp32] [INF] DRAM segment: start=0x25f10, size=0x1110, vaddr=0x3ffb0000 |
| 333 | +[esp32] [INF] IRAM segment: start=0x20080, size=0x5e90, vaddr=0x40080000 |
| 334 | +[esp32] [INF] start=0x400830e0 |
| 335 | +I (327) boot: IROM : lma=00040000h vma=400d0000h size=036D8h ( 14040) map |
| 336 | +I (327) boot: DROM : lma=00030000h vma=3f400000h size=00E94h ( 3732) map |
| 337 | +I (343) boot: libc heap size 182 kB. |
| 338 | +I (343) spi_flash: detected chip: generic |
| 339 | +I (343) spi_flash: flash io: dio |
| 340 | +*** Booting Zephyr OS build v4.3.0-rc2-65-g03ce83a18fd5 *** |
| 341 | +Hello World! esp32_devkitc/esp32/procpu |
| 342 | +``` |
| 343 | + |
| 344 | +## Flash Organization |
| 345 | + |
| 346 | +**MCUboot** defines a flash organization where a flash area can contain multiple executable images depending on its boot and update configuration. Each image area contains two image slots: a primary and a secondary. By default, the bootloader only runs an image from the primary slot. The secondary slot is where an incoming image is staged prior to being installed; then its content will be either swapped to the primary slot or overwrite it when updating. |
| 347 | + |
| 348 | +Therefore, we can identify four types of flash areas in the layout: |
| 349 | + |
| 350 | +| AREA | ID | DESCRIPTION | |
| 351 | +|------|----|----| |
| 352 | +| Bootloader | 0 | Bootloader region (MCUboot) | |
| 353 | +| Primary Slot | 1 | Main bootable image | |
| 354 | +| Secondary Slot | 2 | Staging area for firmware updates | |
| 355 | +| Scratch | 3 | Temporary area for image swapping | |
| 356 | + |
| 357 | +**MCUboot** also supports multiple images, allowing you to define additional image areas with their own primary and secondary slots. |
| 358 | + |
| 359 | +The layout information is stored in the `bootloader.conf` file from the **Espressif Port**. Addresses and sizes can be modified, but the following rules must be followed: |
| 360 | + |
| 361 | +- Bootloader address must be kept since it's where **ESP32** jumps after reset by default. |
| 362 | +- None of the slots must overlap. |
| 363 | +- Primary and Secondary slots must be the same size. |
| 364 | +- Scratch area must be large enough to store at least the largest flash sector that will be swapped. |
| 365 | +- Both **MCUboot** and the application must be aware of this layout for correct operation. |
| 366 | +
|
| 367 | +{{< alert icon="eye" >}} |
| 368 | +Flash organization is configurable and must match between **MCUboot** and the application being booted to ensure proper operation. |
| 369 | +{{< /alert >}} |
| 370 | +
|
| 371 | +## Conclusion |
| 372 | +
|
| 373 | +**MCUboot** provides a solid structure and defines a standard flow for firmware updates and secure boot. These features are already implemented in the bootloader and can be easily enabled without many modifications when developing firmware. |
| 374 | +
|
| 375 | +Furthermore, as an open source project, **MCUboot** benefits from development by an interested and diverse community, resulting in faster issue resolution and active development. |
| 376 | +
|
| 377 | +In this guide, we covered how to build **MCUboot** bootloader for ESP32, how to sign an image, and how to organize flash properly. For more detailed information, refer to the [official MCUboot documentation](https://docs.mcuboot.com/). |
| 378 | +
|
| 379 | +The next step for this series is to understand how updates work in the **MCUboot** and use this feature appropriately. |
| 380 | +
|
| 381 | +## References |
| 382 | +
|
| 383 | +- https://embarcados.com.br/primeiros-passos-com-esp32-utilizando-mcuboot-como-bootloader/ |
| 384 | +- https://docs.mcuboot.com/design.html |
| 385 | +- https://docs.mcuboot.com/readme-espressif.html |
| 386 | +- https://interrupt.memfault.com/blog/mcuboot-overview |
0 commit comments