From c15c0d1a782f26575c67b27814575a402d1742e7 Mon Sep 17 00:00:00 2001 From: Eren Terzioglu Date: Fri, 28 Jun 2024 14:43:59 +0200 Subject: [PATCH] esp32[h2]: Add MCUBoot support --- .../esp32h2/boards/esp32h2-devkit/index.rst | 7 ++ .../platforms/risc-v/esp32h2/index.rst | 18 +++++ arch/risc-v/src/common/espressif/Kconfig | 1 - arch/risc-v/src/common/espressif/esp_start.c | 3 + .../common/scripts/esp32h2_flat_memory.ld | 59 ++++++++++++-- ...e_boot_sections.ld => esp32h2_sections.ld} | 76 ++++++++++++++++++- .../configs/mcuboot_nsh/defconfig | 48 ++++++++++++ .../esp32h2/esp32h2-devkit/scripts/Make.defs | 6 +- 8 files changed, 205 insertions(+), 13 deletions(-) rename boards/risc-v/esp32h2/common/scripts/{esp32h2_simple_boot_sections.ld => esp32h2_sections.ld} (86%) create mode 100644 boards/risc-v/esp32h2/esp32h2-devkit/configs/mcuboot_nsh/defconfig diff --git a/Documentation/platforms/risc-v/esp32h2/boards/esp32h2-devkit/index.rst b/Documentation/platforms/risc-v/esp32h2/boards/esp32h2-devkit/index.rst index d7c031cac4..9eb1998524 100644 --- a/Documentation/platforms/risc-v/esp32h2/boards/esp32h2-devkit/index.rst +++ b/Documentation/platforms/risc-v/esp32h2/boards/esp32h2-devkit/index.rst @@ -137,6 +137,13 @@ You can scan for all I2C devices using the following command:: nsh> i2c dev 0x00 0x7f +mcuboot_nsh +-------------------- + +This configuration is the same as the ``nsh`` configuration, but it generates the application +image in a format that can be used by MCUboot. It also makes the ``make bootloader`` command to +build the MCUboot bootloader image using the Espressif HAL. + nsh --- diff --git a/Documentation/platforms/risc-v/esp32h2/index.rst b/Documentation/platforms/risc-v/esp32h2/index.rst index 9531499985..a06b036bbb 100644 --- a/Documentation/platforms/risc-v/esp32h2/index.rst +++ b/Documentation/platforms/risc-v/esp32h2/index.rst @@ -82,6 +82,24 @@ require any specific configuration (it is selectable by default if no other of 2nd stage bootloaders, the commands ``make bootloader`` and the ``ESPTOOL_BINDIR`` option (for the ``make flash``) are kept (and ignored if Simple Boot is used). +If other features are required, an externally-built 2nd stage bootloader is needed. +The bootloader is built using the ``make bootloader`` command. This command generates +the firmware in the ``nuttx`` folder. The ``ESPTOOL_BINDIR`` is used in the +``make flash`` command to specify the path to the bootloader. For compatibility +among other SoCs and future options of 2nd stage bootloaders, the commands +``make bootloader`` and the ``ESPTOOL_BINDIR`` option (for the ``make flash``) +can be used even if no externally-built 2nd stage bootloader +is being built (they will be ignored if Simple Boot is used, for instance):: + + $ make bootloader + +.. note:: It is recommended that if this is the first time you are using the board with NuttX to + perform a complete SPI FLASH erase. + + .. code-block:: console + + $ esptool.py erase_flash + Building and flashing --------------------- diff --git a/arch/risc-v/src/common/espressif/Kconfig b/arch/risc-v/src/common/espressif/Kconfig index 355766e36c..8ec86d07c9 100644 --- a/arch/risc-v/src/common/espressif/Kconfig +++ b/arch/risc-v/src/common/espressif/Kconfig @@ -164,7 +164,6 @@ config ESPRESSIF_SIMPLE_BOOT config ESPRESSIF_BOOTLOADER_MCUBOOT bool "Enable MCUboot-bootable format" select ESPRESSIF_HAVE_OTA_PARTITION - depends on !ESPRESSIF_ESP32H2 ---help--- Enables the Espressif port of MCUboot to be used as 2nd stage bootloader. diff --git a/arch/risc-v/src/common/espressif/esp_start.c b/arch/risc-v/src/common/espressif/esp_start.c index 25685998bf..421eb7749d 100644 --- a/arch/risc-v/src/common/espressif/esp_start.c +++ b/arch/risc-v/src/common/espressif/esp_start.c @@ -492,6 +492,9 @@ void __esp_start(void) wdt_hal_context_t rwdt_ctx = RWDT_HAL_CONTEXT_DEFAULT(); wdt_hal_write_protect_disable(&rwdt_ctx); +#if defined(CONFIG_ESPRESSIF_BOOTLOADER_MCUBOOT) && defined(CONFIG_ESPRESSIF_ESP32H2) + wdt_hal_set_flashboot_en(&rwdt_ctx, false); +#endif wdt_hal_disable(&rwdt_ctx); wdt_hal_write_protect_enable(&rwdt_ctx); diff --git a/boards/risc-v/esp32h2/common/scripts/esp32h2_flat_memory.ld b/boards/risc-v/esp32h2/common/scripts/esp32h2_flat_memory.ld index 809704f5d3..f30676a269 100644 --- a/boards/risc-v/esp32h2/common/scripts/esp32h2_flat_memory.ld +++ b/boards/risc-v/esp32h2/common/scripts/esp32h2_flat_memory.ld @@ -50,9 +50,32 @@ #define DRAM0_0_SEG_LEN I_D_SRAM_SIZE +#ifdef CONFIG_ESPRESSIF_FLASH_2M +# define FLASH_SIZE 0x200000 +#elif defined (CONFIG_ESPRESSIF_FLASH_4M) +# define FLASH_SIZE 0x400000 +#elif defined (CONFIG_ESPRESSIF_FLASH_8M) +# define FLASH_SIZE 0x800000 +#elif defined (CONFIG_ESPRESSIF_FLASH_16M) +# define FLASH_SIZE 0x1000000 +#endif + MEMORY { -#ifdef CONFIG_ESPRESSIF_SIMPLE_BOOT +#ifdef CONFIG_ESPRESSIF_BOOTLOADER_MCUBOOT + /* The origin values for "metadata" and "ROM" memory regions are the actual + * load addresses. + * + * NOTE: The memory region starting from 0x0 with length represented by + * CONFIG_ESPRESSIF_APP_MCUBOOT_HEADER_SIZE is reserved for the MCUboot header, + * which will be prepended to the binary file by the "imgtool" during the + * signing of firmware image. + */ + + metadata (RX) : org = CONFIG_ESPRESSIF_APP_MCUBOOT_HEADER_SIZE, len = 0x20 + ROM (RX) : org = ORIGIN(metadata) + LENGTH(metadata), + len = FLASH_SIZE - ORIGIN(ROM) +#elif defined (CONFIG_ESPRESSIF_SIMPLE_BOOT) ROM (R) : org = ORIGIN(ROM), len = IDRAM0_2_SEG_SIZE #endif @@ -65,9 +88,12 @@ MEMORY iram0_0_seg (RX) : org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE - /* Flash mapped instruction data. - * - * The 0x20 offset is a convenience for the app binary image generation. + /* Flash mapped instruction data. */ + +#ifdef CONFIG_ESPRESSIF_BOOTLOADER_MCUBOOT + irom_seg (RX) : org = 0x42000000, len = FLASH_SIZE +#else + /* The 0x20 offset is a convenience for the app binary image generation. * Flash cache has 64KB pages. The .bin file which is flashed to the chip * has a 0x18 byte file header, and each segment has a 0x08 byte segment * header. Setting this offset makes it simple to meet the flash cache MMU's @@ -75,6 +101,7 @@ MEMORY */ irom_seg (RX) : org = 0x42000000, len = IDRAM0_2_SEG_SIZE +#endif /* Shared data RAM, excluding memory reserved for ROM bss/data/stack. * Enabling Bluetooth & Trace Memory features in menuconfig will decrease @@ -83,9 +110,26 @@ MEMORY dram0_0_seg (RW) : org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN - /* Flash mapped constant data. - * - * The 0x20 offset is a convenience for the app binary image generation. + /* Flash mapped constant data. */ + +#ifdef CONFIG_ESPRESSIF_BOOTLOADER_MCUBOOT + /* The DROM segment origin is offset by 0x40 for mirroring the actual ROM + * image layout: + * 0x0 - 0x1F : MCUboot header + * 0x20 - 0x3F : Application image metadata section + * 0x40 onwards: ROM code and data + * This is required to meet the following constraint from the external + * flash MMU: + * VMA % 64KB == LMA % 64KB + * i.e. the lower 16 bits of both the virtual address (address seen by the + * CPU) and the load address (physical address of the external flash) must + * be equal. + */ + + drom_seg (R) : org = 0x42000000 + ORIGIN(ROM), + len = FLASH_SIZE - ORIGIN(ROM) +#else + /* The 0x20 offset is a convenience for the app binary image generation. * Flash cache has 64KB pages. The .bin file which is flashed to the chip * has a 0x18 byte file header, and each segment has a 0x08 byte segment * header. Setting this offset makes it simple to meet the flash cache MMU's @@ -93,6 +137,7 @@ MEMORY */ drom_seg (R) : org = 0x42000000, len = IDRAM0_2_SEG_SIZE +#endif /* RTC fast memory (executable). Persists over deep sleep. */ diff --git a/boards/risc-v/esp32h2/common/scripts/esp32h2_simple_boot_sections.ld b/boards/risc-v/esp32h2/common/scripts/esp32h2_sections.ld similarity index 86% rename from boards/risc-v/esp32h2/common/scripts/esp32h2_simple_boot_sections.ld rename to boards/risc-v/esp32h2/common/scripts/esp32h2_sections.ld index 51a41b2073..c3a77bc2d2 100644 --- a/boards/risc-v/esp32h2/common/scripts/esp32h2_simple_boot_sections.ld +++ b/boards/risc-v/esp32h2/common/scripts/esp32h2_sections.ld @@ -1,5 +1,5 @@ /**************************************************************************** - * boards/risc-v/esp32h2/common/scripts/esp32h2_simple_boot_sections.ld + * boards/risc-v/esp32h2/common/scripts/esp32h2_sections.ld * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -18,12 +18,47 @@ * ****************************************************************************/ +#include "common.ld" + /* Default entry point: */ ENTRY(__start); SECTIONS { +#ifdef CONFIG_ESPRESSIF_BOOTLOADER_MCUBOOT + .metadata : + { + /* Magic for load header */ + + LONG(0xace637d3) + + /* Application entry point address */ + + KEEP(*(.entry_addr)) + + /* IRAM metadata: + * - Destination address (VMA) for IRAM region + * - Flash offset (LMA) for start of IRAM region + * - Size of IRAM region + */ + + LONG(ADDR(.iram0.text)) + LONG(LOADADDR(.iram0.text)) + LONG(SIZEOF(.iram0.text)) + + /* DRAM metadata: + * - Destination address (VMA) for DRAM region + * - Flash offset (LMA) for start of DRAM region + * - Size of DRAM region + */ + + LONG(ADDR(.dram0.data)) + LONG(LOADADDR(.dram0.data)) + LONG(SIZEOF(.dram0.data)) + } >metadata +#endif + .iram0.text : { _iram_start = ABSOLUTE(.); @@ -35,6 +70,7 @@ SECTIONS *(.iram1) *(.iram1.*) +#ifdef CONFIG_ESPRESSIF_SIMPLE_BOOT *libsched.a:irq_dispatch.*(.text .text.* .literal .literal.*) *libarch.a:*brownout.*(.text .text.* .literal .literal.*) @@ -98,6 +134,12 @@ SECTIONS *libarch.a:*log.*(.text .text.* .literal .literal.*) *libarch.a:*log_noos.*(.text .text.* .literal .literal.*) *libarch.a:esp_spiflash.*(.literal .text .literal.* .text.*) +#else + *libarch.a:*cache_hal.*(.text .text.* .literal .literal.*) + *libarch.a:*mpu_hal.*(.text .text.* .literal .literal.*) + *libarch.a:*mmu_hal.*(.text .text.* .literal .literal.*) + *libarch.a:esp_spiflash.*(.literal .text .literal.* .text.*) +#endif esp_head.*(.literal .text .literal.* .text.*) esp_start.*(.literal .text .literal.* .text.*) @@ -166,6 +208,7 @@ SECTIONS *(.jcr) *(.dram1) *(.dram1.*) +#ifdef CONFIG_ESPRESSIF_SIMPLE_BOOT *libsched.a:irq_dispatch.*(.rodata .rodata.*) *libarch.a:*brownout.*(.rodata .rodata.*) @@ -229,6 +272,12 @@ SECTIONS *libarch.a:*log.*(.rodata .rodata.*) *libarch.a:*log_noos.*(.rodata .rodata.*) *libarch.a:esp_spiflash.*(.rodata .rodata.*) +#else + *libarch.a:*cache_hal.*(.rodata .rodata.*) + *libarch.a:*mpu_hal.*(.rodata .rodata.*) + *libarch.a:*mmu_hal.*(.rodata .rodata.*) + *libarch.a:esp_spiflash.*(.rodata .rodata.*) +#endif esp_head.*(.rodata .rodata.*) esp_start.*(.rodata .rodata.*) @@ -274,7 +323,7 @@ SECTIONS . = ALIGN(0x10000); } > ROM - .flash.text : + .flash.text : ALIGN(0xFFFF) { _stext = .; @@ -303,7 +352,18 @@ SECTIONS _image_drom_lma = LOADADDR(.flash.rodata); _image_drom_size = SIZEOF(.flash.rodata); - .flash.rodata : + .flash.appdesc : ALIGN(0x10) + { + _rodata_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */ + _rodata_start = ABSOLUTE(.); + + /* Create an empty gap within this section. Thanks to this, the end of this + * section will match .flash.rodata's begin address. Thus, both sections + * will be merged when creating the final bin image. */ + . = ALIGN(ALIGNOF(.flash.rodata)); + } >default_rodata_seg + + .flash.rodata : ALIGN(0xFFFF) { _srodata = ABSOLUTE(.); @@ -360,6 +420,16 @@ SECTIONS . = ALIGN(4); } >default_rodata_seg AT > ROM + .flash.rodata_noload (NOLOAD) : + { + /* + This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address + We don't need to include the noload rodata in this section + */ + _rodata_reserved_end = ABSOLUTE(.); + . = ALIGN (4); + } > default_rodata_seg AT > ROM + /* RTC fast memory holds RTC wake stub code !*/ .rtc.text : diff --git a/boards/risc-v/esp32h2/esp32h2-devkit/configs/mcuboot_nsh/defconfig b/boards/risc-v/esp32h2/esp32h2-devkit/configs/mcuboot_nsh/defconfig new file mode 100644 index 0000000000..9f628c198b --- /dev/null +++ b/boards/risc-v/esp32h2/esp32h2-devkit/configs/mcuboot_nsh/defconfig @@ -0,0 +1,48 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32h2-devkit" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32H2_DEVKIT=y +CONFIG_ARCH_CHIP="esp32h2" +CONFIG_ARCH_CHIP_ESP32H2=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILTIN=y +CONFIG_DEV_ZERO=y +CONFIG_ESPRESSIF_BOOTLOADER_MCUBOOT=y +CONFIG_ESPRESSIF_ESP32H2=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=29 +CONFIG_START_MONTH=11 +CONFIG_START_YEAR=2019 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/risc-v/esp32h2/esp32h2-devkit/scripts/Make.defs b/boards/risc-v/esp32h2/esp32h2-devkit/scripts/Make.defs index eb5773bfae..64dc0ed7e0 100644 --- a/boards/risc-v/esp32h2/esp32h2-devkit/scripts/Make.defs +++ b/boards/risc-v/esp32h2/esp32h2-devkit/scripts/Make.defs @@ -34,8 +34,10 @@ ARCHSCRIPT += $(BOARD_COMMON_DIR)/scripts/$(CHIP_SERIES)_aliases.ld ARCHSCRIPT += $(call FINDSCRIPT,$(CHIP_SERIES)_flat_memory.ld) -ifeq ($(CONFIG_ESPRESSIF_SIMPLE_BOOT),y) - ARCHSCRIPT += $(call FINDSCRIPT,$(CHIP_SERIES)_simple_boot_sections.ld) +ifeq ($(CONFIG_ESPRESSIF_BOOTLOADER_MCUBOOT),y) + ARCHSCRIPT += $(call FINDSCRIPT,$(CHIP_SERIES)_sections.ld) +else ifeq ($(CONFIG_ESPRESSIF_SIMPLE_BOOT),y) + ARCHSCRIPT += $(call FINDSCRIPT,$(CHIP_SERIES)_sections.ld) else ARCHSCRIPT += $(call FINDSCRIPT,$(CHIP_SERIES)_legacy_sections.ld) endif