From 874265feea628e33014b0619a82e74b25a61352b Mon Sep 17 00:00:00 2001 From: Almir Okato Date: Tue, 23 Jun 2026 17:53:08 -0300 Subject: [PATCH] espressif: ESP32-H4 initial support Add ESP32-H4 initial support Signed-off-by: Almir Okato --- .github/workflows/espressif.yaml | 2 +- boot/espressif/CMakeLists.txt | 5 + .../ci_configs/esp32h4-secureboot.conf | 11 + .../hal/include/esp32h4/esp32h4.cmake | 47 ++++ .../espressif/hal/include/esp32h4/sdkconfig.h | 40 ++++ .../include/mcuboot_config/mcuboot_logging.h | 2 + boot/espressif/port/esp32h4/bootloader.conf | 99 ++++++++ boot/espressif/port/esp32h4/ld/bootloader.ld | 211 ++++++++++++++++++ boot/espressif/port/esp_loader.c | 2 + boot/espressif/port/include/esp32h4/memory.h | 35 +++ boot/espressif/port/serial_adapter.c | 6 + boot/espressif/tools/toolchain-esp32h4.cmake | 16 ++ docs/readme-espressif.md | 61 ++++- .../espressif-update-idf-hal-v6.md | 1 + 14 files changed, 529 insertions(+), 9 deletions(-) create mode 100644 boot/espressif/ci_configs/esp32h4-secureboot.conf create mode 100644 boot/espressif/hal/include/esp32h4/esp32h4.cmake create mode 100644 boot/espressif/hal/include/esp32h4/sdkconfig.h create mode 100644 boot/espressif/port/esp32h4/bootloader.conf create mode 100644 boot/espressif/port/esp32h4/ld/bootloader.ld create mode 100644 boot/espressif/port/include/esp32h4/memory.h create mode 100644 boot/espressif/tools/toolchain-esp32h4.cmake diff --git a/.github/workflows/espressif.yaml b/.github/workflows/espressif.yaml index 055f473250..deb32a7373 100644 --- a/.github/workflows/espressif.yaml +++ b/.github/workflows/espressif.yaml @@ -18,7 +18,7 @@ jobs: environment: strategy: matrix: - targets: [esp32, esp32s2, esp32s3, esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32p4] + targets: [esp32, esp32s2, esp32s3, esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32h4, esp32p4] features: - "secureboot-sign-rsa2048,secureboot-sign-rsa3072,secureboot-sign-ec256,secureboot-sign-ed25519" - "serialrecovery" diff --git a/boot/espressif/CMakeLists.txt b/boot/espressif/CMakeLists.txt index 31087fbc66..dcb3b3250d 100644 --- a/boot/espressif/CMakeLists.txt +++ b/boot/espressif/CMakeLists.txt @@ -40,6 +40,7 @@ elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c2" OR "${MCUBOOT_TARGET}" STREQUAL "esp32c6" OR "${MCUBOOT_TARGET}" STREQUAL "esp32c61" OR "${MCUBOOT_TARGET}" STREQUAL "esp32p4" OR + "${MCUBOOT_TARGET}" STREQUAL "esp32h4" OR "${MCUBOOT_TARGET}" STREQUAL "esp32h2") set(MCUBOOT_ARCH "riscv") endif() @@ -115,6 +116,8 @@ elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c61") set(ESP_MIN_REVISION 0) elseif("${MCUBOOT_TARGET}" STREQUAL "esp32p4") set(ESP_MIN_REVISION 3) +elseif("${MCUBOOT_TARGET}" STREQUAL "esp32h4") + set(ESP_MIN_REVISION 0) elseif("${MCUBOOT_TARGET}" STREQUAL "esp32h2") set(ESP_MIN_REVISION 0) else() @@ -444,6 +447,8 @@ if(NOT DEFINED ESP_FLASH_FREQ) set(ESP_FLASH_FREQ "40m") elseif("${MCUBOOT_TARGET}" STREQUAL "esp32p4") set(ESP_FLASH_FREQ "80m") + elseif("${MCUBOOT_TARGET}" STREQUAL "esp32h4") + set(ESP_FLASH_FREQ "48m") elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c2") set(ESP_FLASH_FREQ "60m") elseif("${MCUBOOT_TARGET}" STREQUAL "esp32h2") diff --git a/boot/espressif/ci_configs/esp32h4-secureboot.conf b/boot/espressif/ci_configs/esp32h4-secureboot.conf new file mode 100644 index 0000000000..eea088ab40 --- /dev/null +++ b/boot/espressif/ci_configs/esp32h4-secureboot.conf @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: Apache-2.0 + +# ATTENTION: +# This configuration file targets the building for CI environment and contains +# a set of definitions to resemble a bootloader image for RELEASE environment. +# Running the generated firmware image may result in irreversible operations +# to the chip! + +CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME=1 diff --git a/boot/espressif/hal/include/esp32h4/esp32h4.cmake b/boot/espressif/hal/include/esp32h4/esp32h4.cmake new file mode 100644 index 0000000000..3de359bb9f --- /dev/null +++ b/boot/espressif/hal/include/esp32h4/esp32h4.cmake @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: Apache-2.0 + +list(APPEND include_dirs + ${esp_hal_dir}/components/esp_hw_support/port/${MCUBOOT_TARGET}/private_include + ${esp_hal_dir}/components/soc/${MCUBOOT_TARGET}/include/hw_ver_mp + ${esp_hal_dir}/components/soc/${MCUBOOT_TARGET}/register/hw_ver_mp +) + +list(APPEND hal_srcs + ${esp_hal_dir}/components/hal/cache_hal.c + ${esp_hal_dir}/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c + ${esp_hal_dir}/components/esp_rom/patches/esp_rom_regi2c_${MCUBOOT_TARGET}.c + ${esp_hal_dir}/components/esp_hw_support/port/${MCUBOOT_TARGET}/pmu_param.c +) + +# ESP32-H4 uses stub RNG enable/disable in bootloader_random.c (bring-up) +list(REMOVE_ITEM hal_srcs + ${esp_hal_dir}/components/bootloader_support/src/bootloader_random_esp32h4.c) + +if (DEFINED CONFIG_ESP_CONSOLE_UART_CUSTOM) + list(APPEND hal_srcs + ${src_dir}/${MCUBOOT_TARGET}/console_uart_custom.c + ) +endif() + +list(APPEND LINKER_SCRIPTS + -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.ld + -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.libgcc.ld + -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.libc.ld + -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.newlib.ld + -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.version.ld +) + +# ESP32-H4 ROM does not provide the misaligned-mem libc variant +list(REMOVE_ITEM LINKER_SCRIPTS + -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.libc-suboptimal_for_misaligned_mem.ld) + +set_source_files_properties( + ${esp_hal_dir}/components/bootloader_support/src/esp_image_format.c + ${esp_hal_dir}/components/bootloader_support/bootloader_flash/src/bootloader_flash.c + ${esp_hal_dir}/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_${MCUBOOT_TARGET}.c + ${esp_hal_dir}/components/hal/mmu_hal.c + ${esp_hal_dir}/components/hal/cache_hal.c + PROPERTIES COMPILE_FLAGS + "-Wno-logical-op") diff --git a/boot/espressif/hal/include/esp32h4/sdkconfig.h b/boot/espressif/hal/include/esp32h4/sdkconfig.h new file mode 100644 index 0000000000..9a4abffa49 --- /dev/null +++ b/boot/espressif/hal/include/esp32h4/sdkconfig.h @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define BOOTLOADER_BUILD 1 +#define NON_OS_BUILD 1 +#define CONFIG_LIBC_PICOLIBC 1 +#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x001C +#define CONFIG_IDF_TARGET "esp32h4" +#define CONFIG_IDF_TARGET_ESP32H4 1 +#define CONFIG_ESP32H4_SELECTS_REV_MP 1 +#define CONFIG_ESP32H4_REV_MIN_0 1 +#define CONFIG_ESP32H4_REV_MIN_FULL 0 +#define CONFIG_ESP_REV_MIN_FULL CONFIG_ESP32H4_REV_MIN_FULL +#define CONFIG_ESP32H4_REV_MAX_FULL 99 +#define CONFIG_ESP_REV_MAX_FULL CONFIG_ESP32H4_REV_MAX_FULL +#define CONFIG_IDF_TARGET_ARCH_RISCV 1 +#define CONFIG_MMU_PAGE_SIZE 0x10000 +#define SOC_MMU_PAGE_SIZE CONFIG_MMU_PAGE_SIZE /* from soc/CMakeLists */ +#define CONFIG_XTAL_FREQ_32 1 +#define CONFIG_XTAL_FREQ 32 +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_MCUBOOT 1 +#define NDEBUG 1 +#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 +#ifdef CONFIG_ESP_CONSOLE_UART_NUM +#define CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM CONFIG_ESP_CONSOLE_UART_NUM +#endif +#ifdef CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG +#define CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM ESP_ROM_USB_SERIAL_DEVICE_NUM +#endif +#define CONFIG_ESP_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_BOOTLOADER_OFFSET_IN_FLASH 0x2000 +#define CONFIG_PARTITION_TABLE_OFFSET 0x10000 +#define CONFIG_EFUSE_MAX_BLK_LEN 256 +#define CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT 1 +#define CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ 48 +#define CONFIG_ESP_BRINGUP_BYPASS_RANDOM_SETTING 1 diff --git a/boot/espressif/hal/include/mcuboot_config/mcuboot_logging.h b/boot/espressif/hal/include/mcuboot_config/mcuboot_logging.h index e905650539..81e6968e5e 100644 --- a/boot/espressif/hal/include/mcuboot_config/mcuboot_logging.h +++ b/boot/espressif/hal/include/mcuboot_config/mcuboot_logging.h @@ -33,6 +33,8 @@ extern int ets_printf(const char *fmt, ...); #define TARGET "[esp32c5]" #elif CONFIG_IDF_TARGET_ESP32P4 #define TARGET "[esp32p4]" +#elif CONFIG_IDF_TARGET_ESP32H4 +#define TARGET "[esp32h4]" #elif CONFIG_IDF_TARGET_ESP32C2 #define TARGET "[esp32c2]" #elif CONFIG_IDF_TARGET_ESP32H2 diff --git a/boot/espressif/port/esp32h4/bootloader.conf b/boot/espressif/port/esp32h4/bootloader.conf new file mode 100644 index 0000000000..6d7d887646 --- /dev/null +++ b/boot/espressif/port/esp32h4/bootloader.conf @@ -0,0 +1,99 @@ +# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: Apache-2.0 + +# Define upgrade mode (default is CONFIG_ESP_BOOT_SWAP_USING_SCRATCH) +# CONFIG_ESP_BOOT_SWAP_USING_MOVE=y +# CONFIG_ESP_BOOT_UPGRADE_ONLY=y + +CONFIG_ESP_FLASH_SIZE=4MB +CONFIG_ESP_BOOTLOADER_SIZE=0xF000 +CONFIG_ESP_BOOTLOADER_OFFSET=0x2000 +CONFIG_ESP_IMAGE0_PRIMARY_START_ADDRESS=0x20000 +CONFIG_ESP_APPLICATION_SIZE=0x1C0000 +CONFIG_ESP_IMAGE0_SECONDARY_START_ADDRESS=0x1E0000 +CONFIG_ESP_MCUBOOT_WDT_ENABLE=y +CONFIG_ESP_SCRATCH_OFFSET=0x3E0000 +CONFIG_ESP_SCRATCH_SIZE=0x1F000 + +CONFIG_BOOTLOADER_PROJECT_VER=0x1 + +# When enabled, prevents updating image to an older version +# CONFIG_ESP_DOWNGRADE_PREVENTION=y +# This option makes downgrade prevention rely also on security +# counter (defined using imgtool) instead of only image version +# CONFIG_ESP_DOWNGRADE_PREVENTION_SECURITY_COUNTER=y + +# Enables the MCUboot Serial Recovery, that allows the use of +# MCUMGR to upload a firmware through the serial port +# CONFIG_ESP_MCUBOOT_SERIAL=y +# Use Serial through USB JTAG Serial port for Serial Recovery +# CONFIG_ESP_MCUBOOT_SERIAL_USB_SERIAL_JTAG=y +# Use sector erasing (recommended) instead of entire image size +# erasing when uploading through Serial Recovery +# CONFIG_ESP_MCUBOOT_ERASE_PROGRESSIVELY=y + +# GPIO used to boot on Serial Recovery +# CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT=3 +# GPIO input type (0 for Pull-down, 1 for Pull-up) +# CONFIG_ESP_SERIAL_BOOT_GPIO_INPUT_TYPE=0 +# GPIO signal value +# CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT_VAL=1 +# Delay time for identify the GPIO signal +# CONFIG_ESP_SERIAL_BOOT_DETECT_DELAY_S=5 +# UART port used for serial communication (not needed when using USB) +# CONFIG_ESP_SERIAL_BOOT_UART_NUM=1 +# GPIO for Serial RX signal +# CONFIG_ESP_SERIAL_BOOT_GPIO_RX=10 +# GPIO for Serial TX signal +# CONFIG_ESP_SERIAL_BOOT_GPIO_TX=11 +# Baudrate for Serial Recovery communication +# CONFIG_ESP_SERIAL_BOOT_BAUDRATE=115200 + +# Use UART0 for console printing (use either UART or USB alone) +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +# Configures alternative UART port for console printing +# (UART_NUM=0 must not be changed) +# CONFIG_ESP_CONSOLE_UART_CUSTOM=y +# CONFIG_ESP_CONSOLE_UART_TX_GPIO=24 +# CONFIG_ESP_CONSOLE_UART_RX_GPIO=23 +# Use USB JTAG Serial for console printing +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y + +# CONFIG_ESP_SIGN_EC256=y +# CONFIG_ESP_SIGN_ED25519=n +# CONFIG_ESP_SIGN_RSA=n +# CONFIG_ESP_SIGN_RSA_LEN=2048 + +# Use Tinycrypt lib for EC256 or ED25519 signing +# CONFIG_ESP_USE_TINYCRYPT=y +# Use Mbed TLS lib for RSA image signing +# CONFIG_ESP_USE_MBEDTLS=n + +# It is strongly recommended to generate a new signing key +# using imgtool instead of use the existent sample +# CONFIG_ESP_SIGN_KEY_FILE=root-ec-p256.pem + +# Hardware Secure Boot related options +# CONFIG_SECURE_SIGNED_ON_BOOT=1 +# CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME=1 +# CONFIG_SECURE_BOOT=1 +# CONFIG_SECURE_BOOT_V2_ENABLED=1 + +# Hardware Flash Encryption related options +# CONFIG_SECURE_FLASH_ENC_ENABLED=1 +# CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC=1 +# CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC=1 +# CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE=1 +# CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT=1 +# CONFIG_SECURE_BOOT_ALLOW_JTAG=1 +# CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC=1 + +# Options for enabling eFuse emulation in Flash (adjust +# CONFIG_EFUSE_VIRTUAL_OFFSET accordingly in order +# to not overlap with other flash regions) +# CONFIG_EFUSE_VIRTUAL=1 +# CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH=1 +# CONFIG_EFUSE_VIRTUAL_OFFSET=0x250000 +# CONFIG_EFUSE_VIRTUAL_SIZE=0x2000 diff --git a/boot/espressif/port/esp32h4/ld/bootloader.ld b/boot/espressif/port/esp32h4/ld/bootloader.ld new file mode 100644 index 0000000000..c50b2a25ff --- /dev/null +++ b/boot/espressif/port/esp32h4/ld/bootloader.ld @@ -0,0 +1,211 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Simplified memory map for the ESP32-H4 bootloader (MP revision). + * + * The main purpose is to make sure the bootloader can load into main memory + * without overwriting itself. + */ + +#include "memory.h" + +_bootloader_iram_loader_seg_start = BOOTLOADER_IRAM_LOADER_SEG_START; +_bootloader_dram_loader_seg_start = BOOTLOADER_DRAM_LOADER_SEG_START; + +MEMORY +{ + iram_loader_seg (RWX) : org = BOOTLOADER_IRAM_LOADER_SEG_START, len = BOOTLOADER_IRAM_LOADER_SEG_LEN + dram_loader_seg (RW) : org = BOOTLOADER_DRAM_LOADER_SEG_START, len = BOOTLOADER_DRAM_LOADER_SEG_LEN + iram_seg (RWX) : org = BOOTLOADER_IRAM_SEG_START, len = BOOTLOADER_IRAM_SEG_LEN + dram_seg (RW) : org = BOOTLOADER_DRAM_SEG_START, len = BOOTLOADER_DRAM_SEG_LEN +} + +/* Default entry point: */ +ENTRY(main); + +SECTIONS +{ + .iram_loader.text : + { + . = ALIGN (16); + _loader_text_start = ABSOLUTE(.); + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *esp_mcuboot.*(.literal .text .literal.* .text.*) + *esp_loader.*(.literal .text .literal.* .text.*) + *main.*(.literal .text .literal.* .text.*) + + /* iram_loader section must not be overlapped by application IRAM/DRAM + * mapping, therefore the following were added based on the dependencies + * from esp_loader as its from where the application RAM parts will be + * loaded into memory and ultimately boot. The cross reference table + * were used to map the reachable dependencies */ + *libhal.a:bootloader_flash.*(.literal .text .literal.* .text.* .iram0 .iram0.* .iram1 .iram1.*) + *libhal.a:bootloader_sha.*(.literal .text .literal.* .text.* .iram0 .iram0.* .iram1 .iram1.*) + *libhal.a:bootloader_wdt.*(.literal .text .literal.* .text.* .iram0 .iram0.* .iram1 .iram1.*) + *libhal.a:bootloader_panic.*(.literal .text .literal.* .text.* .iram0 .iram0.* .iram1 .iram1.*) + *libhal.a:cache_hal.*(.literal .text .literal.* .text.* .iram0 .iram0.* .iram1 .iram1.*) + *libhal.a:efuse_hal.*(.literal .text .literal.* .text.* .iram0 .iram0.* .iram1 .iram1.*) + *libhal.a:mmu_hal.*(.literal .text .literal.* .text.* .iram0 .iram0.* .iram1 .iram1.*) + *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.* .iram0 .iram0.* .iram1 .iram1.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _loader_text_end = ABSOLUTE(.); + } > iram_loader_seg + + ASSERT((_loader_text_end - ORIGIN(iram_loader_seg)) <= BOOTLOADER_IRAM_LOADER_SEG_LEN, + "iram_loader_seg overflow: increase BOOTLOADER_IRAM_LOADER_SEG_LEN") + + .dram_loader.bss (NOLOAD) : + { + . = ALIGN (8); + _dram_loader_start = ABSOLUTE(.); + _loader_bss_start = ABSOLUTE(.); + *esp_loader.*(.sbss .sbss.* .sbss2 .sbss2.* .bss .bss.*) + *esp_mcuboot.*(.sbss .sbss.* .sbss2 .sbss2.* .bss .bss.*) + *main.*(.sbss .sbss.* .sbss2 .sbss2.* .bss .bss.*) + *libhal.a:bootloader_flash.*(.sbss .sbss.* .sbss2 .sbss2.* .bss .bss.*) + *libhal.a:bootloader_sha.*(.sbss .sbss.* .sbss2 .sbss2.* .bss .bss.*) + *libhal.a:bootloader_wdt.*(.sbss .sbss.* .sbss2 .sbss2.* .bss .bss.*) + *libhal.a:bootloader_panic.*(.sbss .sbss.* .sbss2 .sbss2.* .bss .bss.*) + *libhal.a:cache_hal.*(.sbss .sbss.* .sbss2 .sbss2.* .bss .bss.*) + *libhal.a:efuse_hal.*(.sbss .sbss.* .sbss2 .sbss2.* .bss .bss.*) + *libhal.a:mmu_hal.*(.sbss .sbss.* .sbss2 .sbss2.* .bss .bss.*) + *libhal.a:wdt_hal_iram.*(.sbss .sbss.* .sbss2 .sbss2.* .bss .bss.*) + . = ALIGN (8); + _loader_bss_end = ABSOLUTE(.); + } > dram_loader_seg + + .dram_loader.data : + { + . = ALIGN(16); + *esp_loader.*(.data .data.* .rodata .rodata.* .sdata .sdata.* .sdata2 .sdata2.* .srodata .srodata.*) + *esp_mcuboot.*(.data .data.* .rodata .rodata.* .sdata .sdata.* .sdata2 .sdata2.* .srodata .srodata.*) + *main.*(.data .data.* .rodata .rodata.* .sdata .sdata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libhal.a:bootloader_flash.*(.data .data.* .rodata .rodata.* .sdata .sdata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libhal.a:bootloader_sha.*(.data .data.* .rodata .rodata.* .sdata .sdata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libhal.a:bootloader_wdt.*(.data .data.* .rodata .rodata.* .sdata .sdata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libhal.a:bootloader_panic.*(.data .data.* .rodata .rodata.* .sdata .sdata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libhal.a:cache_hal.*(.data .data.* .rodata .rodata.* .sdata .sdata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libhal.a:efuse_hal.*(.data .data.* .rodata .rodata.* .sdata .sdata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libhal.a:mmu_hal.*(.data .data.* .rodata .rodata.* .sdata .sdata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libhal.a:wdt_hal_iram.*(.data .data.* .rodata .rodata.* .sdata .sdata.* .sdata2 .sdata2.* .srodata .srodata.*) + . = ALIGN(16); + _dram_loader_end = ABSOLUTE(.); + } > dram_loader_seg + + ASSERT((_dram_loader_end - ORIGIN(dram_loader_seg)) <= BOOTLOADER_DRAM_LOADER_SEG_LEN, + "dram_loader_seg overflow: increase BOOTLOADER_DRAM_LOADER_SEG_LEN") + + .iram.text : + { + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + } > iram_seg + + /* Shared RAM */ + .dram0.bss (NOLOAD) : + { + . = ALIGN (8); + _dram_start = ABSOLUTE(.); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } > dram_seg + + .dram0.data : + { + _data_start = ABSOLUTE(.); + *(.dram1 .dram1.*) + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + _data_end = ABSOLUTE(.); + } > dram_seg + + .dram0.rodata : + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + *(.sdata2 .sdata2.* .srodata .srodata.*) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + *(.eh_frame_hdr) + *(.eh_frame) + . = (. + 3) & ~ 3; + __init_array_start = ABSOLUTE(.); + KEEP (*crtbegin.*(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __init_array_end = ABSOLUTE(.); + KEEP (*crtbegin.*(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + _rodata_end = ABSOLUTE(.); + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _dram_end = ABSOLUTE(.); + } > dram_seg + + .iram.text : + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.iram .iram.*) + *(.iram1 .iram1.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + . += 16; + _text_end = ABSOLUTE(.); + _etext = .; + } > iram_seg + + .riscv.attributes 0: { *(.riscv.attributes) } +} diff --git a/boot/espressif/port/esp_loader.c b/boot/espressif/port/esp_loader.c index a6d101edae..87fb3045e5 100644 --- a/boot/espressif/port/esp_loader.c +++ b/boot/espressif/port/esp_loader.c @@ -45,6 +45,8 @@ #define LP_RTC_PREFIX "LP" #elif CONFIG_IDF_TARGET_ESP32P4 #define LP_RTC_PREFIX "LP" +#elif CONFIG_IDF_TARGET_ESP32H4 +#define LP_RTC_PREFIX "LP" #elif CONFIG_IDF_TARGET_ESP32H2 #define LP_RTC_PREFIX "LP" #endif diff --git a/boot/espressif/port/include/esp32h4/memory.h b/boot/espressif/port/include/esp32h4/memory.h new file mode 100644 index 0000000000..fa9bc840b8 --- /dev/null +++ b/boot/espressif/port/include/esp32h4/memory.h @@ -0,0 +1,35 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/* Default memory layout for ESP32-H4 bootloader (MP revision) */ + +/* Note: this and subsequent addresses calculations keep retrocompatibility + * for standalone builds of Espressif Port. + * For builds integrated with the RTOS (e.g. Zephyr), they must provide their + * `memory.h` which must set the proper bootloader and application boundaries. + * + * Derived from IDF bootloader.ld.in: + * bootloader_usable_dram_end = 0x4085d350 - 0x2000 + */ +#define BOOTLOADER_RAM_END 0x4085B350 + +#define BOOTLOADER_IRAM_LOADER_SEG_LEN 0x2400 +#define BOOTLOADER_IRAM_LOADER_SEG_START \ + (BOOTLOADER_RAM_END - BOOTLOADER_IRAM_LOADER_SEG_LEN) + +#define BOOTLOADER_DRAM_LOADER_SEG_LEN 0x1800 +#define BOOTLOADER_DRAM_LOADER_SEG_START \ + (BOOTLOADER_IRAM_LOADER_SEG_START - BOOTLOADER_DRAM_LOADER_SEG_LEN) + +#define BOOTLOADER_IRAM_SEG_LEN 0xF000 +#define BOOTLOADER_IRAM_SEG_START \ + (BOOTLOADER_DRAM_LOADER_SEG_START - BOOTLOADER_IRAM_SEG_LEN) + +#define BOOTLOADER_DRAM_SEG_LEN 0xB000 +#define BOOTLOADER_DRAM_SEG_START \ + (BOOTLOADER_IRAM_SEG_START - BOOTLOADER_DRAM_SEG_LEN) diff --git a/boot/espressif/port/serial_adapter.c b/boot/espressif/port/serial_adapter.c index 999a13d97b..597be4b294 100644 --- a/boot/espressif/port/serial_adapter.c +++ b/boot/espressif/port/serial_adapter.c @@ -53,6 +53,8 @@ #define SERIAL_BOOT_GPIO_DETECT GPIO_NUM_3 #elif CONFIG_IDF_TARGET_ESP32P4 #define SERIAL_BOOT_GPIO_DETECT GPIO_NUM_3 +#elif CONFIG_IDF_TARGET_ESP32H4 +#define SERIAL_BOOT_GPIO_DETECT GPIO_NUM_3 #elif CONFIG_IDF_TARGET_ESP32H2 #define SERIAL_BOOT_GPIO_DETECT GPIO_NUM_12 #endif @@ -107,6 +109,8 @@ #define SERIAL_BOOT_GPIO_RX GPIO_NUM_10 #elif CONFIG_IDF_TARGET_ESP32P4 #define SERIAL_BOOT_GPIO_RX GPIO_NUM_5 +#elif CONFIG_IDF_TARGET_ESP32H4 +#define SERIAL_BOOT_GPIO_RX GPIO_NUM_10 #elif CONFIG_IDF_TARGET_ESP32H2 #define SERIAL_BOOT_GPIO_RX GPIO_NUM_10 #endif @@ -134,6 +138,8 @@ #define SERIAL_BOOT_GPIO_TX GPIO_NUM_11 #elif CONFIG_IDF_TARGET_ESP32P4 #define SERIAL_BOOT_GPIO_TX GPIO_NUM_6 +#elif CONFIG_IDF_TARGET_ESP32H4 +#define SERIAL_BOOT_GPIO_TX GPIO_NUM_11 #elif CONFIG_IDF_TARGET_ESP32H2 #define SERIAL_BOOT_GPIO_TX GPIO_NUM_11 #endif diff --git a/boot/espressif/tools/toolchain-esp32h4.cmake b/boot/espressif/tools/toolchain-esp32h4.cmake new file mode 100644 index 0000000000..8d01c759ac --- /dev/null +++ b/boot/espressif/tools/toolchain-esp32h4.cmake @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: Apache-2.0 + +set(CMAKE_SYSTEM_NAME Generic) + +set(CMAKE_C_COMPILER riscv32-esp-elf-gcc) +set(CMAKE_CXX_COMPILER riscv32-esp-elf-g++) +set(CMAKE_ASM_COMPILER riscv32-esp-elf-gcc) + +set(_march "rv32imafcb_zicsr_zifencei_zaamo_zalrsc_zba_zbb_zbs_xespdsp") +set(_mflags "-march=${_march} -mabi=ilp32f") + +set(CMAKE_C_FLAGS "${_mflags}" CACHE STRING "C Compiler Base Flags") +set(CMAKE_CXX_FLAGS "${_mflags}" CACHE STRING "C++ Compiler Base Flags") +set(CMAKE_EXE_LINKER_FLAGS "-nostartfiles ${_mflags} --specs=nosys.specs" CACHE STRING "Linker Base Flags") diff --git a/docs/readme-espressif.md b/docs/readme-espressif.md index ee5004f125..2bfbf16d73 100644 --- a/docs/readme-espressif.md +++ b/docs/readme-espressif.md @@ -21,10 +21,10 @@ Documentation about the MCUboot bootloader design, operation and features can be The current port is available for use in the following SoCs within the OSes: -| | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | ESP32-C2 | ESP32-C6 | ESP32-H2 | ESP32-C5 | ESP32-C61 | ESP32-P4 | -| :----: | :-------: | :-------: | :-------: | :-------: | :---------: | :-------: | :-------: | :---------: | :---------: | :---------: | -| Zephyr | Supported | Supported | Supported | Supported | Supported | Supported | Supported | Supported | In progress | In progress | -| NuttX | Supported | Supported | Supported | Supported | In progress | Supported | Supported | ----------- | ----------- | ----------- | +| | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | ESP32-C2 | ESP32-C6 | ESP32-H2 | ESP32-H4 | ESP32-C5 | ESP32-C61 | ESP32-P4 | +| :----: | :-------: | :-------: | :-------: | :-------: | :---------: | :-------: | :-------: | :---------: | :---------: | :---------: | :---------: | +| Zephyr | Supported | Supported | Supported | Supported | Supported | Supported | Supported | In progress | Supported | In progress | In progress | +| NuttX | Supported | Supported | Supported | Supported | In progress | Supported | Supported | ----------- | ----------- | ----------- | ----------- | Notice that any customization in the memory layout from the OS application must be done aware of the bootloader own memory layout to avoid overlapping. More information on the section @@ -160,6 +160,7 @@ Additional configuration related to MCUboot features and slot partitioning may b - `ESP_FLASH_MODE`: "dio" - `ESP_FLASH_FREQ`: "40m" for ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6, ESP32-C5, ESP32-C61; "80m" for ESP32-P4; + "48m" for ESP32-H4; "60m" for ESP32-C2; "24m" for ESP32-H2. @@ -192,9 +193,9 @@ Additional configuration related to MCUboot features and slot partitioning may b *`` value must follow one of the addresses below:* - | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | ESP32-C2 | ESP32-C6 | ESP32-H2 | ESP32-C5 | ESP32-C61 | ESP32-P4 | - | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: | :-------: | :------: | - | 0x1000 | 0x1000 | 0x0000 | 0x0000 | 0x0000 | 0x0000 | 0x0000 | 0x2000 | 0x0000 | 0x2000 | + | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | ESP32-C2 | ESP32-C6 | ESP32-H2 | ESP32-H4 | ESP32-C5 | ESP32-C61 | ESP32-P4 | + | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: | :-------: | :------: | + | 0x1000 | 0x1000 | 0x0000 | 0x0000 | 0x0000 | 0x0000 | 0x0000 | 0x2000 | 0x2000 | 0x0000 | 0x2000 | --- @@ -877,7 +878,7 @@ Serial mode then uses the UART port configured for communication ### [Serial Recovery through USB JTAG Serial port](#serial-recovery-through-usb-jtag-serial-port) -Some chips, like ESP32-C3, ESP32-S3, ESP32-C6, ESP32-C61, and ESP32-P4 have an integrated USB JTAG Serial Controller that +Some chips, like ESP32-C3, ESP32-S3, ESP32-C6, ESP32-C61, ESP32-H4, and ESP32-P4 have an integrated USB JTAG Serial Controller that implements a serial port (CDC) that can also be used for handling MCUboot Serial Recovery. More information about the USB pins and hardware configuration: @@ -887,6 +888,7 @@ More information about the USB pins and hardware configuration: - ESP32-H2: - ESP32-C5: - ESP32-C61: +- ESP32-H4: - ESP32-P4: Configuration example: @@ -1526,6 +1528,7 @@ application. `iram_loader_seg` uses `BOOTLOADER_IRAM_LOADER_SEG_START_MP` (0x400 * +--------+--------------+------+ 0x4FFBCFC0 / 0x4FFBCFC0 - ROM bootloader stack region ``` + ### ESP32-H2 ``` @@ -1575,3 +1578,45 @@ application. `iram_loader_seg` uses `BOOTLOADER_IRAM_LOADER_SEG_START_MP` (0x400 * | v | * +--------+--------------+------+ 0x4084FFFF / 0x4084FFFF - HP SRAM END ``` + +### ESP32-H4 (MP revision) + +``` + IRAM ADDR / DRAM ADDR + * +--------+--------------+------+ 0x40810000 / 0x40810000 - HP SRAM START + * | ^ | + * | | | + * | | FREE | *CLAIMABLE BY OS RAM + * | | | + * | v | + * +--------+--------------+------+ 0x4083D750 / 0x4083D750 + * | ^ | + * | | | + * | | dram_seg | *CLAIMABLE BY OS RAM + * | | | (length 0xB000) + * | v | + * +------------------------------+ 0x40848750 / 0x40848750 + * | ^ | + * | | | + * | | iram_seg | *CLAIMABLE BY OS RAM (length 0xF000) + * | | | + * | v | + * +------------------------------+ 0x40857750 / 0x40857750 + * | ^ | + * | | | *** SHOULD NOT BE OVERLAPPED *** + * | | dram_loader_seg | *** OS CAN RECLAIM IT AFTER BOOT LATER AS HEAP *** + * | | | (length 0x1800) + * | v | + * +------------------------------+ 0x40858F50 / 0x40858F50 + * | ^ | + * | | | *** SHOULD NOT BE OVERLAPPED *** + * | | iram_loader_seg | *** OS CAN RECLAIM IT AFTER BOOT LATER AS HEAP *** + * | | | (length 0x2400) + * | v | + * +--------+--------------+------+ 0x4085B350 / 0x4085B350 - `BOOTLOADER_RAM_END` + * | ^ | + * | | FREE | above `BOOTLOADER_RAM_END` + * | | | *** OS CAN RECLAIM IT AFTER BOOT LATER AS HEAP *** + * | v | + * +--------+--------------+------+ 0x40860000 / 0x40860000 - HP SRAM END +``` diff --git a/docs/release-notes.d/espressif-update-idf-hal-v6.md b/docs/release-notes.d/espressif-update-idf-hal-v6.md index 320217a9a3..4cff4cb8fb 100644 --- a/docs/release-notes.d/espressif-update-idf-hal-v6.md +++ b/docs/release-notes.d/espressif-update-idf-hal-v6.md @@ -2,3 +2,4 @@ - Add ESP32-C5 initial support. - Add ESP32-C61 initial support. - Add ESP32-P4 initial support. +- Add ESP32-H4 initial support.