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 -#include #include +#include -#include #include #include +#include +#include #include +#ifdef CONFIG_MM_KERNEL_HEAP +#include +#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,10 +97,48 @@ 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,18 +30,20 @@ #include #include "esp32c3.h" -#include "esp32c3_clockconfig.h" -#include "esp32c3_irq.h" -#include "esp32c3_lowputc.h" -#include "esp32c3_start.h" -#include "esp32c3_wdt.h" -#include "esp32c3_rtc.h" -#include "hardware/esp32c3_cache_memory.h" -#include "hardware/extmem_reg.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" +#ifdef CONFIG_BUILD_PROTECTED +# include "esp32c3_userspace.h" +#endif +#include "hardware/esp32c3_cache_memory.h" +#include "hardware/extmem_reg.h" /**************************************************************************** * 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 + +#include +#include +#include +#include + +#include + +#include + +#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 + +/**************************************************************************** + * 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 + +/**************************************************************************** + * 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 + +#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 + +/**************************************************************************** + * 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 + +#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