You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/05/18 03:43:58 UTC
[incubator-nuttx] 01/02: risc-v/esp32c3: Add support for Protected Mode
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit c778f35f08fd8e8867fe9d8ae4ccfa33ee2dacd5
Author: Gustavo Henrique Nihei <gu...@espressif.com>
AuthorDate: Mon Apr 11 21:09:25 2022 -0300
risc-v/esp32c3: Add support for Protected Mode
Signed-off-by: Gustavo Henrique Nihei <gu...@espressif.com>
---
arch/risc-v/Kconfig | 1 +
arch/risc-v/src/esp32c3/Bootloader.mk | 2 +
arch/risc-v/src/esp32c3/Kconfig | 10 +
arch/risc-v/src/esp32c3/Make.defs | 10 +
arch/risc-v/src/esp32c3/esp32c3_allocateheap.c | 82 ++++-
arch/risc-v/src/esp32c3/esp32c3_start.c | 25 +-
arch/risc-v/src/esp32c3/esp32c3_userspace.c | 403 +++++++++++++++++++++
arch/risc-v/src/esp32c3/esp32c3_userspace.h | 49 +++
.../esp32c3/esp32c3-devkit/configs/knsh/defconfig | 57 +++
.../esp32c3-devkit/include/board_memorymap.h | 116 ++++++
.../risc-v/esp32c3/esp32c3-devkit/kernel/Makefile | 98 +++++
.../esp32c3-devkit/kernel/esp32c3_userspace.c | 114 ++++++
.../esp32c3/esp32c3-devkit/scripts/Make.defs | 10 +-
.../esp32c3/esp32c3-devkit/scripts/kernel-space.ld | 230 ++++++++++++
.../esp32c3-devkit/scripts/protected.template.ld | 95 +++++
.../esp32c3/esp32c3-devkit/scripts/user-space.ld | 214 +++++++++++
boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile | 4 +
tools/esp32c3/Config.mk | 4 +
18 files changed, 1507 insertions(+), 17 deletions(-)
diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig
index 025e186d97..f2e05f50fa 100644
--- a/arch/risc-v/Kconfig
+++ b/arch/risc-v/Kconfig
@@ -67,6 +67,7 @@ config ARCH_CHIP_ESP32C3
select ARCH_RV_ISA_M
select ARCH_RV_ISA_C
select ARCH_VECNOTIRQ
+ select ARCH_HAVE_MPU
select ARCH_HAVE_RESET
select LIBC_ARCH_ATOMIC
select LIBC_ARCH_MEMCPY
diff --git a/arch/risc-v/src/esp32c3/Bootloader.mk b/arch/risc-v/src/esp32c3/Bootloader.mk
index ba399457da..7b6429f4a1 100644
--- a/arch/risc-v/src/esp32c3/Bootloader.mk
+++ b/arch/risc-v/src/esp32c3/Bootloader.mk
@@ -34,6 +34,7 @@ $(BOOTLOADER_SRCDIR):
# Helpers for creating the configuration file
cfg_en = echo "$(1)=$(if $(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),1,y)";
+cfg_dis = echo "$(1)=$(if $(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),0,n)";
cfg_val = echo "$(1)=$(2)";
# Commands for colored and formatted output
@@ -96,6 +97,7 @@ ifeq ($(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),y)
} >> $(BOOTLOADER_CONFIG)
else ifeq ($(CONFIG_ESP32C3_APP_FORMAT_LEGACY),y)
$(Q) { \
+ $(if $(CONFIG_BUILD_PROTECTED),$(call cfg_dis,CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE)) \
$(call cfg_en,CONFIG_PARTITION_TABLE_CUSTOM) \
$(call cfg_val,CONFIG_PARTITION_TABLE_CUSTOM_FILENAME,\"partitions.csv\") \
$(call cfg_val,CONFIG_PARTITION_TABLE_OFFSET,$(CONFIG_ESP32C3_PARTITION_TABLE_OFFSET)) \
diff --git a/arch/risc-v/src/esp32c3/Kconfig b/arch/risc-v/src/esp32c3/Kconfig
index 92b9e1cba6..aa91feb89a 100644
--- a/arch/risc-v/src/esp32c3/Kconfig
+++ b/arch/risc-v/src/esp32c3/Kconfig
@@ -1150,6 +1150,16 @@ config ESP32C3_PARTITION_TABLE_OFFSET
default 0x8000
depends on ESP32C3_APP_FORMAT_LEGACY
+if BUILD_PROTECTED
+
+config ESP32C3_USER_IMAGE_OFFSET
+ hex "User image offset"
+ default 0x90000
+ ---help---
+ Offset in SPI Flash for flashing the User application firmware image.
+
+endif
+
source "arch/risc-v/src/esp32c3/Kconfig.security"
endmenu # Application Image Configuration
diff --git a/arch/risc-v/src/esp32c3/Make.defs b/arch/risc-v/src/esp32c3/Make.defs
index db2ff2b812..ab16d97406 100644
--- a/arch/risc-v/src/esp32c3/Make.defs
+++ b/arch/risc-v/src/esp32c3/Make.defs
@@ -56,6 +56,10 @@ CMN_ASRCS += vfork.S
CMN_CSRCS += riscv_vfork.c
endif
+ifeq ($(CONFIG_ARCH_USE_MPU),y)
+CMN_CSRCS += riscv_pmp.c
+endif
+
# Specify our C code within this directory to be included
CHIP_CSRCS = esp32c3_allocateheap.c esp32c3_start.c esp32c3_wdt.c esp32c3_idle.c
@@ -65,6 +69,12 @@ CHIP_CSRCS += esp32c3_lowputc.c esp32c3_serial.c
CHIP_CSRCS += esp32c3_systemreset.c esp32c3_resetcause.c
CHIP_CSRCS += esp32c3_uid.c
+ifeq ($(CONFIG_BUILD_PROTECTED),y)
+CHIP_CSRCS += esp32c3_userspace.c
+CMN_UASRCS += riscv_signal_handler.S
+CMN_CSRCS += riscv_task_start.c riscv_pthread_start.c riscv_signal_dispatch.c
+endif
+
ifeq ($(CONFIG_SCHED_TICKLESS),y)
CHIP_CSRCS += esp32c3_tickless.c
else
diff --git a/arch/risc-v/src/esp32c3/esp32c3_allocateheap.c b/arch/risc-v/src/esp32c3/esp32c3_allocateheap.c
index 42d68e1961..f5997a6f3c 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_allocateheap.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_allocateheap.c
@@ -24,16 +24,19 @@
#include <nuttx/config.h>
-#include <sys/types.h>
#include <debug.h>
+#include <sys/types.h>
-#include <nuttx/mm/mm.h>
#include <nuttx/arch.h>
#include <nuttx/board.h>
+#include <nuttx/mm/mm.h>
+#include <nuttx/userspace.h>
#include <arch/board/board.h>
+#ifdef CONFIG_MM_KERNEL_HEAP
+#include <arch/board/board_memorymap.h>
+#endif
#include "esp32c3.h"
-
#include "hardware/esp32c3_rom_layout.h"
/****************************************************************************
@@ -50,19 +53,42 @@
* Description:
* This function will be called to dynamically set aside the heap region.
*
- * For the kernel build (CONFIG_BUILD_KERNEL=y) with both kernel- and
- * user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the
- * size of the unprotected, user-space heap.
+ * For the kernel build (CONFIG_BUILD_KERNEL=y) with both kernel and
+ * userspace heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the
+ * size of the unprotected, userspace heap.
*
- * If a protected kernel-space heap is provided, the kernel heap must be
+ * If a protected kernel space heap is provided, the kernel heap must be
* allocated (and protected) by an analogous up_allocate_kheap().
*
****************************************************************************/
void up_allocate_heap(void **heap_start, size_t *heap_size)
{
+#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP)
+ extern const struct esp32c3_rom_layout_s *ets_rom_layout_p;
+
+ uintptr_t ubase = USERSPACE->us_dataend;
+ uintptr_t utop = ets_rom_layout_p->dram0_rtos_reserved_start;
+ size_t usize = utop - ubase;
+
+ minfo("Heap: start=%" PRIxPTR " end=%" PRIxPTR " size=%zu\n",
+ ubase, utop, usize);
+
+ board_autoled_on(LED_HEAPALLOCATE);
+
+ /* Return the userspace heap settings */
+
+ *heap_start = (void *)ubase;
+ *heap_size = usize;
+
+ /* Allow user-mode access to the user heap memory in PMP
+ * is already done in esp32c3_userspace().
+ */
+
+#else
/* These values come from the linker scripts (esp32c3.ld and
- * esp32c3.template.ld.) Check boards/risc-v/esp32c3.
+ * esp32c3.template.ld).
+ * Check boards/risc-v/esp32c3.
*/
extern uint8_t *_sheap;
@@ -71,9 +97,47 @@ void up_allocate_heap(void **heap_start, size_t *heap_size)
board_autoled_on(LED_HEAPALLOCATE);
*heap_start = (void *)&_sheap;
- *heap_size = (size_t)(ets_rom_layout_p->dram0_rtos_reserved_start -
+ *heap_size = (size_t)(ets_rom_layout_p->dram0_rtos_reserved_start -
(uintptr_t)&_sheap);
+#endif /* CONFIG_BUILD_PROTECTED && CONFIG_MM_KERNEL_HEAP */
+}
+
+/****************************************************************************
+ * Name: up_allocate_kheap
+ *
+ * Description:
+ * This function will be called to dynamically set aside the heap region.
+ *
+ * For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel and
+ * userspace heaps (CONFIG_MM_KERNEL_HEAP=y), this function allocates
+ * (and protects) the kernel space heap.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) && \
+ defined(__KERNEL__)
+void up_allocate_kheap(void **heap_start, size_t *heap_size)
+{
+ /* These values come from the linker scripts (kernel-space.ld and
+ * protected.template.ld).
+ * Check boards/risc-v/esp32c3.
+ */
+
+ extern uint8_t *_sheap;
+
+ uintptr_t kbase = (uintptr_t)&_sheap;
+ uintptr_t ktop = KDRAM_END;
+ size_t ksize = ktop - kbase;
+
+ minfo("Heap: start=%" PRIxPTR " end=%" PRIxPTR " size=%zu\n",
+ kbase, ktop, ksize);
+
+ board_autoled_on(LED_HEAPALLOCATE);
+
+ *heap_start = (void *)kbase;
+ *heap_size = ksize;
}
+#endif /* CONFIG_BUILD_PROTECTED && CONFIG_MM_KERNEL_HEAP */
/****************************************************************************
* Name: riscv_addregion
diff --git a/arch/risc-v/src/esp32c3/esp32c3_start.c b/arch/risc-v/src/esp32c3/esp32c3_start.c
index 0bc54c7a1c..2679cd6d15 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_start.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_start.c
@@ -30,19 +30,21 @@
#include <arch/board/board.h>
#include "esp32c3.h"
+#ifdef CONFIG_ESP32C3_BROWNOUT_DET
+# include "esp32c3_brownout.h"
+#endif
#include "esp32c3_clockconfig.h"
#include "esp32c3_irq.h"
#include "esp32c3_lowputc.h"
+#include "esp32c3_rtc.h"
#include "esp32c3_start.h"
#include "esp32c3_wdt.h"
-#include "esp32c3_rtc.h"
+#ifdef CONFIG_BUILD_PROTECTED
+# include "esp32c3_userspace.h"
+#endif
#include "hardware/esp32c3_cache_memory.h"
#include "hardware/extmem_reg.h"
-#ifdef CONFIG_ESP32C3_BROWNOUT_DET
-# include "esp32c3_brownout.h"
-#endif
-
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -292,6 +294,19 @@ void __esp32c3_start(void)
esp32c3_board_initialize();
+ showprogress('C');
+
+ /* 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 user space .data and .bss
+ * segments.
+ */
+
+#ifdef CONFIG_BUILD_PROTECTED
+ esp32c3_userspace();
+ showprogress('D');
+#endif
+
/* Bring up NuttX */
nx_start();
diff --git a/arch/risc-v/src/esp32c3/esp32c3_userspace.c b/arch/risc-v/src/esp32c3/esp32c3_userspace.c
new file mode 100755
index 0000000000..9f885a92e5
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_userspace.c
@@ -0,0 +1,403 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_userspace.c
+ *
+ * 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 <nuttx/config.h>
+
+#include <assert.h>
+#include <debug.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <nuttx/userspace.h>
+
+#include <arch/board/board_memorymap.h>
+
+#include "riscv_internal.h"
+#include "esp32c3.h"
+#include "esp32c3_userspace.h"
+#include "hardware/esp32c3_cache_memory.h"
+#include "hardware/extmem_reg.h"
+
+#ifdef CONFIG_BUILD_PROTECTED
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define USER_IMAGE_OFFSET CONFIG_ESP32C3_USER_IMAGE_OFFSET
+
+#define MMU_BLOCK0_VADDR SOC_DROM_LOW
+#define MMU_SIZE 0x3f0000
+#define MMU_BLOCK63_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
+
+/* Cache MMU block size */
+
+#define MMU_BLOCK_SIZE 0x00010000 /* 64 KB */
+
+/* Cache MMU address mask (MMU tables ignore bits which are zero) */
+
+#define MMU_FLASH_MASK (~(MMU_BLOCK_SIZE - 1))
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+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 */
+};
+
+/****************************************************************************
+ * ROM Function Prototypes
+ ****************************************************************************/
+
+extern uint32_t cache_suspend_icache(void);
+extern void cache_resume_icache(uint32_t val);
+extern void cache_invalidate_icache_all(void);
+extern int cache_dbus_mmu_set(uint32_t ext_ram, uint32_t vaddr,
+ uint32_t paddr, uint32_t psize, uint32_t num,
+ uint32_t fixed);
+extern int cache_ibus_mmu_set(uint32_t ext_ram, uint32_t vaddr,
+ uint32_t paddr, uint32_t psize, uint32_t num,
+ uint32_t fixed);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct user_image_load_header_s g_header;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: calc_mmu_pages
+ *
+ * Description:
+ * Calculate the required number of MMU pages for mapping a given region
+ * from External Flash into Internal RAM.
+ *
+ * Input Parameters:
+ * size - Length of the region to map
+ * vaddr - Starting External Flash offset to map to Internal RAM
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static inline uint32_t calc_mmu_pages(uint32_t size, uint32_t vaddr)
+{
+ return (size + (vaddr - (vaddr & MMU_FLASH_MASK)) + MMU_BLOCK_SIZE - 1) /
+ MMU_BLOCK_SIZE;
+}
+
+/****************************************************************************
+ * Name: configure_mmu
+ *
+ * Description:
+ * Configure the External Flash MMU and Cache for enabling access to code
+ * and read-only data of the userspace image.
+ *
+ * Input Parameters:
+ * None.
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static noinline_function IRAM_ATTR void configure_mmu(void)
+{
+ uint32_t drom_lma_aligned;
+ uint32_t drom_vma_aligned;
+ uint32_t drom_page_count;
+ uint32_t irom_lma_aligned;
+ uint32_t irom_vma_aligned;
+ uint32_t irom_page_count;
+
+ size_t partition_offset = USER_IMAGE_OFFSET;
+ uint32_t app_drom_lma = partition_offset + g_header.drom_lma;
+ uint32_t app_drom_size = g_header.drom_size;
+ uint32_t app_drom_vma = g_header.drom_vma;
+ uint32_t app_irom_lma = partition_offset + g_header.irom_lma;
+ uint32_t app_irom_size = g_header.irom_size;
+ uint32_t app_irom_vma = g_header.irom_vma;
+
+ uint32_t autoload = cache_suspend_icache();
+ cache_invalidate_icache_all();
+
+ drom_lma_aligned = app_drom_lma & MMU_FLASH_MASK;
+ drom_vma_aligned = app_drom_vma & MMU_FLASH_MASK;
+ drom_page_count = calc_mmu_pages(app_drom_size, app_drom_vma);
+ DEBUGVERIFY(cache_dbus_mmu_set(MMU_ACCESS_FLASH, drom_vma_aligned,
+ drom_lma_aligned, 64,
+ (int)drom_page_count, 0));
+
+ irom_lma_aligned = app_irom_lma & MMU_FLASH_MASK;
+ irom_vma_aligned = app_irom_vma & MMU_FLASH_MASK;
+ irom_page_count = calc_mmu_pages(app_irom_size, app_irom_vma);
+ DEBUGVERIFY(cache_ibus_mmu_set(MMU_ACCESS_FLASH, irom_vma_aligned,
+ irom_lma_aligned, 64,
+ (int)irom_page_count, 0));
+
+ cache_resume_icache(autoload);
+}
+
+/****************************************************************************
+ * Name: map_flash
+ *
+ * Description:
+ * Map a region of the External Flash memory to Internal RAM.
+ *
+ * Input Parameters:
+ * src_addr - Starting External Flash offset to map to Internal RAM
+ * size - Length of the region to map
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static noinline_function IRAM_ATTR const void *map_flash(uint32_t src_addr,
+ uint32_t size)
+{
+ uint32_t src_addr_aligned;
+ uint32_t page_count;
+
+ uint32_t autoload = cache_suspend_icache();
+ cache_invalidate_icache_all();
+
+ src_addr_aligned = src_addr & MMU_FLASH_MASK;
+ page_count = calc_mmu_pages(size, src_addr);
+ DEBUGVERIFY(cache_dbus_mmu_set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR,
+ src_addr_aligned, 64, (int)page_count, 0));
+
+ cache_resume_icache(autoload);
+
+ return (void *)(MMU_BLOCK63_VADDR + (src_addr - src_addr_aligned));
+}
+
+/****************************************************************************
+ * Name: load_header
+ *
+ * Description:
+ * Load IROM and DROM information from image header to enable the correct
+ * configuration of the Flash MMU and Cache.
+ *
+ * Input Parameters:
+ * None.
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static void load_header(void)
+{
+ size_t length = sizeof(struct user_image_load_header_s);
+ const uint8_t *data =
+ (const uint8_t *)map_flash(USER_IMAGE_OFFSET, length);
+
+ DEBUGASSERT(data != NULL);
+
+ memcpy(&g_header, data, length);
+}
+
+/****************************************************************************
+ * Name: initialize_data
+ *
+ * Description:
+ * Initialize data sections of the userspace image.
+ *
+ * Input Parameters:
+ * None.
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static void initialize_data(void)
+{
+ uint8_t *dest;
+ uint8_t *end;
+ size_t length = USERSPACE->us_dataend - USERSPACE->us_datastart;
+ const uint8_t *src =
+ (const uint8_t *)map_flash(USER_IMAGE_OFFSET + USERSPACE->us_datasource,
+ length);
+
+ DEBUGASSERT(src != NULL);
+
+ dest = (uint8_t *)USERSPACE->us_datastart;
+ end = (uint8_t *)USERSPACE->us_dataend;
+
+ while (dest != end)
+ {
+ *dest++ = *src++;
+ }
+}
+
+/****************************************************************************
+ * Name: configure_mpu
+ *
+ * Description:
+ * Configure the MPU for kernel/userspace separation.
+ *
+ * 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;
+ const uintptr_t RWX = PMPCFG_R | PMPCFG_W | PMPCFG_X;
+
+ /* Ensure PMP had not been previously configured by the bootloader */
+
+ DEBUGASSERT(riscv_configured_pmp_regions() == 0);
+
+ /* Region for the userspace read-only data in SPI Flash */
+
+ riscv_config_pmp_region(0, PMPCFG_A_TOR, UDROM_START, 0);
+ riscv_config_pmp_region(1, PMPCFG_A_TOR | R, UDROM_END, 0);
+
+ /* Region for the userspace data.
+ * NOTE: User-space heap may extend further than UDRAM_END.
+ */
+
+ riscv_config_pmp_region(2, PMPCFG_A_TOR, UDRAM_START, 0);
+ riscv_config_pmp_region(3, PMPCFG_A_TOR | RW, SOC_DRAM_HIGH, 0);
+
+ /* Region for the memory-mapped functions located in internal ROM */
+
+ riscv_config_pmp_region(4, PMPCFG_L | PMPCFG_A_NAPOT | R,
+ SOC_DROM_MASK_LOW,
+ SOC_DROM_MASK_HIGH - SOC_DROM_MASK_LOW);
+
+ riscv_config_pmp_region(5, PMPCFG_L | PMPCFG_A_TOR | RX,
+ SOC_IROM_MASK_HIGH,
+ 0);
+
+ /* Region for the exception vectors located in internal SRAM area reserved
+ * for the kernel space.
+ */
+
+ riscv_config_pmp_region(6, PMPCFG_A_NAPOT | RX,
+ VECTORS_START,
+ VECTORS_END - VECTORS_START);
+
+ /* Region for the userspace code located in internal SRAM */
+
+ riscv_config_pmp_region(7, PMPCFG_A_TOR, UIRAM_START, 0);
+ riscv_config_pmp_region(8, PMPCFG_A_TOR | RWX, UIRAM_END, 0);
+
+ /* Region for the userspace code in SPI Flash */
+
+ riscv_config_pmp_region(9, PMPCFG_A_TOR, UIROM_START, 0);
+ riscv_config_pmp_region(10, PMPCFG_A_TOR | RX, UIROM_END, 0);
+
+ /* Region for peripheral addresses */
+
+ riscv_config_pmp_region(11, PMPCFG_A_TOR, SOC_PERIPHERAL_HIGH, 0);
+
+ /* Region for the remainder of the address space */
+
+ riscv_config_pmp_region(12, PMPCFG_L | PMPCFG_A_TOR, UINT32_MAX, 0);
+ riscv_config_pmp_region(13, PMPCFG_L | PMPCFG_A_NA4, UINT32_MAX, 0);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32c3_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.
+ *
+ * Input Parameters:
+ * None.
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+void esp32c3_userspace(void)
+{
+ uint8_t *dest;
+ uint8_t *end;
+
+ /* Load IROM and DROM information from image header */
+
+ load_header();
+
+ /* Configure the MMU for enabling access to the userspace image */
+
+ 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();
+
+ /* Configure MPU / PMP to grant access to the userspace */
+
+ configure_mpu();
+}
+
+#endif /* CONFIG_BUILD_PROTECTED */
diff --git a/arch/risc-v/src/esp32c3/esp32c3_userspace.h b/arch/risc-v/src/esp32c3/esp32c3_userspace.h
new file mode 100755
index 0000000000..bc1d135174
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_userspace.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_userspace.h
+ *
+ * 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_ESP32C3_ESP32C3_USERSPACE_H
+#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_USERSPACE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Public Functions Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32c3_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 user space .data and .bss
+ * segments.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_BUILD_PROTECTED
+void esp32c3_userspace(void);
+#endif
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_USERSPACE_H */
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/knsh/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/knsh/defconfig
new file mode 100644
index 0000000000..694a952499
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/knsh/defconfig
@@ -0,0 +1,57 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+# CONFIG_NSH_CMDPARMS is not set
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="esp32c3-devkit"
+CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y
+CONFIG_ARCH_CHIP="esp32c3"
+CONFIG_ARCH_CHIP_ESP32C3=y
+CONFIG_ARCH_CHIP_ESP32C3WROOM02=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_USE_MPU=y
+CONFIG_BOARD_LOOPSPERMSEC=15000
+CONFIG_BUILD_PROTECTED=y
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_ASSERTIONS=y
+CONFIG_DEBUG_ERROR=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEBUG_WARN=y
+CONFIG_DEV_ZERO=y
+CONFIG_ESP32C3_BOOTLOADER_BUILD_FROM_SOURCE=y
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_READLINE=y
+CONFIG_NSH_STRERROR=y
+CONFIG_NUTTX_USERSPACE=0x3c080018
+CONFIG_PASS1_BUILDIR="boards/risc-v/esp32c3/esp32c3-devkit/kernel"
+CONFIG_PREALLOC_TIMERS=0
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_STACK_COLORATION=y
+CONFIG_START_DAY=29
+CONFIG_START_MONTH=11
+CONFIG_START_YEAR=2019
+CONFIG_SYSTEM_NSH=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_UART0_SERIAL_CONSOLE=y
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/include/board_memorymap.h b/boards/risc-v/esp32c3/esp32c3-devkit/include/board_memorymap.h
new file mode 100644
index 0000000000..31ee7d9af4
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/include/board_memorymap.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+ * boards/risc-v/esp32c3/esp32c3-devkit/include/board_memorymap.h
+ *
+ * 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_ESP32C3_ESP32C3_DEVKIT_INCLUDE_BOARD_MEMORYMAP_H
+#define __BOARDS_RISCV_ESP32C3_ESP32C3_DEVKIT_INCLUDE_BOARD_MEMORYMAP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+/****************************************************************************
+ * 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 uintptr_t __kirom_start;
+extern uintptr_t __kirom_size;
+extern uintptr_t __kdrom_start;
+extern uintptr_t __kdrom_size;
+
+/* Kernel RAM (RW) */
+
+extern uintptr_t __kiram_start;
+extern uintptr_t __kiram_size;
+extern uintptr_t __kiram_end;
+extern uintptr_t __kdram_start;
+extern uintptr_t __kdram_size;
+extern uintptr_t __kdram_end;
+
+/* Exception vectors */
+
+extern uintptr_t __vectors_start;
+extern uintptr_t __vectors_end;
+
+/* User ROM (RX) */
+
+extern uintptr_t __uirom_start;
+extern uintptr_t __uirom_size;
+extern uintptr_t __uirom_end;
+extern uintptr_t __udrom_start;
+extern uintptr_t __udrom_size;
+extern uintptr_t __udrom_end;
+
+/* User RAM (RW) */
+
+extern uintptr_t __uiram_start;
+extern uintptr_t __uiram_size;
+extern uintptr_t __uiram_end;
+extern uintptr_t __udram_start;
+extern uintptr_t __udram_size;
+extern uintptr_t __udram_end;
+
+#endif /* __BOARDS_RISCV_ESP32C3_ESP32C3_DEVKIT_INCLUDE_BOARD_MEMORYMAP_H */
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/kernel/Makefile b/boards/risc-v/esp32c3/esp32c3-devkit/kernel/Makefile
new file mode 100755
index 0000000000..2b6b056e1f
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/kernel/Makefile
@@ -0,0 +1,98 @@
+############################################################################
+# boards/risc-v/esp32c3/esp32c3-devkit/kernel/Makefile
+#
+# 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 = -T $(call CONVERT_PATH,$(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32c3_out.ld)
+USER_LDSCRIPT += -T $(call CONVERT_PATH,$(BOARD_DIR)$(DELIM)scripts$(DELIM)user-space.ld)
+USER_LDSCRIPT += -T $(call CONVERT_PATH,$(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32c3_rom.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) $(USER_LDSCRIPT) -melf32lriscv
+
+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 = esp32c3_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, $<, $@)
+
+# Create the nuttx_user.elf file containing all of the user-mode code
+
+nuttx_user.elf: $(OBJS)
+ $(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
+
+.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/esp32c3/esp32c3-devkit/kernel/esp32c3_userspace.c b/boards/risc-v/esp32c3/esp32c3-devkit/kernel/esp32c3_userspace.c
new file mode 100755
index 0000000000..82fa9907be
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/kernel/esp32c3_userspace.c
@@ -0,0 +1,114 @@
+/****************************************************************************
+ * boards/risc-v/esp32c3/esp32c3-devkit/kernel/esp32c3_userspace.c
+ *
+ * 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 <nuttx/config.h>
+
+#include <stdlib.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/mm/mm.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/userspace.h>
+
+#if defined(CONFIG_BUILD_PROTECTED) && !defined(__KERNEL__)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_NUTTX_USERSPACE
+# error "CONFIG_NUTTX_USERSPACE not defined"
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* These 'addresses' of these values are setup by the linker script.
+ * They are not actual uint32_t storage locations!
+ * They are only used meaningfully in the following way:
+ *
+ * - The linker script defines, for example, the symbol_sdata.
+ * - The declaration extern uint32_t _sdata; makes C happy. C will believe
+ * that the value _sdata is the address of a uint32_t variable _data
+ * (it is not!).
+ * - We can recover the linker value then by simply taking the address of
+ * of _data. like: uint32_t *pdata = &_sdata;
+ */
+
+extern uint32_t _stext; /* Start of .text */
+extern uint32_t _etext; /* End+1 of .text + .rodata */
+extern const uint32_t _eronly; /* End+1 of read only section */
+extern uint32_t _sdata; /* Start of .data */
+extern uint32_t _edata; /* End+1 of .data */
+extern uint32_t _sbss; /* Start of .bss */
+extern uint32_t _ebss; /* End+1 of .bss */
+
+extern uintptr_t *__ld_udram_end; /* End+1 of user ram section */
+
+/* This is the user space entry point */
+
+int CONFIG_INIT_ENTRYPOINT(int argc, char *argv[]);
+
+const struct userspace_s userspace locate_data(".userspace") =
+{
+ /* General memory map */
+
+ .us_entrypoint = (main_t)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,
+
+ /* Memory manager heap structure */
+
+ .us_heap = &g_mmheap,
+
+ /* 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/esp32c3/esp32c3-devkit/scripts/Make.defs b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/Make.defs
index 393bda1470..7d6789f6bb 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/Make.defs
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/Make.defs
@@ -25,10 +25,14 @@ include $(TOPDIR)/arch/risc-v/src/common/Toolchain.defs
ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32c3_out.ld
-ifeq ($(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),y)
- ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32c3_mcuboot.ld
+ifeq ($(CONFIG_BUILD_PROTECTED),y)
+ ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)kernel-space.ld
else
- ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32c3.ld
+ ifeq ($(CONFIG_ESP32C3_APP_FORMAT_MCUBOOT),y)
+ ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32c3_mcuboot.ld
+ else
+ ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32c3.ld
+ endif
endif
ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32c3_rom.ld
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/kernel-space.ld b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/kernel-space.ld
new file mode 100755
index 0000000000..87c0c99c0c
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/kernel-space.ld
@@ -0,0 +1,230 @@
+/****************************************************************************
+ * boards/risc-v/esp32c3/esp32c3-devkit/scripts/kernel-space.ld
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* Provide these so there is no need for using config files for this */
+
+__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);
+__uiram_start = ORIGIN(UIRAM);
+__uiram_size = LENGTH(UIRAM);
+__uiram_end = ORIGIN(UIRAM) + LENGTH(UIRAM);
+__udram_start = ORIGIN(UDRAM);
+__udram_size = LENGTH(UDRAM);
+__udram_end = ORIGIN(UDRAM) + LENGTH(UDRAM);
+
+/* Provide the kernel boundaries as well */
+
+__kirom_start = ORIGIN(KIROM);
+__kirom_size = LENGTH(KIROM);
+__kdrom_start = ORIGIN(KDROM);
+__kdrom_size = LENGTH(KDROM);
+__kiram_start = ORIGIN(KIRAM);
+__kiram_size = LENGTH(KIRAM);
+__kiram_end = ORIGIN(KIRAM) + LENGTH(KIRAM);
+__kdram_start = ORIGIN(KDRAM);
+__kdram_size = LENGTH(KDRAM);
+__kdram_end = ORIGIN(KDRAM) + LENGTH(KDRAM);
+
+ENTRY(_stext)
+
+SECTIONS
+{
+ .iram0.text :
+ {
+ _iram_start = ABSOLUTE(.);
+
+ __vectors_start = ABSOLUTE(.);
+
+ /* Vectors go to start of IRAM */
+
+ KEEP(*(.exception_vectors.text));
+ . = ALIGN(4);
+
+ __vectors_end = ABSOLUTE(.);
+
+ *(.iram1)
+ *(.iram1.*)
+
+ *libsched.a:irq_dispatch.*(.text .text.* .literal .literal.*)
+
+ *(.wifi0iram .wifi0iram.*)
+ *(.wifirxiram .wifirxiram.*)
+ *(.wifislpiram .wifislpiram.*)
+ *(.wifislprxiram .wifislprxiram.*)
+
+ _iram_end = ABSOLUTE(.);
+ } >KIRAM
+
+ /* This section is required to skip .iram0.text area because iram0_0_seg
+ * and dram0_0_seg reflect the same address space on different buses.
+ */
+
+ .dram0.dummy (NOLOAD):
+ {
+ . = ORIGIN(KDRAM) + _iram_end - _iram_start;
+ } >KDRAM
+
+ /* Shared RAM */
+
+ .dram0.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 (8);
+ _ebss = ABSOLUTE(.);
+ } >KDRAM
+
+ .noinit (NOLOAD):
+ {
+ /* This section contains data that is not initialized during load,
+ * or during the application's initialization sequence.
+ */
+
+ *(.noinit)
+ *(.noinit.*)
+ } >KDRAM
+
+ .dram0.data :
+ {
+ _sdata = ABSOLUTE(.);
+ *(.data)
+ *(.data.*)
+ *(.gnu.linkonce.d.*)
+ *(.data1)
+ __global_pointer$ = . + 0x800;
+ *(.sdata)
+ *(.sdata.*)
+ *(.gnu.linkonce.s.*)
+ *(.sdata2)
+ *(.sdata2.*)
+ *(.gnu.linkonce.s2.*)
+ *(.jcr)
+ *(.dram1)
+ *(.dram1.*)
+ . = ALIGN(4);
+ _edata = ABSOLUTE(.);
+
+ /* Heap starts at the end of .data */
+
+ _sheap = ABSOLUTE(.);
+ } >KDRAM
+
+ .flash.text :
+ {
+ _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 */
+ *(.fini.literal)
+ *(.fini)
+ *(.gnu.version)
+ _etext = .;
+
+ /* Similar to _iram_start, this symbol goes here so it is
+ * resolved by addr2line in preference to the first symbol in
+ * the flash.text segment.
+ */
+
+ _flash_cache_start = ABSOLUTE(0);
+ } >KIROM
+
+ .flash_rodata_dummy (NOLOAD):
+ {
+ . = ALIGN(ALIGNOF(.flash.text));
+ . = . + SIZEOF(.flash.text);
+ . = ALIGN(0x10000) + 0x20;
+ } >KDROM
+
+ .flash.rodata : ALIGN(0x10)
+ {
+ _srodata = ABSOLUTE(.);
+
+ *(.rodata)
+ *(.rodata.*)
+
+ *(.srodata.*)
+
+ *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
+ *(.gnu.linkonce.r.*)
+ *(.rodata1)
+ __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
+ *(.xt_except_table)
+ *(.gcc_except_table .gcc_except_table.*)
+ *(.gnu.linkonce.e.*)
+ *(.gnu.version_r)
+ . = (. + 3) & ~ 3;
+ __eh_frame = ABSOLUTE(.);
+ KEEP(*(.eh_frame))
+ . = (. + 7) & ~ 3;
+
+ /* C++ constructor and destructor tables:
+ * RISC-V GCC is configured with --enable-initfini-array so it emits an
+ * .init_array section instead.
+ */
+
+ _sinit = ABSOLUTE(.);
+ KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*))
+ KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array))
+ _einit = ABSOLUTE(.);
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+
+ /* C++ exception handlers table: */
+
+ __XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
+ *(.xt_except_desc)
+ *(.gnu.linkonce.h.*)
+ __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
+ *(.xt_except_desc_end)
+ *(.dynamic)
+ *(.gnu.version_d)
+ _erodata = ABSOLUTE(.);
+
+ /* Literals are also RO data. */
+
+ _lit4_start = ABSOLUTE(.);
+ *(*.lit4)
+ *(.lit4.*)
+ *(.gnu.linkonce.lit4.*)
+ _lit4_end = ABSOLUTE(.);
+ . = ALIGN(4);
+ } >KDROM
+}
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/protected.template.ld b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/protected.template.ld
new file mode 100644
index 0000000000..6e0e33ab6b
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/protected.template.ld
@@ -0,0 +1,95 @@
+/****************************************************************************
+ * boards/risc-v/esp32c3/esp32c3-devkit/scripts/protected.template.ld
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * This file describes the memory layout (memory blocks) as virtual
+ * memory addresses.
+ *
+ * NOTE: That this is not the actual linker script but rather a "template"
+ * for the esp32c3_out.ld script. This template script is passed through
+ * the C preprocessor to include selected configuration options.
+ *
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "esp32c3_aliases.ld"
+
+#define SRAM_IRAM_START 0x4037c000
+#define SRAM_DRAM_START 0x3fc7c000
+
+/* ICache size is fixed to 16KB on ESP32-C3 */
+
+#define ICACHE_SIZE 0x4000
+#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START)
+
+/* 2nd stage bootloader iram_loader_seg start address */
+
+#define SRAM_IRAM_END 0x403d0000
+#define SRAM_DRAM_END SRAM_IRAM_END - I_D_SRAM_OFFSET
+
+#define SRAM_IRAM_ORG (SRAM_IRAM_START + ICACHE_SIZE)
+#define SRAM_DRAM_ORG (SRAM_DRAM_START + ICACHE_SIZE)
+
+#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG
+
+MEMORY
+{
+ metadata (RX) : org = 0x0, len = 0x18
+ ROM (RX) : org = 0x18, len = 0x100000
+
+ /* Below values assume the flash cache is on, and have the blocks this
+ * uses subtracted from the length of the various regions. The 'data access
+ * port' dram/drom regions map to the same iram/irom regions but are
+ * connected to the data port of the CPU and e.g. allow bytewise access.
+ */
+
+ KIRAM (RWX) : org = SRAM_IRAM_ORG, len = 64K
+ UIRAM (RWX) : org = SRAM_IRAM_ORG + 64K, len = 256K
+
+ /* Flash mapped instruction data. */
+
+ /* The 0x20 offset is a convenience for the app binary image generation.
+ * Flash cache has 64KB pages. The .bin file which is flashed to the chip
+ * has a 0x18 byte file header, and each segment has a 0x08 byte segment
+ * header. Setting this offset makes it simple to meet the flash cache MMU's
+ * constraint that (paddr % 64KB == vaddr % 64KB).
+ */
+
+ KIROM (RX) : org = 0x42000020, len = 0x80000 - 0x20
+ UIROM (RX) : org = 0x42080000, len = 0x180000
+
+ /* Shared data RAM, excluding memory reserved for ROM bss/data/stack. */
+
+ KDRAM (RW) : org = SRAM_DRAM_ORG, len = 64K
+ UDRAM (RW) : org = SRAM_DRAM_ORG + 64K, len = 256K
+
+ /* Flash mapped constant data */
+
+ /* The 0x20 offset is a convenience for the app binary image generation.
+ * Flash cache has 64KB pages. The .bin file which is flashed to the chip
+ * has a 0x18 byte file header, and each segment has a 0x08 byte segment
+ * header. Setting this offset makes it simple to meet the flash cache MMU's
+ * constraint that (paddr % 64KB == vaddr % 64KB).
+ */
+
+ KDROM (R) : org = 0x3c000020, len = 0x80000 - 0x20
+ UDROM (R) : org = 0x3c080018, len = 0x180000 - 0x18
+}
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/user-space.ld b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/user-space.ld
new file mode 100755
index 0000000000..717c77efd9
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/user-space.ld
@@ -0,0 +1,214 @@
+/****************************************************************************
+ * boards/risc-v/esp32c3/esp32c3-devkit/scripts/user-space.ld
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+SECTIONS
+{
+ .metadata :
+ {
+ /* DROM metadata:
+ * - Destination address (VMA) for DROM region
+ * - Flash offset (LMA) for start of DROM region
+ * - Size of DROM region
+ */
+
+ LONG(ADDR(.userspace))
+ LONG(LOADADDR(.userspace))
+ LONG(SIZEOF(.userspace) + SIZEOF(.flash.rodata))
+
+ /* IROM metadata:
+ * - Destination address (VMA) for IROM region
+ * - Flash offset (LMA) for start of IROM region
+ * - Size of IROM region
+ */
+
+ LONG(ADDR(.flash.text))
+ LONG(LOADADDR(.flash.text))
+ LONG(SIZEOF(.flash.text))
+ } >metadata
+
+ /* section info */
+
+ __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_uiram_start = ORIGIN(UIRAM);
+ __ld_uiram_size = LENGTH(UIRAM);
+ __ld_uiram_end = ORIGIN(UIRAM) + LENGTH(UIRAM);
+ __ld_udram_start = ORIGIN(UDRAM);
+ __ld_udram_size = LENGTH(UDRAM);
+ __ld_udram_end = ORIGIN(UDRAM) + LENGTH(UDRAM);
+
+ _eronly = LOADADDR(.dram0.data);
+
+ .userspace : {
+ *(.userspace)
+ } >UDROM AT>ROM
+
+ .flash.rodata :
+ {
+ _srodata = ABSOLUTE(.);
+
+ *(.rodata)
+ *(.rodata.*)
+
+ *(.srodata.*)
+
+ *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
+ *(.gnu.linkonce.r.*)
+ *(.rodata1)
+ __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
+ *(.xt_except_table)
+ *(.gcc_except_table .gcc_except_table.*)
+ *(.gnu.linkonce.e.*)
+ *(.gnu.version_r)
+ . = (. + 3) & ~ 3;
+ __eh_frame = ABSOLUTE(.);
+ KEEP(*(.eh_frame))
+ . = (. + 7) & ~ 3;
+
+ /* C++ constructor and destructor tables:
+ * RISC-V GCC is configured with --enable-initfini-array so it emits an
+ * .init_array section instead.
+ */
+
+ _sinit = ABSOLUTE(.);
+ KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*))
+ KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array))
+ _einit = ABSOLUTE(.);
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+
+ /* C++ exception handlers table: */
+
+ __XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
+ *(.xt_except_desc)
+ *(.gnu.linkonce.h.*)
+ __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
+ *(.xt_except_desc_end)
+ *(.dynamic)
+ *(.gnu.version_d)
+ _erodata = ABSOLUTE(.);
+
+ /* Literals are also RO data. */
+
+ _lit4_start = ABSOLUTE(.);
+ *(*.lit4)
+ *(.lit4.*)
+ *(.gnu.linkonce.lit4.*)
+ _lit4_end = ABSOLUTE(.);
+ . = ALIGN(4);
+ } >UDROM AT>ROM
+
+ .iram0.text :
+ {
+ _iram_start = ABSOLUTE(.);
+
+ *(.iram1)
+ *(.iram1.*)
+
+ _iram_end = ABSOLUTE(.);
+ } >UIRAM AT>ROM
+
+ /* This section is required to skip .iram0.text area because iram0_0_seg
+ * and dram0_0_seg reflect the same address space on different buses.
+ */
+
+ .dram0.dummy (NOLOAD):
+ {
+ . = ORIGIN(UDRAM) + _iram_end - _iram_start;
+ } >UDRAM
+
+ /* Shared RAM */
+
+ .dram0.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 (8);
+ _ebss = ABSOLUTE(.);
+ } >UDRAM
+
+ .noinit (NOLOAD):
+ {
+ /* This section contains data that is not initialized during load,
+ * or during the application's initialization sequence.
+ */
+
+ *(.noinit)
+ *(.noinit.*)
+ } >UDRAM
+
+ .dram0.data :
+ {
+ _sdata = ABSOLUTE(.);
+ *(.data)
+ *(.data.*)
+ *(.gnu.linkonce.d.*)
+ *(.data1)
+ *(.sdata)
+ *(.sdata.*)
+ *(.gnu.linkonce.s.*)
+ *(.sdata2)
+ *(.sdata2.*)
+ *(.gnu.linkonce.s2.*)
+ *(.jcr)
+ *(.dram1)
+ *(.dram1.*)
+ . = ALIGN(4);
+ _edata = ABSOLUTE(.);
+ } >UDRAM AT>ROM
+
+ .flash_text_dummy (NOLOAD) : ALIGN(0x00010000)
+ {
+ . = SIZEOF(.userspace) + SIZEOF(.flash.rodata);
+ } >UIROM
+
+ .flash.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 */
+ *(.fini.literal)
+ *(.fini)
+ *(.gnu.version)
+ _etext = .;
+ } >UIROM AT>ROM
+}
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile b/boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile
index 8b0e0bbf40..3bbfad7aa6 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile
@@ -113,7 +113,11 @@ ifneq ($(CONFIG_NSH_CUSTOMROMFS),y)
endif
endif
+ifeq ($(CONFIG_BUILD_PROTECTED),y)
+SCRIPTIN = $(SCRIPTDIR)$(DELIM)protected.template.ld
+else
SCRIPTIN = $(SCRIPTDIR)$(DELIM)esp32c3.template.ld
+endif
SCRIPTOUT = $(SCRIPTDIR)$(DELIM)esp32c3_out.ld
.PHONY = context distclean
diff --git a/tools/esp32c3/Config.mk b/tools/esp32c3/Config.mk
index f48b2c4e18..3fcdc1c11d 100644
--- a/tools/esp32c3/Config.mk
+++ b/tools/esp32c3/Config.mk
@@ -128,6 +128,10 @@ endif
ESPTOOL_BINS += $(FLASH_APP)
+ifeq ($(CONFIG_BUILD_PROTECTED),y)
+ ESPTOOL_BINS += $(CONFIG_ESP32C3_USER_IMAGE_OFFSET) nuttx_user.bin
+endif
+
# Commands for colored and formatted output
RED = \033[1;31m