Skip to content

Commit 6601f2b

Browse files
authored
Fix/update: Blog ESP32 bootstrapping fixes (#356)
Multiple updates and fixes: - Add memory layouts for AMP scenarios - Fix typos and errors in diagrams - Fix typos and errors in text - Remove unused file Signed-off-by: Marek Matej <[email protected]> Co-authored-by: Marek Matej <[email protected]>
1 parent 71c76cd commit 6601f2b

File tree

6 files changed

+175
-22
lines changed

6 files changed

+175
-22
lines changed
56.2 KB
Loading
49.5 KB
Loading
50.7 KB
Loading
44 KB
Loading
Binary file not shown.

content/blog/esp32-bootstrapping/index.md

Lines changed: 175 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ You can refer to the table with list of features and boot scenarios for the Zeph
9797
### Simpleboot
9898

9999
The default build scenario in Zephyr RTOS port of ESP32. The configuration option indicating the use of this build scenario:
100-
- `CONFIG_ESP_SIMPLE_BOOT`
100+
- `CONFIG_ESP_SIMPLE_BOOT=y`
101+
- `CONFIG_BOOTLOADER_MCUBOOT=n`
101102

102103
***NOTE:** Do not confuse Simple Boot with the `CONFIG_DIRECT_BOOT`, which is native to newest RISC-V based SoCs, such as ESP32-C3.*
103104

@@ -154,7 +155,7 @@ Currently there are two ESP32 ports of MCUboot that can be used in Zephyr RTOS.
154155
```mermaid
155156
flowchart TD
156157
ROM .->|load| FP0;
157-
BL2 .->|load/map| FP1;
158+
BL2 .->|load| FP1;
158159
APP .->|load/map| FP1;
159160
ROM ==> BL2;
160161
subgraph RC ["ROM code"];
@@ -174,7 +175,23 @@ flowchart TD
174175
FP1@{ shape: das, label: "**Application partition**</br>*DT_NODE_LABEL(slot0_partition)*</br>*DT_NODE_BY_FIXED_PARTITION_LABEL(image_0)*" };
175176
```
176177

177-
The application image loaded by the MCUboot has additional header with information about the SRAM segments.
178+
The standard MCUboot header is placed at the offset `0x00`. Following structure represent its format:
179+
```cpp
180+
/* MCUboot image header. All fields are in little endian byte order. */
181+
struct image_header {
182+
uint32_t ih_magic; /* 0x96f3b83d OR 0x96f3b83c (V1) */
183+
uint32_t ih_load_addr; /* Subsequent ESP header is used to hold application entry address */
184+
uint16_t ih_hdr_size; /* Size of image header (bytes) */
185+
uint16_t ih_protect_tlv_size; /* Size of protected TLV area (bytes) */
186+
uint32_t ih_img_size; /* Does not include header */
187+
uint32_t ih_flags; /* Image flags */
188+
struct image_version ih_ver; /* Image version */
189+
uint32_t _pad1; /* Padding */
190+
} __packed;
191+
192+
```
193+
194+
The application image loaded by the MCUboot has an additional header with the information about used SRAM segments, which is placed at the offset `0x20`, just after the standard MCUboot header.
178195
179196
```cpp
180197
typedef struct esp_image_load_header {
@@ -191,32 +208,74 @@ typedef struct esp_image_load_header {
191208

192209
Additional information on the flash and/or SPIRAM regions are provided as a linker symbols and are embedded inside the application image.
193210

194-
## Building
195211

196-
Following is the description of some basic build steps so you can create the images and scenarios discussed in this article at home.
212+
## Memory utilization
213+
214+
Before we build some example applications, let’s take a moment to discuss how the linking process utilizes SRAM on the ESP32-S3.
215+
It’s important to note that different Espressif SoCs can have unique memory layouts, which can affect how resources are allocated.
216+
Therefore each SoC is using slightly different linker script.
217+
218+
The images below illustrate the process of application linking, focusing on how the ROM code interacts with SRAM. Key details, such as I-Cache and D-Cache allocations, are highlighted for clarity.
219+
Important linker symbols, crucial to understanding the memory layout, are shown in green bubbles.
220+
221+
- Yellow area is the memory used by the 2nd stage bootloader that can be re-claimed by the application code run-time.
222+
- Orange area is the memory used by the 1st stage bootloader (or ROM-loader), that can be re-claimed after the application loading is done.
223+
- Red area is the memory that is not available for the user and should not be used by the linker to spill the code or data.
197224

198-
But first lets talk briefly about how the link process utilize the SRAM memory on the ESP32-S3. Note, that different Espressif SoCs have different memory layout.
199225

200-
### Memory utilization
226+
### ESP32-S3 use-case
201227

202-
Bellow is the image which illustrates how the application linking is done. Highlighted are details of ROM code usage in SRAM1, and I-Cache, D-Cache placement.
203-
The illustration is covering an single CPU scenario and does not cover the AMP case.
228+
Here we are using the ESP32-S3 to illustrate memory utilization, which is **suitable as a reference for most of the newer SoCs**.
204229

205-
- Yellow hatched area is the memory that can't be rewritten during the 2nd stage loading (it can be re-claimed during the runtime)
206-
- Orange hatched area is the memory that can be re-claimed after the application loading is done.
207-
- Red hatched areas are the memory parts that are not available for the user and should be avoided by the linker.
230+
The following picture illustrates the memory utilization for an single CPU scenario.
208231

209232
{{< figure
210233
default=true
211-
src="img/esp32s3-zephyr-memory-usage.webp"
234+
src="img/esp32s3-zephyr-memory-default.webp"
212235
alt=""
213-
caption="The ESP32-S3 memory utilization."
236+
caption="The ESP32-S3 'default' memory utilization."
214237
>}}
215238

239+
240+
The following picture illustrates memory utilization in a multi-CPU scenario.
241+
242+
{{< figure
243+
default=true
244+
src="img/esp32s3-zephyr-memory-amp.webp"
245+
alt=""
246+
caption="The ESP32-S3 'AMP' memory utilization."
247+
>}}
248+
249+
216250
***NOTE:***
217251
*The I-Cache allocation SRAM blocks (0,1) are set by the **`PMS_INTERNAL_SRAM_ICACHE_USAGE`** bits
218252
and the D-Cache allocation SRAM blocks (9,10) are set by the **`PMS_INTERNAL_SRAM_DCACHE_USAGE`** bits, both in the register `PMC_INTERNAL_SRAM_USAGE_1_REG`*
219253

254+
255+
### ESP32 use-case
256+
257+
Here is the memory utilization for the ESP32 platform as its memory model is significantly different from other Espressif SoCs.
258+
259+
The following picture illustrates memory utilization in a single CPU scenario.
260+
261+
{{< figure
262+
default=true
263+
src="img/esp32-zephyr-memory-default.webp"
264+
alt=""
265+
caption="The ESP32 'default' memory layout."
266+
>}}
267+
268+
269+
Following picture illustrates the memory utilization in the multi CPU scenario.
270+
271+
{{< figure
272+
default=true
273+
src="img/esp32-zephyr-memory-amp.webp"
274+
alt=""
275+
caption="The ESP32-S3 'AMP' memory layout."
276+
>}}
277+
278+
220279
### Tooling - esptool.py
221280

222281
The *esptool.py* is the essential tool used to manipulate the binaries for the ESP32 SoCs. Among the other features our focus is on the `--elf2image` command, which is used to convert the `.elf` images to the loadable `.bin` images. This tool is used to create the images loadable by the ROM loader.
@@ -235,13 +294,30 @@ flowchart LR
235294

236295
Resulting binary can be loaded to any LMA location (in flash). Its segments will be processed at the location and SRAM will be copied to the corresponding SRAM location, and possible FLASH or SPIRAM segments will be mapped to the virtual address space VMA.
237296

297+
298+
## Building
299+
300+
Finally let's build some real life examples that can be flashed into the target board to demonstrate what was discussed in previous chapters.
301+
Before that it is important to note the image formats used with the Zephyr port of the Espressif SoCs.
302+
303+
The table shows the image formats used in various build scenarios:
304+
305+
| Image / core | Image format |
306+
| :---------------------------------------: | :-------------: |
307+
| Application (Simple Boot) /<br>`@PRO_CPU` | *ESP image* |
308+
| MCUboot / `@PRO_CPU` | *ESP image* |
309+
| Application / `@PRO_CPU` | *MCUboot image* |
310+
| Application / `@APP_CPU` | *MCUboot image* |
311+
312+
238313
### Simpleboot
239314

240-
Single image builds are used as a default build option in the Zephyr RTOS and the CI, unless `--sysbuild` is used.
315+
Single image builds are used as a default build option in the Zephyr RTOS and the CI (unless `--sysbuild` is used).
241316

317+
Building and flashing a WiFi sample application using the Simple Boot:
242318
```shell
243319
cd zephyrproject/zephyr
244-
west build -b esp32s3_devkitm/esp32s3/procpu samples/net/wifi -p
320+
west build -b esp32s3_devkitm/esp32s3/procpu samples/net/wifi/shell -p
245321
west flash && west espressif monitor
246322
```
247323

@@ -283,18 +359,18 @@ uart:~$
283359
```
284360

285361

286-
### MCUboot Zephyr RTOS port (ZP)
362+
### MCUboot Zephyr port (ZP)
287363

288364
First lets take a look at how to manually build the MCUboot and the subsequent application. Each `west flash` in the code is using its own flash partition and it is not overwritten by each other.
289365

290-
Building MCUboot separately at its location:
366+
Building and flashing the MCUboot separately at its location:
291367
```shell
292368
cd zephyrproject/bootloader/mcuboot
293369
west build -b esp32s3_devkitm/esp32s3/procpu boot/zephyr -p
294370
west flash && west espressif monitor
295371
```
296372

297-
Building the sample application that is loadable by the MCUboot created in previous step:
373+
Building and flashing the sample application that is loadable by the MCUboot created in previous step:
298374
```shell
299375
cd zephyrproject/zephyr
300376
west build -b esp32s3_devkitm/esp32s3/procpu samples/net/wifi -p -DCONFIG_BOOTLOADER_MCUBOOT=y
@@ -303,14 +379,14 @@ west flash && west espressif monitor
303379

304380
Now, we can rely on the Sysbuild and build all images at once.
305381

306-
Building the application with MCUboot(ZP) using sysbuild:
382+
Building and flashing the application with MCUboot (ZP) using ***sysbuild***:
307383
```shell
308384
cd zephyrproject/zephyr
309385
west build -b esp32s3_devkitm/esp32s3/procpu samples/new/wifi -p --sysbuild
310386
west flash && west espressif monitor
311387
```
312388

313-
In both cases (manual & sysbuild) we should see the following console output after the image boots:
389+
In both cases (manual build & using `--sysbuild` option) we should see the following console output after the image boots:
314390
```
315391
ESP-ROM:esp32s3-20210327
316392
Build:Mar 27 2021
@@ -347,11 +423,88 @@ I (205) heap_runtime: ESP heap runtime init at 0x3fca4f70 size 273 kB.
347423
uart:~$
348424
```
349425

426+
350427
### MCUboot Espressif port (EP)
351428

352429
To learn how to build the MCUboot Espressif Port, check out this [article](https://docs.mcuboot.com/readme-espressif.html)
353430

354-
## Feature table
431+
432+
### AMP enabled sample code
433+
434+
AMP builds require several images to be built and flashed onto a target SoC. Let's use ESP32-S3 as our test platform and demonstrate the sysbuild capabilities on the sample code provided by the Zephyr RTOS sources.
435+
The Zephyr sample code (`samples/drivers/ipm/ipm_esp32`) uses IPM (Inter-Processor Mailbox) to demonstrate a simple two-way communication between the `PRO_CPU` core and `APP_CPU` core. Images for both CPU cores must be loaded using the MCUboot.
436+
Note that there is no support for running AMP if the Simple Boot mechanism is used.
437+
438+
Now we can build and flash a complete set of images running the IPM sample:
439+
```shell
440+
cd zephyrproject/zephyr
441+
west build -b esp32s3_devkitm/esp32s3/procpu samples/drivers/ipm/ipm_esp32/ -p --sysbuild
442+
west flash && west espressif monitor
443+
```
444+
445+
As a result, three images should be created:
446+
447+
- `ipm_esp32` - the image for the `PRO_CPU` core
448+
- `ipm_esp32_remote` - the image for the `APP_CPU` core
449+
- `mcuboot` - the MCUboot image, which is run by `PRO_CPU`
450+
451+
452+
After flashing and connecting to a target using the serial port, we should be able to see the following output in the console:
453+
```
454+
ESP-ROM:esp32s3-20210327
455+
Build:Mar 27 2021
456+
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
457+
SPIWP:0xee
458+
mode:DIO, clock div:2
459+
load:0x3fcb5400,len:0x2bd8
460+
load:0x403ba400,len:0xa1fc
461+
load:0x403c6400,len:0x15c4
462+
entry 0x403bd044
463+
I (61) soc_init: MCUboot 2nd stage bootloader
464+
I (61) soc_init: compile time Dec 12 2024 16:26:23
465+
W (61) soc_init: Unicore bootloader
466+
I (61) spi_flash: detected chip: generic
467+
I (65) spi_flash: flash io: dio
468+
W (68) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
469+
I (80) soc_init: chip revision: v0.1
470+
I (83) flash_init: Boot SPI Speed : 40MHz
471+
I (87) flash_init: SPI Mode : DIO
472+
I (90) flash_init: SPI Flash Size : 8MB
473+
I (94) soc_random: Enabling RNG early entropy source
474+
I (99) soc_random: Disabling RNG early entropy source
475+
I (103) boot: Disabling glitch detection
476+
I (107) boot: Jumping to the main image...
477+
I (145) spi_flash: flash io: dio
478+
[esp32s3] [INF] Image index: 0, Swap type: none
479+
[esp32s3] [INF] Loading image 0 - slot 0 from flash, area id: 1
480+
[esp32s3] [INF] Application start=40378a48h
481+
[esp32s3] [INF] DRAM segment: paddr=00026ee8h, vaddr=3fc8aec8h, size=010e4h ( 4324) load
482+
[esp32s3] [INF] IRAM segment: paddr=00020040h, vaddr=40374000h, size=06ea8h ( 28328) load
483+
I (177) boot: DROM segment: paddr=00040000h, vaddr=3c010000h, size=016A0h ( 5792) map
484+
I (177) boot: IROM segment: paddr=00030000h, vaddr=42000000h, size=042A2h ( 17058) map
485+
I (193) soc_random: Disabling RNG early entropy source
486+
I (193) boot: Disabling glitch detection
487+
I (193) boot: Jumping to the main image...
488+
I (228) heap_runtime: ESP heap runtime init at 0x3fc8f960 size 154 kB.
489+
490+
APPCPU image, area id: 2, offset: 0x170000, hdr.off: 0x20, size: 512 kB
491+
IRAM segment: paddr=00170040h, vaddr=403a6400h, size=0571ch ( 22300) load
492+
DRAM segment: paddr=0017575ch, vaddr=3fcbbb20h, size=00a58h ( 2648) load
493+
Application start=403a6924h
494+
495+
*** Booting Zephyr OS build v4.0.0-1981-g5e6b13a7bbff ***
496+
PRO_CPU is sending a request, waiting remote response...
497+
PRO_CPU received a message from APP_CPU : APP_CPU uptime ticks 501
498+
499+
PRO_CPU is sending a request, waiting remote response...
500+
PRO_CPU received a message from APP_CPU : APP_CPU uptime ticks 10503
501+
502+
PRO_CPU is sending a request, waiting remote response...
503+
PRO_CPU received a message from APP_CPU : APP_CPU uptime ticks 20504
504+
```
505+
506+
507+
## Bootloader Feature table
355508

356509
The ESP32 port in Zephyr RTOS has variety of booting options.
357510

0 commit comments

Comments
 (0)