This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 8f3c425067 xtensa/esp32s3: Enable booting from MCUboot bootloader
8f3c425067 is described below

commit 8f3c425067bcfe12be235916e68afcbd37d06e0b
Author: Almir Okato <almir.ok...@espressif.com>
AuthorDate: Sun Dec 4 22:22:43 2022 -0300

    xtensa/esp32s3: Enable booting from MCUboot bootloader
    
    Add support for booting from MCUboot bootloader on ESP32-S3.
    
    Signed-off-by: Almir Okato <almir.ok...@espressif.com>
---
 .../xtensa/esp32s3/boards/esp32s3-devkit/index.rst |   6 +
 arch/xtensa/src/esp32s3/Bootloader.mk              |  48 +++-
 arch/xtensa/src/esp32s3/Kconfig                    |  84 +++++++
 arch/xtensa/src/esp32s3/esp32s3_start.c            | 141 +++++++++++
 .../xtensa/esp32s3/common/scripts/flat_memory.ld   |  37 +++
 .../{esp32s3_sections.ld => legacy_sections.ld}    |   2 +-
 .../{esp32s3_sections.ld => mcuboot_sections.ld}   | 272 +++++++++++++--------
 boards/xtensa/esp32s3/esp32s3-devkit/Kconfig       |   3 +-
 .../esp32s3-devkit/configs/mcuboot_nsh/defconfig   |  48 ++++
 .../esp32s3/esp32s3-devkit/scripts/Make.defs       |   6 +-
 .../xtensa/esp32s3/esp32s3-eye/scripts/Make.defs   |   2 +-
 tools/esp32s3/Config.mk                            |  36 +++
 12 files changed, 577 insertions(+), 108 deletions(-)

diff --git 
a/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst 
b/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst
index a5e69ec6e4..12ec1e8fe1 100644
--- a/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst
+++ b/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst
@@ -55,3 +55,9 @@ nsh
 
 Basic NuttShell configuration (console enabled in UART0, exposed via
 USB connection by means of CP2102 converter, at 115200 bps).
+
+mcuboot_nsh
+---
+
+Similar configuration as nsh, except that it enables booting from
+MCUboot and the experimental features configuration.
diff --git a/arch/xtensa/src/esp32s3/Bootloader.mk 
b/arch/xtensa/src/esp32s3/Bootloader.mk
index 7de5162218..6d6455e52a 100644
--- a/arch/xtensa/src/esp32s3/Bootloader.mk
+++ b/arch/xtensa/src/esp32s3/Bootloader.mk
@@ -33,7 +33,7 @@ $(BOOTLOADER_SRCDIR):
 
 # Helpers for creating the configuration file
 
-cfg_en  = echo "$(1)=y";
+cfg_en  = echo "$(1)=$(if $(CONFIG_ESP32S3_APP_FORMAT_MCUBOOT),1,y)";
 cfg_val = echo "$(1)=$(2)";
 
 $(BOOTLOADER_CONFIG): $(TOPDIR)/.config
@@ -51,7 +51,18 @@ $(BOOTLOADER_CONFIG): $(TOPDIR)/.config
                $(if $(CONFIG_ESP32S3_FLASH_FREQ_40M),$(call 
cfg_en,CONFIG_ESPTOOLPY_FLASHFREQ_40M)) \
                $(if $(CONFIG_ESP32S3_FLASH_FREQ_20M),$(call 
cfg_en,CONFIG_ESPTOOLPY_FLASHFREQ_20M)) \
        } > $(BOOTLOADER_CONFIG)
-ifeq ($(CONFIG_ESP32S3_APP_FORMAT_LEGACY),y)
+ifeq ($(CONFIG_ESP32S3_APP_FORMAT_MCUBOOT),y)
+       $(Q) { \
+               $(call cfg_val,CONFIG_ESP_BOOTLOADER_OFFSET,0x0000) \
+               $(call cfg_val,CONFIG_ESP_BOOTLOADER_SIZE,0xF000) \
+               $(call 
cfg_val,CONFIG_ESP_APPLICATION_PRIMARY_START_ADDRESS,$(CONFIG_ESP32S3_OTA_PRIMARY_SLOT_OFFSET))
 \
+               $(call 
cfg_val,CONFIG_ESP_APPLICATION_SIZE,$(CONFIG_ESP32S3_OTA_SLOT_SIZE)) \
+               $(call 
cfg_val,CONFIG_ESP_APPLICATION_SECONDARY_START_ADDRESS,$(CONFIG_ESP32S3_OTA_SECONDARY_SLOT_OFFSET))
 \
+               $(call cfg_en,CONFIG_ESP_MCUBOOT_WDT_ENABLE) \
+               $(call 
cfg_val,CONFIG_ESP_SCRATCH_OFFSET,$(CONFIG_ESP32S3_OTA_SCRATCH_OFFSET)) \
+               $(call 
cfg_val,CONFIG_ESP_SCRATCH_SIZE,$(CONFIG_ESP32S3_OTA_SCRATCH_SIZE)) \
+       } >> $(BOOTLOADER_CONFIG)
+else ifeq ($(CONFIG_ESP32S3_APP_FORMAT_LEGACY),y)
        $(Q) { \
                $(call cfg_en,CONFIG_PARTITION_TABLE_CUSTOM) \
                $(call 
cfg_val,CONFIG_PARTITION_TABLE_CUSTOM_FILENAME,\"partitions.csv\") \
@@ -59,6 +70,24 @@ ifeq ($(CONFIG_ESP32S3_APP_FORMAT_LEGACY),y)
        } >> $(BOOTLOADER_CONFIG)
 endif
 
+ifeq ($(CONFIG_ESP32S3_APP_FORMAT_MCUBOOT),y)
+
+BOOTLOADER_BIN        = $(TOPDIR)/mcuboot-esp32s3.bin
+
+$(BOOTLOADER_BIN): $(BOOTLOADER_CONFIG)
+       $(Q) echo "Building Bootloader"
+       $(Q) $(BOOTLOADER_SRCDIR)/build_mcuboot.sh -c esp32s3 -s -f 
$(BOOTLOADER_CONFIG)
+       $(call COPYFILE, 
$(BOOTLOADER_SRCDIR)/$(BOOTLOADER_OUTDIR)/mcuboot-esp32s3.bin, $(TOPDIR))
+
+bootloader: $(BOOTLOADER_CONFIG) $(BOOTLOADER_SRCDIR) $(BOOTLOADER_BIN)
+
+clean_bootloader:
+       $(call DELDIR,$(BOOTLOADER_SRCDIR))
+       $(call DELFILE,$(BOOTLOADER_CONFIG))
+       $(call DELFILE,$(BOOTLOADER_BIN))
+
+else ifeq ($(CONFIG_ESP32S3_APP_FORMAT_LEGACY),y)
+
 bootloader: $(BOOTLOADER_SRCDIR) $(BOOTLOADER_CONFIG)
        $(Q) echo "Building Bootloader binaries"
        $(Q) $(BOOTLOADER_SRCDIR)/build_idfboot.sh -c esp32s3 -s -f 
$(BOOTLOADER_CONFIG)
@@ -71,11 +100,24 @@ clean_bootloader:
        $(call DELFILE,$(TOPDIR)/bootloader-esp32s3.bin)
        $(call DELFILE,$(TOPDIR)/partition-table-esp32s3.bin)
 
+endif
+
 else ifeq ($(CONFIG_ESP32S3_BOOTLOADER_DOWNLOAD_PREBUILT),y)
 
 BOOTLOADER_VERSION = latest
 BOOTLOADER_URL     = 
https://github.com/espressif/esp-nuttx-bootloader/releases/download/$(BOOTLOADER_VERSION)
 
+ifeq ($(CONFIG_ESP32S3_APP_FORMAT_MCUBOOT),y)
+
+bootloader:
+       $(Q) echo "Downloading Bootloader binaries"
+       $(Q) curl -L $(BOOTLOADER_URL)/mcuboot-esp32s3.bin -o 
$(TOPDIR)/mcuboot-esp32s3.bin
+
+clean_bootloader:
+       $(call DELFILE,$(TOPDIR)/mcuboot-esp32s3.bin)
+
+else ifeq ($(CONFIG_ESP32S3_APP_FORMAT_LEGACY),y)
+
 bootloader:
        $(Q) echo "Downloading Bootloader binaries"
        $(Q) curl -L $(BOOTLOADER_URL)/bootloader-esp32s3.bin -o 
$(TOPDIR)/bootloader-esp32s3.bin
@@ -86,3 +128,5 @@ clean_bootloader:
        $(call DELFILE,$(TOPDIR)/partition-table-esp32s3.bin)
 
 endif
+
+endif
diff --git a/arch/xtensa/src/esp32s3/Kconfig b/arch/xtensa/src/esp32s3/Kconfig
index 99c70d8ce9..9d77896512 100644
--- a/arch/xtensa/src/esp32s3/Kconfig
+++ b/arch/xtensa/src/esp32s3/Kconfig
@@ -833,6 +833,48 @@ choice ESP32S3_FLASH_FREQ
 
 endchoice # ESP32S3_FLASH_FREQ
 
+config ESP32S3_HAVE_OTA_PARTITION
+       bool
+       default n
+
+if ESP32S3_HAVE_OTA_PARTITION
+
+comment "Application Image OTA Update support"
+
+config ESP32S3_OTA_PRIMARY_SLOT_OFFSET
+       hex "Application image primary slot offset"
+       default 0x10000
+
+config ESP32S3_OTA_PRIMARY_SLOT_DEVPATH
+       string "Application image primary slot device path"
+       default "/dev/ota0"
+
+config ESP32S3_OTA_SECONDARY_SLOT_OFFSET
+       hex "Application image secondary slot offset"
+       default 0x110000
+
+config ESP32S3_OTA_SECONDARY_SLOT_DEVPATH
+       string "Application image secondary slot device path"
+       default "/dev/ota1"
+
+config ESP32S3_OTA_SLOT_SIZE
+       hex "Application image slot size (in bytes)"
+       default 0x100000
+
+config ESP32S3_OTA_SCRATCH_OFFSET
+       hex "Scratch partition offset"
+       default 0x210000
+
+config ESP32S3_OTA_SCRATCH_SIZE
+       hex "Scratch partition size"
+       default 0x40000
+
+config ESP32S3_OTA_SCRATCH_DEVPATH
+       string "Scratch partition device path"
+       default "/dev/otascratch"
+
+endif
+
 if ESP32S3_SPIFLASH
 
 comment "General storage MTD configuration"
@@ -881,6 +923,18 @@ config ESP32S3_APP_FORMAT_LEGACY
                This is the legacy application image format, as supported by 
the ESP-IDF
                2nd stage bootloader.
 
+config ESP32S3_APP_FORMAT_MCUBOOT
+       bool "MCUboot-bootable format"
+       select ESP32S3_HAVE_OTA_PARTITION
+       depends on EXPERIMENTAL
+       ---help---
+               The Espressif port of MCUboot supports the loading of 
unsegmented firmware
+               images.
+
+comment "MCUboot support depends on CONFIG_EXPERIMENTAL"
+       depends on !EXPERIMENTAL
+
+
 endchoice # Application Image Format
 
 choice
@@ -907,6 +961,36 @@ config ESP32S3_BOOTLOADER_BUILD_FROM_SOURCE
 
 endchoice
 
+choice
+       prompt "Target slot for image flashing"
+       default ESP32S3_ESPTOOL_TARGET_PRIMARY
+       depends on ESP32S3_HAVE_OTA_PARTITION
+       ---help---
+               Slot to which ESPTOOL will flash the generated binary image.
+
+config ESP32S3_ESPTOOL_TARGET_PRIMARY
+       bool "Application image primary slot"
+       ---help---
+               This assumes that the generated image is already pre-validated.
+               This is the recommended option for the initial stages of the
+               application firmware image development.
+
+config ESP32S3_ESPTOOL_TARGET_SECONDARY
+       bool "Application image secondary slot"
+       ---help---
+               The application needs to confirm the generated image as valid,
+               otherwise the bootloader may consider it invalid and perform the
+               rollback of the update after a reset.
+               This is the choice most suitable for the development and 
verification
+               of a secure firmware update workflow.
+
+endchoice
+
+config ESP32S3_APP_MCUBOOT_HEADER_SIZE
+       int "Application image header size (in bytes)"
+       default 32
+       depends on ESP32S3_APP_FORMAT_MCUBOOT
+
 config ESP32S3_PARTITION_TABLE_OFFSET
        hex "Partition Table offset"
        default 0x8000
diff --git a/arch/xtensa/src/esp32s3/esp32s3_start.c 
b/arch/xtensa/src/esp32s3/esp32s3_start.c
index fc6091c9ca..45ec39c99e 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_start.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_start.c
@@ -44,6 +44,7 @@
 #endif
 #include "hardware/esp32s3_cache_memory.h"
 #include "hardware/esp32s3_system.h"
+#include "hardware/esp32s3_extmem.h"
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -55,20 +56,53 @@
 #  define showprogress(c)
 #endif
 
+#ifdef CONFIG_ESP32S3_APP_FORMAT_MCUBOOT
+
+#define PRIMARY_SLOT_OFFSET   CONFIG_ESP32S3_OTA_PRIMARY_SLOT_OFFSET
+
+#define HDR_ATTR              locate_code(".entry_addr") used_code
+
+/* Cache MMU address mask (MMU tables ignore bits which are zero) */
+
+#define MMU_FLASH_MASK        (~(MMU_PAGE_SIZE - 1))
+
+#endif
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
 
+#ifdef CONFIG_ESP32S3_APP_FORMAT_MCUBOOT
+extern uint8_t _image_irom_vma[];
+extern uint8_t _image_irom_lma[];
+extern uint8_t _image_irom_size[];
+
+extern uint8_t _image_drom_vma[];
+extern uint8_t _image_drom_lma[];
+extern uint8_t _image_drom_size[];
+#endif
+
 /****************************************************************************
  * ROM Function Prototypes
  ****************************************************************************/
 
+#ifdef CONFIG_ESP32S3_APP_FORMAT_MCUBOOT
+extern int ets_printf(const char *fmt, ...) printflike(1, 2);
+extern int cache_dbus_mmu_set(uint32_t ext_ram, uint32_t vaddr,
+                              uint32_t paddr, uint32_t psize, uint32_t num,
+                              uint32_t fixed);
+extern int cache_ibus_mmu_set(uint32_t ext_ram, uint32_t vaddr,
+                              uint32_t paddr, uint32_t psize, uint32_t num,
+                              uint32_t fixed);
+#endif
+
 extern void rom_config_instruction_cache_mode(uint32_t cfg_cache_size,
                                               uint8_t cfg_cache_ways,
                                               uint8_t cfg_cache_line_size);
 extern void rom_config_data_cache_mode(uint32_t cfg_cache_size,
                                        uint8_t cfg_cache_ways,
                                        uint8_t cfg_cache_line_size);
+extern void cache_invalidate_dcache_all(void);
 extern uint32_t cache_suspend_dcache(void);
 extern void cache_resume_dcache(uint32_t val);
 extern uint32_t cache_set_idrom_mmu_size(uint32_t irom_size,
@@ -88,10 +122,18 @@ extern int cache_occupy_addr(uint32_t addr, uint32_t size);
  * Private Function Prototypes
  ****************************************************************************/
 
+#ifdef CONFIG_ESP32S3_APP_FORMAT_MCUBOOT
+noreturn_function void __start(void);
+#endif
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
 
+#ifdef CONFIG_ESP32S3_APP_FORMAT_MCUBOOT
+HDR_ATTR static void (*_entry_point)(void) = __start;
+#endif
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
@@ -332,6 +374,97 @@ void noreturn_function IRAM_ATTR __esp32s3_start(void)
   for (; ; ); /* Should not return */
 }
 
+/****************************************************************************
+ * Name: calc_mmu_pages
+ *
+ * Description:
+ *   Calculate the number of cache pages to map.
+ *
+ * Input Parameters:
+ *   size  - Size of data to map
+ *   vaddr - Virtual address where data will be mapped
+ *
+ * Returned Value:
+ *   Number of cache MMU pages required to do the mapping.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32S3_APP_FORMAT_MCUBOOT
+static inline uint32_t calc_mmu_pages(uint32_t size, uint32_t vaddr)
+{
+  return (size + (vaddr - (vaddr & MMU_FLASH_MASK)) + MMU_PAGE_SIZE - 1) /
+    MMU_PAGE_SIZE;
+}
+#endif
+
+/****************************************************************************
+ * Name: map_rom_segments
+ *
+ * Description:
+ *   Configure the MMU and Cache peripherals for accessing ROM code and data.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32S3_APP_FORMAT_MCUBOOT
+static int map_rom_segments(void)
+{
+  uint32_t rc = 0;
+  uint32_t regval;
+  uint32_t drom_lma_aligned;
+  uint32_t drom_vma_aligned;
+  uint32_t drom_page_count;
+  uint32_t irom_lma_aligned;
+  uint32_t irom_vma_aligned;
+  uint32_t irom_page_count;
+
+  size_t partition_offset = PRIMARY_SLOT_OFFSET;
+  uint32_t app_irom_lma = partition_offset + (uint32_t)_image_irom_lma;
+  uint32_t app_irom_size = (uint32_t)_image_irom_size;
+  uint32_t app_irom_vma = (uint32_t)_image_irom_vma;
+  uint32_t app_drom_lma = partition_offset + (uint32_t)_image_drom_lma;
+  uint32_t app_drom_size = (uint32_t)_image_drom_size;
+  uint32_t app_drom_vma = (uint32_t)_image_drom_vma;
+
+  uint32_t autoload = cache_suspend_dcache();
+  cache_invalidate_dcache_all();
+
+  /* Clear the MMU entries that are already set up, so the new app only has
+   * the mappings it creates.
+   */
+
+  for (size_t i = 0; i < FLASH_MMU_TABLE_SIZE; i++)
+    {
+      FLASH_MMU_TABLE[i] = MMU_TABLE_INVALID_VAL;
+    }
+
+  drom_lma_aligned = app_drom_lma & MMU_FLASH_MASK;
+  drom_vma_aligned = app_drom_vma & MMU_FLASH_MASK;
+  drom_page_count = calc_mmu_pages(app_drom_size, app_drom_vma);
+  rc = cache_dbus_mmu_set(MMU_ACCESS_FLASH, drom_vma_aligned,
+                          drom_lma_aligned, 64, drom_page_count, 0);
+
+  irom_lma_aligned = app_irom_lma & MMU_FLASH_MASK;
+  irom_vma_aligned = app_irom_vma & MMU_FLASH_MASK;
+  irom_page_count = calc_mmu_pages(app_irom_size, app_irom_vma);
+  rc = cache_ibus_mmu_set(MMU_ACCESS_FLASH, irom_vma_aligned,
+                          irom_lma_aligned, 64, irom_page_count, 0);
+
+  regval  = getreg32(EXTMEM_DCACHE_CTRL1_REG);
+  regval &= EXTMEM_DCACHE_SHUT_CORE0_BUS;
+  putreg32(regval, EXTMEM_DCACHE_CTRL1_REG);
+
+  cache_resume_dcache(autoload);
+
+  return (int)rc;
+}
+#endif
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -351,6 +484,14 @@ void noreturn_function IRAM_ATTR __esp32s3_start(void)
 
 void IRAM_ATTR __start(void)
 {
+#ifdef CONFIG_ESP32S3_APP_FORMAT_MCUBOOT
+  if (map_rom_segments() != 0)
+    {
+      ets_printf("Failed to setup XIP, aborting\n");
+      while (true);
+    }
+
+#endif
   configure_cpu_caches();
 
   __esp32s3_start();
diff --git a/boards/xtensa/esp32s3/common/scripts/flat_memory.ld 
b/boards/xtensa/esp32s3/common/scripts/flat_memory.ld
index ecf26a8a84..d55b1f7d5d 100644
--- a/boards/xtensa/esp32s3/common/scripts/flat_memory.ld
+++ b/boards/xtensa/esp32s3/common/scripts/flat_memory.ld
@@ -51,6 +51,21 @@
 
 MEMORY
 {
+#ifdef CONFIG_ESP32S3_APP_FORMAT_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_ESP32S3_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_ESP32S3_APP_MCUBOOT_HEADER_SIZE, len = 
0x20
+  ROM (RX) :             org = ORIGIN(metadata) + LENGTH(metadata),
+                         len = FLASH_SIZE - ORIGIN(ROM)
+#endif
+
   /* Below values assume the flash cache is on, and have the blocks this
    * uses subtracted from the length of the various regions. The 'data access
    * port' dram/drom regions map to the same iram/irom regions but are
@@ -63,6 +78,9 @@ MEMORY
 
   /* Flash mapped instruction data. */
 
+#ifdef CONFIG_ESP32S3_APP_FORMAT_MCUBOOT
+  irom0_0_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
@@ -71,6 +89,7 @@ MEMORY
    */
 
   irom0_0_seg (RX) :                 org = 0x42000020, len = FLASH_SIZE - 0x20
+#endif
 
   /* Shared data RAM, excluding memory reserved for bootloader and ROM
    * bss/data/stack.
@@ -80,6 +99,23 @@ MEMORY
 
   /* Flash mapped constant data */
 
+#ifdef CONFIG_ESP32S3_APP_FORMAT_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.
+   */
+
+  drom0_0_seg (R) :      org = 0x3c000000 + 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
@@ -88,6 +124,7 @@ MEMORY
    */
 
   drom0_0_seg (R) :                  org = 0x3c000020, len = FLASH_SIZE - 0x20
+#endif
 
   /* RTC fast memory (executable). Persists over deep sleep. */
 
diff --git a/boards/xtensa/esp32s3/common/scripts/esp32s3_sections.ld 
b/boards/xtensa/esp32s3/common/scripts/legacy_sections.ld
similarity index 98%
copy from boards/xtensa/esp32s3/common/scripts/esp32s3_sections.ld
copy to boards/xtensa/esp32s3/common/scripts/legacy_sections.ld
index 2b70913a43..1a3580491b 100644
--- a/boards/xtensa/esp32s3/common/scripts/esp32s3_sections.ld
+++ b/boards/xtensa/esp32s3/common/scripts/legacy_sections.ld
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/xtensa/esp32s3/common/scripts/esp32s3_sections.ld
+ * boards/xtensa/esp32s3/common/scripts/legacy_sections.ld
  ****************************************************************************/
 
 /* Default entry point: */
diff --git a/boards/xtensa/esp32s3/common/scripts/esp32s3_sections.ld 
b/boards/xtensa/esp32s3/common/scripts/mcuboot_sections.ld
similarity index 59%
rename from boards/xtensa/esp32s3/common/scripts/esp32s3_sections.ld
rename to boards/xtensa/esp32s3/common/scripts/mcuboot_sections.ld
index 2b70913a43..961ae83176 100644
--- a/boards/xtensa/esp32s3/common/scripts/esp32s3_sections.ld
+++ b/boards/xtensa/esp32s3/common/scripts/mcuboot_sections.ld
@@ -1,5 +1,21 @@
 /****************************************************************************
- * boards/xtensa/esp32s3/common/scripts/esp32s3_sections.ld
+ * boards/xtensa/esp32s3/common/scripts/mcuboot_sections.ld
+  *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
  ****************************************************************************/
 
 /* Default entry point: */
@@ -10,6 +26,99 @@ _diram_i_start = 0x40378000;
 
 SECTIONS
 {
+  .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.vectors))
+    LONG(LOADADDR(.iram0.vectors))
+    LONG(LOADADDR(.iram0.text) + SIZEOF(.iram0.text) - 
LOADADDR(.iram0.vectors))
+
+    /* 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
+
+  _image_drom_vma = ADDR(.flash.rodata);
+  _image_drom_lma = LOADADDR(.flash.rodata);
+  _image_drom_size = LOADADDR(.flash.rodata) + SIZEOF(.flash.rodata) - 
_image_drom_lma;
+
+  .flash.rodata :
+  {
+    _rodata_reserved_start = .;
+
+    _srodata = ABSOLUTE(.);
+    *(EXCLUDE_FILE (esp32s3_start.*) .rodata)
+    *(EXCLUDE_FILE (esp32s3_start.*) .rodata.*)
+
+    *(.rodata)
+    *(.rodata.*)
+    *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
+    *(.gnu.linkonce.r.*)
+    *(.rodata1)
+    __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
+    *(.xt_except_table)
+    *(.gcc_except_table)
+    *(.gcc_except_table.*)
+    *(.gnu.linkonce.e.*)
+    *(.gnu.version_r)
+    *(.eh_frame)
+
+    . = ALIGN(4);
+
+    /* C++ constructor and destructor tables, properly ordered: */
+
+    _sinit = ABSOLUTE(.);
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+    _einit = ABSOLUTE(.);
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+
+    /* C++ exception handlers table: */
+
+    __XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
+    *(.xt_except_desc)
+    *(.gnu.linkonce.h.*)
+    __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
+    *(.xt_except_desc_end)
+    *(.dynamic)
+    *(.gnu.version_d)
+    _erodata = ABSOLUTE(.);
+
+    /* Literals are also RO data. */
+
+    _lit4_start = ABSOLUTE(.);
+    *(*.lit4)
+    *(.lit4.*)
+    *(.gnu.linkonce.lit4.*)
+    _lit4_end = ABSOLUTE(.);
+    _rodata_reserved_end = ABSOLUTE(.);
+    . = ALIGN(4);
+  } >drom0_0_seg AT>ROM
+
   /* Send .iram0 code to iram */
 
   .iram0.vectors :
@@ -50,13 +159,14 @@ SECTIONS
     *(.entry.text)
     *(.init.literal)
     *(.init)
-  } >iram0_0_seg
+  } >iram0_0_seg AT>ROM
 
   .iram0.text :
   {
     /* Code marked as running out of IRAM */
 
     *(.iram1 .iram1.*)
+    esp32s3_start.*(.literal .text .literal.* .text.*)
 
     /* align + add 16B for CPU dummy speculative instr. fetch */
 
@@ -131,16 +241,53 @@ SECTIONS
     KEEP (*(.gnu.linkonce.s2.*))
     KEEP (*(.jcr))
     *(.dram1 .dram1.*)
-
+    esp32s3_start.*(.rodata .rodata.*)
     _edata = ABSOLUTE(.);
     . = ALIGN(4);
 
     /* Heap starts at the end of .data */
 
     _sheap = ABSOLUTE(.);
-  } >dram0_0_seg
+  } >dram0_0_seg AT>ROM
+
+  /* Marks the end of IRAM code segment */
+
+  .iram0.text_end (NOLOAD) :
+  {
+    /* ESP32-S3 memprot requires 16B padding for possible CPU prefetch and
+     * 256B alignment for PMS split lines.
+     */
+
+    . += 16;
+    . = ALIGN(256);
+    _iram_end = ABSOLUTE(.);
+  } >iram0_0_seg
 
-  .flash.text :
+  _image_irom_vma = ADDR(.flash.text);
+  _image_irom_lma = LOADADDR(.flash.text);
+  _image_irom_size = LOADADDR(.flash.text) + SIZEOF(.flash.text) - 
_image_irom_lma;
+
+  /* The alignment of the ".flash.text" output section is forced to
+   * 0x00010000 (64KB) to ensure that it will be allocated at the beginning
+   * of the next available Flash block.
+   * 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.
+   */
+
+  .flash_text_dummy (NOLOAD) : ALIGN(0x00010000)
+  {
+    /* This section is required to skip .flash.rodata area because irom0_0_seg
+     * and drom0_0_seg reflect the same address space on different buses.
+     */
+
+    . = SIZEOF(.flash.rodata);
+  } >irom0_0_seg
+
+  .flash.text : ALIGN(0x00010000)
   {
     _stext = .;
     *(.literal .text .literal.* .text.* .stub .gnu.warning 
.gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
@@ -158,112 +305,33 @@ SECTIONS
     . += 16;
 
     _etext = .;
-  } >default_code_seg
+  } >irom0_0_seg AT>ROM
 
-  .flash_rodata_dummy (NOLOAD) :
+  .rtc.text :
   {
-    /* This dummy section represents the .flash.text section but in 
default_rodata_seg.
-     * Thus, it must have its alignment and (at least) its size.
-     */
-
-    /* Start at the same alignment constraint than .flash.text */
-
-    . = ALIGN(ALIGNOF(.flash.text));
-
-    /* Create an empty gap as big as .flash.text section */
-
-    . = SIZEOF(.flash.text);
-
-    /* Prepare the alignment of the section above. Few bytes (0x20) must be
-     * added for the mapping header.
-     */
-
-    . = ALIGN(0x10000) + 0x20;
-    _rodata_reserved_start = .;
-  } >default_rodata_seg
-
-  .flash.rodata : ALIGN(0x10)
-  {
-    _srodata = ABSOLUTE(.);
-
-    *(.rodata)
-    *(.rodata.*)
-    *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
-    *(.gnu.linkonce.r.*)
-    *(.rodata1)
-    __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
-    *(.xt_except_table)
-    *(.gcc_except_table)
-    *(.gcc_except_table.*)
-    *(.gnu.linkonce.e.*)
-    *(.gnu.version_r)
-    *(.eh_frame)
-
-    . = ALIGN(4);
-
-    /* C++ constructor and destructor tables, properly ordered: */
-
-    _sinit = ABSOLUTE(.);
-    KEEP (*crtbegin.o(.ctors))
-    KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
-    KEEP (*(SORT(.ctors.*)))
-    KEEP (*(.ctors))
-    _einit = ABSOLUTE(.);
-    KEEP (*crtbegin.o(.dtors))
-    KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
-    KEEP (*(SORT(.dtors.*)))
-    KEEP (*(.dtors))
-
-    /* C++ exception handlers table: */
-
-    __XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
-    *(.xt_except_desc)
-    *(.gnu.linkonce.h.*)
-    __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
-    *(.xt_except_desc_end)
-    *(.dynamic)
-    *(.gnu.version_d)
-    _erodata = ABSOLUTE(.);
-
-    /* Literals are also RO data. */
-
-    _lit4_start = ABSOLUTE(.);
-    *(*.lit4)
-    *(.lit4.*)
-    *(.gnu.linkonce.lit4.*)
-    _lit4_end = ABSOLUTE(.);
-    _rodata_reserved_end = ABSOLUTE(.);
     . = ALIGN(4);
-  } >default_rodata_seg
+    *(.rtc.literal .rtc.text)
+  } >rtc_iram_seg AT>ROM
 
-  /* Marks the end of IRAM code segment */
-
-  .iram0.text_end (NOLOAD) :
+  .rtc.dummy (NOLOAD) :
   {
-    /* ESP32-S3 memprot requires 16B padding for possible CPU prefetch and
-     * 256B alignment for PMS split lines.
+    /* This section is required to skip .rtc.text area because the text and
+     * data segments reflect the same address space on different buses.
      */
 
-    . += 16;
-    . = ALIGN(256);
-  } >iram0_0_seg
-
-  .iram0.data :
-  {
-    . = ALIGN(4);
+    . = SIZEOF(.rtc.text);
+  } >rtc_data_seg
 
-    *(.iram.data)
-    *(.iram.data.*)
-  } >iram0_0_seg
+  /* RTC BSS section. */
 
-  .iram0.bss (NOLOAD) :
+  .rtc.bss (NOLOAD) :
   {
-    . = ALIGN(4);
+    *(.rtc.bss)
+  } >rtc_data_seg
 
-    *(.iram.bss)
-    *(.iram.bss.*)
-
-    . = ALIGN(4);
-    _iram_end = ABSOLUTE(.);
-  } >iram0_0_seg
+  .rtc.data :
+  {
+    *(.rtc.data)
+    *(.rtc.rodata)
+  } >rtc_data_seg AT>ROM
 }
diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/Kconfig 
b/boards/xtensa/esp32s3/esp32s3-devkit/Kconfig
index 9c3a0d9c6e..6dfe6e5805 100644
--- a/boards/xtensa/esp32s3/esp32s3-devkit/Kconfig
+++ b/boards/xtensa/esp32s3/esp32s3-devkit/Kconfig
@@ -7,7 +7,8 @@ if ARCH_BOARD_ESP32S3_DEVKIT
 
 config ESP32S3_STORAGE_MTD_OFFSET
        hex "Storage MTD base address in SPI Flash"
-       default 0x180000
+       default 0x180000 if !ESP32S3_HAVE_OTA_PARTITION
+       default 0x250000 if ESP32S3_HAVE_OTA_PARTITION
        depends on ESP32S3_MTD
        ---help---
                MTD base address in SPI Flash.
diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/configs/mcuboot_nsh/defconfig 
b/boards/xtensa/esp32s3/esp32s3-devkit/configs/mcuboot_nsh/defconfig
new file mode 100644
index 0000000000..b5cdca1d68
--- /dev/null
+++ b/boards/xtensa/esp32s3/esp32s3-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_ARCH_LEDS is not set
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+# CONFIG_NSH_CMDPARMS is not set
+CONFIG_ARCH="xtensa"
+CONFIG_ARCH_BOARD="esp32s3-devkit"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_ESP32S3_DEVKIT=y
+CONFIG_ARCH_CHIP="esp32s3"
+CONFIG_ARCH_CHIP_ESP32S3=y
+CONFIG_ARCH_CHIP_ESP32S3WROOM1=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_XTENSA=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=16717
+CONFIG_BUILTIN=y
+CONFIG_ESP32S3_APP_FORMAT_MCUBOOT=y
+CONFIG_ESP32S3_SPIFLASH=y
+CONFIG_ESP32S3_UART0=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=3072
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=114688
+CONFIG_RAM_START=0x20000000
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_START_DAY=6
+CONFIG_START_MONTH=12
+CONFIG_START_YEAR=2011
+CONFIG_SYSTEM_NSH=y
+CONFIG_UART0_SERIAL_CONSOLE=y
diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/scripts/Make.defs 
b/boards/xtensa/esp32s3/esp32s3-devkit/scripts/Make.defs
index f1c02022f6..154b50a697 100644
--- a/boards/xtensa/esp32s3/esp32s3-devkit/scripts/Make.defs
+++ b/boards/xtensa/esp32s3/esp32s3-devkit/scripts/Make.defs
@@ -34,7 +34,11 @@ ifeq ($(CONFIG_BUILD_PROTECTED),y)
   ARCHSCRIPT += $(call FINDSCRIPT,kernel-space.ld)
 else
   ARCHSCRIPT += $(call FINDSCRIPT,flat_memory.ld)
-  ARCHSCRIPT += $(call FINDSCRIPT,esp32s3_sections.ld)
+  ifeq ($(CONFIG_ESP32S3_APP_FORMAT_MCUBOOT),y)
+    ARCHSCRIPT += $(call FINDSCRIPT,mcuboot_sections.ld)
+  else
+    ARCHSCRIPT += $(call FINDSCRIPT,legacy_sections.ld)
+  endif
 endif
 
 ifneq ($(CONFIG_DEBUG_NOOPT),y)
diff --git a/boards/xtensa/esp32s3/esp32s3-eye/scripts/Make.defs 
b/boards/xtensa/esp32s3/esp32s3-eye/scripts/Make.defs
index 2a7742006d..056bbf7b31 100644
--- a/boards/xtensa/esp32s3/esp32s3-eye/scripts/Make.defs
+++ b/boards/xtensa/esp32s3/esp32s3-eye/scripts/Make.defs
@@ -34,7 +34,7 @@ ifeq ($(CONFIG_BUILD_PROTECTED),y)
   ARCHSCRIPT += $(call FINDSCRIPT,kernel-space.ld)
 else
   ARCHSCRIPT += $(call FINDSCRIPT,flat_memory.ld)
-  ARCHSCRIPT += $(call FINDSCRIPT,esp32s3_sections.ld)
+  ARCHSCRIPT += $(call FINDSCRIPT,legacy_sections.ld)
 endif
 
 ifneq ($(CONFIG_DEBUG_NOOPT),y)
diff --git a/tools/esp32s3/Config.mk b/tools/esp32s3/Config.mk
index 26b876b5b1..f3e7f00782 100644
--- a/tools/esp32s3/Config.mk
+++ b/tools/esp32s3/Config.mk
@@ -69,6 +69,11 @@ ifdef ESPTOOL_BINDIR
                FLASH_BL        := $(BL_OFFSET) $(BOOTLOADER)
                FLASH_PT        := $(PT_OFFSET) $(PARTITION_TABLE)
                ESPTOOL_BINS    := $(FLASH_BL) $(FLASH_PT)
+       else ifeq ($(CONFIG_ESP32S3_APP_FORMAT_MCUBOOT),y)
+               BL_OFFSET       := 0x0000
+               BOOTLOADER      := $(ESPTOOL_BINDIR)/mcuboot-esp32s3.bin
+               FLASH_BL        := $(BL_OFFSET) $(BOOTLOADER)
+               ESPTOOL_BINS    := $(FLASH_BL)
        endif
 endif
 
@@ -76,6 +81,21 @@ ifeq ($(CONFIG_ESP32S3_APP_FORMAT_LEGACY),y)
        APP_OFFSET     := 0x10000
        APP_IMAGE      := nuttx.bin
        FLASH_APP      := $(APP_OFFSET) $(APP_IMAGE)
+else ifeq ($(CONFIG_ESP32S3_APP_FORMAT_MCUBOOT),y)
+       ifeq ($(CONFIG_ESP32S3_ESPTOOL_TARGET_PRIMARY),y)
+               VERIFIED   := --confirm
+               APP_OFFSET := $(CONFIG_ESP32S3_OTA_PRIMARY_SLOT_OFFSET)
+       else ifeq ($(CONFIG_ESP32S3_ESPTOOL_TARGET_SECONDARY),y)
+               VERIFIED   :=
+               APP_OFFSET := $(CONFIG_ESP32S3_OTA_SECONDARY_SLOT_OFFSET)
+       endif
+
+       APP_IMAGE      := nuttx.bin
+       FLASH_APP      := $(APP_OFFSET) $(APP_IMAGE)
+       IMGTOOL_ALIGN_ARGS := --align 4
+       IMGTOOL_SIGN_ARGS  := --pad $(VERIFIED) $(IMGTOOL_ALIGN_ARGS) -v 0 -s 
auto \
+               -H $(CONFIG_ESP32S3_APP_MCUBOOT_HEADER_SIZE) --pad-header \
+               -S $(CONFIG_ESP32S3_OTA_SLOT_SIZE)
 endif
 
 ESPTOOL_BINS += $(FLASH_APP)
@@ -103,6 +123,7 @@ endef
 
 # MKIMAGE -- Convert an ELF file into a compatible binary file
 
+ifeq ($(CONFIG_ESP32S3_APP_FORMAT_LEGACY),y)
 define MKIMAGE
        $(Q) echo "MKIMAGE: ESP32-S3 binary"
        $(Q) if ! esptool.py version 1>/dev/null 2>&1; then \
@@ -120,6 +141,21 @@ define MKIMAGE
        $(Q) echo nuttx.bin >> nuttx.manifest
        $(Q) echo "Generated: nuttx.bin (ESP32-S3 compatible)"
 endef
+else ifeq ($(CONFIG_ESP32S3_APP_FORMAT_MCUBOOT),y)
+define MKIMAGE
+       $(Q) echo "MKIMAGE: ESP32-S3 binary"
+       $(Q) if ! imgtool version 1>/dev/null 2>&1; then \
+               echo ""; \
+               echo "imgtool not found.  Please run: \"pip install imgtool\""; 
\
+               echo ""; \
+               echo "Run make again to create the nuttx.bin image."; \
+               exit 1; \
+       fi
+       imgtool sign $(IMGTOOL_SIGN_ARGS) nuttx.hex nuttx.bin
+       $(Q) echo nuttx.bin >> nuttx.manifest
+       $(Q) echo "Generated: nuttx.bin (MCUboot compatible)"
+endef
+endif
 
 # POSTBUILD -- Perform post build operations
 

Reply via email to