diff --git a/Documentation/platforms/risc-v/esp32p4/boards/esp32p4-tab5/index.rst b/Documentation/platforms/risc-v/esp32p4/boards/esp32p4-tab5/index.rst index 60710556b7d2e..a981726117a2f 100644 --- a/Documentation/platforms/risc-v/esp32p4/boards/esp32p4-tab5/index.rst +++ b/Documentation/platforms/risc-v/esp32p4/boards/esp32p4-tab5/index.rst @@ -200,6 +200,20 @@ We can use the interrupt pin to send a signal when the interrupt fires:: The pin is configured as a rising edge interrupt, so after issuing the above command, connect it to 3.3V. +knsh +---- + +This is identical to the ``nsh`` configuration below except that NuttX is +built in protected mode (``CONFIG_BUILD_PROTECTED``): the kernel and the user +applications are linked as two separate images, the kernel runs in machine +mode and user code in user mode, and the PMP enforces the split. + +The console is UART0 rather than the USB Serial/JTAG port, so connect to the +board's UART adapter rather than ``/dev/ttyACM0``. + +The build produces two images, ``nuttx.bin`` and ``nuttx_user.bin``; see +`Building and flashing`_ for the offsets. + lvgl_demo --------- @@ -301,3 +315,19 @@ Then open the console: $ picocom -b 115200 /dev/ttyACM0 nsh> + +Protected build +--------------- + +The ``knsh`` configuration produces a second image for user space, which is +flashed at ``CONFIG_ESPRESSIF_USER_IMAGE_OFFSET`` (``0x110000`` by default): + +.. code-block:: console + + $ ./tools/configure.sh esp32p4-tab5:knsh + $ make -j + $ esptool.py -c esp32p4 -p /dev/ttyACM0 -b 921600 write_flash \ + 0x2000 nuttx.bin 0x110000 nuttx_user.bin + +``make flash ESPTOOL_PORT=`` does both in one step. The console for this +configuration is UART0 at 115200, not the USB Serial/JTAG port. diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index 8ca236430636e..aad6b6ec4f808 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -222,6 +222,7 @@ config ARCH_CHIP_ESP32P4 select ARCH_RV_ISA_M select ARCH_RV_ISA_A select ARCH_RV_ISA_C + select ARCH_RV_HAVE_CLIC select ARCH_VECNOTIRQ select ARCH_HAVE_BOOTLOADER if !ESPRESSIF_SIMPLE_BOOT select ARCH_HAVE_I2CRESET @@ -776,6 +777,15 @@ config ARCH_RV_HAVE_APLIC Controller (APLIC) to provide flexible interrupt control. This device is not backward compatible with PLIC. +config ARCH_RV_HAVE_CLIC + bool + default n + ---help--- + RISC-V defines Core-Level Interrupt Controller (CLIC) to provide + flexible interrupt control. When enabled, CLIC uses interrupt + threshold (MINTTHRESH/SINTTHRESH) CSRs for interrupt control + instead of the standard IE bit in STATUS register. + config ARCH_RV_EXT_AIA bool "Enable RISC-V SxAIA support" default n diff --git a/arch/risc-v/include/irq.h b/arch/risc-v/include/irq.h index 77ef18eca0719..55c399e5f5daa 100644 --- a/arch/risc-v/include/irq.h +++ b/arch/risc-v/include/irq.h @@ -201,7 +201,30 @@ #define REG_INT_CTX_NDX 32 -#ifdef CONFIG_ARCH_RISCV_INTXCPT_EXTREGS +/* On a CLIC part, mcause carries mpp / mpie / mpil / interrupt -- state that + * mret consults -- so it must be saved and restored with the frame, not just + * read for dispatch. Uses the ARCH_RISCV_INTXCPT_EXTREGS extension slot, + * so REG_INT_CTX and everything below it keep their existing offsets. + * + * Only a protected build needs this: a flat build never returns to a lower + * privilege level, so nothing consumes the saved mpp. Keeping the frame at + * its original size there leaves every flat RISC-V target untouched. + */ + +#if defined(CONFIG_ARCH_RV_HAVE_CLIC) && !defined(CONFIG_BUILD_FLAT) +# define REG_MCAUSE_NDX 33 +#endif + +#ifdef REG_MCAUSE_NDX + +/* The frame carries mcause as well; keep it sized to match. */ + +# ifdef CONFIG_ARCH_RISCV_INTXCPT_EXTREGS +# define INT_XCPT_REGS (34 + CONFIG_ARCH_RISCV_INTXCPT_EXTREGS) +# else +# define INT_XCPT_REGS 34 +# endif +#elif defined(CONFIG_ARCH_RISCV_INTXCPT_EXTREGS) # define INT_XCPT_REGS (33 + CONFIG_ARCH_RISCV_INTXCPT_EXTREGS) #else # define INT_XCPT_REGS 33 @@ -347,6 +370,9 @@ # define REG_X30 (INT_REG_SIZE*REG_X30_NDX) # define REG_X31 (INT_REG_SIZE*REG_X31_NDX) # define REG_INT_CTX (INT_REG_SIZE*REG_INT_CTX_NDX) +#ifdef REG_MCAUSE_NDX +# define REG_MCAUSE (INT_REG_SIZE*REG_MCAUSE_NDX) +#endif #ifdef CONFIG_ARCH_FPU # define REG_F0 (INT_REG_SIZE*REG_F0_NDX) @@ -426,6 +452,9 @@ # define REG_X30 REG_X30_NDX # define REG_X31 REG_X31_NDX # define REG_INT_CTX REG_INT_CTX_NDX +#ifdef REG_MCAUSE_NDX +# define REG_MCAUSE REG_MCAUSE_NDX +#endif #ifdef CONFIG_ARCH_FPU # define REG_F0 REG_F0_NDX diff --git a/arch/risc-v/src/common/espressif/CMakeLists.txt b/arch/risc-v/src/common/espressif/CMakeLists.txt index 350a7beede9bc..2a9db6c62e7b9 100644 --- a/arch/risc-v/src/common/espressif/CMakeLists.txt +++ b/arch/risc-v/src/common/espressif/CMakeLists.txt @@ -23,6 +23,14 @@ set(SRCS) # Head/startup file +if(CONFIG_ESPRESSIF_KERNEL_OWNS_PMP) + list(APPEND SRCS esp_region_protect.c) +endif() + +if(CONFIG_BUILD_PROTECTED) + list(APPEND SRCS esp_userspace.c) +endif() + list(APPEND SRCS esp_head.S) # Custom vector table (skip common RISC-V vector table) diff --git a/arch/risc-v/src/common/espressif/Kconfig b/arch/risc-v/src/common/espressif/Kconfig index 5cb80562ed0bf..b74fe0ef46879 100644 --- a/arch/risc-v/src/common/espressif/Kconfig +++ b/arch/risc-v/src/common/espressif/Kconfig @@ -34,6 +34,19 @@ config ESPRESSIF_FLASH_32M endchoice # ESPRESSIF_FLASH +config ESPRESSIF_P4DBG + bool "ESP32-P4 protected-build debug counters" + default n + depends on ARCH_CHIP_ESP32P4 && !BUILD_FLAT + ---help--- + Maintain counters and CLIC state snapshots in the interrupt, idle and + timer paths. Emit progress markers from board bring-up using the + ROM printf rather than syslog. + + The counters should be read with a debugger. + + Debug aid, do not activate in a production build. + config ESPRESSIF_DONT_USE_ROM_LIBC bool "Don't use ROM libc functions" default n @@ -238,6 +251,84 @@ config ESPRESSIF_REGION_PROTECTION ---help--- Configure the MPU to disable access to invalid memory regions. + Must be disabled in a protected build; esp_start.c fails the build + if it is not. It only adds a second, redundant call to + esp_cpu_configure_region_protection() late in esp_start() -- the + regions have already been programmed from bootloader_init() by then + -- and in a protected build the kernel owns the PMP and re-describes + it during userspace initialisation, so the extra call is pointless + at best and racy against that setup at worst. + + This is enforced with a compile-time check rather than + "depends on !BUILD_PROTECTED". This symbol selects ARCH_USE_MPU and + BUILD_PROTECTED depends on ARCH_USE_MPU, so a dependency on the + build type closes a loop that Kconfig resolves by making + BUILD_PROTECTED unsatisfiable -- which silently collapses the whole + "Memory organization" choice for every board in the tree. + +config ESPRESSIF_KERNEL_OWNS_PMP + bool "Kernel owns the PMP configuration" + depends on ARCH_CHIP_ESP32P4 + default n + select ARCH_USE_MPU + ---help--- + Drop the HAL's esp_cpu_configure_region_protection() from the build + and supply a NuttX build of the same code with the PMP lock bit + cleared. The region layout, and the PMA setup the SoC needs in + order to run at all, are unchanged; only the lock bit differs. + + The HAL version sets the lock bit on every entry it writes, and runs + from bootloader_init() before NuttX can intervene. PMP lock bits + are irreversible without the Smepmp extension, which the ESP32-P4 + does not implement, so a protected build has to prevent the locking + rather than undo it. + + A protected build requires this and must set it explicitly in its + defconfig; esp_start.c fails the build if the two disagree. It is + deliberately not "default y if BUILD_PROTECTED": this symbol selects + ARCH_USE_MPU, BUILD_PROTECTED depends on ARCH_USE_MPU, and a default + conditioned on BUILD_PROTECTED closes that loop. Kconfig resolves + the circularity by making BUILD_PROTECTED unsatisfiable, which + silently collapses the whole "Memory organization" choice for every + board in the tree. + + Enabling it on its own is legitimate only for bring-up: unlocked + entries do not constrain machine mode, so a flat build ends up with + less protection than it would otherwise have. + +if BUILD_PROTECTED + +config ESPRESSIF_USER_IMAGE_OFFSET + hex "User image offset" + default 0x110000 + ---help--- + Offset in SPI Flash for flashing the User application firmware + image (nuttx_user.bin). + + Must be aligned to the flash MMU page size (64 KB on ESP32-P4) so + that the cache MMU constraint paddr % 64KB == vaddr % 64KB can be + met, and must be beyond the end of the kernel image. + +endif # BUILD_PROTECTED + +config ESPRESSIF_PMP_EARLY_SNAPSHOT + bool "Dump PMP state during early boot (diagnostic)" + default n + ---help--- + Bring-up diagnostic. Prints the raw PMP configuration via the ROM + printf immediately before and after the bootloader_init() call in + esp_start(), long before the console driver exists. + + Use it to determine whether PMP entries are already locked when + NuttX gains control, or whether the lock bits are set by + bootloader_init() -> bootloader_init_mem() -> + esp_cpu_configure_region_protection(). PMP lock bits cannot be + cleared without the Smepmp extension, so a protected-mode port has + to prevent the locking rather than undo it, and that requires + knowing which code sets it. + + This is a debug aid only; leave it disabled in normal builds. + config ESPRESSIF_RUN_IRAM bool "Run from IRAM" default n diff --git a/arch/risc-v/src/common/espressif/Make.defs b/arch/risc-v/src/common/espressif/Make.defs index 5216b98a9eebe..6f9c3f68c0873 100644 --- a/arch/risc-v/src/common/espressif/Make.defs +++ b/arch/risc-v/src/common/espressif/Make.defs @@ -39,6 +39,14 @@ CHIP_CSRCS += esp_irq.c esp_gpio.c esp_rtc_gpio.c esp_libc_stubs.c CHIP_CSRCS += esp_lowputc.c esp_serial.c CHIP_CSRCS += esp_systemreset.c +ifeq ($(CONFIG_ESPRESSIF_KERNEL_OWNS_PMP),y) + CHIP_CSRCS += esp_region_protect.c +endif + +ifeq ($(CONFIG_BUILD_PROTECTED),y) + CHIP_CSRCS += esp_userspace.c +endif + ifeq ($(CONFIG_ARCH_HAVE_EXTRA_HEAPS),y) CHIP_CSRCS += esp_extraheaps.c ifeq ($(CONFIG_ESPRESSIF_RETENTION_HEAP),y) diff --git a/arch/risc-v/src/common/espressif/esp_allocateheap.c b/arch/risc-v/src/common/espressif/esp_allocateheap.c index 5e562aedf49e7..5adbd1c2293d0 100644 --- a/arch/risc-v/src/common/espressif/esp_allocateheap.c +++ b/arch/risc-v/src/common/espressif/esp_allocateheap.c @@ -31,6 +31,8 @@ #include #include +#include +#include #include #include @@ -103,7 +105,20 @@ void up_allocate_heap(void **heap_start, size_t *heap_size) board_autoled_on(LED_HEAPALLOCATE); -#if defined(CONFIG_MM_KERNEL_HEAP) && \ +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) + /* In a protected build this call describes the USER heap, not the + * kernel's. It runs from the end of the user image's .bss to the top of + * the user RAM region, both of which the user image published in its + * userspace structure. esp_userspace() has already granted user mode + * read/write over that span in the PMP. + * + * Using the kernel's own SRAM here -- as the flat path below does -- would + * hand user mode memory it cannot touch and would overlap the kernel heap. + */ + + *heap_start = (void *)USERSPACE->us_bssend; + *heap_size = USERSPACE->us_heapend - USERSPACE->us_bssend; +#elif defined(CONFIG_MM_KERNEL_HEAP) && \ defined(CONFIG_ESPRESSIF_SPIRAM) && \ defined(CONFIG_ESPRESSIF_SPIRAM_USER_HEAP) DEBUGASSERT(esp_psram_is_initialized()); @@ -182,9 +197,14 @@ void up_allocate_kheap(void **heap_start, size_t *heap_size) #if CONFIG_MM_REGIONS > 1 void riscv_addregion(void) { -#if defined(CONFIG_ESP32P4_SELECTS_REV_LESS_V3) +#if defined(CONFIG_ESP32P4_SELECTS_REV_LESS_V3) && \ + !defined(CONFIG_BUILD_PROTECTED) /* ESP32-P4 rev < v3 has non-contiguous SRAM: sram_low + sram_high. * The primary heap is in sram_low. Add sram_high as a second region. + * + * Not in a protected build: there sram_high is the user RAM region + * (see esp32p4_protected_memory.ld), so adding it to the kernel heap + * would hand the kernel memory that belongs to user space. */ extern uint8_t _sram_high_heap_start[]; @@ -202,8 +222,21 @@ void riscv_addregion(void) } #endif -#if !defined(CONFIG_MM_KERNEL_HEAP) -# if defined(CONFIG_ESPRESSIF_SPIRAM_USER_HEAP) + /* External PSRAM is user memory. kumm_addregion() resolves to + * mm_addregion(USR_HEAP, ...), and USR_HEAP is the single heap in a flat + * build and (*USERSPACE->us_data->us_heap) in the kernel phase of a + * protected one, so the same call reaches user-accessible memory in both. + * + * configure_mpu() has already granted user mode read/write over this + * span. The two must agree: a region added here without the grant is in + * the heap but faults on first touch from user code. + * + * A flat build that keeps a separate kernel heap is deliberately left as + * it was; changing where PSRAM lands there is not part of this change. + */ + +#if defined(CONFIG_ESPRESSIF_SPIRAM_USER_HEAP) && \ + (defined(CONFIG_BUILD_PROTECTED) || !defined(CONFIG_MM_KERNEL_HEAP)) if (esp_psram_is_initialized()) { uintptr_t start = esp_psram_extram_vaddr_start(); @@ -214,7 +247,6 @@ void riscv_addregion(void) kumm_addregion((void *)start, end - start); } } -# endif #endif } #endif diff --git a/arch/risc-v/src/common/espressif/esp_idle.c b/arch/risc-v/src/common/espressif/esp_idle.c index 1d1384ab7d3ae..9bd4fba88bab8 100644 --- a/arch/risc-v/src/common/espressif/esp_idle.c +++ b/arch/risc-v/src/common/espressif/esp_idle.c @@ -37,6 +37,7 @@ #include #include "riscv_internal.h" +#include "esp_p4dbg.h" #include "esp_pm.h" #ifdef CONFIG_ESPRESSIF_HR_TIMER @@ -236,6 +237,66 @@ void up_idle(void) * sleep in a reduced power mode until an interrupt occurs to save power */ +#ifdef P4DBG + /* If this counter advances while g_p4dbg_irq_n does not, the + * core is leaving WFI without taking an interrupt -- which on RISC-V means + * an interrupt is PENDING BUT MASKED, and mintstatus.mil below says why. + */ + + { + uint32_t v; + + g_p4dbg_idle_n++; + __asm__ __volatile__ ("csrr %0, 0x346" : "=r"(v)); + + if (v != g_p4dbg_idle_mint && g_p4dbg_mintlog_n < P4DBG_MINTLOG_N) + { + g_p4dbg_mintlog[g_p4dbg_mintlog_n][0] = g_p4dbg_idle_n; + g_p4dbg_mintlog[g_p4dbg_mintlog_n][1] = v; + g_p4dbg_mintlog_n++; + } + + g_p4dbg_idle_mint = v; + + /* Is the stuck CLIC level the blocker? Write it down to canonical + * level 0 (0x1f, NLBITS = 3) and record whether the CSR took the + * write. If it did and interrupts start flowing again, the level is + * the blocker and any fix must make it unwind; if the write is + * ignored, mintstatus is read-only here and the level is a symptom of + * something else. + */ + + if (g_p4dbg_force_mil0 != 0 && (v >> 24) != 0x1f) + { + uint32_t after; + + __asm__ __volatile__ ("csrw 0x346, %0" :: "r"(0x1f000000u)); + __asm__ __volatile__ ("csrr %0, 0x346" : "=r"(after)); + + g_p4dbg_mil_before = v; + g_p4dbg_mil_after = after; + } + + __asm__ __volatile__ ("csrr %0, mstatus" : "=r"(v)); + g_p4dbg_idle_mstatus = v; + + /* Snapshot the CLIC occasionally rather than every pass: this loop spins + * at millions of iterations a second once delivery has stopped. + */ + + if ((g_p4dbg_idle_n & 0xffff) == 0) + { + g_p4dbg_idle_thresh = *(volatile uint32_t *)(P4DBG_CLIC_BASE + 8); + + for (v = 0; v < P4DBG_CLIC_N; v++) + { + g_p4dbg_idle_clic[v] = + *(volatile uint32_t *)(P4DBG_CLIC_CTRL + v * 4); + } + } + } +#endif + esp_pm_impl_idle_hook(); esp_pm_impl_waiti(); diff --git a/arch/risc-v/src/common/espressif/esp_irq.c b/arch/risc-v/src/common/espressif/esp_irq.c index 991ac89e47250..9ac7b11f5809a 100644 --- a/arch/risc-v/src/common/espressif/esp_irq.c +++ b/arch/risc-v/src/common/espressif/esp_irq.c @@ -41,6 +41,7 @@ #include "esp_gpio.h" #include "esp_irq.h" +#include "esp_p4dbg.h" #include "esp_rtc_gpio.h" #include "esp_attr.h" @@ -251,6 +252,44 @@ IRAM_ATTR static int esp_isr_demultiplexing(int irq, void *context, * Public Functions ****************************************************************************/ +/**************************************************************************** + * Temporary instrumentation. + * + * After the SCHED_RR pthreads exit, a usleep() never wakes: the + * nxsig_timeout watchdog sits on g_wdactivelist unserviced while the idle + * task runs. These counters separate "the tick stopped" from "the tick + * runs but the watchdog arithmetic is wrong", and record mintstatus.mil, + * which can stick at a level that masks every interrupt. + * + * Read them with an observe-only halt, twice a few seconds apart: whichever + * counters advance is the answer. + ****************************************************************************/ + +#ifdef P4DBG +volatile uint32_t g_p4dbg_irq_n; /* interrupts dispatched */ +volatile uint32_t g_p4dbg_exc_n; /* exceptions dispatched */ +volatile uint32_t g_p4dbg_last_mcause; /* mcause of the last interrupt */ +volatile uint32_t g_p4dbg_tick_n; /* systimer_irq_handler entries */ +volatile uint32_t g_p4dbg_idle_n; /* up_idle() passes */ +volatile uint32_t g_p4dbg_idle_mint; /* mintstatus sampled in up_idle */ +volatile uint32_t g_p4dbg_idle_mstatus; /* mstatus sampled in up_idle */ +volatile uint32_t g_p4dbg_mil_first_tick; +volatile uint32_t g_p4dbg_mil_first_mcause; +volatile uint32_t g_p4dbg_mil_first_epc; +volatile uint32_t g_p4dbg_mil_ticks; +volatile uint32_t g_p4dbg_mil_last_zero_tick; +volatile uint32_t g_p4dbg_tick_thresh; +volatile uint32_t g_p4dbg_tick_mint; +volatile uint32_t g_p4dbg_tick_clic[P4DBG_CLIC_N]; +volatile uint32_t g_p4dbg_idle_thresh; +volatile uint32_t g_p4dbg_idle_clic[P4DBG_CLIC_N]; +volatile uint32_t g_p4dbg_mintlog[P4DBG_MINTLOG_N][2]; +volatile uint32_t g_p4dbg_mintlog_n; +volatile uint32_t g_p4dbg_force_mil0; /* 0: answered, see 36.21 */ +volatile uint32_t g_p4dbg_mil_before; +volatile uint32_t g_p4dbg_mil_after; +#endif + /**************************************************************************** * Name: up_irq_to_ndx * @@ -564,6 +603,18 @@ IRAM_ATTR void *riscv_dispatch_irq(uintreg_t mcause, uintreg_t *regs) bool is_edge = false; int cpu = this_cpu(); +#ifdef P4DBG + if (is_irq) + { + g_p4dbg_irq_n++; + g_p4dbg_last_mcause = (uint32_t)mcause; + } + else + { + g_p4dbg_exc_n++; + } +#endif + if (is_irq) { uint8_t cpuint = (mcause & VECTORS_MCAUSE_REASON_MASK) - diff --git a/arch/risc-v/src/common/espressif/esp_p4dbg.h b/arch/risc-v/src/common/espressif/esp_p4dbg.h new file mode 100644 index 0000000000000..a781de2d8db6e --- /dev/null +++ b/arch/risc-v/src/common/espressif/esp_p4dbg.h @@ -0,0 +1,99 @@ +/**************************************************************************** + * arch/risc-v/src/common/espressif/esp_p4dbg.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Debug counters for the protected build, CONFIG_ESPRESSIF_P4DBG. + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_P4DBG_H +#define __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_P4DBG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifdef CONFIG_ESPRESSIF_P4DBG +# define P4DBG 1 + +extern volatile uint32_t g_p4dbg_irq_n; +extern volatile uint32_t g_p4dbg_exc_n; +extern volatile uint32_t g_p4dbg_last_mcause; +extern volatile uint32_t g_p4dbg_tick_n; +extern volatile uint32_t g_p4dbg_idle_n; +extern volatile uint32_t g_p4dbg_idle_mint; +extern volatile uint32_t g_p4dbg_idle_mstatus; + +/* Onset detector for the stuck mintstatus.mil. mcause.mpil sampled at + * tick entry is the CLIC level of the context the tick INTERRUPTED, which + * for task context must be 0. The first tick that sees it non-zero is + * where the level started sticking. + */ + +extern volatile uint32_t g_p4dbg_mil_first_tick; +extern volatile uint32_t g_p4dbg_mil_first_mcause; +extern volatile uint32_t g_p4dbg_mil_first_epc; +extern volatile uint32_t g_p4dbg_mil_ticks; +extern volatile uint32_t g_p4dbg_mil_last_zero_tick; + +/* The pre-rev3 ESP32-P4 gates interrupt delivery on a MEMORY-MAPPED CLIC + * threshold (INTTHRESH_STANDARD = 0), not on a CSR, and the whole CLIC + * block reads back as zero over the JTAG debug bus -- so it has to be + * sampled by the target itself. Snapshot it from the tick handler (last + * healthy state) and from up_idle (hung state) and diff the two. + */ + +#define P4DBG_CLIC_BASE 0x20800000 /* CLIC_INT_CONFIG / INFO / THRESH */ +#define P4DBG_CLIC_CTRL 0x20801000 /* per-source IP/IE/ATTR/CTL, 1 word */ +#define P4DBG_CLIC_N 48 + +extern volatile uint32_t g_p4dbg_tick_thresh; +extern volatile uint32_t g_p4dbg_tick_mint; +extern volatile uint32_t g_p4dbg_tick_clic[P4DBG_CLIC_N]; +extern volatile uint32_t g_p4dbg_idle_thresh; +extern volatile uint32_t g_p4dbg_idle_clic[P4DBG_CLIC_N]; + +/* mintstatus sampled from up_idle -- TASK context, not a handler -- every + * time it changes. g_p4dbg_tick_mint is sampled inside the tick handler, + * where mil is legitimately raised, so it cannot answer "was mil ever 0 in + * task context". This can. + */ + +#define P4DBG_MINTLOG_N 12 + +extern volatile uint32_t g_p4dbg_mintlog[P4DBG_MINTLOG_N][2]; /* n, mint */ +extern volatile uint32_t g_p4dbg_mintlog_n; + +/* DIAGNOSTIC, not a fix: try writing mintstatus.mil down to canonical + * level 0 from the idle loop and see (a) whether the CSR is writable and + * (b) whether interrupt delivery resumes. Answers "is the stuck level the + * blocker" directly, instead of inferring it from another failed fix. + */ + +extern volatile uint32_t g_p4dbg_force_mil0; /* 1 = attempt the write */ +extern volatile uint32_t g_p4dbg_mil_before; +extern volatile uint32_t g_p4dbg_mil_after; +#endif + +#endif /* __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_P4DBG_H */ diff --git a/arch/risc-v/src/common/espressif/esp_region_protect.c b/arch/risc-v/src/common/espressif/esp_region_protect.c new file mode 100644 index 0000000000000..011bbf3f8cf0a --- /dev/null +++ b/arch/risc-v/src/common/espressif/esp_region_protect.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * arch/risc-v/src/common/espressif/esp_region_protect.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Unlocked build of the HAL's esp_cpu_configure_region_protection(). + * + * The HAL implementation programs every PMP entry with the lock bit set. It + * runs very early, from esp_start() -> bootloader_init() -> + * bootloader_init_mem(), and that path is not gated by + * CONFIG_ESPRESSIF_REGION_PROTECTION -- that option guards only a second, + * redundant call later in esp_start(). + * + * PMP lock bits cannot be cleared without the Smepmp extension, which the + * ESP32-P4 does not implement (reading mseccfg raises an illegal + * instruction). Once the HAL has run, 14 of the 16 entries are dead for the + * remainder of the boot, and one of the survivors grants U-mode read/write + * across the whole kernel data region. A protected build therefore has to + * stop the entries being locked in the first place. + * + * The same function also programs the 16 PMA entries that mark the invalid + * address ranges and make external flash/RAM, ROM and L2MEM cacheable. That + * work is required for the SoC to run at all: replacing this function with + * an empty stub boot-loops inside bootloader_init(). + * + * So rather than reimplement any of it, the HAL translation unit is dropped + * from the build (see hal_.mk / hal_.cmake) and its source is + * included below with PMP_L defined to zero. Including "riscv/csr.h" first + * means its include guard is already set when the HAL source includes it + * again, so the redefinition survives. Everything else -- the PMA setup, + * the chip-revision variants, the PSRAM handling -- stays byte for byte + * identical to the vendored source and tracks it when the HAL is updated. + * + * The result is the HAL's own region layout with every PMP entry left + * unlocked, so the kernel can re-describe them for a kernel/user split. + * + * NOTE: unlocked PMP entries do not constrain machine mode, so this reduces + * the protection a flat build gets. It is meant to be paired with a + * protected build, whose userspace initialisation re-establishes the + * boundaries. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* Pulled in first so that its include guard is already set when the HAL + * source below includes it again, keeping the redefinition that follows. + */ + +#include "riscv/csr.h" + +#undef PMP_L +#define PMP_L 0 + +/* The HAL implementation itself, compiled with the lock bit cleared. The + * chip directory is spelled out rather than derived from + * CONFIG_ESPRESSIF_CHIP_SERIES because an #include directive cannot + * concatenate string literals; CONFIG_ESPRESSIF_KERNEL_OWNS_PMP depends on + * ARCH_CHIP_ESP32P4, so this file is only ever built for that chip. + */ + +#include "../../chip/esp-hal-3rdparty/components/esp_hw_support/port/esp32p4/cpu_region_protect.c" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The whole point of this file is that the HAL body above was compiled with + * the lock bit cleared. If the HAL ever reorganises its includes so that + * "riscv/csr.h" is no longer guarded by the time it is reached, the + * redefinition would be silently undone and every PMP entry would be locked + * again -- which would not fail the build, and would not show up until the + * kernel tried to reprogram an entry at run time. Fail loudly instead. + */ + +#if PMP_L != 0 +# error "PMP lock bit was not neutralised" +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* esp_cpu_configure_region_protection() is defined by the HAL source + * included above, and is the only symbol this translation unit exports. + */ diff --git a/arch/risc-v/src/common/espressif/esp_start.c b/arch/risc-v/src/common/espressif/esp_start.c index debc53e5eb2c9..0324a5ade3b1d 100644 --- a/arch/risc-v/src/common/espressif/esp_start.c +++ b/arch/risc-v/src/common/espressif/esp_start.c @@ -33,6 +33,9 @@ #include #include "riscv_internal.h" +#ifdef CONFIG_ESPRESSIF_PMP_EARLY_SNAPSHOT +# include +#endif #include "esp_irq.h" #include "esp_libc_stubs.h" @@ -65,6 +68,9 @@ #include "soc/rtc.h" #include "bootloader_init.h" +#ifdef CONFIG_BUILD_PROTECTED +# include "esp_userspace.h" +#endif #include "bootloader_sha.h" #ifdef CONFIG_ESPRESSIF_SIMPLE_BOOT @@ -89,6 +95,33 @@ * Pre-processor Definitions ****************************************************************************/ +/* A protected build must own the PMP outright. Without + * CONFIG_ESPRESSIF_KERNEL_OWNS_PMP the HAL programs every entry with the + * lock bit set, from bootloader_init() and before any NuttX code can + * intervene; the ESP32-P4 has no Smepmp, so those entries can never be + * re-described. The build would succeed, boot, run NSH in user mode and + * enforce nothing -- which is worse than a flat build, because it looks + * protected. Refuse to build it instead. + */ + +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_ARCH_CHIP_ESP32P4) && \ + !defined(CONFIG_ESPRESSIF_KERNEL_OWNS_PMP) +# error "BUILD_PROTECTED needs ESPRESSIF_KERNEL_OWNS_PMP; the HAL locks every PMP entry" +#endif + +/* Region protection would re-run esp_cpu_configure_region_protection() + * late in esp_start(), after bootloader_init() has already programmed the + * regions, racing the userspace PMP setup. Enforced here rather than with + * a Kconfig dependency: both symbols select ARCH_USE_MPU, which + * BUILD_PROTECTED depends on, so a Kconfig dependency on the build type + * would be circular. + */ + +#if defined(CONFIG_BUILD_PROTECTED) && \ + defined(CONFIG_ESPRESSIF_REGION_PROTECTION) +# error "BUILD_PROTECTED needs ESPRESSIF_REGION_PROTECTION disabled" +#endif + #ifdef CONFIG_DEBUG_FEATURES # define showprogress(c) esp_rom_printf(c) #else @@ -474,6 +507,89 @@ void sys_startup_fn(void) SYS_STARTUP_FN(); } +#ifdef CONFIG_ESPRESSIF_PMP_EARLY_SNAPSHOT + +/**************************************************************************** + * Name: esp_pmp_early_snapshot + * + * Description: + * Bring-up diagnostic. Dumps the raw PMP configuration at a given point + * in early startup, before the console is available, using the ROM printf. + * + * Its purpose is to establish whether PMP entries are already locked when + * NuttX gains control, or whether the lock bits are set later by + * bootloader_init() -> bootloader_init_mem() -> + * esp_cpu_configure_region_protection(). Lock bits are irreversible + * without Smepmp, so this distinction decides whether a protected build is + * possible on a given part. + * + * Input Parameters: + * tag - Short label identifying the sample point. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void esp_pmp_early_snapshot(const char *tag) +{ + uintptr_t cfg[4]; + uintptr_t addr[16]; + int locked = 0; + int active = 0; + int i; + + cfg[0] = READ_CSR(pmpcfg0); + cfg[1] = READ_CSR(pmpcfg1); + cfg[2] = READ_CSR(pmpcfg2); + cfg[3] = READ_CSR(pmpcfg3); + + addr[0] = READ_CSR(pmpaddr0); + addr[1] = READ_CSR(pmpaddr1); + addr[2] = READ_CSR(pmpaddr2); + addr[3] = READ_CSR(pmpaddr3); + addr[4] = READ_CSR(pmpaddr4); + addr[5] = READ_CSR(pmpaddr5); + addr[6] = READ_CSR(pmpaddr6); + addr[7] = READ_CSR(pmpaddr7); + addr[8] = READ_CSR(pmpaddr8); + addr[9] = READ_CSR(pmpaddr9); + addr[10] = READ_CSR(pmpaddr10); + addr[11] = READ_CSR(pmpaddr11); + addr[12] = READ_CSR(pmpaddr12); + addr[13] = READ_CSR(pmpaddr13); + addr[14] = READ_CSR(pmpaddr14); + addr[15] = READ_CSR(pmpaddr15); + + for (i = 0; i < 16; i++) + { + uint8_t b = (uint8_t)((cfg[i / 4] >> ((i % 4) * 8)) & 0xff); + + if ((b & PMPCFG_L) != 0) + { + locked++; + } + + if ((b & PMPCFG_A_MASK) != PMPCFG_A_OFF) + { + active++; + } + } + + ets_printf("PMP[%s]: cfg %08x %08x %08x %08x active=%d locked=%d\n", + tag, (unsigned int)cfg[0], (unsigned int)cfg[1], + (unsigned int)cfg[2], (unsigned int)cfg[3], active, locked); + + for (i = 0; i < 16; i += 4) + { + ets_printf("PMP[%s]: addr%-2d %08x %08x %08x %08x\n", tag, i, + (unsigned int)addr[i], (unsigned int)addr[i + 1], + (unsigned int)addr[i + 2], (unsigned int)addr[i + 3]); + } +} + +#endif /* CONFIG_ESPRESSIF_PMP_EARLY_SNAPSHOT */ + /**************************************************************************** * Name: __esp_start ****************************************************************************/ @@ -499,6 +615,10 @@ void __esp_start(void) bootloader_clear_bss_section(); +#ifdef CONFIG_ESPRESSIF_PMP_EARLY_SNAPSHOT + esp_pmp_early_snapshot("pre-bl"); +#endif + #ifdef CONFIG_ESPRESSIF_SIMPLE_BOOT if (bootloader_init() != 0) { @@ -507,6 +627,10 @@ void __esp_start(void) } #endif +#ifdef CONFIG_ESPRESSIF_PMP_EARLY_SNAPSHOT + esp_pmp_early_snapshot("post-bl"); +#endif + /* Initialize the per CPU areas */ #ifdef CONFIG_RISCV_PERCPU_SCRATCH @@ -659,6 +783,16 @@ void __esp_start(void) showprogress("D"); +#ifdef CONFIG_BUILD_PROTECTED + /* Initialise the user-space image and put the PMP boundaries in place + * before any user code becomes reachable. + */ + + esp_userspace(); + + showprogress("E"); +#endif + nx_start(); UNUSED(ret); diff --git a/arch/risc-v/src/common/espressif/esp_timerisr.c b/arch/risc-v/src/common/espressif/esp_timerisr.c index b0b0945cc0779..6a51e1b5b9ccd 100644 --- a/arch/risc-v/src/common/espressif/esp_timerisr.c +++ b/arch/risc-v/src/common/espressif/esp_timerisr.c @@ -34,6 +34,7 @@ #include #include "chip.h" +#include "esp_p4dbg.h" #include "esp_irq.h" #include "hal/systimer_hal.h" @@ -88,6 +89,52 @@ static systimer_hal_context_t systimer_hal; static int systimer_irq_handler(int irq, void *context, void *arg) { +#ifdef P4DBG + { + uint32_t c; + + g_p4dbg_tick_n++; + + /* mcause.mpil here is the CLIC level of the context this tick + * interrupted. Task context must be level 0; anything else means the + * level was left raised by an earlier return. + */ + + __asm__ __volatile__ ("csrr %0, mcause" : "=r"(c)); + + if ((c & 0x00ff0000) != 0) + { + g_p4dbg_mil_ticks++; + + if (g_p4dbg_mil_first_tick == 0) + { + g_p4dbg_mil_first_tick = g_p4dbg_tick_n; + g_p4dbg_mil_first_mcause = c; + g_p4dbg_mil_first_epc = + (uint32_t)((uintreg_t *)context)[REG_EPC]; + } + } + else + { + g_p4dbg_mil_last_zero_tick = g_p4dbg_tick_n; + } + + /* Last healthy CLIC snapshot: this handler running IS the proof that + * delivery still works at this instant. + */ + + __asm__ __volatile__ ("csrr %0, 0x346" : "=r"(c)); + g_p4dbg_tick_mint = c; + g_p4dbg_tick_thresh = *(volatile uint32_t *)(P4DBG_CLIC_BASE + 8); + + for (c = 0; c < P4DBG_CLIC_N; c++) + { + g_p4dbg_tick_clic[c] = + *(volatile uint32_t *)(P4DBG_CLIC_CTRL + c * 4); + } + } +#endif + systimer_ll_clear_alarm_int(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0); diff --git a/arch/risc-v/src/common/espressif/esp_userspace.c b/arch/risc-v/src/common/espressif/esp_userspace.c new file mode 100644 index 0000000000000..563ae4d829d83 --- /dev/null +++ b/arch/risc-v/src/common/espressif/esp_userspace.c @@ -0,0 +1,458 @@ +/**************************************************************************** + * arch/risc-v/src/common/espressif/esp_userspace.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include + +#include "riscv_internal.h" + +#include "esp_userspace.h" + +#include "esp_rom_sys.h" +#include "soc/soc.h" +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" +#include "hal/mmu_hal.h" +#include "hal/mmu_types.h" +#include "spi_flash_mmap.h" +#include "bootloader_flash_priv.h" + +#if defined(CONFIG_ESPRESSIF_SPIRAM) && \ + defined(CONFIG_ESPRESSIF_SPIRAM_USER_HEAP) +# include "esp_psram.h" +# include "esp_private/esp_psram_extram.h" +#endif + +#ifdef CONFIG_BUILD_PROTECTED + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define USER_IMAGE_OFFSET CONFIG_ESPRESSIF_USER_IMAGE_OFFSET + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Emitted at the start of the user image by user-space.ld. It tells the + * kernel where the user image expects its flash-mapped regions to live, so + * that the flash MMU can be programmed before any user code is reachable. + */ + +struct user_image_load_header_s +{ + uintptr_t drom_vma; /* Destination address (VMA) for DROM region */ + uintptr_t drom_lma; /* Flash offset (LMA) for start of DROM region */ + uintptr_t drom_size; /* Size of DROM region */ + uintptr_t irom_vma; /* Destination address (VMA) for IROM region */ + uintptr_t irom_lma; /* Flash offset (LMA) for start of IROM region */ + uintptr_t irom_size; /* Size of IROM region */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct user_image_load_header_s g_header; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: load_header + * + * Description: + * Read the user image load header out of flash. + * + * Unlike the ESP32-C3 protected port, which temporarily mapped a scratch + * flash window to reach the header, this reads it directly. The SPI flash + * driver is already initialised by the time esp_userspace() runs, and + * esp_start() uses the same call to parse the kernel image header, so no + * scratch mapping is needed. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void load_header(void) +{ + int ret = bootloader_flash_read(USER_IMAGE_OFFSET, &g_header, + sizeof(g_header), true); + + if (ret != 0) + { + esp_rom_printf("ERROR: user image header read failed: rc=%d at 0x%x\n", + ret, (unsigned int)USER_IMAGE_OFFSET); + PANIC(); + } +} + +/**************************************************************************** + * Name: configure_mmu + * + * Description: + * Map the user image's flash-resident code and read-only data into the + * virtual address space. + * + * This is deliberately additive. esp_start()'s map_rom_segments() calls + * mmu_hal_unmap_all() before installing the kernel's own mappings; doing + * that here would unmap the kernel while it is executing. Only the two + * user regions are added. + * + * The cache is disabled across the update, so this function -- and + * everything it calls -- must be resident in IRAM. The linker script + * places this object there by name. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void noinline_function configure_mmu(void) +{ + uint32_t actual_mapped_len = 0; + uint32_t drom_lma = USER_IMAGE_OFFSET + g_header.drom_lma; + uint32_t irom_lma = USER_IMAGE_OFFSET + g_header.irom_lma; + uint32_t drom_lma_aligned = drom_lma & MMU_FLASH_MASK; + uint32_t drom_vma_aligned = g_header.drom_vma & MMU_FLASH_MASK; + uint32_t irom_lma_aligned = irom_lma & MMU_FLASH_MASK; + uint32_t irom_vma_aligned = g_header.irom_vma & MMU_FLASH_MASK; + cache_bus_mask_t bus_mask; + + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); + + mmu_hal_map_region(0, MMU_TARGET_FLASH0, + drom_vma_aligned, drom_lma_aligned, + g_header.drom_size, &actual_mapped_len); + + mmu_hal_map_region(0, MMU_TARGET_FLASH0, + irom_vma_aligned, irom_lma_aligned, + g_header.irom_size, &actual_mapped_len); + + bus_mask = cache_ll_l1_get_bus(0, drom_vma_aligned, g_header.drom_size); + cache_ll_l1_enable_bus(0, bus_mask); + bus_mask = cache_ll_l1_get_bus(0, irom_vma_aligned, g_header.irom_size); + cache_ll_l1_enable_bus(0, bus_mask); + +#if CONFIG_ESPRESSIF_NUM_CPUS > 1 + bus_mask = cache_ll_l1_get_bus(1, drom_vma_aligned, g_header.drom_size); + cache_ll_l1_enable_bus(1, bus_mask); + bus_mask = cache_ll_l1_get_bus(1, irom_vma_aligned, g_header.irom_size); + cache_ll_l1_enable_bus(1, bus_mask); +#endif + +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + cache_ll_invalidate_addr(CACHE_LL_LEVEL_ALL, CACHE_TYPE_ALL, + CACHE_LL_ID_ALL, irom_vma_aligned, + actual_mapped_len); +#endif + + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); +} + +/**************************************************************************** + * Name: initialize_data + * + * Description: + * Copy the user image's initialised data from flash into user RAM. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void initialize_data(void) +{ + size_t length = USERSPACE->us_dataend - USERSPACE->us_datastart; + int ret; + + uintptr_t src = USER_IMAGE_OFFSET + USERSPACE->us_datasource; + + ret = bootloader_flash_read(src, (void *)USERSPACE->us_datastart, + length, true); + if (ret != 0) + { + /* The usual cause is alignment: this read wants its flash offset and + * length aligned, and .data's load address is whatever the end of + * .rodata left it at. user-space.ld pads both to 16 for that reason. + */ + + esp_rom_printf("ERROR: user .data read failed: rc=%d src=0x%x " + "dst=0x%x len=0x%x\n", + ret, (unsigned int)src, + (unsigned int)USERSPACE->us_datastart, + (unsigned int)length); + PANIC(); + } +} + +/**************************************************************************** + * Name: configure_mpu + * + * Description: + * Establish the PMP regions that separate kernel from user. + * + * Every entry is reset first. By the time this runs the HAL has already + * programmed eleven regions from bootloader_init(), several of which would + * grant user mode access to kernel memory -- entry 5 in particular covers + * the whole of SRAM as read/write. They are only reprogrammable because + * CONFIG_ESPRESSIF_KERNEL_OWNS_PMP built them without the lock bit. + * + * Only user-accessible regions are then described. Per the RISC-V + * privileged specification an access matching no PMP entry is permitted in + * machine mode and denied in user mode, so the kernel needs no entries of + * its own and everything not listed below is automatically inaccessible to + * user code. + * + * Regions are expressed as TOR pairs because the linker-defined bounds are + * not naturally aligned powers of two. Every boundary must respect the + * 128-byte PMP granularity of this SoC; user-space.ld is responsible for + * that alignment. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void configure_mpu(void) +{ + const uintptr_t r = PMPCFG_R; + const uintptr_t rw = PMPCFG_R | PMPCFG_W; + const uintptr_t rx = PMPCFG_R | PMPCFG_X; + + /* Drop everything the HAL left behind. Machine mode is unaffected: an + * unlocked entry never constrains it, and an address matching no entry is + * permitted in machine mode. + */ + + riscv_config_pmp_region(0, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(1, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(2, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(3, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(4, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(5, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(6, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(7, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(8, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(9, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(10, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(11, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(12, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(13, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(14, PMPCFG_A_OFF, 0, 0); + riscv_config_pmp_region(15, PMPCFG_A_OFF, 0, 0); + + /* TOR entries take their lower bound from the preceding entry's address, + * so each pair is an unmatched gap followed by the region proper. + * + * 0/1 UIROM 0x40200000 - 0x40300000 user code, execute in place + * 2/3 UDROM 0x40300080 - 0x40380000 user rodata (0x80 metadata gap) + * 4/5 PSRAM runtime bounds external RAM, in the user heap + * 6/7 ROM SOC_IROM_MASK_* ROM routines the user image calls + * 8/9 UDRAM 0x4ff40000 - 0x4ff80000 user data, bss and heap + * + * The whole table must be in ascending address order, not merely each pair + * internally. PMP resolves an access to the LOWEST-numbered entry that + * matches it, so a low-numbered gap silently shadows any grant above it. + * Appending PSRAM after UDRAM does not work for exactly that reason: the + * gap at entry 4 spans UDROM_END up to SOC_IROM_MASK_LOW (0x40380000 to + * 0x4fc00000) and swallows 0x48000000, denying user access however the + * higher entries are programmed. It presents as a load/store access fault + * on the first user-mode touch of PSRAM, with the heap none the wiser. + */ + + /* User code, executed in place from flash */ + + riscv_config_pmp_region(0, PMPCFG_A_TOR, UIROM_START, 0); + riscv_config_pmp_region(1, PMPCFG_A_TOR | rx, UIROM_END, 0); + + /* User read-only data, mapped from flash */ + + riscv_config_pmp_region(2, PMPCFG_A_TOR, UDROM_START, 0); + riscv_config_pmp_region(3, PMPCFG_A_TOR | r, UDROM_END, 0); + +#if defined(CONFIG_ESPRESSIF_SPIRAM) && \ + defined(CONFIG_ESPRESSIF_SPIRAM_USER_HEAP) + /* External PSRAM. riscv_addregion() adds this same span to the user heap; + * without the grant here it would be in the heap but would fault on the + * first touch from user code. Read/write only: it is a data heap, and + * user code executes in place from flash. + * + * If PSRAM did not initialise, entries 4 and 5 are left off by the reset + * above and entry 6 simply takes its base from a zero pmpaddr5, which + * widens the following gap harmlessly. + */ + + if (esp_psram_is_initialized()) + { + uintptr_t pstart = esp_psram_extram_vaddr_start(); + uintptr_t pend = esp_psram_extram_vaddr_end(); + + /* Both bounds come from the HAL's mapping of a 64 KB-aligned window, + * so they already satisfy the 128-byte PMP granularity. Assert it + * rather than assume it: a misaligned bound silently rounds and would + * grant a different region than the heap is handed. + */ + + DEBUGASSERT((pstart & 0x7f) == 0 && (pend & 0x7f) == 0); + + if (pend > pstart) + { + riscv_config_pmp_region(4, PMPCFG_A_TOR, pstart, 0); + riscv_config_pmp_region(5, PMPCFG_A_TOR | rw, pend, 0); + } + } +#endif + + /* Internal ROM. CONFIG_LIBC_ARCH_* is selected for this chip, so libc + * omits its generic memcpy(), strcmp() and friends and the user image is + * linked against the ROM implementations instead (see the ROM linker + * scripts in common/kernel/Makefile). Without this grant the first such + * call from user mode takes an instruction access fault. + */ + + riscv_config_pmp_region(6, PMPCFG_A_TOR, SOC_IROM_MASK_LOW, 0); + riscv_config_pmp_region(7, PMPCFG_A_TOR | rx, SOC_IROM_MASK_HIGH, 0); + + /* User data, bss and heap in internal SRAM */ + + riscv_config_pmp_region(8, PMPCFG_A_TOR, UDRAM_START, 0); + riscv_config_pmp_region(9, PMPCFG_A_TOR | rw, UDRAM_END, 0); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_userspace + * + * Description: + * See esp_userspace.h. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_userspace(void) +{ + uint8_t *dest; + uint8_t *end; + + /* Where does the user image expect to be mapped? */ + + load_header(); + + /* Make its code and rodata reachable before anything touches them. The + * header values are echoed first: if the metadata block and + * struct user_image_load_header_s ever disagree, this is where it shows. + */ + + esp_rom_printf("userspace: drom vma=0x%x lma=0x%x size=0x%x\n", + (unsigned int)g_header.drom_vma, + (unsigned int)g_header.drom_lma, + (unsigned int)g_header.drom_size); + esp_rom_printf("userspace: irom vma=0x%x lma=0x%x size=0x%x\n", + (unsigned int)g_header.irom_vma, + (unsigned int)g_header.irom_lma, + (unsigned int)g_header.irom_size); + + configure_mmu(); + + /* Clear all of userspace .bss */ + + DEBUGASSERT(USERSPACE->us_bssstart != 0 && USERSPACE->us_bssend != 0 && + USERSPACE->us_bssstart <= USERSPACE->us_bssend); + + dest = (uint8_t *)USERSPACE->us_bssstart; + end = (uint8_t *)USERSPACE->us_bssend; + + while (dest != end) + { + *dest++ = 0; + } + + /* Initialize all of userspace .data */ + + DEBUGASSERT(USERSPACE->us_datasource != 0 && + USERSPACE->us_datastart != 0 && USERSPACE->us_dataend != 0 && + USERSPACE->us_datastart <= USERSPACE->us_dataend); + + initialize_data(); + + /* Finally, take ownership of the PMP and fence the two worlds apart */ + + configure_mpu(); + + /* Not showprogress(): that expands to nothing unless + * CONFIG_DEBUG_FEATURES is set, which would make a hang here + * indistinguishable from one inside nx_start(). + */ + + /* Echo what the kernel will actually act on. us_entrypoint should be an + * address inside UIROM and the heap bounds should lie inside UDRAM; if the + * user image's .userspace structure were mislinked or not loaded, this is + * where it becomes visible rather than showing up later as a silent + * failure to start the initial task. + */ + + esp_rom_printf("userspace: entry=0x%x heap=0x%x..0x%x bss=0x%x..0x%x\n", + (unsigned int)USERSPACE->us_entrypoint, + (unsigned int)USERSPACE->us_bssend, + (unsigned int)USERSPACE->us_heapend, + (unsigned int)USERSPACE->us_bssstart, + (unsigned int)USERSPACE->us_bssend); + esp_rom_printf("userspace: ready\n"); +} + +#endif /* CONFIG_BUILD_PROTECTED */ diff --git a/arch/risc-v/src/common/espressif/esp_userspace.h b/arch/risc-v/src/common/espressif/esp_userspace.h new file mode 100644 index 0000000000000..46b47fd6c68fc --- /dev/null +++ b/arch/risc-v/src/common/espressif/esp_userspace.h @@ -0,0 +1,65 @@ +/**************************************************************************** + * arch/risc-v/src/common/espressif/esp_userspace.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_USERSPACE_H +#define __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_USERSPACE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_BUILD_PROTECTED + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Name: esp_userspace + * + * Description: + * For the case of the separate user/kernel space build, perform whatever + * platform specific initialization of the user memory is required. + * Normally this just means initializing the userspace .data and .bss + * segments, but on this SoC it also means mapping the user image out of + * external flash and establishing the PMP regions that separate the two + * worlds. + * + * Must be called from esp_start() immediately before nx_start(). + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_userspace(void); + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_BUILD_PROTECTED */ +#endif /* __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_USERSPACE_H */ diff --git a/arch/risc-v/src/common/riscv_exception_common.S b/arch/risc-v/src/common/riscv_exception_common.S index 11570b3d69fae..e318b4489c38e 100644 --- a/arch/risc-v/src/common/riscv_exception_common.S +++ b/arch/risc-v/src/common/riscv_exception_common.S @@ -159,6 +159,12 @@ exception_common: REGSTORE s1, REG_EPC(sp) REGSTORE s3, REG_SP(sp) +#ifdef REG_MCAUSE + /* s2 still holds the RAW mcause here, before it is masked for dispatch. */ + + REGSTORE s2, REG_MCAUSE(sp) +#endif + #ifdef CONFIG_LIB_SYSCALL csrr tp, CSR_SCRATCH /* Load kernel TP */ REGLOAD tp, RISCV_PERCPU_TCB(tp) @@ -204,6 +210,7 @@ return_from_syscall: /* Clean up after system call */ REGSTORE a0, REG_A0(sp) /* Syscall return value to user context */ + mv a0, sp /* Return to same context */ tail return_from_exception @@ -279,6 +286,52 @@ return_from_exception: REGLOAD s0, REG_EPC(sp) /* restore sepc */ csrw CSR_EPC, s0 +#ifdef REG_MCAUSE + /* Restore mcause with the frame. On a CLIC part mcause holds mpp, mpie and + * mpil; mret restores privilege from mpp and mintstatus.mil from mpil. + * Leaving it as whatever the last trap wrote makes mret restore the wrong + * privilege or the wrong interrupt level -- mil stuck at 63 + * masks every interrupt and deadlocks the system. The frame's + * value is by construction what the hardware latched for this trap, so it is + * correct at any nesting depth. + * + * Restored BEFORE mstatus, deliberately. mstatus.MPP/MPIE are aliased into + * mcause[29:28]/[27], so whichever is written last wins for those fields. + * Synthesised frames -- up_initial_state(), riscv_jump_to_user() -- leave + * this slot zero, and writing that after mstatus dropped kernel threads to + * U-mode and faulted on the first instruction fetch of kernel text. Writing + * mcause first lets mstatus stay authoritative for privilege while mcause + * still supplies mpil, which lives nowhere else. + */ + + REGLOAD s1, REG_MCAUSE(sp) + + /* On a return to U-MODE, clear mcause.interrupt (31) and mcause.minhv (30) + * while keeping mpp/mpie/mpil. An mret to U-mode whose mcause has bit 31 + * set breaks the next trap this core takes: the trap latches + * mepc/mcause/mstatus and raises privilege, but the pc never reaches + * mtvec.base. The frame's mcause is the value the hardware latched for the + * trap that SAVED the frame, so after a context switch it is restored by a + * different trap -- SYS_restore_context, an ECALLM -- and interrupt = 1 then + * tells the CLIC it is returning from an interrupt that is not in flight. + * + * mpil (23:16) is deliberately NOT cleared: doing so was measured to change + * nothing, so the raised level does not come from this path. + * + * Kernel returns are left alone. s0 is reloaded from the frame immediately + * below; s2 is reloaded by load_ctx further down. + */ + + REGLOAD s0, REG_INT_CTX(sp) + li s2, STATUS_PPP + and s0, s0, s2 + bnez s0, 1f /* kernel return: leave mcause alone */ + li s2, 0x3fffffff /* clear interrupt (31) and minhv (30) */ + and s1, s1, s2 +1: + csrw mcause, s1 +#endif + REGLOAD s0, REG_INT_CTX(sp) /* restore status */ csrw CSR_STATUS, s0 @@ -354,6 +407,7 @@ riscv_jump_to_user: li a1, ~STATUS_PPP and a0, a0, a1 REGSTORE a0, REG_INT_CTX(sp) + mv a0, sp tail return_from_exception diff --git a/arch/risc-v/src/common/riscv_internal.h b/arch/risc-v/src/common/riscv_internal.h index d8a1e969afdb2..da0814aea628b 100644 --- a/arch/risc-v/src/common/riscv_internal.h +++ b/arch/risc-v/src/common/riscv_internal.h @@ -202,6 +202,7 @@ void riscv_ack_irq(int irq); void riscv_sigdeliver(void); int riscv_swint(int irq, void *context, void *arg); + uintptr_t riscv_get_newintctx(void); void riscv_set_idleintctx(void); void riscv_exception_attach(void); diff --git a/arch/risc-v/src/esp32p4/hal_esp32p4.cmake b/arch/risc-v/src/esp32p4/hal_esp32p4.cmake index 04b130a95d6b1..5a7d19db61273 100644 --- a/arch/risc-v/src/esp32p4/hal_esp32p4.cmake +++ b/arch/risc-v/src/esp32p4/hal_esp32p4.cmake @@ -456,6 +456,17 @@ list( ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/heap_caps.c ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/platform/os.c) +# The kernel takes ownership of the PMP: drop the HAL implementation, which +# locks every entry it programs. See esp_region_protect.c. + +if(CONFIG_ESPRESSIF_KERNEL_OWNS_PMP) + list( + REMOVE_ITEM + HAL_SRCS + ${ESP_HAL_3RDPARTY_REPO}/components/esp_hw_support/port/${CHIP_SERIES}/cpu_region_protect.c + ) +endif() + if(CONFIG_ESPRESSIF_WIFI OR CONFIG_ESPRESSIF_EMAC) list(APPEND HAL_SRCS ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/esp_event.c) endif() diff --git a/arch/risc-v/src/esp32p4/hal_esp32p4.mk b/arch/risc-v/src/esp32p4/hal_esp32p4.mk index 0899e2c2fcb94..be14b4b9b54e7 100644 --- a/arch/risc-v/src/esp32p4/hal_esp32p4.mk +++ b/arch/risc-v/src/esp32p4/hal_esp32p4.mk @@ -294,7 +294,9 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)lowpower$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)sleep_cpu_static.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)lowpower$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)sleep_clock.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)regdma_link.c +ifneq ($(CONFIG_ESPRESSIF_KERNEL_OWNS_PMP),y) CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)cpu_region_protect.c +endif CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)esp_clk_tree.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)esp_cpu_intr.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)io_mux.c diff --git a/boards/risc-v/esp32p4/common/kernel/Makefile b/boards/risc-v/esp32p4/common/kernel/Makefile new file mode 100644 index 0000000000000..7dafb5fb7fddb --- /dev/null +++ b/boards/risc-v/esp32p4/common/kernel/Makefile @@ -0,0 +1,125 @@ +############################################################################ +# boards/risc-v/esp32p4/common/kernel/Makefile +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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. +# +############################################################################ + +include $(TOPDIR)/Make.defs + +# The entry point name (if none is provided in the .config file) + +CONFIG_INIT_ENTRYPOINT ?= user_start +ENTRYPT = $(patsubst "%",%,$(CONFIG_INIT_ENTRYPOINT)) + +# Get the paths to the libraries and the links script path in format that +# is appropriate for the host OS + +USER_LIBPATHS = $(addprefix -L,$(call CONVERT_PATH,$(addprefix $(TOPDIR)$(DELIM),$(dir $(USERLIBS))))) +USER_LDSCRIPT = $(call CONVERT_PATH,$(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32p4_protected_memory.ld) +USER_LDSCRIPT += $(call CONVERT_PATH,$(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)user-space.ld) + +USER_HEXFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.hex) +USER_BINFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.bin) + +USER_LDFLAGS = --undefined=$(ENTRYPT) --entry=$(ENTRYPT) $(addprefix -T,$(addsuffix .tmp,$(USER_LDSCRIPT))) -melf32lriscv + +# The user image resolves memcpy(), strlen() and friends from ROM, exactly as +# the kernel does. CONFIG_LIBC_ARCH_* is selected by ARCH_CHIP_ESP32P4, so +# libc omits its generic implementations and expects the architecture to +# supply them; on this SoC they live in ROM and are named by these scripts. +# Without them the user link fails with undefined references to the whole +# string and memory family. + +ESP_ROM_LD_DIR = $(TOPDIR)$(DELIM)arch$(DELIM)risc-v$(DELIM)src$(DELIM)chip$(DELIM)esp-hal-3rdparty$(DELIM)components$(DELIM)esp_rom$(DELIM)esp32p4$(DELIM)ld + +USER_LDFLAGS += -T$(call CONVERT_PATH,$(ESP_ROM_LD_DIR)$(DELIM)esp32p4.rom.ld) +USER_LDFLAGS += -T$(call CONVERT_PATH,$(ESP_ROM_LD_DIR)$(DELIM)esp32p4.rom.libc.ld) + +# Deliberately NOT esp32p4.rom.newlib.ld. That script defines newlib's stdio +# symbols absolutely -- fflush = 0x4fc00370 among them -- which beats NuttX's +# own libc to the symbol. User mode then jumps into ROM, where it has no PMP +# grant and where ROM newlib's private state does not exist, and faults. It +# showed up as exit() -> fflush(NULL) faulting the moment a user task first ran +# to completion. NuttX supplies fflush itself; user space must use it. +USER_LDFLAGS += -T$(call CONVERT_PATH,$(ESP_ROM_LD_DIR)$(DELIM)esp32p4.rom.libc-suboptimal_for_misaligned_mem.ld) +USER_LDFLAGS += -T$(call CONVERT_PATH,$(ESP_ROM_LD_DIR)$(DELIM)esp32p4.rom.libgcc.ld) + +ifeq ($(CONFIG_DEBUG_LINK_MAP),y) +USER_LDFLAGS += --cref -Map="$(TOPDIR)$(DELIM)User.map" +endif + +USER_LDLIBS = $(patsubst lib%,-l%,$(basename $(notdir $(USERLIBS)))) +USER_LIBGCC = "${shell "$(CC)" $(ARCHCPUFLAGS) -print-libgcc-file-name}" + +# Source files + +CSRCS = esp_userspace.c +COBJS = $(CSRCS:.c=$(OBJEXT)) +OBJS = $(COBJS) + +ifeq ($(LD),$(CC)) + LDSTARTGROUP ?= -Wl,--start-group + LDENDGROUP ?= -Wl,--end-group + USER_LDFLAGS := $(addprefix -Xlinker ,$(USER_LDFLAGS)) + USER_LDFLAGS += $(CFLAGS) +else + LDSTARTGROUP ?= --start-group + LDENDGROUP ?= --end-group +endif + +# Targets: + +all: $(TOPDIR)$(DELIM)nuttx_user.elf +.PHONY: nuttx_user.elf depend clean distclean + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(addsuffix .tmp,$(USER_LDSCRIPT)): $(USER_LDSCRIPT) + $(call PREPROCESS,$(patsubst %.tmp,%,$@),$@) + +# Create the nuttx_user.elf file containing all of the user-mode code + +nuttx_user.elf: $(OBJS) $(addsuffix .tmp,$(USER_LDSCRIPT)) + $(Q) $(LD) -o $@ $(USER_LDFLAGS) $(USER_LIBPATHS) $(OBJS) $(LDSTARTGROUP) $(USER_LDLIBS) $(LDENDGROUP) $(USER_LIBGCC) + +$(TOPDIR)$(DELIM)nuttx_user.elf: nuttx_user.elf + $(Q) echo "LD: nuttx_user.elf" + $(Q) cp -a nuttx_user.elf $(TOPDIR)$(DELIM)nuttx_user.elf +ifeq ($(CONFIG_INTELHEX_BINARY),y) + $(Q) echo "CP: nuttx_user.hex" + $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O ihex nuttx_user.elf $(USER_HEXFILE) +endif +ifeq ($(CONFIG_RAW_BINARY),y) + $(Q) echo "CP: nuttx_user.bin" + $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O binary nuttx_user.elf $(USER_BINFILE) +endif + $(Q) $(call DELFILE,$(addsuffix .tmp,$(USER_LDSCRIPT))) + +.depend: + +depend: .depend + +clean: + $(call DELFILE, nuttx_user.elf) + $(call DELFILE, "$(TOPDIR)$(DELIM)nuttx_user.*") + $(call DELFILE, "$(TOPDIR)$(DELIM)User.map") + $(call CLEAN) + +distclean: clean diff --git a/boards/risc-v/esp32p4/common/kernel/esp_userspace.c b/boards/risc-v/esp32p4/common/kernel/esp_userspace.c new file mode 100644 index 0000000000000..41aeef74ba08e --- /dev/null +++ b/boards/risc-v/esp32p4/common/kernel/esp_userspace.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/common/kernel/esp_userspace.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include + +#if defined(CONFIG_BUILD_PROTECTED) && !defined(__KERNEL__) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_NUTTX_USERSPACE +# error "CONFIG_NUTTX_USERSPACE not defined" +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct userspace_data_s g_userspace_data = +{ + .us_heap = &g_mmheap, +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* These 'addresses' of these values are setup by the linker script. */ + +extern uint8_t _stext[]; /* Start of .text */ +extern uint8_t _etext[]; /* End_1 of .text + .rodata */ +extern const uint8_t _eronly[]; /* End+1 of read only section (.text + .rodata) */ +extern uint8_t _sdata[]; /* Start of .data */ +extern uint8_t _edata[]; /* End+1 of .data */ +extern uint8_t _sbss[]; /* Start of .bss */ +extern uint8_t _ebss[]; /* End+1 of .bss */ + +extern uint8_t __ld_udram_end[]; /* End+1 of user ram section */ + +const struct userspace_s userspace locate_data(".userspace") = +{ + /* General memory map */ + + .us_entrypoint = CONFIG_INIT_ENTRYPOINT, + .us_textstart = (uintptr_t)_stext, + .us_textend = (uintptr_t)_etext, + .us_datasource = (uintptr_t)_eronly, + .us_datastart = (uintptr_t)_sdata, + .us_dataend = (uintptr_t)_edata, + .us_bssstart = (uintptr_t)_sbss, + .us_bssend = (uintptr_t)_ebss, + + .us_heapend = (uintptr_t)__ld_udram_end, + + /* User data memory structure */ + + .us_data = &g_userspace_data, + + /* Task/thread startup routines */ + + .task_startup = nxtask_startup, + + /* Signal handler trampoline */ + + .signal_handler = up_signal_handler, + + /* Userspace work queue support (declared in include/nuttx/wqueue.h) */ + +#ifdef CONFIG_LIBC_USRWORK + .work_usrstart = work_usrstart, +#endif +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* CONFIG_BUILD_PROTECTED && !__KERNEL__ */ diff --git a/boards/risc-v/esp32p4/common/scripts/esp32p4_protected_memory.ld b/boards/risc-v/esp32p4/common/scripts/esp32p4_protected_memory.ld new file mode 100644 index 0000000000000..3c51b2c09b3e6 --- /dev/null +++ b/boards/risc-v/esp32p4/common/scripts/esp32p4_protected_memory.ld @@ -0,0 +1,183 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/common/scripts/esp32p4_protected_memory.ld + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * ESP32-P4 memory layout for the protected build. + * + * kernel-space.ld and user-space.ld link the kernel and user images into + * these blocks respectively. + * + * Three properties of this SoC shape the layout: + * + * 1. Instruction and data share one virtual window for external flash + * (SOC_MMU_DI_VADDR_SHARED). Unlike parts with separate IROM and DROM + * windows, all four flash regions are carved out of 0x40000000 upwards + * and are distinguished only by address range. + * + * 2. On silicon older than v3.0 the internal SRAM is two banks with a + * hardware gap. That maps neatly onto the kernel/user split: the kernel + * takes sram_low, user data takes sram_high, and the boundary needs no + * artificial alignment because the banks are already far apart. + * + * 3. PMP granularity is 128 bytes, so every region boundary that the PMP + * describes must be 128-byte aligned. This is why the metadata block + * below is 0x80 rather than the 0x18 used by parts with 4-byte + * granularity: UDROM starts immediately after it, and that start address + * becomes a PMP TOR boundary. + * + * Flash offsets must also satisfy the cache MMU constraint + * paddr % 64KB == vaddr % 64KB. All four flash regions are placed on 64 KB + * boundaries, with the metadata offset applied on top for UDROM. + ****************************************************************************/ + +#include + +/* common.ld would supply RESERVE_RTC_MEM and MSPI_WORKAROUND_SIZE, but it + * also pulls in the HAL's sdkconfig.h, which is not on the include path when + * the user image is linked in pass 1. This file is shared by both links, so + * the two constants are reproduced here instead. Values are the ESP32-P4 + * ones: 24 bytes of RTC timer retention, and no MSPI workaround because that + * applies to revision v3 silicon only. + */ + +#ifndef RESERVE_RTC_MEM +# define RESERVE_RTC_MEM 24 +#endif + +#ifndef MSPI_WORKAROUND_SIZE +# define MSPI_WORKAROUND_SIZE 0x0 +#endif + +/* Internal SRAM. Bank boundaries come from the flat layout so that the two + * stay in step; see esp32p4_flat_memory.ld. + */ + +#define SRAM_LOW_START 0x4ff00000 +#define SRAM_LOW_END 0x4ff2cbd0 /* 2nd stage bootloader iram_loader_seg */ +#define SRAM_LOW_SIZE (SRAM_LOW_END - SRAM_LOW_START) + +#define SRAM_HIGH_START 0x4ff40000 +/* CONFIG_CACHE_L2_CACHE_SIZE is a HAL sdkconfig alias that is not visible + * here; the NuttX-side symbol it is derived from is used directly instead. + */ + +#define SRAM_HIGH_SIZE (0x80000 - CONFIG_ESPRESSIF_CACHE_L2_CACHE_SIZE) + +/* Flash, mapped into the shared instruction/data window. The 0x20 offset on + * KIROM is the usual Espressif convenience: the image has a 0x18 byte file + * header and each segment an 0x08 byte header, so starting 0x20 in keeps + * paddr % 64KB == vaddr % 64KB satisfied for the first segment. + */ + +#define IDROM_SEG_SIZE (CONFIG_MMU_PAGE_SIZE << 10) + +#define FLASH_WINDOW 0x40000000 + +#define KIROM_ORG (FLASH_WINDOW + 0x20) +#define KIROM_LEN (0x180000 - 0x20) + +#define KDROM_ORG (FLASH_WINDOW + 0x180000) +#define KDROM_LEN 0x080000 + +#define UIROM_ORG (FLASH_WINDOW + 0x200000) +#define UIROM_LEN 0x100000 + +/* The user image begins with a metadata block that the kernel reads to learn + * where this image expects to be mapped. UDROM starts just past it, and + * that address is a PMP boundary, hence the 128-byte size. + */ + +#define UDROM_METADATA_LEN 0x80 +#define UDROM_ORG (FLASH_WINDOW + 0x300000 + UDROM_METADATA_LEN) +#define UDROM_LEN (0x080000 - UDROM_METADATA_LEN) + +MEMORY +{ + /* Load-only block carrying the user image metadata. It is emitted at the + * start of the user image file, not mapped at run time. + */ + + metadata (RX) : org = 0x0, len = UDROM_METADATA_LEN + ROM (RX) : org = ORIGIN(metadata) + LENGTH(metadata), + len = 0x400000 - ORIGIN(ROM) + + /* TCM, kernel only */ + + tcm_idram_seg (RX) : org = 0x30100000, len = 0x2000 + + /* Kernel internal SRAM: code, data, bss and the kernel heap. This is one + * region rather than separate IRAM and DRAM blocks because SRAM is + * unified on this SoC -- there is no second view of it at another + * address, as there is on the ESP32-C3. + */ + + KRAM (RWX) : org = SRAM_LOW_START, len = SRAM_LOW_SIZE + + /* User internal SRAM: data, bss and the user heap. User code executes in + * place from flash, so there is no UIRAM region. + */ + + UDRAM (RW) : org = SRAM_HIGH_START, len = SRAM_HIGH_SIZE + + /* Flash-mapped kernel code and read-only data */ + + KIROM (RX) : org = KIROM_ORG, len = KIROM_LEN + KDROM (R) : org = KDROM_ORG, len = KDROM_LEN + + /* Flash-mapped user code and read-only data */ + + UIROM (RX) : org = UIROM_ORG, len = UIROM_LEN + UDROM (R) : org = UDROM_ORG, len = UDROM_LEN + + /* PSRAM */ + + extern_ram_seg (RWX) : org = 0x48000000, len = IDROM_SEG_SIZE + + /* LP/RTC memory, kernel only */ + + rev3_mspi_workaround_seg (RWX) : org = 0x50108000, len = MSPI_WORKAROUND_SIZE + lp_reserved_seg (RW) : org = 0x50108000 + MSPI_WORKAROUND_SIZE, + len = RESERVE_RTC_MEM + lp_ram_seg (RW) : org = 0x50108000 + MSPI_WORKAROUND_SIZE + RESERVE_RTC_MEM, + len = 0x8000 - RESERVE_RTC_MEM - MSPI_WORKAROUND_SIZE +} + +/* The flat layout's alias names are reused so that the kernel sections can + * be taken from esp32p4_sections.ld unchanged. + * + * Both sram_low and sram_high alias the single kernel RAM region: the flat + * script spills some sections into sram_high, and with both names pointing + * at KRAM those sections simply flow on sequentially instead of landing in + * memory that now belongs to user space. + */ + +REGION_ALIAS("rtc_iram_seg", lp_ram_seg); +REGION_ALIAS("rtc_data_seg", rtc_iram_seg); +REGION_ALIAS("rtc_slow_seg", rtc_iram_seg); +REGION_ALIAS("rtc_data_location", rtc_iram_seg); +REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg); +REGION_ALIAS("ext_ram_seg", extern_ram_seg); + +REGION_ALIAS("sram_low", KRAM); +REGION_ALIAS("sram_high", KRAM); +REGION_ALIAS("text_seg_low", KIROM); +REGION_ALIAS("rodata_seg_low", KDROM); diff --git a/boards/risc-v/esp32p4/common/scripts/esp32p4_sections.ld b/boards/risc-v/esp32p4/common/scripts/esp32p4_sections.ld index 85acf24527b1e..0580a39513390 100644 --- a/boards/risc-v/esp32p4/common/scripts/esp32p4_sections.ld +++ b/boards/risc-v/esp32p4/common/scripts/esp32p4_sections.ld @@ -202,100 +202,102 @@ SECTIONS *libsched.a:sched_lock.*(.text .text.* .literal .literal.*) *libsched.a:sched_unlock.*(.text .text.* .literal .literal.*) - *libarch.a:*(.text.esprv_intc_int_get_type .literal.esprv_intc_int_get_type) - *libarch.a:*riscv_doirq.*(.text .text.* .literal .literal.*) - *libarch.a:*brownout.*(.text .text.* .literal .literal.*) - *libarch.a:*cpu.*(.text .text.* .literal .literal.*) - *libarch.a:*gpio_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*periph_ctrl.*(.text .text.* .literal .literal.*) - *libarch.a:*clk.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_clk.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_clk_tree.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_clk_tree_common.*(.text .text.* .literal .literal.*) - *libarch.a:*clk_tree_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*pmu_init.*(.text .text.* .literal .literal.*) - *libarch.a:*modem_clock.*(.text .text.* .literal .literal.*) - *libarch.a:*regi2c_ctrl.*(.text .text.* .literal .literal.*) - *libarch.a:*gpio_periph.*(.text .text.* .literal .literal.*) - *libarch.a:*modem_clock_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_rom_systimer.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_rom_wdt.*(.text .text.* .literal .literal.*) - *libarch.a:*ocode_init.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_rom_regi2c_esp32p4.*(.text .text.* .literal .literal.*) - *libarch.a:*rtc_clk.*(.text .text.* .literal .literal.*) - *libarch.a:*rtc_clk_init.*(.text .text.* .literal .literal.*) - *libarch.a:*pmu_sleep.*(.text .text.* .literal .literal.*) - *libarch.a:*pmu_param.*(.text .text.* .literal .literal.*) - *libarch.a:*rtc_time.*(.text .text.* .literal .literal.*) - *libarch.a:*systimer.*(.text .text.* .literal .literal.*) - *libarch.a:*systimer_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*uart_hal_iram.*(.text .text.* .literal .literal.*) - *libarch.a:*wdt_hal_iram.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_banner_wrap.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_init.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_common.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_common_loader.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_console.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_console_loader.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_esp32p4.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_flash.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_flash_config_esp32p4.*(.text .text.* .literal .literal.*) - *libarch.a:*flash_qio_mode.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_clock_init.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_clock_loader.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_efuse.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_panic.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_mem.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_random.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_random_esp32p4.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_image_format.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_soc.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_sha.*(.text .text.* .literal .literal.*) - *libarch.a:*flash_encrypt.*(.text .text.* .literal .literal.*) - *libarch.a:*cache_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*uart_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*mpu_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*mmu_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*uart_periph.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_rom_uart.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_rom_sys.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_rom_spiflash.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_efuse_fields.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_efuse_api_key.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_efuse_utility.*(.text .text.* .literal .literal.*) - *libarch.a:*efuse_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*apm_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*log.*(.text .text.* .literal .literal.*) - *libarch.a:*cpu_region_protect.*(.text .text.* .literal .literal.*) - *libarch.a:*log_lock.*(.literal .literal.* .text .text.*) - *libarch.a:*log_print.*(.literal .literal.* .text .text.*) - *libarch.a:*log_timestamp.*(.literal.esp_log_early_timestamp .text.esp_log_early_timestamp) - *libarch.a:*log_timestamp.*(.literal.esp_log_timestamp .text.esp_log_timestamp) - *libarch.a:*log_timestamp_common.*(.literal .literal.* .text .text.*) - *libarch.a:*log_write.*(.literal.esp_log_write .text.esp_log_write) - *libarch.a:*log_write.*(.literal.esp_log_writev .text.esp_log_writev) - *libarch.a:*rv_utils.*(.literal .literal.* .text .text.*) - *libarch.a:*libarch.*(.literal .literal.* .text .text.*) - *libarch.a:*riscv_modifyreg32.*(.literal .literal.* .text .text.*) - *libarch.a:critical_section.*(.literal .literal.* .text .text.*) - *libarch.a:os.*(.literal.nuttx_enter_critical .text.nuttx_enter_critical) - *libarch.a:os.*(.literal.nuttx_exit_critical .text.nuttx_exit_critical) - *libarch.a:spi_flash_hpm_enable.*(.literal .literal.* .text .text.*) - *libarch.a:*sleep_modes.*(.literal.esp_sleep_pd_config* .text.esp_sleep_pd_config*) - *libarch.a:esp_spiflash.*(.literal .text .literal.* .text.*) - *libarch.a:esp_flash_api.*(.text .text.* .literal .literal.*) - *libarch.a:esp_flash_spi_init.*(.text .text.* .literal .literal.*) - *libarch.a:spi_flash_hal_iram.*(.literal .literal.* .text .text.*) - *libarch.a:spi_flash_encrypt_hal_iram.*(.text .text.* .literal .literal.*) - *libarch.a:spi_flash_hal_gpspi.*(.literal .literal.* .text .text.*) - *libarch.a:spi_flash_chip*.*(.literal .literal.* .text .text.*) - *libarch.a:spi_flash_wrap.*(.literal .literal.* .text .text.*) - *libarch.a:spi_flash_os_func_noos.*(.literal .literal.* .text .text.*) - *libarch.a:spi_flash_os_func_app.*(.literal .literal.* .text .text.*) - *libarch.a:flash_brownout_hook.*(.literal .literal.* .text .text.*) - *libarch.a:esp_cache.*(.literal .literal.* .text .text.*) - *libarch.a:cache_utils.*(.literal .literal.* .text .text.*) - *libarch.a:memspi_host_driver.*(.literal .literal.* .text .text.*) + *arch.a:*(.text.esprv_intc_int_get_type .literal.esprv_intc_int_get_type) + *arch.a:*riscv_doirq.*(.text .text.* .literal .literal.*) + *arch.a:*brownout.*(.text .text.* .literal .literal.*) + *arch.a:*cpu.*(.text .text.* .literal .literal.*) + *arch.a:*gpio_hal.*(.text .text.* .literal .literal.*) + *arch.a:*periph_ctrl.*(.text .text.* .literal .literal.*) + *arch.a:*clk.*(.text .text.* .literal .literal.*) + *arch.a:*esp_clk.*(.text .text.* .literal .literal.*) + *arch.a:*esp_clk_tree.*(.text .text.* .literal .literal.*) + *arch.a:*esp_clk_tree_common.*(.text .text.* .literal .literal.*) + *arch.a:*clk_tree_hal.*(.text .text.* .literal .literal.*) + *arch.a:*pmu_init.*(.text .text.* .literal .literal.*) + *arch.a:*modem_clock.*(.text .text.* .literal .literal.*) + *arch.a:*regi2c_ctrl.*(.text .text.* .literal .literal.*) + *arch.a:*gpio_periph.*(.text .text.* .literal .literal.*) + *arch.a:*modem_clock_hal.*(.text .text.* .literal .literal.*) + *arch.a:*esp_rom_systimer.*(.text .text.* .literal .literal.*) + *arch.a:*esp_rom_wdt.*(.text .text.* .literal .literal.*) + *arch.a:*ocode_init.*(.text .text.* .literal .literal.*) + *arch.a:*esp_rom_regi2c_esp32p4.*(.text .text.* .literal .literal.*) + *arch.a:*rtc_clk.*(.text .text.* .literal .literal.*) + *arch.a:*rtc_clk_init.*(.text .text.* .literal .literal.*) + *arch.a:*pmu_sleep.*(.text .text.* .literal .literal.*) + *arch.a:*pmu_param.*(.text .text.* .literal .literal.*) + *arch.a:*rtc_time.*(.text .text.* .literal .literal.*) + *arch.a:*systimer.*(.text .text.* .literal .literal.*) + *arch.a:*systimer_hal.*(.text .text.* .literal .literal.*) + *arch.a:*uart_hal_iram.*(.text .text.* .literal .literal.*) + *arch.a:*wdt_hal_iram.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_banner_wrap.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_init.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_common.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_common_loader.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_console.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_console_loader.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_esp32p4.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_flash.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_flash_config_esp32p4.*(.text .text.* .literal .literal.*) + *arch.a:*flash_qio_mode.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_clock_init.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_clock_loader.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_efuse.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_panic.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_mem.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_random.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_random_esp32p4.*(.text .text.* .literal .literal.*) + *arch.a:*esp_image_format.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_soc.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_sha.*(.text .text.* .literal .literal.*) + *arch.a:*flash_encrypt.*(.text .text.* .literal .literal.*) + *arch.a:*cache_hal.*(.text .text.* .literal .literal.*) + *arch.a:*uart_hal.*(.text .text.* .literal .literal.*) + *arch.a:*mpu_hal.*(.text .text.* .literal .literal.*) + *arch.a:*mmu_hal.*(.text .text.* .literal .literal.*) + *arch.a:*uart_periph.*(.text .text.* .literal .literal.*) + *arch.a:*esp_rom_uart.*(.text .text.* .literal .literal.*) + *arch.a:*esp_rom_sys.*(.text .text.* .literal .literal.*) + *arch.a:*esp_rom_spiflash.*(.text .text.* .literal .literal.*) + *arch.a:*esp_efuse_fields.*(.text .text.* .literal .literal.*) + *arch.a:*esp_efuse_api_key.*(.text .text.* .literal .literal.*) + *arch.a:*esp_efuse_utility.*(.text .text.* .literal .literal.*) + *arch.a:*efuse_hal.*(.text .text.* .literal .literal.*) + *arch.a:*apm_hal.*(.text .text.* .literal .literal.*) + *arch.a:*log.*(.text .text.* .literal .literal.*) + *arch.a:*cpu_region_protect.*(.text .text.* .literal .literal.*) + *arch.a:*esp_region_protect.*(.text .text.* .literal .literal.*) + *arch.a:*esp_userspace.*(.text .text.* .literal .literal.*) + *arch.a:*log_lock.*(.literal .literal.* .text .text.*) + *arch.a:*log_print.*(.literal .literal.* .text .text.*) + *arch.a:*log_timestamp.*(.literal.esp_log_early_timestamp .text.esp_log_early_timestamp) + *arch.a:*log_timestamp.*(.literal.esp_log_timestamp .text.esp_log_timestamp) + *arch.a:*log_timestamp_common.*(.literal .literal.* .text .text.*) + *arch.a:*log_write.*(.literal.esp_log_write .text.esp_log_write) + *arch.a:*log_write.*(.literal.esp_log_writev .text.esp_log_writev) + *arch.a:*rv_utils.*(.literal .literal.* .text .text.*) + *arch.a:*libarch.*(.literal .literal.* .text .text.*) + *arch.a:*riscv_modifyreg32.*(.literal .literal.* .text .text.*) + *arch.a:critical_section.*(.literal .literal.* .text .text.*) + *arch.a:os.*(.literal.nuttx_enter_critical .text.nuttx_enter_critical) + *arch.a:os.*(.literal.nuttx_exit_critical .text.nuttx_exit_critical) + *arch.a:spi_flash_hpm_enable.*(.literal .literal.* .text .text.*) + *arch.a:*sleep_modes.*(.literal.esp_sleep_pd_config* .text.esp_sleep_pd_config*) + *arch.a:esp_spiflash.*(.literal .text .literal.* .text.*) + *arch.a:esp_flash_api.*(.text .text.* .literal .literal.*) + *arch.a:esp_flash_spi_init.*(.text .text.* .literal .literal.*) + *arch.a:spi_flash_hal_iram.*(.literal .literal.* .text .text.*) + *arch.a:spi_flash_encrypt_hal_iram.*(.text .text.* .literal .literal.*) + *arch.a:spi_flash_hal_gpspi.*(.literal .literal.* .text .text.*) + *arch.a:spi_flash_chip*.*(.literal .literal.* .text .text.*) + *arch.a:spi_flash_wrap.*(.literal .literal.* .text .text.*) + *arch.a:spi_flash_os_func_noos.*(.literal .literal.* .text .text.*) + *arch.a:spi_flash_os_func_app.*(.literal .literal.* .text .text.*) + *arch.a:flash_brownout_hook.*(.literal .literal.* .text .text.*) + *arch.a:esp_cache.*(.literal .literal.* .text .text.*) + *arch.a:cache_utils.*(.literal .literal.* .text .text.*) + *arch.a:memspi_host_driver.*(.literal .literal.* .text .text.*) *libc.a:sq_remlast.*(.literal .text .literal.* .text.*) @@ -353,106 +355,106 @@ SECTIONS *(.dram1) *(.dram1.*) - *libarch.a:brownout.*(.rodata .rodata.*) - *libarch.a:cpu.*(.rodata .rodata.*) - *libarch.a:gpio_hal.*(.rodata .rodata.*) - *libarch.a:interrupt.*(.rodata .rodata.*) - *libarch.a:periph_ctrl.*(.rodata .rodata.*) - *libarch.a:rtc_clk.*(.rodata .rodata.*) - *libarch.a:rtc_sleep.*(.rodata .rodata.*) - *libarch.a:rtc_time.*(.rodata .rodata.*) - *libarch.a:systimer.*(.rodata .rodata.*) - *libarch.a:systimer_hal.*(.rodata .rodata.*) - *libarch.a:uart_hal_iram.*(.rodata .rodata.*) - *libarch.a:wdt_hal_iram.*(.rodata .rodata.*) + *arch.a:brownout.*(.rodata .rodata.*) + *arch.a:cpu.*(.rodata .rodata.*) + *arch.a:gpio_hal.*(.rodata .rodata.*) + *arch.a:interrupt.*(.rodata .rodata.*) + *arch.a:periph_ctrl.*(.rodata .rodata.*) + *arch.a:rtc_clk.*(.rodata .rodata.*) + *arch.a:rtc_sleep.*(.rodata .rodata.*) + *arch.a:rtc_time.*(.rodata .rodata.*) + *arch.a:systimer.*(.rodata .rodata.*) + *arch.a:systimer_hal.*(.rodata .rodata.*) + *arch.a:uart_hal_iram.*(.rodata .rodata.*) + *arch.a:wdt_hal_iram.*(.rodata .rodata.*) *libsched.a:irq_dispatch.*(.rodata .rodata.*) *libsched.a:irq_dispatch.*(.rodata .rodata.*) *libsched.a:sched_lock.*(.rodata .rodata.*) *libsched.a:sched_unlock.*(.rodata .rodata.*) - *libarch.a:*(.rodata.esprv_intc_int_get_type) - *libarch.a:*riscv_doirq.*(.rodata .rodata.*) - *libarch.a:*brownout.*(.rodata .rodata.*) - *libarch.a:*cpu.*(.rodata .rodata.*) - *libarch.a:*gpio_hal.*(.rodata .rodata.*) - *libarch.a:*periph_ctrl.*(.rodata .rodata.*) - *libarch.a:*clk.*(.rodata .rodata.*) - *libarch.a:*esp_clk.*(.rodata .rodata.*) - *libarch.a:*esp_clk_tree.*(.rodata .rodata.*) - *libarch.a:*esp_clk_tree_common.*(.rodata .rodata.*) - *libarch.a:*clk_tree_hal.*(.rodata .rodata.*) - *libarch.a:*pmu_init.*(.rodata .rodata.*) - *libarch.a:*modem_clock.*(.rodata .rodata.*) - *libarch.a:*modem_clock_hal.*(.rodata .rodata.*) - *libarch.a:*regi2c_ctrl.*(.rodata .rodata.*) - *libarch.a:*gpio_periph.*(.rodata .rodata.*) - *libarch.a:*esp_rom_systimer.*(.rodata .rodata.*) - *libarch.a:*esp_rom_wdt.*(.rodata .rodata.*) - *libarch.a:*ocode_init.*(.rodata .rodata.*) - *libarch.a:*esp_rom_regi2c_esp32p4.*(.rodata .rodata.*) - *libarch.a:*rtc_clk.*(.rodata .rodata.*) - *libarch.a:*rtc_clk_init.*(.rodata .rodata.*) - *libarch.a:*pmu_param.*(.rodata .rodata.*) - *libarch.a:*pmu_sleep.*(.rodata .rodata.*) - *libarch.a:*rtc_time.*(.rodata .rodata.*) - *libarch.a:*systimer.*(.rodata .rodata.*) - *libarch.a:*systimer_hal.*(.rodata .rodata.*) - *libarch.a:*uart_hal_iram.*(.rodata .rodata.*) - *libarch.a:*wdt_hal_iram.*(.rodata .rodata.*) - *libarch.a:*bootloader_banner_wrap.*(.rodata .rodata.*) - *libarch.a:*bootloader_init.*(.rodata .rodata.*) - *libarch.a:*bootloader_common.*(.rodata .rodata.*) - *libarch.a:*bootloader_common_loader.*(.rodata .rodata.*) - *libarch.a:*bootloader_console.*(.rodata .rodata.*) - *libarch.a:*bootloader_console_loader.*(.rodata .rodata.*) - *libarch.a:*bootloader_esp32p4.*(.rodata .rodata.*) - *libarch.a:*bootloader_flash.*(.rodata .rodata.*) - *libarch.a:*bootloader_flash_config_esp32p4.*(.rodata .rodata.*) - *libarch.a:*flash_qio_mode.*(.rodata .rodata.*) - *libarch.a:*bootloader_clock_init.*(.rodata .rodata.*) - *libarch.a:*bootloader_clock_loader.*(.rodata .rodata.*) - *libarch.a:*bootloader_efuse.*(.rodata .rodata.*) - *libarch.a:*bootloader_panic.*(.rodata .rodata.*) - *libarch.a:*bootloader_mem.*(.rodata .rodata.*) - *libarch.a:*bootloader_random.*(.rodata .rodata.*) - *libarch.a:*bootloader_random_esp32p4.*(.rodata .rodata.*) - *libarch.a:*esp_image_format.*(.rodata .rodata.*) - *libarch.a:*bootloader_soc.*(.rodata .rodata.*) - *libarch.a:*bootloader_sha.*(.rodata .rodata.*) - *libarch.a:*flash_encrypt.*(.rodata .rodata.*) - *libarch.a:*cache_hal.*(.rodata .rodata.*) - *libarch.a:*uart_hal.*(.rodata .rodata.*) - *libarch.a:*mpu_hal.*(.rodata .rodata.*) - *libarch.a:*mmu_hal.*(.rodata .rodata.*) - *libarch.a:*uart_periph.*(.rodata .rodata.*) - *libarch.a:*esp_rom_uart.*(.rodata .rodata.*) - *libarch.a:*esp_rom_sys.*(.rodata .rodata.*) - *libarch.a:*esp_rom_spiflash.*(.rodata .rodata.*) - *libarch.a:*esp_efuse_fields.*(.rodata .rodata.*) - *libarch.a:*esp_efuse_api_key.*(.rodata .rodata.*) - *libarch.a:*esp_efuse_utility.*(.rodata .rodata.*) - *libarch.a:*efuse_hal.*(.rodata .rodata.*) - *libarch.a:*log.*(.rodata .rodata.*) - *libarch.a:*log_noos.*(.rodata .rodata.*) - *libarch.a:esp_spiflash.*(.rodata .rodata.*) - *libarch.a:esp_chip_rev.*(.rodata .rodata.*) - *libarch.a:critical_section.*(.rodata .rodata.*) - *libarch.a:os.*(.rodata.g_int_flags_count .rodata.g_int_flags) - *libarch.a:spi_flash_hpm_enable.*(.rodata .rodata.*) - *libarch.a:*sleep_modes.*(.rodata.esp_sleep_pd_config*) - *libarch.a:esp_flash_api.*(.rodata .rodata.*) - *libarch.a:esp_flash_spi_init.*(.rodata .rodata.*) - *libarch.a:spi_flash_hal_iram.*(.rodata .rodata.*) - *libarch.a:spi_flash_encrypt_hal_iram.*(.rodata .rodata.*) - *libarch.a:spi_flash_hal_gpspi.*(.rodata .rodata.*) - *libarch.a:spi_flash_chip*.*(.rodata .rodata.*) - *libarch.a:spi_flash_wrap.*(.rodata .rodata.*) - *libarch.a:spi_flash_os_func_noos.*(.rodata .rodata.*) - *libarch.a:spi_flash_os_func_app.*(.rodata .rodata.*) - *libarch.a:flash_brownout_hook.*(.rodata .rodata.*) - *libarch.a:esp_cache.*(.rodata .rodata.*) - *libarch.a:cache_utils.*(.rodata .rodata.*) - *libarch.a:memspi_host_driver.*(.rodata .rodata.*) + *arch.a:*(.rodata.esprv_intc_int_get_type) + *arch.a:*riscv_doirq.*(.rodata .rodata.*) + *arch.a:*brownout.*(.rodata .rodata.*) + *arch.a:*cpu.*(.rodata .rodata.*) + *arch.a:*gpio_hal.*(.rodata .rodata.*) + *arch.a:*periph_ctrl.*(.rodata .rodata.*) + *arch.a:*clk.*(.rodata .rodata.*) + *arch.a:*esp_clk.*(.rodata .rodata.*) + *arch.a:*esp_clk_tree.*(.rodata .rodata.*) + *arch.a:*esp_clk_tree_common.*(.rodata .rodata.*) + *arch.a:*clk_tree_hal.*(.rodata .rodata.*) + *arch.a:*pmu_init.*(.rodata .rodata.*) + *arch.a:*modem_clock.*(.rodata .rodata.*) + *arch.a:*modem_clock_hal.*(.rodata .rodata.*) + *arch.a:*regi2c_ctrl.*(.rodata .rodata.*) + *arch.a:*gpio_periph.*(.rodata .rodata.*) + *arch.a:*esp_rom_systimer.*(.rodata .rodata.*) + *arch.a:*esp_rom_wdt.*(.rodata .rodata.*) + *arch.a:*ocode_init.*(.rodata .rodata.*) + *arch.a:*esp_rom_regi2c_esp32p4.*(.rodata .rodata.*) + *arch.a:*rtc_clk.*(.rodata .rodata.*) + *arch.a:*rtc_clk_init.*(.rodata .rodata.*) + *arch.a:*pmu_param.*(.rodata .rodata.*) + *arch.a:*pmu_sleep.*(.rodata .rodata.*) + *arch.a:*rtc_time.*(.rodata .rodata.*) + *arch.a:*systimer.*(.rodata .rodata.*) + *arch.a:*systimer_hal.*(.rodata .rodata.*) + *arch.a:*uart_hal_iram.*(.rodata .rodata.*) + *arch.a:*wdt_hal_iram.*(.rodata .rodata.*) + *arch.a:*bootloader_banner_wrap.*(.rodata .rodata.*) + *arch.a:*bootloader_init.*(.rodata .rodata.*) + *arch.a:*bootloader_common.*(.rodata .rodata.*) + *arch.a:*bootloader_common_loader.*(.rodata .rodata.*) + *arch.a:*bootloader_console.*(.rodata .rodata.*) + *arch.a:*bootloader_console_loader.*(.rodata .rodata.*) + *arch.a:*bootloader_esp32p4.*(.rodata .rodata.*) + *arch.a:*bootloader_flash.*(.rodata .rodata.*) + *arch.a:*bootloader_flash_config_esp32p4.*(.rodata .rodata.*) + *arch.a:*flash_qio_mode.*(.rodata .rodata.*) + *arch.a:*bootloader_clock_init.*(.rodata .rodata.*) + *arch.a:*bootloader_clock_loader.*(.rodata .rodata.*) + *arch.a:*bootloader_efuse.*(.rodata .rodata.*) + *arch.a:*bootloader_panic.*(.rodata .rodata.*) + *arch.a:*bootloader_mem.*(.rodata .rodata.*) + *arch.a:*bootloader_random.*(.rodata .rodata.*) + *arch.a:*bootloader_random_esp32p4.*(.rodata .rodata.*) + *arch.a:*esp_image_format.*(.rodata .rodata.*) + *arch.a:*bootloader_soc.*(.rodata .rodata.*) + *arch.a:*bootloader_sha.*(.rodata .rodata.*) + *arch.a:*flash_encrypt.*(.rodata .rodata.*) + *arch.a:*cache_hal.*(.rodata .rodata.*) + *arch.a:*uart_hal.*(.rodata .rodata.*) + *arch.a:*mpu_hal.*(.rodata .rodata.*) + *arch.a:*mmu_hal.*(.rodata .rodata.*) + *arch.a:*uart_periph.*(.rodata .rodata.*) + *arch.a:*esp_rom_uart.*(.rodata .rodata.*) + *arch.a:*esp_rom_sys.*(.rodata .rodata.*) + *arch.a:*esp_rom_spiflash.*(.rodata .rodata.*) + *arch.a:*esp_efuse_fields.*(.rodata .rodata.*) + *arch.a:*esp_efuse_api_key.*(.rodata .rodata.*) + *arch.a:*esp_efuse_utility.*(.rodata .rodata.*) + *arch.a:*efuse_hal.*(.rodata .rodata.*) + *arch.a:*log.*(.rodata .rodata.*) + *arch.a:*log_noos.*(.rodata .rodata.*) + *arch.a:esp_spiflash.*(.rodata .rodata.*) + *arch.a:esp_chip_rev.*(.rodata .rodata.*) + *arch.a:critical_section.*(.rodata .rodata.*) + *arch.a:os.*(.rodata.g_int_flags_count .rodata.g_int_flags) + *arch.a:spi_flash_hpm_enable.*(.rodata .rodata.*) + *arch.a:*sleep_modes.*(.rodata.esp_sleep_pd_config*) + *arch.a:esp_flash_api.*(.rodata .rodata.*) + *arch.a:esp_flash_spi_init.*(.rodata .rodata.*) + *arch.a:spi_flash_hal_iram.*(.rodata .rodata.*) + *arch.a:spi_flash_encrypt_hal_iram.*(.rodata .rodata.*) + *arch.a:spi_flash_hal_gpspi.*(.rodata .rodata.*) + *arch.a:spi_flash_chip*.*(.rodata .rodata.*) + *arch.a:spi_flash_wrap.*(.rodata .rodata.*) + *arch.a:spi_flash_os_func_noos.*(.rodata .rodata.*) + *arch.a:spi_flash_os_func_app.*(.rodata .rodata.*) + *arch.a:flash_brownout_hook.*(.rodata .rodata.*) + *arch.a:esp_cache.*(.rodata .rodata.*) + *arch.a:cache_utils.*(.rodata .rodata.*) + *arch.a:memspi_host_driver.*(.rodata .rodata.*) esp_head.*(.rodata .rodata.*) esp_start.*(.rodata .rodata.*) diff --git a/boards/risc-v/esp32p4/common/scripts/esp32p4_sections.rev3.ld b/boards/risc-v/esp32p4/common/scripts/esp32p4_sections.rev3.ld index 8afb4d1e0cdd0..12c9d0b235bc1 100644 --- a/boards/risc-v/esp32p4/common/scripts/esp32p4_sections.rev3.ld +++ b/boards/risc-v/esp32p4/common/scripts/esp32p4_sections.rev3.ld @@ -211,102 +211,104 @@ SECTIONS *libsched.a:sched_lock.*(.text .text.* .literal .literal.*) *libsched.a:sched_unlock.*(.text .text.* .literal .literal.*) - *libarch.a:*(.text.esprv_intc_int_get_type .literal.esprv_intc_int_get_type) - *libarch.a:*riscv_doirq.*(.text .text.* .literal .literal.*) - *libarch.a:*brownout.*(.text .text.* .literal .literal.*) - *libarch.a:*cpu.*(.text .text.* .literal .literal.*) - *libarch.a:*gpio_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*periph_ctrl.*(.text .text.* .literal .literal.*) - *libarch.a:*clk.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_clk.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_clk_tree.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_clk_tree_common.*(.text .text.* .literal .literal.*) - *libarch.a:*clk_tree_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*pmu_init.*(.text .text.* .literal .literal.*) - *libarch.a:*modem_clock.*(.text .text.* .literal .literal.*) - *libarch.a:*regi2c_ctrl.*(.text .text.* .literal .literal.*) - *libarch.a:*gpio_periph.*(.text .text.* .literal .literal.*) - *libarch.a:*modem_clock_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_rom_systimer.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_rom_wdt.*(.text .text.* .literal .literal.*) - *libarch.a:*ocode_init.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_rom_regi2c_esp32p4.*(.text .text.* .literal .literal.*) - *libarch.a:*rtc_clk.*(.text .text.* .literal .literal.*) - *libarch.a:*rtc_clk_init.*(.text .text.* .literal .literal.*) - *libarch.a:*pmu_sleep.*(.text .text.* .literal .literal.*) - *libarch.a:*pmu_param.*(.text .text.* .literal .literal.*) - *libarch.a:*rtc_time.*(.text .text.* .literal .literal.*) - *libarch.a:*systimer.*(.text .text.* .literal .literal.*) - *libarch.a:*systimer_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*uart_hal_iram.*(.text .text.* .literal .literal.*) - *libarch.a:*wdt_hal_iram.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_banner_wrap.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_init.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_common.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_common_loader.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_console.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_console_loader.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_esp32p4.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_flash.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_flash_config_esp32p4.*(.text .text.* .literal .literal.*) - *libarch.a:*flash_qio_mode.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_clock_init.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_clock_loader.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_efuse.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_panic.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_mem.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_random.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_random_esp32p4.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_image_format.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_soc.*(.text .text.* .literal .literal.*) - *libarch.a:*bootloader_sha.*(.text .text.* .literal .literal.*) - *libarch.a:*flash_encrypt.*(.text .text.* .literal .literal.*) - *libarch.a:*cache_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*uart_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*mpu_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*mmu_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*uart_periph.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_rom_uart.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_rom_sys.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_rom_spiflash.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_efuse_fields.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_efuse_api_key.*(.text .text.* .literal .literal.*) - *libarch.a:*esp_efuse_utility.*(.text .text.* .literal .literal.*) - *libarch.a:*efuse_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*apm_hal.*(.text .text.* .literal .literal.*) - *libarch.a:*log.*(.text .text.* .literal .literal.*) - *libarch.a:*cpu_region_protect.*(.text .text.* .literal .literal.*) - *libarch.a:*log_lock.*(.literal .literal.* .text .text.*) - *libarch.a:*log_print.*(.literal .literal.* .text .text.*) - *libarch.a:*log_timestamp.*(.literal.esp_log_early_timestamp .text.esp_log_early_timestamp) - *libarch.a:*log_timestamp.*(.literal.esp_log_timestamp .text.esp_log_timestamp) - *libarch.a:*log_timestamp_common.*(.literal .literal.* .text .text.*) - *libarch.a:*log_write.*(.literal.esp_log_write .text.esp_log_write) - *libarch.a:*log_write.*(.literal.esp_log_writev .text.esp_log_writev) - *libarch.a:*rv_utils.*(.literal .literal.* .text .text.*) - *libarch.a:*libarch.*(.literal .literal.* .text .text.*) - *libarch.a:*riscv_modifyreg32.*(.literal .literal.* .text .text.*) - *libarch.a:critical_section.*(.literal .literal.* .text .text.*) - *libarch.a:os.*(.literal.nuttx_enter_critical .text.nuttx_enter_critical) - *libarch.a:os.*(.literal.nuttx_exit_critical .text.nuttx_exit_critical) - *libarch.a:spi_flash_hpm_enable.*(.literal .literal.* .text .text.*) - *libarch.a:*sleep_modes.*(.literal.esp_sleep_pd_config* .text.esp_sleep_pd_config*) - *libarch.a:esp_spiflash.*(.literal .text .literal.* .text.*) - *libarch.a:esp_flash_api.*(.text .text.* .literal .literal.*) - *libarch.a:esp_flash_spi_init.*(.text .text.* .literal .literal.*) - *libarch.a:spi_flash_hal_iram.*(.literal .literal.* .text .text.*) - *libarch.a:spi_flash_encrypt_hal_iram.*(.text .text.* .literal .literal.*) - *libarch.a:spi_flash_hal_gpspi.*(.literal .literal.* .text .text.*) - *libarch.a:spi_flash_chip*.*(.literal .literal.* .text .text.*) - *libarch.a:spi_flash_wrap.*(.literal .literal.* .text .text.*) - *libarch.a:spi_flash_os_func_noos.*(.literal .literal.* .text .text.*) - *libarch.a:spi_flash_os_func_app.*(.literal .literal.* .text .text.*) - *libarch.a:flash_brownout_hook.*(.literal .literal.* .text .text.*) - *libarch.a:esp_cache.*(.literal .literal.* .text .text.*) - *libarch.a:cache_utils.*(.literal .literal.* .text .text.*) - *libarch.a:memspi_host_driver.*(.literal .literal.* .text .text.*) - *libarch.a:esp_psram_impl_ap_hex.*(.literal .literal.* .text .text.*) - *libarch.a:esp_psram.*(.literal.esp_psram_get_heap_size_to_protect .text.esp_psram_get_heap_size_to_protect) + *arch.a:*(.text.esprv_intc_int_get_type .literal.esprv_intc_int_get_type) + *arch.a:*riscv_doirq.*(.text .text.* .literal .literal.*) + *arch.a:*brownout.*(.text .text.* .literal .literal.*) + *arch.a:*cpu.*(.text .text.* .literal .literal.*) + *arch.a:*gpio_hal.*(.text .text.* .literal .literal.*) + *arch.a:*periph_ctrl.*(.text .text.* .literal .literal.*) + *arch.a:*clk.*(.text .text.* .literal .literal.*) + *arch.a:*esp_clk.*(.text .text.* .literal .literal.*) + *arch.a:*esp_clk_tree.*(.text .text.* .literal .literal.*) + *arch.a:*esp_clk_tree_common.*(.text .text.* .literal .literal.*) + *arch.a:*clk_tree_hal.*(.text .text.* .literal .literal.*) + *arch.a:*pmu_init.*(.text .text.* .literal .literal.*) + *arch.a:*modem_clock.*(.text .text.* .literal .literal.*) + *arch.a:*regi2c_ctrl.*(.text .text.* .literal .literal.*) + *arch.a:*gpio_periph.*(.text .text.* .literal .literal.*) + *arch.a:*modem_clock_hal.*(.text .text.* .literal .literal.*) + *arch.a:*esp_rom_systimer.*(.text .text.* .literal .literal.*) + *arch.a:*esp_rom_wdt.*(.text .text.* .literal .literal.*) + *arch.a:*ocode_init.*(.text .text.* .literal .literal.*) + *arch.a:*esp_rom_regi2c_esp32p4.*(.text .text.* .literal .literal.*) + *arch.a:*rtc_clk.*(.text .text.* .literal .literal.*) + *arch.a:*rtc_clk_init.*(.text .text.* .literal .literal.*) + *arch.a:*pmu_sleep.*(.text .text.* .literal .literal.*) + *arch.a:*pmu_param.*(.text .text.* .literal .literal.*) + *arch.a:*rtc_time.*(.text .text.* .literal .literal.*) + *arch.a:*systimer.*(.text .text.* .literal .literal.*) + *arch.a:*systimer_hal.*(.text .text.* .literal .literal.*) + *arch.a:*uart_hal_iram.*(.text .text.* .literal .literal.*) + *arch.a:*wdt_hal_iram.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_banner_wrap.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_init.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_common.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_common_loader.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_console.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_console_loader.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_esp32p4.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_flash.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_flash_config_esp32p4.*(.text .text.* .literal .literal.*) + *arch.a:*flash_qio_mode.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_clock_init.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_clock_loader.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_efuse.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_panic.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_mem.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_random.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_random_esp32p4.*(.text .text.* .literal .literal.*) + *arch.a:*esp_image_format.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_soc.*(.text .text.* .literal .literal.*) + *arch.a:*bootloader_sha.*(.text .text.* .literal .literal.*) + *arch.a:*flash_encrypt.*(.text .text.* .literal .literal.*) + *arch.a:*cache_hal.*(.text .text.* .literal .literal.*) + *arch.a:*uart_hal.*(.text .text.* .literal .literal.*) + *arch.a:*mpu_hal.*(.text .text.* .literal .literal.*) + *arch.a:*mmu_hal.*(.text .text.* .literal .literal.*) + *arch.a:*uart_periph.*(.text .text.* .literal .literal.*) + *arch.a:*esp_rom_uart.*(.text .text.* .literal .literal.*) + *arch.a:*esp_rom_sys.*(.text .text.* .literal .literal.*) + *arch.a:*esp_rom_spiflash.*(.text .text.* .literal .literal.*) + *arch.a:*esp_efuse_fields.*(.text .text.* .literal .literal.*) + *arch.a:*esp_efuse_api_key.*(.text .text.* .literal .literal.*) + *arch.a:*esp_efuse_utility.*(.text .text.* .literal .literal.*) + *arch.a:*efuse_hal.*(.text .text.* .literal .literal.*) + *arch.a:*apm_hal.*(.text .text.* .literal .literal.*) + *arch.a:*log.*(.text .text.* .literal .literal.*) + *arch.a:*cpu_region_protect.*(.text .text.* .literal .literal.*) + *arch.a:*esp_region_protect.*(.text .text.* .literal .literal.*) + *arch.a:*esp_userspace.*(.text .text.* .literal .literal.*) + *arch.a:*log_lock.*(.literal .literal.* .text .text.*) + *arch.a:*log_print.*(.literal .literal.* .text .text.*) + *arch.a:*log_timestamp.*(.literal.esp_log_early_timestamp .text.esp_log_early_timestamp) + *arch.a:*log_timestamp.*(.literal.esp_log_timestamp .text.esp_log_timestamp) + *arch.a:*log_timestamp_common.*(.literal .literal.* .text .text.*) + *arch.a:*log_write.*(.literal.esp_log_write .text.esp_log_write) + *arch.a:*log_write.*(.literal.esp_log_writev .text.esp_log_writev) + *arch.a:*rv_utils.*(.literal .literal.* .text .text.*) + *arch.a:*libarch.*(.literal .literal.* .text .text.*) + *arch.a:*riscv_modifyreg32.*(.literal .literal.* .text .text.*) + *arch.a:critical_section.*(.literal .literal.* .text .text.*) + *arch.a:os.*(.literal.nuttx_enter_critical .text.nuttx_enter_critical) + *arch.a:os.*(.literal.nuttx_exit_critical .text.nuttx_exit_critical) + *arch.a:spi_flash_hpm_enable.*(.literal .literal.* .text .text.*) + *arch.a:*sleep_modes.*(.literal.esp_sleep_pd_config* .text.esp_sleep_pd_config*) + *arch.a:esp_spiflash.*(.literal .text .literal.* .text.*) + *arch.a:esp_flash_api.*(.text .text.* .literal .literal.*) + *arch.a:esp_flash_spi_init.*(.text .text.* .literal .literal.*) + *arch.a:spi_flash_hal_iram.*(.literal .literal.* .text .text.*) + *arch.a:spi_flash_encrypt_hal_iram.*(.text .text.* .literal .literal.*) + *arch.a:spi_flash_hal_gpspi.*(.literal .literal.* .text .text.*) + *arch.a:spi_flash_chip*.*(.literal .literal.* .text .text.*) + *arch.a:spi_flash_wrap.*(.literal .literal.* .text .text.*) + *arch.a:spi_flash_os_func_noos.*(.literal .literal.* .text .text.*) + *arch.a:spi_flash_os_func_app.*(.literal .literal.* .text .text.*) + *arch.a:flash_brownout_hook.*(.literal .literal.* .text .text.*) + *arch.a:esp_cache.*(.literal .literal.* .text .text.*) + *arch.a:cache_utils.*(.literal .literal.* .text .text.*) + *arch.a:memspi_host_driver.*(.literal .literal.* .text .text.*) + *arch.a:esp_psram_impl_ap_hex.*(.literal .literal.* .text .text.*) + *arch.a:esp_psram.*(.literal.esp_psram_get_heap_size_to_protect .text.esp_psram_get_heap_size_to_protect) *libc.a:sq_remlast.*(.literal .text .literal.* .text.*) @@ -374,108 +376,109 @@ SECTIONS *(.dram1) *(.dram1.*) - *libarch.a:brownout.*(.rodata .rodata.*) - *libarch.a:cpu.*(.rodata .rodata.*) - *libarch.a:gpio_hal.*(.rodata .rodata.*) - *libarch.a:interrupt.*(.rodata .rodata.*) - *libarch.a:periph_ctrl.*(.rodata .rodata.*) - *libarch.a:rtc_clk.*(.rodata .rodata.*) - *libarch.a:rtc_sleep.*(.rodata .rodata.*) - *libarch.a:rtc_time.*(.rodata .rodata.*) - *libarch.a:systimer.*(.rodata .rodata.*) - *libarch.a:systimer_hal.*(.rodata .rodata.*) - *libarch.a:uart_hal_iram.*(.rodata .rodata.*) - *libarch.a:wdt_hal_iram.*(.rodata .rodata.*) + *arch.a:brownout.*(.rodata .rodata.*) + *arch.a:cpu.*(.rodata .rodata.*) + *arch.a:gpio_hal.*(.rodata .rodata.*) + *arch.a:interrupt.*(.rodata .rodata.*) + *arch.a:periph_ctrl.*(.rodata .rodata.*) + *arch.a:rtc_clk.*(.rodata .rodata.*) + *arch.a:rtc_sleep.*(.rodata .rodata.*) + *arch.a:rtc_time.*(.rodata .rodata.*) + *arch.a:systimer.*(.rodata .rodata.*) + *arch.a:systimer_hal.*(.rodata .rodata.*) + *arch.a:uart_hal_iram.*(.rodata .rodata.*) + *arch.a:wdt_hal_iram.*(.rodata .rodata.*) *libsched.a:irq_dispatch.*(.rodata .rodata.*) *libsched.a:irq_dispatch.*(.rodata .rodata.*) *libsched.a:sched_lock.*(.rodata .rodata.*) *libsched.a:sched_unlock.*(.rodata .rodata.*) - *libarch.a:*(.rodata.esprv_intc_int_get_type) - *libarch.a:*riscv_doirq.*(.rodata .rodata.*) - *libarch.a:*brownout.*(.rodata .rodata.*) - *libarch.a:*cpu.*(.rodata .rodata.*) - *libarch.a:*gpio_hal.*(.rodata .rodata.*) - *libarch.a:*periph_ctrl.*(.rodata .rodata.*) - *libarch.a:*clk.*(.rodata .rodata.*) - *libarch.a:*esp_clk.*(.rodata .rodata.*) - *libarch.a:*esp_clk_tree.*(.rodata .rodata.*) - *libarch.a:*esp_clk_tree_common.*(.rodata .rodata.*) - *libarch.a:*clk_tree_hal.*(.rodata .rodata.*) - *libarch.a:*pmu_init.*(.rodata .rodata.*) - *libarch.a:*modem_clock.*(.rodata .rodata.*) - *libarch.a:*modem_clock_hal.*(.rodata .rodata.*) - *libarch.a:*regi2c_ctrl.*(.rodata .rodata.*) - *libarch.a:*gpio_periph.*(.rodata .rodata.*) - *libarch.a:*esp_rom_systimer.*(.rodata .rodata.*) - *libarch.a:*esp_rom_wdt.*(.rodata .rodata.*) - *libarch.a:*ocode_init.*(.rodata .rodata.*) - *libarch.a:*esp_rom_regi2c_esp32p4.*(.rodata .rodata.*) - *libarch.a:*rtc_clk.*(.rodata .rodata.*) - *libarch.a:*rtc_clk_init.*(.rodata .rodata.*) - *libarch.a:*pmu_param.*(.rodata .rodata.*) - *libarch.a:*pmu_sleep.*(.rodata .rodata.*) - *libarch.a:*rtc_time.*(.rodata .rodata.*) - *libarch.a:*systimer.*(.rodata .rodata.*) - *libarch.a:*systimer_hal.*(.rodata .rodata.*) - *libarch.a:*uart_hal_iram.*(.rodata .rodata.*) - *libarch.a:*wdt_hal_iram.*(.rodata .rodata.*) - *libarch.a:*bootloader_banner_wrap.*(.rodata .rodata.*) - *libarch.a:*bootloader_init.*(.rodata .rodata.*) - *libarch.a:*bootloader_common.*(.rodata .rodata.*) - *libarch.a:*bootloader_common_loader.*(.rodata .rodata.*) - *libarch.a:*bootloader_console.*(.rodata .rodata.*) - *libarch.a:*bootloader_console_loader.*(.rodata .rodata.*) - *libarch.a:*bootloader_esp32p4.*(.rodata .rodata.*) - *libarch.a:*bootloader_flash.*(.rodata .rodata.*) - *libarch.a:*bootloader_flash_config_esp32p4.*(.rodata .rodata.*) - *libarch.a:*flash_qio_mode.*(.rodata .rodata.*) - *libarch.a:*bootloader_clock_init.*(.rodata .rodata.*) - *libarch.a:*bootloader_clock_loader.*(.rodata .rodata.*) - *libarch.a:*bootloader_efuse.*(.rodata .rodata.*) - *libarch.a:*bootloader_panic.*(.rodata .rodata.*) - *libarch.a:*bootloader_mem.*(.rodata .rodata.*) - *libarch.a:*bootloader_random.*(.rodata .rodata.*) - *libarch.a:*bootloader_random_esp32p4.*(.rodata .rodata.*) - *libarch.a:*esp_image_format.*(.rodata .rodata.*) - *libarch.a:*bootloader_soc.*(.rodata .rodata.*) - *libarch.a:*bootloader_sha.*(.rodata .rodata.*) - *libarch.a:*flash_encrypt.*(.rodata .rodata.*) - *libarch.a:*cache_hal.*(.rodata .rodata.*) - *libarch.a:*uart_hal.*(.rodata .rodata.*) - *libarch.a:*mpu_hal.*(.rodata .rodata.*) - *libarch.a:*mmu_hal.*(.rodata .rodata.*) - *libarch.a:*uart_periph.*(.rodata .rodata.*) - *libarch.a:*esp_rom_uart.*(.rodata .rodata.*) - *libarch.a:*esp_rom_sys.*(.rodata .rodata.*) - *libarch.a:*esp_rom_spiflash.*(.rodata .rodata.*) - *libarch.a:*esp_efuse_fields.*(.rodata .rodata.*) - *libarch.a:*esp_efuse_api_key.*(.rodata .rodata.*) - *libarch.a:*esp_efuse_utility.*(.rodata .rodata.*) - *libarch.a:*efuse_hal.*(.rodata .rodata.*) - *libarch.a:*log.*(.rodata .rodata.*) - *libarch.a:*log_noos.*(.rodata .rodata.*) - *libarch.a:esp_spiflash.*(.rodata .rodata.*) - *libarch.a:esp_chip_rev.*(.rodata .rodata.*) - *libarch.a:critical_section.*(.rodata .rodata.*) - *libarch.a:os.*(.rodata.g_int_flags_count .rodata.g_int_flags) - *libarch.a:spi_flash_hpm_enable.*(.rodata .rodata.*) - *libarch.a:*sleep_modes.*(.rodata.esp_sleep_pd_config*) - *libarch.a:esp_flash_api.*(.rodata .rodata.*) - *libarch.a:esp_flash_spi_init.*(.rodata .rodata.*) - *libarch.a:spi_flash_hal_iram.*(.rodata .rodata.*) - *libarch.a:spi_flash_encrypt_hal_iram.*(.rodata .rodata.*) - *libarch.a:spi_flash_hal_gpspi.*(.rodata .rodata.*) - *libarch.a:spi_flash_chip*.*(.rodata .rodata.*) - *libarch.a:spi_flash_wrap.*(.rodata .rodata.*) - *libarch.a:spi_flash_os_func_noos.*(.rodata .rodata.*) - *libarch.a:spi_flash_os_func_app.*(.rodata .rodata.*) - *libarch.a:flash_brownout_hook.*(.rodata .rodata.*) - *libarch.a:esp_cache.*(.rodata .rodata.*) - *libarch.a:cache_utils.*(.rodata .rodata.*) - *libarch.a:memspi_host_driver.*(.rodata .rodata.*) - *libarch.a:esp_psram_impl_ap_hex.*(.rodata .rodata.*) - *libarch.a:cpu_region_protect.*(.rodata .rodata.*) + *arch.a:*(.rodata.esprv_intc_int_get_type) + *arch.a:*riscv_doirq.*(.rodata .rodata.*) + *arch.a:*brownout.*(.rodata .rodata.*) + *arch.a:*cpu.*(.rodata .rodata.*) + *arch.a:*gpio_hal.*(.rodata .rodata.*) + *arch.a:*periph_ctrl.*(.rodata .rodata.*) + *arch.a:*clk.*(.rodata .rodata.*) + *arch.a:*esp_clk.*(.rodata .rodata.*) + *arch.a:*esp_clk_tree.*(.rodata .rodata.*) + *arch.a:*esp_clk_tree_common.*(.rodata .rodata.*) + *arch.a:*clk_tree_hal.*(.rodata .rodata.*) + *arch.a:*pmu_init.*(.rodata .rodata.*) + *arch.a:*modem_clock.*(.rodata .rodata.*) + *arch.a:*modem_clock_hal.*(.rodata .rodata.*) + *arch.a:*regi2c_ctrl.*(.rodata .rodata.*) + *arch.a:*gpio_periph.*(.rodata .rodata.*) + *arch.a:*esp_rom_systimer.*(.rodata .rodata.*) + *arch.a:*esp_rom_wdt.*(.rodata .rodata.*) + *arch.a:*ocode_init.*(.rodata .rodata.*) + *arch.a:*esp_rom_regi2c_esp32p4.*(.rodata .rodata.*) + *arch.a:*rtc_clk.*(.rodata .rodata.*) + *arch.a:*rtc_clk_init.*(.rodata .rodata.*) + *arch.a:*pmu_param.*(.rodata .rodata.*) + *arch.a:*pmu_sleep.*(.rodata .rodata.*) + *arch.a:*rtc_time.*(.rodata .rodata.*) + *arch.a:*systimer.*(.rodata .rodata.*) + *arch.a:*systimer_hal.*(.rodata .rodata.*) + *arch.a:*uart_hal_iram.*(.rodata .rodata.*) + *arch.a:*wdt_hal_iram.*(.rodata .rodata.*) + *arch.a:*bootloader_banner_wrap.*(.rodata .rodata.*) + *arch.a:*bootloader_init.*(.rodata .rodata.*) + *arch.a:*bootloader_common.*(.rodata .rodata.*) + *arch.a:*bootloader_common_loader.*(.rodata .rodata.*) + *arch.a:*bootloader_console.*(.rodata .rodata.*) + *arch.a:*bootloader_console_loader.*(.rodata .rodata.*) + *arch.a:*bootloader_esp32p4.*(.rodata .rodata.*) + *arch.a:*bootloader_flash.*(.rodata .rodata.*) + *arch.a:*bootloader_flash_config_esp32p4.*(.rodata .rodata.*) + *arch.a:*flash_qio_mode.*(.rodata .rodata.*) + *arch.a:*bootloader_clock_init.*(.rodata .rodata.*) + *arch.a:*bootloader_clock_loader.*(.rodata .rodata.*) + *arch.a:*bootloader_efuse.*(.rodata .rodata.*) + *arch.a:*bootloader_panic.*(.rodata .rodata.*) + *arch.a:*bootloader_mem.*(.rodata .rodata.*) + *arch.a:*bootloader_random.*(.rodata .rodata.*) + *arch.a:*bootloader_random_esp32p4.*(.rodata .rodata.*) + *arch.a:*esp_image_format.*(.rodata .rodata.*) + *arch.a:*bootloader_soc.*(.rodata .rodata.*) + *arch.a:*bootloader_sha.*(.rodata .rodata.*) + *arch.a:*flash_encrypt.*(.rodata .rodata.*) + *arch.a:*cache_hal.*(.rodata .rodata.*) + *arch.a:*uart_hal.*(.rodata .rodata.*) + *arch.a:*mpu_hal.*(.rodata .rodata.*) + *arch.a:*mmu_hal.*(.rodata .rodata.*) + *arch.a:*uart_periph.*(.rodata .rodata.*) + *arch.a:*esp_rom_uart.*(.rodata .rodata.*) + *arch.a:*esp_rom_sys.*(.rodata .rodata.*) + *arch.a:*esp_rom_spiflash.*(.rodata .rodata.*) + *arch.a:*esp_efuse_fields.*(.rodata .rodata.*) + *arch.a:*esp_efuse_api_key.*(.rodata .rodata.*) + *arch.a:*esp_efuse_utility.*(.rodata .rodata.*) + *arch.a:*efuse_hal.*(.rodata .rodata.*) + *arch.a:*log.*(.rodata .rodata.*) + *arch.a:*log_noos.*(.rodata .rodata.*) + *arch.a:esp_spiflash.*(.rodata .rodata.*) + *arch.a:esp_chip_rev.*(.rodata .rodata.*) + *arch.a:critical_section.*(.rodata .rodata.*) + *arch.a:os.*(.rodata.g_int_flags_count .rodata.g_int_flags) + *arch.a:spi_flash_hpm_enable.*(.rodata .rodata.*) + *arch.a:*sleep_modes.*(.rodata.esp_sleep_pd_config*) + *arch.a:esp_flash_api.*(.rodata .rodata.*) + *arch.a:esp_flash_spi_init.*(.rodata .rodata.*) + *arch.a:spi_flash_hal_iram.*(.rodata .rodata.*) + *arch.a:spi_flash_encrypt_hal_iram.*(.rodata .rodata.*) + *arch.a:spi_flash_hal_gpspi.*(.rodata .rodata.*) + *arch.a:spi_flash_chip*.*(.rodata .rodata.*) + *arch.a:spi_flash_wrap.*(.rodata .rodata.*) + *arch.a:spi_flash_os_func_noos.*(.rodata .rodata.*) + *arch.a:spi_flash_os_func_app.*(.rodata .rodata.*) + *arch.a:flash_brownout_hook.*(.rodata .rodata.*) + *arch.a:esp_cache.*(.rodata .rodata.*) + *arch.a:cache_utils.*(.rodata .rodata.*) + *arch.a:memspi_host_driver.*(.rodata .rodata.*) + *arch.a:esp_psram_impl_ap_hex.*(.rodata .rodata.*) + *arch.a:cpu_region_protect.*(.rodata .rodata.*) + *arch.a:esp_region_protect.*(.rodata .rodata.*) esp_head.*(.rodata .rodata.*) esp_start.*(.rodata .rodata.*) diff --git a/boards/risc-v/esp32p4/common/scripts/kernel-space.ld b/boards/risc-v/esp32p4/common/scripts/kernel-space.ld new file mode 100644 index 0000000000000..089e02672a374 --- /dev/null +++ b/boards/risc-v/esp32p4/common/scripts/kernel-space.ld @@ -0,0 +1,76 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/common/scripts/kernel-space.ld + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Kernel image layout for the protected build. + * + * The kernel's own output sections are identical to the flat build's, so + * rather than maintaining a second copy of a 700-line script this exports + * the region boundaries and then includes esp32p4_sections.ld verbatim. + * The split between kernel and user is expressed entirely in + * esp32p4_protected_memory.ld, whose REGION_ALIAS definitions point the + * flat script's region names at the kernel's half of the map. + * + * The symbols below are what the kernel needs at run time. The __u* ones + * are consumed by esp_userspace.c to program the flash MMU and the PMP; the + * __k* ones are exported for debugging and for board_memorymap.h. + ****************************************************************************/ + +#include + +/* User regions. esp_userspace.c uses these to describe what user mode may + * reach; everything not covered is denied to user mode by default. + */ + +__uirom_start = ORIGIN(UIROM); +__uirom_size = LENGTH(UIROM); +__uirom_end = ORIGIN(UIROM) + LENGTH(UIROM); +__udrom_start = ORIGIN(UDROM); +__udrom_size = LENGTH(UDROM); +__udrom_end = ORIGIN(UDROM) + LENGTH(UDROM); +__udram_start = ORIGIN(UDRAM); +__udram_size = LENGTH(UDRAM); +__udram_end = ORIGIN(UDRAM) + LENGTH(UDRAM); + +/* There is no UIRAM region: user code executes in place from flash. The + * symbols are still defined, pointing at an empty span at the base of + * UDRAM, so that board_memorymap.h can declare them unconditionally. + */ + +__uiram_start = ORIGIN(UDRAM); +__uiram_size = 0; +__uiram_end = ORIGIN(UDRAM); + +/* Kernel regions */ + +__kirom_start = ORIGIN(KIROM); +__kirom_size = LENGTH(KIROM); +__kdrom_start = ORIGIN(KDROM); +__kdrom_size = LENGTH(KDROM); +__kiram_start = ORIGIN(KRAM); +__kiram_size = LENGTH(KRAM); +__kiram_end = ORIGIN(KRAM) + LENGTH(KRAM); +__kdram_start = ORIGIN(KRAM); +__kdram_size = LENGTH(KRAM); +__kdram_end = ORIGIN(KRAM) + LENGTH(KRAM); + +#include "esp32p4_sections.ld" diff --git a/boards/risc-v/esp32p4/common/scripts/user-space.ld b/boards/risc-v/esp32p4/common/scripts/user-space.ld new file mode 100644 index 0000000000000..27c59e5989566 --- /dev/null +++ b/boards/risc-v/esp32p4/common/scripts/user-space.ld @@ -0,0 +1,221 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/common/scripts/user-space.ld + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * User image layout for the protected build. + * + * Two differences from the equivalent ESP32-C3 script are worth noting: + * + * 1. There is no UIRAM region. On the C3, IRAM and DRAM are two views of + * the same internal SRAM at different addresses, so the user image needs + * an .iram0.text section and a .dram0.dummy section to skip past it. + * SRAM is unified here, and user code executes in place from flash, so + * .iram1 input sections are collected into the flash text output section + * and neither the IRAM output section nor the dummy is required. + * + * 2. The metadata block is 0x80 bytes rather than 0x18. UDROM starts + * immediately after it and that address becomes a PMP TOR boundary, so + * it has to respect this SoC's 128-byte PMP granularity. + ****************************************************************************/ + +#include + +SECTIONS +{ + /* Consumed by esp_userspace.c in the kernel before any user code is + * reachable. The layout must match struct user_image_load_header_s. + */ + + .metadata : + { + /* DROM: destination address, flash offset, size */ + + LONG(ADDR(.userspace)) + LONG(LOADADDR(.userspace)) + LONG(SIZEOF(.userspace) + SIZEOF(.rodata)) + + /* IROM: destination address, flash offset, size */ + + LONG(ADDR(.text)) + LONG(LOADADDR(.text)) + LONG(SIZEOF(.text)) + } >metadata + + /* Region boundaries, for the user image's own use */ + + __ld_uirom_start = ORIGIN(UIROM); + __ld_uirom_size = LENGTH(UIROM); + __ld_uirom_end = ORIGIN(UIROM) + LENGTH(UIROM); + __ld_udrom_start = ORIGIN(UDROM); + __ld_udrom_size = LENGTH(UDROM); + __ld_udrom_end = ORIGIN(UDROM) + LENGTH(UDROM); + __ld_udram_start = ORIGIN(UDRAM); + __ld_udram_size = LENGTH(UDRAM); + __ld_udram_end = ORIGIN(UDRAM) + LENGTH(UDRAM); + + _eronly = LOADADDR(.data); + + .userspace : { + *(.userspace) + } >UDROM AT>ROM + + /* Output sections carry standard names rather than the Espressif-usual + * ".flash.text" so that GDB's "add-symbol-file" can find a .text section + * when symbols from both images are loaded together. + */ + + .rodata : + { + _srodata = ABSOLUTE(.); + + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + + /* Collect the small read-only sections here too. Left to themselves the + * linker emits them as orphan output sections after .rodata, and their + * unaligned sizes then push the load address of .data to an odd offset. + */ + + *(.srodata) + *(.srodata.*) + *(.sdata2) + *(.sdata2.*) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + + /* C++ constructor and destructor tables: classes would be sorted by + * init priority, but NuttX does not use priorities here. + */ + + _sinit = ABSOLUTE(.); + KEEP (*(.init_array .init_array.*)) + _einit = ABSOLUTE(.); + + KEEP (*(.fini_array .fini_array.*)) + + *(.lit4) + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + + /* esp_userspace() copies .data out of flash with bootloader_flash_read(), + * which requires an aligned source address; .data's load address follows + * the end of this section, so pad to 16 here and again at the end of + * .data so that both the offset and the length are aligned. + */ + + . = ALIGN(16); + _erodata = ABSOLUTE(.); + } >UDROM AT>ROM + + .noinit (NOLOAD): + { + /* Data that is neither loaded nor initialised at startup */ + + *(.noinit) + *(.noinit.*) + } >UDRAM + + .data : + { + _sdata = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + *(.dram1) + *(.dram1.*) + . = ALIGN(16); + _edata = ABSOLUTE(.); + } >UDRAM AT>ROM + + .bss (NOLOAD) : + { + . = ALIGN (8); + _sbss = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + + . = ALIGN (32); + _ebss = ABSOLUTE(.); + } >UDRAM + + /* Skip the flash space already consumed by .userspace and .rodata so that + * the text output section's load address follows them in the image while + * its virtual address sits in UIROM. + */ + + .flash_text_dummy (NOLOAD) : ALIGN(0x00010000) + { + . = SIZEOF(.userspace) + SIZEOF(.rodata); + } >UIROM + + .text : ALIGN(0x00010000) + { + _stext = .; + + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + + /* No UIRAM region on this SoC: anything the user image marked for + * internal instruction RAM is executed in place from flash instead. + */ + + *(.iram1) + *(.iram1.*) + + *(.fini.literal) + *(.fini) + *(.gnu.version) + _etext = .; + } >UIROM AT>ROM +} diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/configs/knsh/defconfig b/boards/risc-v/esp32p4/esp32p4-tab5/configs/knsh/defconfig new file mode 100644 index 0000000000000..9024fc3183647 --- /dev/null +++ b/boards/risc-v/esp32p4/esp32p4-tab5/configs/knsh/defconfig @@ -0,0 +1,72 @@ +# +# 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_ESPRESSIF_REGION_PROTECTION is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32p4-tab5" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32P4_TAB5=y +CONFIG_ARCH_CHIP="esp32p4" +CONFIG_ARCH_CHIP_ESP32P4=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_IRQ_TO_NDX=y +CONFIG_ARCH_MINIMAL_VECTORTABLE_DYNAMIC=y +CONFIG_ARCH_NUSER_INTERRUPTS=17 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILD_PROTECTED=y +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_BINFMT=y +CONFIG_DEBUG_BINFMT_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SCHED=y +CONFIG_DEBUG_SCHED_ERROR=y +CONFIG_DEBUG_SCHED_WARN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_SYSCALL=y +CONFIG_DEBUG_SYSCALL_ERROR=y +CONFIG_DEBUG_SYSCALL_WARN=y +CONFIG_ESP32P4_REV_MIN_100=y +CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y +CONFIG_ESPRESSIF_FLASH_16M=y +CONFIG_ESPRESSIF_KERNEL_OWNS_PMP=y +CONFIG_ESPRESSIF_SPIRAM=y +CONFIG_EXPERIMENTAL=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_MM_REGIONS=3 +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_NUTTX_USERSPACE=0x40300080 +CONFIG_PASS1_BUILDIR="boards/risc-v/esp32p4/common/kernel" +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=18 +CONFIG_START_MONTH=3 +CONFIG_START_YEAR=2026 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_TESTING_RAMTEST=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/include/board_memorymap.h b/boards/risc-v/esp32p4/esp32p4-tab5/include/board_memorymap.h new file mode 100644 index 0000000000000..4019a9a01fe2c --- /dev/null +++ b/boards/risc-v/esp32p4/esp32p4-tab5/include/board_memorymap.h @@ -0,0 +1,118 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/esp32p4-tab5/include/board_memorymap.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +#ifndef __BOARDS_RISCV_ESP32P4_ESP32P4_TAB5_INCLUDE_BOARD_MEMORYMAP_H +#define __BOARDS_RISCV_ESP32P4_ESP32P4_TAB5_INCLUDE_BOARD_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Kernel ROM */ + +#define KIROM_START (uintptr_t)__kirom_start +#define KIROM_SIZE (uintptr_t)__kirom_size +#define KDROM_START (uintptr_t)__kdrom_start +#define KDROM_SIZE (uintptr_t)__kdrom_size + +/* Kernel RAM */ + +#define KIRAM_START (uintptr_t)__kiram_start +#define KIRAM_SIZE (uintptr_t)__kiram_size +#define KIRAM_END (uintptr_t)__kiram_end +#define KDRAM_START (uintptr_t)__kdram_start +#define KDRAM_SIZE (uintptr_t)__kdram_size +#define KDRAM_END (uintptr_t)__kdram_end + +/* Exception vectors */ + +#define VECTORS_START (uintptr_t)__vectors_start +#define VECTORS_END (uintptr_t)__vectors_end + +/* User ROM */ + +#define UIROM_START (uintptr_t)__uirom_start +#define UIROM_SIZE (uintptr_t)__uirom_size +#define UIROM_END (uintptr_t)__uirom_end +#define UDROM_START (uintptr_t)__udrom_start +#define UDROM_SIZE (uintptr_t)__udrom_size +#define UDROM_END (uintptr_t)__udrom_end + +/* User RAM */ + +#define UIRAM_START (uintptr_t)__uiram_start +#define UIRAM_SIZE (uintptr_t)__uiram_size +#define UIRAM_END (uintptr_t)__uiram_end +#define UDRAM_START (uintptr_t)__udram_start +#define UDRAM_SIZE (uintptr_t)__udram_size +#define UDRAM_END (uintptr_t)__udram_end + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Kernel ROM (RX) */ + +extern uint8_t __kirom_start[]; +extern uint8_t __kirom_size[]; +extern uint8_t __kdrom_start[]; +extern uint8_t __kdrom_size[]; + +/* Kernel RAM (RW) */ + +extern uint8_t __kiram_start[]; +extern uint8_t __kiram_size[]; +extern uint8_t __kiram_end[]; +extern uint8_t __kdram_start[]; +extern uint8_t __kdram_size[]; +extern uint8_t __kdram_end[]; + +/* Exception vectors */ + +extern uint8_t __vectors_start[]; +extern uint8_t __vectors_end[]; + +/* User ROM (RX) */ + +extern uint8_t __uirom_start[]; +extern uint8_t __uirom_size[]; +extern uint8_t __uirom_end[]; +extern uint8_t __udrom_start[]; +extern uint8_t __udrom_size[]; +extern uint8_t __udrom_end[]; + +/* User RAM (RW) */ + +extern uint8_t __uiram_start[]; +extern uint8_t __uiram_size[]; +extern uint8_t __uiram_end[]; +extern uint8_t __udram_start[]; +extern uint8_t __udram_size[]; +extern uint8_t __udram_end[]; + +#endif /* __BOARDS_RISCV_ESP32P4_ESP32P4_TAB5_INCLUDE_BOARD_MEMORYMAP_H */ diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/scripts/Make.defs b/boards/risc-v/esp32p4/esp32p4-tab5/scripts/Make.defs index 51e5bbbf46c55..27c5fe5c3ba02 100644 --- a/boards/risc-v/esp32p4/esp32p4-tab5/scripts/Make.defs +++ b/boards/risc-v/esp32p4/esp32p4-tab5/scripts/Make.defs @@ -34,18 +34,33 @@ CHIP_SERIES = $(patsubst "%",%,$(CONFIG_ESPRESSIF_CHIP_SERIES)) ARCHSCRIPT += $(BOARD_COMMON_DIR)/scripts/$(CHIP_SERIES)_aliases.ld -ARCHSCRIPT += $(call FINDSCRIPT,$(CHIP_SERIES)_flat_memory.ld) - ifneq ($(CONFIG_ESP32P4_SELECTS_REV_LESS_V3),y) BOARD_REV = .rev3 endif +ifeq ($(CONFIG_BUILD_PROTECTED),y) + +# Protected build: the kernel image is linked against its own half of the +# memory map. kernel-space.ld exports the region boundaries and then pulls +# in the flat sections script, so the two stay in step -- the sections script +# must NOT also be added here, or .flash.text is defined twice. + +ARCHSCRIPT += $(call FINDSCRIPT,$(CHIP_SERIES)_protected_memory.ld) +ARCHSCRIPT += $(call FINDSCRIPT,kernel-space.ld) + +else + +ARCHSCRIPT += $(call FINDSCRIPT,$(CHIP_SERIES)_flat_memory.ld) + ifeq ($(CONFIG_ESPRESSIF_BOOTLOADER_MCUBOOT),y) ARCHSCRIPT += $(call FINDSCRIPT,$(CHIP_SERIES)_sections$(BOARD_REV).ld) else ifeq ($(CONFIG_ESPRESSIF_SIMPLE_BOOT),y) ARCHSCRIPT += $(call FINDSCRIPT,$(CHIP_SERIES)_sections$(BOARD_REV).ld) endif +endif + +ARCHPICFLAGS = -fpic CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -Werror=return-type CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_bringup.c b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_bringup.c index 850ea1e3b62bf..d5c9997a436c8 100644 --- a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_bringup.c +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_bringup.c @@ -34,6 +34,12 @@ #include "espressif/esp_start.h" +#ifdef CONFIG_ESPRESSIF_P4DBG +# include +# include +# include "riscv_internal.h" +#endif + #ifdef CONFIG_ESPRESSIF_SPIFLASH # include "esp_board_spiflash.h" #endif @@ -77,10 +83,47 @@ * ****************************************************************************/ +#ifdef CONFIG_ESPRESSIF_P4DBG +/* Declared locally: the HAL header that provides this is not on the include + * path for board sources. esp_start.c declares ets_printf() the same way. + */ + +extern int esp_rom_printf(const char *fmt, ...) printf_like(1, 2); + +/**************************************************************************** + * Name: protected_fault_handler + * + * Description: + * Bring-up scaffolding. Reports a CPU exception using the ROM printf + * rather than syslog(), which needs a working scheduler and console. + * + ****************************************************************************/ + +static int protected_fault_handler(int irq, void *context, void *arg) +{ + uintreg_t *regs = (uintreg_t *)context; + + esp_rom_printf("FAULT: irq=%d epc=0x%x sp=0x%x ra=0x%x mstatus=0x%x\n", + irq, (unsigned int)regs[REG_EPC], + (unsigned int)regs[REG_SP], (unsigned int)regs[REG_RA], + (unsigned int)regs[REG_INT_CTX]); + + for (; ; ) + { + } + + return OK; +} +#endif + int esp_bringup(void) { int ret = OK; +#ifdef CONFIG_ESPRESSIF_P4DBG + esp_rom_printf("bringup: enter\n"); +#endif + #ifdef CONFIG_FS_PROCFS /* Mount the procfs file system */ @@ -253,5 +296,22 @@ int esp_bringup(void) * capabilities. */ +#ifdef CONFIG_ESPRESSIF_P4DBG + esp_rom_printf("bringup: done ret=%d\n", ret); + syslog(LOG_ERR, "bringup: syslog reaches the console\n"); + + /* Take over the fault vectors for the remainder of bring-up, so that a + * fault entering user mode announces itself. + */ + + irq_attach(RISCV_IRQ_IAFAULT, protected_fault_handler, NULL); + irq_attach(RISCV_IRQ_LAFAULT, protected_fault_handler, NULL); + irq_attach(RISCV_IRQ_SAFAULT, protected_fault_handler, NULL); + irq_attach(RISCV_IRQ_IINSTRUCTION, protected_fault_handler, NULL); + irq_attach(RISCV_IRQ_IAMISALIGNED, protected_fault_handler, NULL); + irq_attach(RISCV_IRQ_LAMISALIGNED, protected_fault_handler, NULL); + irq_attach(RISCV_IRQ_SAMISALIGNED, protected_fault_handler, NULL); +#endif + return ret; } diff --git a/tools/espressif/Config.mk b/tools/espressif/Config.mk index 1c705c294a5f5..9fd2a243ea92b 100644 --- a/tools/espressif/Config.mk +++ b/tools/espressif/Config.mk @@ -144,6 +144,16 @@ endif ESPTOOL_BINS += $(FLASH_APP) $(ENC_APP) +# A protected build produces a second image. nuttx_user.bin is a raw binary +# whose first bytes are the metadata block that esp_userspace() reads to learn +# where the user image expects its flash-mapped regions; it is not an +# Espressif application image and is written at its own offset rather than +# being merged into nuttx.bin. + +ifeq ($(CONFIG_BUILD_PROTECTED),y) + ESPTOOL_BINS += $(CONFIG_ESPRESSIF_USER_IMAGE_OFFSET) nuttx_user.bin +endif + # Commands for colored and formatted output RED = \033[1;31m