xtensa/esp32: Allow allocation of user data in SPI RAM

Signed-off-by: Gustavo Henrique Nihei <gustavo.nihei@espressif.com>
This commit is contained in:
Gustavo Henrique Nihei 2022-06-06 17:34:51 -03:00 committed by Petro Karashchenko
parent 523da07778
commit 73678c4839
6 changed files with 158 additions and 48 deletions

View File

@ -624,7 +624,7 @@ config ESP32_SPI3
config ESP32_SPIRAM
bool "SPI RAM Support"
default n
select ARCH_HAVE_HEAP2
select ARCH_HAVE_HEAP2 if !ESP32_USER_DATA_EXTMEM
select XTENSA_IMEM_USE_SEPARATE_HEAP
if ESP32_SPIRAM && SMP
@ -1362,7 +1362,7 @@ endchoice # ESP32_SPIRAM_SPEED
config ESP32_SPIRAM_BOOT_INIT
bool "Initialize SPI RAM during startup"
depends on ESP32_SPIRAM
depends on ESP32_SPIRAM && !ESP32_USER_DATA_EXTMEM
default y
---help---
If this is enabled, the SPI RAM will be enabled during initial
@ -1894,6 +1894,22 @@ config ESP32_USER_IMAGE_OFFSET
---help---
Offset in SPI Flash for flashing the User application firmware image.
config ESP32_USER_DATA_EXTMEM
bool "Allocate user data in SPI RAM (READ HELP FIRST)"
default n
depends on ESP32_SPIRAM && EXPERIMENTAL
---help---
Allocate all data from User application firmware image in the external
SPI RAM.
Enabling this configuration comes with the restriction of running the Userspace
with high privilege (same as Kernel space), which in turn makes the execution
under Protected Mode not really protected.
This feature is intended to allow experimentation of Protected Mode on ESP32 and
should not be used in production. Protected mode on ESP32 is only supported with
PSRAM disabled.
endif
source "arch/xtensa/src/esp32/Kconfig.security"

View File

@ -57,8 +57,18 @@
/* Definitions for the PIDs reserved for Kernel and Userspace */
#define PIDCTRL_PID_KERNEL 0 /* Privileged */
#define PIDCTRL_PID_USER 5 /* Non-privileged */
# define PIDCTRL_PID_KERNEL 0 /* Privileged */
#ifdef CONFIG_ESP32_USER_DATA_EXTMEM
/* Allocating user data in External RAM is currently limited to only using
* privileged PIDs (0 and 1).
*/
# define PIDCTRL_PID_USER 1 /* Privileged */
#else
# define PIDCTRL_PID_USER 5 /* Non-privileged */
#endif
/* Macros for privilege handling with the PID Controller peripheral */

View File

@ -49,6 +49,12 @@
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_BUILD_PROTECTED
# define MM_ADDREGION kmm_addregion
#else
# define MM_ADDREGION umm_addregion
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -75,6 +81,11 @@ void up_allocate_heap(void **heap_start, size_t *heap_size)
uintptr_t utop = USERSPACE->us_heapend;
size_t usize = utop - ubase;
#if defined(CONFIG_ESP32_USER_DATA_EXTMEM) && \
defined(CONFIG_ESP32_SPIRAM_BANKSWITCH_ENABLE)
usize -= esp_himem_reserved_area_size();
#endif
minfo("Heap: start=%" PRIxPTR " end=%" PRIxPTR " size=%zu\n",
ubase, utop, usize);
@ -84,9 +95,6 @@ void up_allocate_heap(void **heap_start, size_t *heap_size)
*heap_start = (void *)ubase;
*heap_size = usize;
/* Allow user-mode access to the user heap memory */
#else
board_autoled_on(LED_HEAPALLOCATE);
@ -160,66 +168,48 @@ void xtensa_add_region(void)
availregions = 2;
#endif
#ifdef CONFIG_ESP32_SPIRAM
#if defined(CONFIG_ESP32_SPIRAM) && !defined(CONFIG_BUILD_PROTECTED)
availregions++;
#endif
if (nregions < availregions)
{
mwarn("Some memory regions are left unused!\n");
mwarn("Increase CONFIG_MM_NREGIONS to add them to the heap\n");
mwarn("Increase CONFIG_MM_REGIONS to add them to the heap\n");
}
#ifndef CONFIG_SMP
start = (void *)(HEAP_REGION2_START + XTENSA_IMEM_REGION_SIZE);
size = (size_t)(uintptr_t)_eheap - (size_t)start;
#ifdef CONFIG_BUILD_PROTECTED
kmm_addregion(start, size);
#else
umm_addregion(start, size);
#endif
#else
#ifdef CONFIG_SMP
start = (void *)HEAP_REGION2_START;
size = (size_t)(HEAP_REGION2_END - HEAP_REGION2_START);
#ifdef CONFIG_BUILD_PROTECTED
kmm_addregion(start, size);
#else
umm_addregion(start, size);
MM_ADDREGION(start, size);
#endif
start = (void *)HEAP_REGION3_START + XTENSA_IMEM_REGION_SIZE;
/* Skip internal heap region if CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP is
* enabled.
*/
start = (void *)ESP32_IMEM_START + XTENSA_IMEM_REGION_SIZE;
size = (size_t)(uintptr_t)_eheap - (size_t)start;
#ifdef CONFIG_BUILD_PROTECTED
kmm_addregion(start, size);
#else
umm_addregion(start, size);
#endif
#endif
MM_ADDREGION(start, size);
#ifndef CONFIG_ESP32_BLE
start = (void *)HEAP_REGION0_START;
size = (size_t)(HEAP_REGION0_END - HEAP_REGION0_START);
#ifdef CONFIG_BUILD_PROTECTED
kmm_addregion(start, size);
#else
umm_addregion(start, size);
#endif
MM_ADDREGION(start, size);
#endif
#ifdef CONFIG_ESP32_SPIRAM
# if defined(CONFIG_HEAP2_BASE) && defined(CONFIG_HEAP2_SIZE)
# ifdef CONFIG_XTENSA_EXTMEM_BSS
start = _ebss_extmem;
size = CONFIG_HEAP2_SIZE - (_ebss_extmem - _sbss_extmem);
# else
start = (void *)CONFIG_HEAP2_BASE;
size = CONFIG_HEAP2_SIZE;
# endif
# ifdef CONFIG_ESP32_SPIRAM_BANKSWITCH_ENABLE
size -= esp_himem_reserved_area_size();
# endif
umm_addregion(start, size);
# endif
#if defined(CONFIG_ESP32_SPIRAM) && defined(CONFIG_ARCH_HAVE_HEAP2)
#ifdef CONFIG_XTENSA_EXTMEM_BSS
start = (void *)(_ebss_extmem);
size = CONFIG_HEAP2_SIZE - (size_t)(_ebss_extmem - _sbss_extmem);
#else
start = (void *)CONFIG_HEAP2_BASE;
size = CONFIG_HEAP2_SIZE;
#endif
#ifdef CONFIG_ESP32_SPIRAM_BANKSWITCH_ENABLE
size -= esp_himem_reserved_area_size();
#endif
MM_ADDREGION(start, size);
#endif
}
#endif

View File

@ -715,7 +715,9 @@ psram_cmd_recv_start(psram_spi_num_t spi_num,
while (getreg32(SPI_EXT2_REG(0)) != 0);
#ifndef CONFIG_ESP32_USER_DATA_EXTMEM
modifyreg32(DPORT_HOST_INF_SEL_REG, 0, 1 << 14);
#endif
/* Start send data */
@ -723,7 +725,9 @@ psram_cmd_recv_start(psram_spi_num_t spi_num,
while ((getreg32(SPI_CMD_REG(spi_num)) & SPI_USR));
#ifndef CONFIG_ESP32_USER_DATA_EXTMEM
modifyreg32(DPORT_HOST_INF_SEL_REG, 1 << 14, 0);
#endif
/* recover spi mode */

View File

@ -36,6 +36,9 @@
#include "chip.h"
#include "xtensa.h"
#include "xtensa_attr.h"
#ifdef CONFIG_ESP32_USER_DATA_EXTMEM
#include "esp32_spiram.h"
#endif
#include "esp32_userspace.h"
#include "hardware/esp32_dport.h"
#include "hardware/esp32_pid.h"
@ -188,6 +191,49 @@ static noinline_function IRAM_ATTR void configure_flash_mmu(void)
cache_read_enable(0);
}
/****************************************************************************
* Name: configure_sram_mmu
*
* Description:
* Configure the External SRAM MMU and Cache for enabling access to the
* data of the userspace image.
*
* Input Parameters:
* None.
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_ESP32_USER_DATA_EXTMEM
static noinline_function IRAM_ATTR void configure_sram_mmu(void)
{
#ifdef CONFIG_SMP
uint32_t regval;
#endif
/* Enable external RAM in MMU */
ASSERT(cache_sram_mmu_set(0, PIDCTRL_PID_KERNEL, SOC_EXTRAM_DATA_LOW, 0,
32, 128) == 0);
ASSERT(cache_sram_mmu_set(0, PIDCTRL_PID_USER, SOC_EXTRAM_DATA_LOW, 0,
32, 128) == 0);
/* Flush and enable icache for APP CPU */
#ifdef CONFIG_SMP
regval = getreg32(DPORT_APP_CACHE_CTRL1_REG);
regval &= ~(1 << DPORT_APP_CACHE_MASK_DRAM1);
putreg32(regval, DPORT_APP_CACHE_CTRL1_REG);
ASSERT(cache_sram_mmu_set(1, PIDCTRL_PID_KERNEL, SOC_EXTRAM_DATA_LOW, 0,
32, 128) == 0);
ASSERT(cache_sram_mmu_set(1, PIDCTRL_PID_USER, SOC_EXTRAM_DATA_LOW, 0,
32, 128) == 0);
#endif
}
#endif
/****************************************************************************
* Name: map_flash
*
@ -322,6 +368,24 @@ static void configure_mpu(void)
REG_SET_FIELD(DPORT_IMMU_TABLE14_REG, DPORT_IMMU_TABLE14, 0x0e);
REG_SET_FIELD(DPORT_IMMU_TABLE15_REG, DPORT_IMMU_TABLE15, 0x0f);
#ifdef CONFIG_ESP32_USER_DATA_EXTMEM
REG_SET_FIELD(DPORT_DMMU_TABLE0_REG, DPORT_DMMU_TABLE0, 0x00);
REG_SET_FIELD(DPORT_DMMU_TABLE1_REG, DPORT_DMMU_TABLE1, 0x01);
REG_SET_FIELD(DPORT_DMMU_TABLE2_REG, DPORT_DMMU_TABLE2, 0x02);
REG_SET_FIELD(DPORT_DMMU_TABLE3_REG, DPORT_DMMU_TABLE3, 0x03);
REG_SET_FIELD(DPORT_DMMU_TABLE4_REG, DPORT_DMMU_TABLE4, 0x04);
REG_SET_FIELD(DPORT_DMMU_TABLE5_REG, DPORT_DMMU_TABLE5, 0x05);
REG_SET_FIELD(DPORT_DMMU_TABLE6_REG, DPORT_DMMU_TABLE6, 0x06);
REG_SET_FIELD(DPORT_DMMU_TABLE7_REG, DPORT_DMMU_TABLE7, 0x07);
REG_SET_FIELD(DPORT_DMMU_TABLE8_REG, DPORT_DMMU_TABLE8, 0x08);
REG_SET_FIELD(DPORT_DMMU_TABLE9_REG, DPORT_DMMU_TABLE9, 0x09);
REG_SET_FIELD(DPORT_DMMU_TABLE10_REG, DPORT_DMMU_TABLE10, 0x0a);
REG_SET_FIELD(DPORT_DMMU_TABLE11_REG, DPORT_DMMU_TABLE11, 0x0b);
REG_SET_FIELD(DPORT_DMMU_TABLE12_REG, DPORT_DMMU_TABLE12, 0x0c);
REG_SET_FIELD(DPORT_DMMU_TABLE13_REG, DPORT_DMMU_TABLE13, 0x0d);
REG_SET_FIELD(DPORT_DMMU_TABLE14_REG, DPORT_DMMU_TABLE14, 0x0e);
REG_SET_FIELD(DPORT_DMMU_TABLE15_REG, DPORT_DMMU_TABLE15, 0x0f);
#else
REG_SET_FIELD(DPORT_DMMU_TABLE0_REG, DPORT_DMMU_TABLE0, 0x00);
REG_SET_FIELD(DPORT_DMMU_TABLE1_REG, DPORT_DMMU_TABLE1, 0x01);
REG_SET_FIELD(DPORT_DMMU_TABLE2_REG, DPORT_DMMU_TABLE2, 0x02);
@ -338,6 +402,7 @@ static void configure_mpu(void)
REG_SET_FIELD(DPORT_DMMU_TABLE13_REG, DPORT_DMMU_TABLE13, 0x5d);
REG_SET_FIELD(DPORT_DMMU_TABLE14_REG, DPORT_DMMU_TABLE14, 0x5e);
REG_SET_FIELD(DPORT_DMMU_TABLE15_REG, DPORT_DMMU_TABLE15, 0x5f);
#endif
/* Configure interrupt vector addresses in PID Controller */
@ -399,6 +464,19 @@ void esp32_userspace(void)
configure_flash_mmu();
#ifdef CONFIG_ESP32_USER_DATA_EXTMEM
if (esp_spiram_init() != OK)
{
mwarn("SPI RAM initialization failed!\n");
PANIC();
}
/* Configure the SRAM MMU for enabling access to the userspace image */
configure_sram_mmu();
#endif
/* Clear all of userspace .bss */
DEBUGASSERT(USERSPACE->us_bssstart != 0 && USERSPACE->us_bssend != 0 &&

View File

@ -73,6 +73,17 @@ MEMORY
* the amount of RAM available to the NuttX Kernel.
*/
#ifdef CONFIG_ESP32_USER_DATA_EXTMEM
/* Physically located in External RAM */
UDRAM (RW) : org = 0x3f800000, len = 0x400000
/* Physically located in SRAM2 */
KDRAM_0 (RW) : org = 0x3ffb0000 + CONFIG_ESP32_BT_RESERVE_DRAM,
len = 0x30000 - CONFIG_ESP32_BT_RESERVE_DRAM
/* Physically located in SRAM1 */
KDRAM_1 (RW) : org = 0x3ffe0000, len = 0x20000
#else
/* Physically located in SRAM2 */
KDRAM_0 (RW) : org = 0x3ffb0000 + CONFIG_ESP32_BT_RESERVE_DRAM,
len = 0x18000 - CONFIG_ESP32_BT_RESERVE_DRAM
@ -80,6 +91,7 @@ MEMORY
/* Physically located in SRAM1 */
KDRAM_1 (RW) : org = 0x3ffe0000, len = 0x20000
#endif
/* Flash mapped constant data */