diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig index ec1a698462..4dde172c70 100644 --- a/arch/xtensa/src/esp32/Kconfig +++ b/arch/xtensa/src/esp32/Kconfig @@ -254,14 +254,6 @@ config ESP32_RT_TIMER default n select ESP32_TIMER0 -config ESP32_PARTITION - bool "ESP32 Partition" - default n - select ESP32_SPIFLASH - ---help--- - Decode esp-idf's partition file and initialize - partition by nuttx MTD. - config ESP32_RUN_IRAM bool "Run from IRAM" default n @@ -834,9 +826,50 @@ endmenu # ESP32_SPI menu "SPI Flash configuration" depends on ESP32_SPIFLASH +if ESP32_HAVE_OTA_PARTITION + +comment "Application Image OTA Update support" + +config ESP32_OTA_PRIMARY_SLOT_OFFSET + hex "Application image primary slot offset" + default "0x10000" + +config ESP32_OTA_PRIMARY_SLOT_DEVPATH + string "Application image primary slot device path" + default "/dev/ota0" + +config ESP32_OTA_SECONDARY_SLOT_OFFSET + hex "Application image secondary slot offset" + default "0x110000" + +config ESP32_OTA_SECONDARY_SLOT_DEVPATH + string "Application image secondary slot device path" + default "/dev/ota1" + +config ESP32_OTA_SLOT_SIZE + hex "Application image slot size (in bytes)" + default "0x100000" + +config ESP32_OTA_SCRATCH_OFFSET + hex "Scratch partition offset" + default "0x210000" + +config ESP32_OTA_SCRATCH_SIZE + hex "Scratch partition size" + default "0x40000" + +config ESP32_OTA_SCRATCH_DEVPATH + string "Scratch partition device path" + default "/dev/otascratch" + +endif + +comment "General MTD configuration" + config ESP32_MTD_OFFSET hex "MTD base address in SPI Flash" - default 0x180000 + default 0x180000 if !ESP32_HAVE_OTA_PARTITION + default 0x250000 if ESP32_HAVE_OTA_PARTITION ---help--- MTD base address in SPI Flash. @@ -1153,6 +1186,82 @@ config ESP32_FREERUN endmenu # Timer/counter Configuration endif # ESP32_TIMER +config ESP32_HAVE_OTA_PARTITION + bool + default n + +menu "Application Image Configuration" + +choice + prompt "Application Image Format" + default ESP32_APP_FORMAT_LEGACY + ---help--- + Depending on the chosen 2nd stage bootloader, the application may + be required to be perform a specific startup routine. Furthermore, + the image binary must be formatted according to the definition from + the 2nd stage bootloader. + +config ESP32_APP_FORMAT_LEGACY + bool "Legacy format" + ---help--- + This is the legacy application image format, as supported by the ESP-IDF + 2nd stage bootloader. + +config ESP32_APP_FORMAT_MCUBOOT + bool "MCUboot-bootable format" + select ESP32_HAVE_OTA_PARTITION + depends on EXPERIMENTAL + ---help--- + The ESP32 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 + prompt "Target slot for image flashing" + default ESP32_ESPTOOL_TARGET_PRIMARY + depends on ESP32_HAVE_OTA_PARTITION + ---help--- + Slot to which ESPTOOL will flash the generated binary image. + +config ESP32_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 ESP32_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 ESP32_APP_MCUBOOT_HEADER_SIZE + int "Application image header size (in bytes)" + default 32 + depends on ESP32_APP_FORMAT_MCUBOOT + +endmenu # Application Image Configuration + +if ESP32_APP_FORMAT_LEGACY + +config ESP32_PARTITION + bool "ESP32 Partition" + default n + select ESP32_SPIFLASH + ---help--- + Decode esp-idf's partition file and initialize + partition by nuttx MTD. + menu "Partition Configuration" depends on ESP32_PARTITION @@ -1164,7 +1273,9 @@ config ESP32_PARTITION_MOUNT string "Partition mount point" default "/dev/esp/partition/" -endmenu # ESP32_PARTITION +endmenu # Partition Configuration + +endif menu "AES accelerate" depends on ESP32_AES_ACCELERATOR diff --git a/arch/xtensa/src/esp32/esp32_start.c b/arch/xtensa/src/esp32/esp32_start.c index 8dcfb3b7f1..ee4ec46a3c 100644 --- a/arch/xtensa/src/esp32/esp32_start.c +++ b/arch/xtensa/src/esp32/esp32_start.c @@ -47,11 +47,81 @@ ****************************************************************************/ #ifdef CONFIG_DEBUG_FEATURES -# define showprogress(c) up_puts(c) +# define showprogress(c) up_puts(c) #else # define showprogress(c) #endif +#ifdef CONFIG_ESP32_APP_FORMAT_MCUBOOT + +#define PRIMARY_SLOT_OFFSET CONFIG_ESP32_OTA_PRIMARY_SLOT_OFFSET + +#define HDR_ATTR __attribute__((section(".entry_addr"))) \ + __attribute__((used)) + +/* Cache MMU block size */ + +#define MMU_BLOCK_SIZE 0x00010000 /* 64 KB */ + +/* Cache MMU address mask (MMU tables ignore bits which are zero) */ + +#define MMU_FLASH_MASK (~(MMU_BLOCK_SIZE - 1)) + +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#ifdef CONFIG_ESP32_APP_FORMAT_MCUBOOT +extern uint32_t _image_irom_vma; +extern uint32_t _image_irom_lma; +extern uint32_t _image_irom_size; + +extern uint32_t _image_drom_vma; +extern uint32_t _image_drom_lma; +extern uint32_t _image_drom_size; +#endif + +/**************************************************************************** + * ROM Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_ESP32_APP_FORMAT_MCUBOOT +extern int ets_printf(const char *fmt, ...); +extern void cache_read_enable(int cpu); +extern void cache_read_disable(int cpu); +extern void cache_flush(int cpu); +extern unsigned int cache_flash_mmu_set(int cpu_no, int pid, + unsigned int vaddr, + unsigned int paddr, + int psize, int num); +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_ESP32_APP_FORMAT_MCUBOOT +noreturn_function void __start(void); +#endif + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +#ifndef CONFIG_SUPPRESS_UART_CONFIG +extern void esp32_lowsetup(void); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_ESP32_APP_FORMAT_MCUBOOT +HDR_ATTR static void (*_entry_point)(void) = &__start; +#endif + /**************************************************************************** * Public Data ****************************************************************************/ @@ -62,27 +132,10 @@ uint32_t g_idlestack[IDLETHREAD_STACKWORDS] aligned_data(16) locate_data(".noinit"); /**************************************************************************** - * Public Functions + * Private Functions ****************************************************************************/ -#ifndef CONFIG_SUPPRESS_UART_CONFIG -extern void esp32_lowsetup(void); -#endif - -/**************************************************************************** - * Name: __start - * - * Description: - * We arrive here after the bootloader finished loading the program from - * flash. The hardware is mostly uninitialized, and the app CPU is in - * reset. We do have a stack, so we can do the initialization in C. - * - * The app CPU will remain in reset unless CONFIG_SMP is selected and - * up_cpu_start() is called later in the bring-up sequeuence. - * - ****************************************************************************/ - -void IRAM_ATTR __start(void) +static noreturn_function void __esp32_start(void) { uint32_t regval; uint32_t sp; @@ -178,3 +231,136 @@ void IRAM_ATTR __start(void) nx_start(); 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_ESP32_APP_FORMAT_MCUBOOT +static inline uint32_t calc_mmu_pages(uint32_t size, uint32_t vaddr) +{ + return (size + (vaddr - (vaddr & MMU_FLASH_MASK)) + MMU_BLOCK_SIZE - 1) / + MMU_BLOCK_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_ESP32_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; + + volatile uint32_t *pro_flash_mmu_table = + (volatile uint32_t *)DPORT_PRO_FLASH_MMU_TABLE_REG; + + cache_read_disable(0); + cache_flush(0); + + /* Clear the MMU entries that are already set up, so the new app only has + * the mappings it creates. + */ + + for (int i = 0; i < DPORT_FLASH_MMU_TABLE_SIZE; i++) + { + putreg32(DPORT_FLASH_MMU_TABLE_INVALID_VAL, pro_flash_mmu_table++); + } + + 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_flash_mmu_set(0, 0, drom_vma_aligned, drom_lma_aligned, 64, + (int)drom_page_count); + rc |= cache_flash_mmu_set(1, 0, drom_vma_aligned, drom_lma_aligned, 64, + (int)drom_page_count); + + 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_flash_mmu_set(0, 0, irom_vma_aligned, irom_lma_aligned, 64, + (int)irom_page_count); + rc |= cache_flash_mmu_set(1, 0, irom_vma_aligned, irom_lma_aligned, 64, + (int)irom_page_count); + + regval = getreg32(DPORT_PRO_CACHE_CTRL1_REG); + regval &= ~(DPORT_PRO_CACHE_MASK_IRAM0 | DPORT_PRO_CACHE_MASK_DROM0 | + DPORT_PRO_CACHE_MASK_DRAM1); + putreg32(regval, DPORT_PRO_CACHE_CTRL1_REG); + + regval = getreg32(DPORT_APP_CACHE_CTRL1_REG); + regval &= ~(DPORT_APP_CACHE_MASK_IRAM0 | DPORT_APP_CACHE_MASK_DROM0 | + DPORT_APP_CACHE_MASK_DRAM1); + putreg32(regval, DPORT_APP_CACHE_CTRL1_REG); + + cache_read_enable(0); + return (int)rc; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: __start + * + * Description: + * We arrive here after the bootloader finished loading the program from + * flash. The hardware is mostly uninitialized, and the app CPU is in + * reset. We do have a stack, so we can do the initialization in C. + * + * The app CPU will remain in reset unless CONFIG_SMP is selected and + * up_cpu_start() is called later in the bring-up sequence. + * + ****************************************************************************/ + +void __start(void) +{ +#ifdef CONFIG_ESP32_APP_FORMAT_MCUBOOT + if (map_rom_segments() != 0) + { + ets_printf("Failed to setup XIP, aborting\n"); + while (true); + } + +#endif + __esp32_start(); +} diff --git a/arch/xtensa/src/esp32/hardware/esp32_dport.h b/arch/xtensa/src/esp32/hardware/esp32_dport.h index de9e1609af..6aa829d6cf 100644 --- a/arch/xtensa/src/esp32/hardware/esp32_dport.h +++ b/arch/xtensa/src/esp32/hardware/esp32_dport.h @@ -4398,4 +4398,10 @@ #define DPORT_APP_FLASH_MMU_TABLE_REG (DR_REG_DPORT_BASE + 0x12000) +#define DPORT_FLASH_MMU_TABLE_SIZE 0x100 + +#define DPORT_FLASH_MMU_TABLE_INVALID_VAL 0x100 + +#define DPORT_MMU_ADDRESS_MASK 0xff + #endif /* __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_DPORT_H */ diff --git a/boards/xtensa/esp32/common/scripts/esp32.template.ld b/boards/xtensa/esp32/common/scripts/esp32.template.ld index 8e711bfe17..7632e2aa5d 100644 --- a/boards/xtensa/esp32/common/scripts/esp32.template.ld +++ b/boards/xtensa/esp32/common/scripts/esp32.template.ld @@ -24,8 +24,8 @@ * This file describes the memory layout (memory blocks) as virtual * memory addresses. * - * esp32.ld contains output sections to link compiler output - * into these memory blocks. + * esp32.ld contains output sections to link compiler output into these + * memory blocks. * * NOTE: That this is not the actual linker script but rather a "template" * for the esp32_out.ld script. This template script is passed through @@ -35,28 +35,57 @@ #include +#ifdef CONFIG_ESP32_FLASH_2M +# define FLASH_SIZE 0x200000 +#elif defined (CONFIG_ESP32_FLASH_4M) +# define FLASH_SIZE 0x400000 +#elif defined (CONFIG_ESP32_FLASH_8M) +# define FLASH_SIZE 0x800000 +#elif defined (CONFIG_ESP32_FLASH_16M) +# define FLASH_SIZE 0x1000000 +#endif + MEMORY { - /* All these values assume the flash cache is on, and have the blocks this +#ifdef CONFIG_ESP32_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_ESP32_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_ESP32_APP_MCUBOOT_HEADER_SIZE, len = 0x20 + ROM (RX) : org = CONFIG_ESP32_APP_MCUBOOT_HEADER_SIZE + 0x20, + len = FLASH_SIZE - (CONFIG_ESP32_APP_MCUBOOT_HEADER_SIZE + 0x20) +#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 - * connected to the data port of the CPU and eg allow bytewise access. + * connected to the data port of the CPU and e.g. allow bytewise access. */ /* IRAM for PRO cpu. Not sure if happy with this, this is MMU area... */ iram0_0_seg (RX) : org = 0x40080000, len = 0x20000 - /* Flash mapped instruction data. - * - * The 0x20 offset is a convenience for the app binary image generation. + /* Flash mapped instruction data. */ + +#ifdef CONFIG_ESP32_APP_FORMAT_MCUBOOT + irom0_0_seg (RX) : org = 0x400d0000, len = 0x330000 +#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 - * constraint that (paddr % 64KB == vaddr % 64KB).) + * constraint that (paddr % 64KB == vaddr % 64KB). */ irom0_0_seg (RX) : org = 0x400d0020, len = 0x330000 - 0x20 +#endif /* Shared data RAM, excluding memory reserved for ROM bss/data/stack. * Enabling Bluetooth & Trace Memory features in menuconfig will decrease @@ -73,23 +102,48 @@ MEMORY /* Flash mapped constant data */ - drom0_0_seg (R) : org = 0x3f400020, len = 0x400000 - 0x20 +#ifdef CONFIG_ESP32_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 = 0x3f400000 + (CONFIG_ESP32_APP_MCUBOOT_HEADER_SIZE + 0x20), + len = FLASH_SIZE - (CONFIG_ESP32_APP_MCUBOOT_HEADER_SIZE + 0x20) +#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 + * constraint that (paddr % 64KB == vaddr % 64KB). + */ + + drom0_0_seg (R) : org = 0x3f400020, len = FLASH_SIZE - 0x20 +#endif /* RTC fast memory (executable). Persists over deep sleep. */ - rtc_iram_seg(RWX) : org = 0x400c0000, len = 0x2000 + rtc_iram_seg (RWX) : org = 0x400c0000, len = 0x2000 /* RTC slow memory (data accessible). Persists over deep sleep. * Start of RTC slow memory is reserved for ULP co-processor code + data, * if enabled. */ - rtc_slow_seg(RW) : org = 0x50000000 + CONFIG_ESP32_ULP_COPROC_RESERVE_MEM, + rtc_slow_seg (RW) : org = 0x50000000 + CONFIG_ESP32_ULP_COPROC_RESERVE_MEM, len = 0x1000 - CONFIG_ESP32_ULP_COPROC_RESERVE_MEM /* External memory, including data and text */ - extmem_seg(RWX) : org = 0x3f800000, len = 0x400000 + extmem_seg (RWX) : org = 0x3f800000, len = 0x400000 } #if CONFIG_ESP32_DEVKIT_RUN_IRAM diff --git a/boards/xtensa/esp32/common/scripts/esp32_mcuboot.ld b/boards/xtensa/esp32/common/scripts/esp32_mcuboot.ld new file mode 100644 index 0000000000..8443b5ce01 --- /dev/null +++ b/boards/xtensa/esp32/common/scripts/esp32_mcuboot.ld @@ -0,0 +1,299 @@ +/**************************************************************************** + * boards/xtensa/esp32/common/scripts/esp32_mcuboot.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: */ + +ENTRY(__start); + +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 : + { + . = ALIGN(4); + _srodata = ABSOLUTE(.); + *(EXCLUDE_FILE (*libarch.a:esp32_spiflash.* esp32_start.*) .rodata) + *(EXCLUDE_FILE (*libarch.a:esp32_spiflash.* esp32_start.*) .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) + + . = (. + 3) & ~ 3; + + /* 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) + . = ALIGN(4); /* This table MUST be 4-byte aligned */ + _erodata = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + } >drom0_0_seg AT>ROM + + /* Send .iram0 code to iram */ + + .iram0.vectors : + { + /* Vectors go to IRAM */ + + _init_start = ABSOLUTE(.); + + /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ + + . = 0x0; + KEEP (*(.window_vectors.text)); + . = 0x180; + KEEP (*(.xtensa_level2_vector.text)); + . = 0x1c0; + KEEP (*(.xtensa_level3_vector.text)); + . = 0x200; + KEEP (*(.xtensa_level4_vector.text)); + . = 0x240; + KEEP (*(.xtensa_level5_vector.text)); + . = 0x280; + KEEP (*(.debug_exception_vector.text)); + . = 0x2c0; + KEEP (*(.nmi_vector.text)); + . = 0x300; + KEEP (*(.kernel_exception_vector.text)); + . = 0x340; + KEEP (*(.user_exception_vector.text)); + . = 0x3c0; + KEEP (*(.double_exception_vector.text)); + . = 0x400; + *(.*_vector.literal) + + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + _init_end = ABSOLUTE(.); + } >iram0_0_seg AT>ROM + + .iram0.text : + { + /* Code marked as running out of IRAM */ + + _iram_text_start = ABSOLUTE(.); + *(.iram1 .iram1.*) + *libphy.a:(.literal .text .literal.* .text.*) + *librtc.a:(.literal .text .literal.* .text.*) + *libpp.a:(.literal .text .literal.* .text.*) + *libhal.a:(.literal .text .literal.* .text.*) + *libarch.a:esp32_spiflash.*(.literal .text .literal.* .text.*) + esp32_start.*(.literal .text .literal.* .text.*) + *(.wifirxiram .wifirxiram.*) + *(.wifirxiram .wifi0iram.*) + *(.wifislpiram .wifislpiram.*) + *(.wifislprxiram .wifislprxiram.*) + *(.phyiram .phyiram.*) + _iram_text_end = ABSOLUTE(.); + + /* IRAM heap starts at the end of iram0_0_seg */ + + . = ALIGN (4); + _siramheap = ABSOLUTE(.); + } >iram0_0_seg AT>ROM + + /* Shared RAM */ + + .dram0.bss (NOLOAD) : + { + /* .bss initialized on power-up */ + + . = ALIGN (8); + _sbss = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + KEEP (*(.bss)) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(8); + _ebss = ABSOLUTE(.); + } >dram0_0_seg + + .noinit (NOLOAD): + { + /* This section contains data that is not initialized during load, + * or during the application's initialization sequence. + */ + + . = ALIGN(8); + *(.noinit) + *(".noinit.*") + . = ALIGN(8); + } >dram0_0_seg + + .dram0.data : + { + /* .data initialized on power-up in ROMed configurations. */ + + _sdata = ABSOLUTE(.); + KEEP (*(.data)) + KEEP (*(.data.*)) + KEEP (*(.gnu.linkonce.d.*)) + KEEP (*(.data1)) + KEEP (*(.sdata)) + KEEP (*(.sdata.*)) + KEEP (*(.gnu.linkonce.s.*)) + KEEP (*(.sdata2)) + KEEP (*(.sdata2.*)) + KEEP (*(.gnu.linkonce.s2.*)) + KEEP (*(.jcr)) + *(.dram1 .dram1.*) + *libarch.a:esp32_spiflash.*(.rodata .rodata.*) + esp32_start.*(.rodata .rodata.*) + _edata = ABSOLUTE(.); + . = ALIGN(4); + + /* Heap starts at the end of .data */ + + _sheap = ABSOLUTE(.); + } >dram0_0_seg AT>ROM + + /* External memory bss, from any global variable with EXT_RAM_ATTR attribute */ + + .extmem.bss (NOLOAD) : + { + _sbss_extmem = ABSOLUTE(.); + *(.extmem.bss .extmem.bss.*) + . = ALIGN(4); + _ebss_extmem = ABSOLUTE(.); + } >extmem_seg + + _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 + * 0x0000FFFF (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 : ALIGN(0x0000FFFF) + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.fini.literal) + *(.fini) + *(.gnu.version) + . = ALIGN(4); + _text_end = ABSOLUTE(.); + _etext = .; + } >irom0_0_seg AT>ROM + + .rtc.text : + { + . = ALIGN(4); + *(.rtc.literal .rtc.text) + } >rtc_iram_seg AT>ROM + + .rtc.data : + { + *(.rtc.data) + *(.rtc.rodata) + + /* Whatever is left from the RTC memory is used as a special heap. */ + + . = ALIGN (4); + _srtcheap = ABSOLUTE(.); + } >rtc_slow_seg AT>ROM +} diff --git a/boards/xtensa/esp32/esp32-devkitc/scripts/Make.defs b/boards/xtensa/esp32/esp32-devkitc/scripts/Make.defs index 71f2926236..a88fda3242 100644 --- a/boards/xtensa/esp32/esp32-devkitc/scripts/Make.defs +++ b/boards/xtensa/esp32/esp32-devkitc/scripts/Make.defs @@ -35,7 +35,11 @@ endif ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld),) LDSCRIPT_SECT = $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld else - LDSCRIPT_SECT = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld + ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y) + LDSCRIPT_SECT = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld + else + LDSCRIPT_SECT = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld + endif endif ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld),) diff --git a/boards/xtensa/esp32/esp32-devkitc/src/esp32_spiflash.c b/boards/xtensa/esp32/esp32-devkitc/src/esp32_spiflash.c index 0de2166b00..aac9cbf40f 100644 --- a/boards/xtensa/esp32/esp32-devkitc/src/esp32_spiflash.c +++ b/boards/xtensa/esp32/esp32-devkitc/src/esp32_spiflash.c @@ -35,6 +35,9 @@ #include #include #include +#ifdef CONFIG_BCH +#include +#endif #include "esp32_spiflash.h" #include "esp32-devkitc.h" @@ -43,9 +46,100 @@ * Pre-processor Definitions ****************************************************************************/ +#define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0])) + #define ESP32_MTD_OFFSET CONFIG_ESP32_MTD_OFFSET #define ESP32_MTD_SIZE CONFIG_ESP32_MTD_SIZE +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION + +struct ota_partition_s +{ + uint32_t offset; /* Partition offset from the beginning of MTD */ + uint32_t size; /* Partition size in bytes */ + const char *devpath; /* Partition device path */ +}; + +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION +static int init_ota_partitions(void); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION +static const struct ota_partition_s g_ota_partition_table[] = +{ + { + .offset = CONFIG_ESP32_OTA_PRIMARY_SLOT_OFFSET, + .size = CONFIG_ESP32_OTA_SLOT_SIZE, + .devpath = CONFIG_ESP32_OTA_PRIMARY_SLOT_DEVPATH + }, + { + .offset = CONFIG_ESP32_OTA_SECONDARY_SLOT_OFFSET, + .size = CONFIG_ESP32_OTA_SLOT_SIZE, + .devpath = CONFIG_ESP32_OTA_SECONDARY_SLOT_DEVPATH + }, + { + .offset = CONFIG_ESP32_OTA_SCRATCH_OFFSET, + .size = CONFIG_ESP32_OTA_SCRATCH_SIZE, + .devpath = CONFIG_ESP32_OTA_SCRATCH_DEVPATH + } +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION +static int init_ota_partitions(void) +{ + FAR struct mtd_dev_s *mtd; +#ifdef CONFIG_BCH + char blockdev[18]; +#endif + int ret = OK; + + for (int i = 0; i < ARRAYSIZE(g_ota_partition_table); ++i) + { + const struct ota_partition_s *part = &g_ota_partition_table[i]; + mtd = esp32_spiflash_alloc_mtdpart(part->offset, part->size); + + ret = ftl_initialize(i, mtd); + if (ret < 0) + { + ferr("ERROR: Failed to initialize the FTL layer: %d\n", ret); + return ret; + } + +#ifdef CONFIG_BCH + snprintf(blockdev, 18, "/dev/mtdblock%d", i); + + ret = bchdev_register(blockdev, part->devpath, false); + if (ret < 0) + { + ferr("ERROR: bchdev_register %s failed: %d\n", part->devpath, ret); + return ret; + } +#endif + } + + return ret; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -62,6 +156,14 @@ int esp32_spiflash_init(void) FAR struct mtd_dev_s *mtd; int ret = ERROR; +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION + ret = init_ota_partitions(); + if (ret < 0) + { + return ret; + } +#endif + mtd = esp32_spiflash_alloc_mtdpart(ESP32_MTD_OFFSET, ESP32_MTD_SIZE); #if defined (CONFIG_ESP32_SPIFLASH_SMARTFS) diff --git a/boards/xtensa/esp32/esp32-ethernet-kit/scripts/Make.defs b/boards/xtensa/esp32/esp32-ethernet-kit/scripts/Make.defs index a575f22010..392b045945 100644 --- a/boards/xtensa/esp32/esp32-ethernet-kit/scripts/Make.defs +++ b/boards/xtensa/esp32/esp32-ethernet-kit/scripts/Make.defs @@ -35,7 +35,11 @@ endif ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld),) LDSCRIPT_SECT = $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld else - LDSCRIPT_SECT = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld + ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y) + LDSCRIPT_SECT = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld + else + LDSCRIPT_SECT = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld + endif endif ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld),) diff --git a/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_spiflash.c b/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_spiflash.c index a8dcb41597..c03d9ee6fa 100644 --- a/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_spiflash.c +++ b/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_spiflash.c @@ -35,6 +35,9 @@ #include #include #include +#ifdef CONFIG_BCH +#include +#endif #include "esp32_spiflash.h" #include "esp32-ethernet-kit.h" @@ -43,9 +46,100 @@ * Pre-processor Definitions ****************************************************************************/ +#define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0])) + #define ESP32_MTD_OFFSET CONFIG_ESP32_MTD_OFFSET #define ESP32_MTD_SIZE CONFIG_ESP32_MTD_SIZE +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION + +struct ota_partition_s +{ + uint32_t offset; /* Partition offset from the beginning of MTD */ + uint32_t size; /* Partition size in bytes */ + const char *devpath; /* Partition device path */ +}; + +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION +static int init_ota_partitions(void); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION +static const struct ota_partition_s g_ota_partition_table[] = +{ + { + .offset = CONFIG_ESP32_OTA_PRIMARY_SLOT_OFFSET, + .size = CONFIG_ESP32_OTA_SLOT_SIZE, + .devpath = CONFIG_ESP32_OTA_PRIMARY_SLOT_DEVPATH + }, + { + .offset = CONFIG_ESP32_OTA_SECONDARY_SLOT_OFFSET, + .size = CONFIG_ESP32_OTA_SLOT_SIZE, + .devpath = CONFIG_ESP32_OTA_SECONDARY_SLOT_DEVPATH + }, + { + .offset = CONFIG_ESP32_OTA_SCRATCH_OFFSET, + .size = CONFIG_ESP32_OTA_SCRATCH_SIZE, + .devpath = CONFIG_ESP32_OTA_SCRATCH_DEVPATH + } +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION +static int init_ota_partitions(void) +{ + FAR struct mtd_dev_s *mtd; +#ifdef CONFIG_BCH + char blockdev[18]; +#endif + int ret = OK; + + for (int i = 0; i < ARRAYSIZE(g_ota_partition_table); ++i) + { + const struct ota_partition_s *part = &g_ota_partition_table[i]; + mtd = esp32_spiflash_alloc_mtdpart(part->offset, part->size); + + ret = ftl_initialize(i, mtd); + if (ret < 0) + { + ferr("ERROR: Failed to initialize the FTL layer: %d\n", ret); + return ret; + } + +#ifdef CONFIG_BCH + snprintf(blockdev, 18, "/dev/mtdblock%d", i); + + ret = bchdev_register(blockdev, part->devpath, false); + if (ret < 0) + { + ferr("ERROR: bchdev_register %s failed: %d\n", part->devpath, ret); + return ret; + } +#endif + } + + return ret; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -62,6 +156,14 @@ int esp32_spiflash_init(void) FAR struct mtd_dev_s *mtd; int ret = ERROR; +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION + ret = init_ota_partitions(); + if (ret < 0) + { + return ret; + } +#endif + mtd = esp32_spiflash_alloc_mtdpart(ESP32_MTD_OFFSET, ESP32_MTD_SIZE); #if defined (CONFIG_ESP32_SPIFLASH_SMARTFS) diff --git a/boards/xtensa/esp32/esp32-wrover-kit/scripts/Make.defs b/boards/xtensa/esp32/esp32-wrover-kit/scripts/Make.defs index 72d2ed8c82..0132e5a058 100644 --- a/boards/xtensa/esp32/esp32-wrover-kit/scripts/Make.defs +++ b/boards/xtensa/esp32/esp32-wrover-kit/scripts/Make.defs @@ -35,7 +35,11 @@ endif ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld),) LDSCRIPT_SECT = $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld else - LDSCRIPT_SECT = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld + ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y) + LDSCRIPT_SECT = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld + else + LDSCRIPT_SECT = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld + endif endif ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld),) diff --git a/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_spiflash.c b/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_spiflash.c index 4eaf028097..67d28d76b3 100644 --- a/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_spiflash.c +++ b/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_spiflash.c @@ -35,6 +35,9 @@ #include #include #include +#ifdef CONFIG_BCH +#include +#endif #include "esp32_spiflash.h" #include "esp32-wrover-kit.h" @@ -43,9 +46,100 @@ * Pre-processor Definitions ****************************************************************************/ +#define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0])) + #define ESP32_MTD_OFFSET CONFIG_ESP32_MTD_OFFSET #define ESP32_MTD_SIZE CONFIG_ESP32_MTD_SIZE +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION + +struct ota_partition_s +{ + uint32_t offset; /* Partition offset from the beginning of MTD */ + uint32_t size; /* Partition size in bytes */ + const char *devpath; /* Partition device path */ +}; + +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION +static int init_ota_partitions(void); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION +static const struct ota_partition_s g_ota_partition_table[] = +{ + { + .offset = CONFIG_ESP32_OTA_PRIMARY_SLOT_OFFSET, + .size = CONFIG_ESP32_OTA_SLOT_SIZE, + .devpath = CONFIG_ESP32_OTA_PRIMARY_SLOT_DEVPATH + }, + { + .offset = CONFIG_ESP32_OTA_SECONDARY_SLOT_OFFSET, + .size = CONFIG_ESP32_OTA_SLOT_SIZE, + .devpath = CONFIG_ESP32_OTA_SECONDARY_SLOT_DEVPATH + }, + { + .offset = CONFIG_ESP32_OTA_SCRATCH_OFFSET, + .size = CONFIG_ESP32_OTA_SCRATCH_SIZE, + .devpath = CONFIG_ESP32_OTA_SCRATCH_DEVPATH + } +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION +static int init_ota_partitions(void) +{ + FAR struct mtd_dev_s *mtd; +#ifdef CONFIG_BCH + char blockdev[18]; +#endif + int ret = OK; + + for (int i = 0; i < ARRAYSIZE(g_ota_partition_table); ++i) + { + const struct ota_partition_s *part = &g_ota_partition_table[i]; + mtd = esp32_spiflash_alloc_mtdpart(part->offset, part->size); + + ret = ftl_initialize(i, mtd); + if (ret < 0) + { + ferr("ERROR: Failed to initialize the FTL layer: %d\n", ret); + return ret; + } + +#ifdef CONFIG_BCH + snprintf(blockdev, 18, "/dev/mtdblock%d", i); + + ret = bchdev_register(blockdev, part->devpath, false); + if (ret < 0) + { + ferr("ERROR: bchdev_register %s failed: %d\n", part->devpath, ret); + return ret; + } +#endif + } + + return ret; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -62,6 +156,14 @@ int esp32_spiflash_init(void) FAR struct mtd_dev_s *mtd; int ret = ERROR; +#ifdef CONFIG_ESP32_HAVE_OTA_PARTITION + ret = init_ota_partitions(); + if (ret < 0) + { + return ret; + } +#endif + mtd = esp32_spiflash_alloc_mtdpart(ESP32_MTD_OFFSET, ESP32_MTD_SIZE); #if defined (CONFIG_ESP32_SPIFLASH_SMARTFS) diff --git a/tools/esp32/Config.mk b/tools/esp32/Config.mk index d814505ea3..5e7c041933 100644 --- a/tools/esp32/Config.mk +++ b/tools/esp32/Config.mk @@ -52,21 +52,51 @@ else ifeq ($(CONFIG_ESP32_FLASH_FREQ_20M),y) FLASH_FREQ := 20m endif -ESPTOOL_ELF2IMG_OPTS := -fs $(FLASH_SIZE) -fm $(FLASH_MODE) -ff $(FLASH_FREQ) - ifeq ($(CONFIG_ESP32_FLASH_DETECT),y) ESPTOOL_WRITEFLASH_OPTS := -fs detect -fm dio -ff $(FLASH_FREQ) else ESPTOOL_WRITEFLASH_OPTS := -fs $(FLASH_SIZE) -fm dio -ff $(FLASH_FREQ) endif -ifdef ESPTOOL_BINDIR - BL_OFFSET=0x1000 - PT_OFFSET=0x8000 - BOOTLOADER=$(ESPTOOL_BINDIR)/bootloader-esp32.bin - PARTITION_TABLE=$(ESPTOOL_BINDIR)/partition-table-esp32.bin - FLASH_BL=$(BL_OFFSET) $(BOOTLOADER) - FLASH_PT=$(PT_OFFSET) $(PARTITION_TABLE) +# ESPTOOL_BINDIR -- Directory for the Bootloader and Partition Table binary +# files. If not provided, assume the current directory. + +ESPTOOL_BINDIR ?= . + +# Configure the variables according to build environment + +ifeq ($(CONFIG_ESP32_BOOTLOADER_BUILD),y) + BL_OFFSET := 0x1000 + BOOTLOADER := nuttx.bin + FLASH_BL := $(BL_OFFSET) $(BOOTLOADER) + ESPTOOL_BINS := $(FLASH_BL) +else ifeq ($(CONFIG_ESP32_APP_FORMAT_LEGACY),y) + BL_OFFSET := 0x1000 + PT_OFFSET := 0x8000 + APP_OFFSET := 0x10000 + BOOTLOADER := $(ESPTOOL_BINDIR)/bootloader-esp32.bin + PARTITION_TABLE := $(ESPTOOL_BINDIR)/partition-table-esp32.bin + APP_IMAGE := nuttx.bin + FLASH_BL := $(BL_OFFSET) $(BOOTLOADER) + FLASH_PT := $(PT_OFFSET) $(PARTITION_TABLE) + FLASH_APP := $(APP_OFFSET) $(APP_IMAGE) + ESPTOOL_BINS := $(FLASH_BL) $(FLASH_PT) $(FLASH_APP) +else ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y) + BL_OFFSET := 0x1000 + BOOTLOADER := $(ESPTOOL_BINDIR)/mcuboot-esp32.bin + FLASH_BL := $(BL_OFFSET) $(BOOTLOADER) + + ifeq ($(CONFIG_ESP32_ESPTOOL_TARGET_PRIMARY),y) + VERIFIED := --confirm + APP_OFFSET := $(CONFIG_ESP32_OTA_PRIMARY_SLOT_OFFSET) + else ifeq ($(CONFIG_ESP32_ESPTOOL_TARGET_SECONDARY),y) + VERIFIED := + APP_OFFSET := $(CONFIG_ESP32_OTA_SECONDARY_SLOT_OFFSET) + endif + + APP_IMAGE := nuttx_signed.bin + FLASH_APP := $(APP_OFFSET) $(APP_IMAGE) + ESPTOOL_BINS := $(FLASH_BL) $(FLASH_APP) endif ifeq ($(CONFIG_ESP32_QEMU_IMAGE),y) @@ -77,6 +107,23 @@ endif # POSTBUILD -- Perform post build operations +ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y) +define POSTBUILD + $(Q) echo "MKIMAGE: ESP32 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_signed.bin image."; \ + exit 1; \ + fi + imgtool sign --pad --pad-sig $(VERIFIED) --align 4 -v 0 \ + -H $(CONFIG_ESP32_APP_MCUBOOT_HEADER_SIZE) --pad-header \ + -S $(CONFIG_ESP32_OTA_SLOT_SIZE) \ + nuttx.bin nuttx_signed.bin + $(Q) echo "Generated: nuttx_signed.bin (MCUboot compatible)" +endef +else define POSTBUILD $(Q) echo "MKIMAGE: ESP32 binary" $(Q) if ! esptool.py version 1>/dev/null 2>&1; then \ @@ -90,10 +137,12 @@ define POSTBUILD echo "Missing Flash memory size configuration for the ESP32 chip."; \ exit 1; \ fi + $(eval ESPTOOL_ELF2IMG_OPTS := -fs $(FLASH_SIZE) -fm $(FLASH_MODE) -ff $(FLASH_FREQ)) esptool.py -c esp32 elf2image $(ESPTOOL_ELF2IMG_OPTS) -o nuttx.bin nuttx $(Q) echo "Generated: nuttx.bin (ESP32 compatible)" $(Q) $(MK_QEMU_IMG) endef +endif # ESPTOOL_BAUD -- Serial port baud rate used when flashing/reading via esptool.py @@ -102,9 +151,6 @@ ESPTOOL_BAUD ?= 921600 # DOWNLOAD -- Download binary image via esptool.py define DOWNLOAD - - $(eval ESPTOOL_BINS := $(FLASH_BL) $(FLASH_PT) 0x10000 $(1).bin) - $(Q) if [ -z $(ESPTOOL_PORT) ]; then \ echo "DOWNLOAD error: Missing serial port device argument."; \ echo "USAGE: make download ESPTOOL_PORT= [ ESPTOOL_BAUD= ] [ ESPTOOL_BINDIR= ]"; \