diff --git a/soc/xtensa/esp32s2/Kconfig.soc b/soc/xtensa/esp32s2/Kconfig.soc index f9ef732ba24..8060796dcdd 100644 --- a/soc/xtensa/esp32s2/Kconfig.soc +++ b/soc/xtensa/esp32s2/Kconfig.soc @@ -45,7 +45,8 @@ endchoice choice prompt "Data cache size" - default ESP32S2_DATA_CACHE_0KB + default ESP32S2_DATA_CACHE_0KB if !ESP_SPIRAM + default ESP32S2_DATA_CACHE_8KB if ESP_SPIRAM config ESP32S2_DATA_CACHE_0KB bool "0KB data cache size" @@ -81,6 +82,97 @@ config ESP32S2_DATA_CACHE_SIZE default 0x4000 if ESP32S2_DATA_CACHE_16KB default 0x0000 +config ESP_SPIRAM + bool "Support for external, SPI-connected RAM" + help + This enables support for an external SPI RAM chip, connected in + parallel with the main SPI flash chip. + +config ESP_HEAP_MIN_EXTRAM_THRESHOLD + int "Minimum threshold for external RAM allocation" + default 8192 + range 1024 131072 + depends on ESP_SPIRAM + help + Threshold to decide if memory will be allocated from DRAM + or SPIRAM. If value of allocation size is less than this value, + memory will be allocated from internal RAM. + +menu "SPI RAM config" + depends on ESP_SPIRAM + +choice SPIRAM_TYPE + prompt "Type of SPI RAM chip in use" + default SPIRAM_TYPE_ESPPSRAM16 + +config SPIRAM_TYPE_ESPPSRAM16 + bool "ESP-PSRAM16 or APS1604" + +config SPIRAM_TYPE_ESPPSRAM32 + bool "ESP-PSRAM32 or IS25WP032" + +config SPIRAM_TYPE_ESPPSRAM64 + bool "ESP-PSRAM64 or LY68L6400" + +endchoice # SPIRAM_TYPE + +config ESP_SPIRAM_SIZE + int "Size of SPIRAM part" + default 2097152 if SPIRAM_TYPE_ESPPSRAM16 + default 4194304 if SPIRAM_TYPE_ESPPSRAM32 + default 8388608 if SPIRAM_TYPE_ESPPSRAM64 + help + Specify size of SPIRAM part. + NOTE: If SPIRAM size is greater than 4MB, only + lower 4MB can be allocated using k_malloc(). + +menu "PSRAM clock and cs IO for ESP32S2" + depends on ESP_SPIRAM + +config DEFAULT_PSRAM_CLK_IO + int "PSRAM CLK IO number" + range 0 33 + default 30 + help + The PSRAM CLOCK IO can be any unused GPIO, user can config + it based on hardware design. + +config DEFAULT_PSRAM_CS_IO + int "PSRAM CS IO number" + range 0 33 + default 26 + help + The PSRAM CS IO can be any unused GPIO, user can config it + based on hardware design. + +endmenu # PSRAM clock and cs IO for ESP32S2 + +choice SPIRAM_SPEED + prompt "Set RAM clock speed" + default SPIRAM_SPEED_40M + help + Select the speed for the SPI RAM chip. + +config SPIRAM_SPEED_80M + bool "80MHz clock speed" + +config SPIRAM_SPEED_40M + bool "40MHz clock speed" + +config SPIRAM_SPEED_26M + bool "26MHz clock speed" + +config SPIRAM_SPEED_20M + bool "20MHz clock speed" + +endchoice # SPIRAM_SPEED + +config SPIRAM + bool + default y + +endmenu # SPI RAM config + choice ESP32S2_UNIVERSAL_MAC_ADDRESSES bool "Number of universally administered (by IEEE) MAC address" default ESP32S2_UNIVERSAL_MAC_ADDRESSES_TWO diff --git a/soc/xtensa/esp32s2/linker.ld b/soc/xtensa/esp32s2/linker.ld index 3cb9e53dacd..a148c144813 100644 --- a/soc/xtensa/esp32s2/linker.ld +++ b/soc/xtensa/esp32s2/linker.ld @@ -42,6 +42,9 @@ MEMORY drom0_0_seg(R): org = 0x3f000020, len = 0x3f0000-0x20 rtc_iram_seg(RWX): org = 0x40070000, len = 0x2000 rtc_slow_seg(RW): org = 0x50000000, len = 0x2000 +#if defined(CONFIG_ESP_SPIRAM) + ext_ram_seg(RW): org = 0x3f500000, len = CONFIG_ESP_SPIRAM_SIZE +#endif #ifdef CONFIG_GEN_ISR_TABLES IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 #endif @@ -238,6 +241,16 @@ _net_buf_pool_list = _esp_net_buf_pool_list; . = ALIGN(4); } GROUP_LINK_IN(RAMABLE_REGION) +#if defined(CONFIG_ESP_SPIRAM) + .ext_ram.bss (NOLOAD): + { + _ext_ram_bss_start = ABSOLUTE(.); + *(.ext_ram.bss*) + . = ALIGN(4); + _ext_ram_bss_end = ABSOLUTE(.) + CONFIG_ESP_SPIRAM_SIZE; + } > ext_ram_seg +#endif + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(20)) { _rodata_start = ABSOLUTE(.); diff --git a/soc/xtensa/esp32s2/soc.c b/soc/xtensa/esp32s2/soc.c index 9023c4fb703..ee00bb9b678 100644 --- a/soc/xtensa/esp32s2/soc.c +++ b/soc/xtensa/esp32s2/soc.c @@ -23,12 +23,18 @@ #include "esp_spi_flash.h" #include "hal/cpu_ll.h" #include "esp_err.h" +#include "esp32s2/spiram.h" #include "sys/printk.h" extern void z_cstart(void); extern void z_bss_zero(void); extern void rtc_clk_cpu_freq_set_xtal(void); +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY +extern int _ext_ram_bss_start; +extern int _ext_ram_bss_end; +#endif + /* * This is written in C rather than assembly since, during the port bring up, * Zephyr is being booted by the Espressif bootloader. With it, the C stack @@ -158,7 +164,32 @@ void __attribute__((section(".iram1"))) __start(void) *wdt_rtc_protect = 0; #endif -#if CONFIG_SOC_FLASH_ESP32 +#if CONFIG_ESP_SPIRAM + esp_err_t err = esp_spiram_init(); + + if (err != ESP_OK) { + printk("Failed to Initialize SPIRAM, aborting.\n"); + abort(); + } + esp_spiram_init_cache(); + if (esp_spiram_get_size() < CONFIG_ESP_SPIRAM_SIZE) { + printk("SPIRAM size is less than configured size, aborting.\n"); + abort(); + } +#endif + +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + memset(&_ext_ram_bss_start, + 0, + (&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start)); +#endif + +/* Scheduler is not started at this point. Hence, guard functions + * must be initialized after esp_spiram_init_cache which internally + * uses guard functions. Setting guard functions before SPIRAM + * cache initialization will result in a crash. + */ +#if CONFIG_SOC_FLASH_ESP32 || CONFIG_ESP_SPIRAM spi_flash_guard_set(&g_flash_guard_default_ops); #endif esp_intr_initialize(); diff --git a/soc/xtensa/esp32s2/soc.h b/soc/xtensa/esp32s2/soc.h index a90388056fd..9af358f832a 100644 --- a/soc/xtensa/esp32s2/soc.h +++ b/soc/xtensa/esp32s2/soc.h @@ -19,6 +19,7 @@ #include #include #include +#include extern void esp_rom_uart_attach(void); extern void esp_rom_uart_tx_wait_idle(uint8_t uart_no);