soc: espressif: psram as shared multi heap
Currently, if the user wants to allocate heap on external RAM he needs to enable CONFIG_ESP_SPIRAM and set a threshold defined with CONFIG_ESP_HEAP_MIN_EXTRAM_THRESHOLD. This approach requires that we re-implement `k_malloc` and allocate the memory on the proper region based on the block size. By using the shared multi heap feature the proccess of allocating memory from external memory becomes more fluent and simple. The attribute SMH_REG_ATTR_EXTERNAL was added to reference the external memory. Signed-off-by: Lucas Tamborrino <lucas.tamborrino@espressif.com>
This commit is contained in:
parent
cfeb325b4f
commit
5dc545290c
8 changed files with 102 additions and 94 deletions
|
@ -4,3 +4,5 @@
|
|||
if(CONFIG_SOC_SERIES_ESP32 OR CONFIG_SOC_SERIES_ESP32S2 OR CONFIG_SOC_SERIES_ESP32S3)
|
||||
zephyr_include_directories(include)
|
||||
endif()
|
||||
|
||||
zephyr_sources_ifdef(CONFIG_ESP_SPIRAM psram.c)
|
||||
|
|
|
@ -7,6 +7,7 @@ config ESP_SPIRAM
|
|||
bool "Support for external, SPI-connected RAM"
|
||||
default n if MCUBOOT
|
||||
default n if ESP32_USE_UNSUPPORTED_REVISION && SOC_SERIES_ESP32
|
||||
select SHARED_MULTI_HEAP
|
||||
help
|
||||
This enables support for an external SPI RAM chip, connected in
|
||||
parallel with the main SPI flash chip.
|
||||
|
@ -14,15 +15,6 @@ config ESP_SPIRAM
|
|||
menu "SPI RAM config"
|
||||
depends on ESP_SPIRAM
|
||||
|
||||
config ESP_HEAP_MIN_EXTRAM_THRESHOLD
|
||||
int "Minimum threshold for external RAM allocation"
|
||||
default 8192
|
||||
range 1024 131072
|
||||
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.
|
||||
|
||||
config ESP_HEAP_SEARCH_ALL_REGIONS
|
||||
bool "Search for all available heap regions"
|
||||
default y
|
||||
|
|
10
soc/espressif/common/include/psram.h
Normal file
10
soc/espressif/common/include/psram.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
int esp_init_psram(void);
|
||||
|
||||
int esp_psram_smh_init(void);
|
52
soc/espressif/common/psram.c
Normal file
52
soc/espressif/common/psram.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <rom/ets_sys.h>
|
||||
#include <esp_psram.h>
|
||||
#include <esp_private/esp_psram_extram.h>
|
||||
#include <zephyr/multi_heap/shared_multi_heap.h>
|
||||
|
||||
#define PSRAM_ADDR (DT_REG_ADDR(DT_NODELABEL(psram0)))
|
||||
|
||||
extern int _spiram_heap_start;
|
||||
extern int _ext_ram_bss_start;
|
||||
extern int _ext_ram_bss_end;
|
||||
|
||||
struct shared_multi_heap_region smh_psram = {
|
||||
.addr = (uintptr_t)&_spiram_heap_start,
|
||||
.size = CONFIG_ESP_SPIRAM_SIZE,
|
||||
.attr = SMH_REG_ATTR_EXTERNAL,
|
||||
};
|
||||
|
||||
int esp_psram_smh_init(void)
|
||||
{
|
||||
shared_multi_heap_pool_init();
|
||||
smh_psram.size = CONFIG_ESP_SPIRAM_SIZE - ((int)&_spiram_heap_start - PSRAM_ADDR);
|
||||
return shared_multi_heap_add(&smh_psram, NULL);
|
||||
}
|
||||
|
||||
void esp_init_psram(void)
|
||||
{
|
||||
if (esp_psram_init()) {
|
||||
ets_printf("Failed to Initialize external RAM, aborting.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (esp_psram_get_size() < CONFIG_ESP_SPIRAM_SIZE) {
|
||||
ets_printf("External RAM size is less than configured.\n");
|
||||
}
|
||||
|
||||
if (esp_psram_is_initialized()) {
|
||||
if (!esp_psram_extram_test()) {
|
||||
ets_printf("External RAM failed memory test!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&_ext_ram_bss_start, 0,
|
||||
(&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start));
|
||||
}
|
|
@ -14,8 +14,7 @@
|
|||
#include <esp_private/spi_flash_os.h>
|
||||
#include <esp_private/esp_mmu_map_private.h>
|
||||
#if CONFIG_ESP_SPIRAM
|
||||
#include <esp_psram.h>
|
||||
#include <esp_private/esp_psram_extram.h>
|
||||
#include "psram.h"
|
||||
#endif
|
||||
|
||||
#include <zephyr/kernel_structs.h>
|
||||
|
@ -45,11 +44,6 @@
|
|||
|
||||
#define TAG "boot.esp32"
|
||||
|
||||
#if CONFIG_ESP_SPIRAM
|
||||
extern int _ext_ram_bss_start;
|
||||
extern int _ext_ram_bss_end;
|
||||
#endif
|
||||
|
||||
extern void z_prep_c(void);
|
||||
extern void esp_reset_reason_init(void);
|
||||
|
||||
|
@ -155,26 +149,7 @@ void IRAM_ATTR __esp_platform_start(void)
|
|||
#endif
|
||||
|
||||
#if CONFIG_ESP_SPIRAM
|
||||
esp_err_t err = esp_psram_init();
|
||||
|
||||
if (err != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to Initialize SPIRAM, aborting.");
|
||||
abort();
|
||||
}
|
||||
if (esp_psram_get_size() < CONFIG_ESP_SPIRAM_SIZE) {
|
||||
ESP_EARLY_LOGE(TAG, "SPIRAM size is less than configured size, aborting.");
|
||||
abort();
|
||||
}
|
||||
|
||||
if (esp_psram_is_initialized()) {
|
||||
if (!esp_psram_extram_test()) {
|
||||
ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
memset(&_ext_ram_bss_start, 0,
|
||||
(&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start));
|
||||
esp_init_psram();
|
||||
#endif /* CONFIG_ESP_SPIRAM */
|
||||
|
||||
/* Scheduler is not started at this point. Hence, guard functions
|
||||
|
@ -190,6 +165,15 @@ void IRAM_ATTR __esp_platform_start(void)
|
|||
|
||||
esp_intr_initialize();
|
||||
|
||||
#if CONFIG_ESP_SPIRAM
|
||||
/* Init Shared Multi Heap for PSRAM */
|
||||
int err = esp_psram_smh_init();
|
||||
|
||||
if (err) {
|
||||
printk("Failed to initialize PSRAM shared multi heap (%d)\n", err);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Start Zephyr */
|
||||
z_prep_c();
|
||||
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
#include <esp_private/esp_mmu_map_private.h>
|
||||
#include <esp_flash_internal.h>
|
||||
#if CONFIG_ESP_SPIRAM
|
||||
#include <esp_psram.h>
|
||||
#include <esp_private/esp_psram_extram.h>
|
||||
#include "psram.h"
|
||||
#endif
|
||||
|
||||
#include <zephyr/kernel_structs.h>
|
||||
|
@ -44,11 +43,6 @@ extern void rtc_clk_cpu_freq_set_xtal(void);
|
|||
extern void esp_reset_reason_init(void);
|
||||
extern void z_prep_c(void);
|
||||
|
||||
#if CONFIG_ESP_SPIRAM
|
||||
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
|
||||
|
@ -110,27 +104,7 @@ void __attribute__((section(".iram1"))) __esp_platform_start(void)
|
|||
esp_mmu_map_init();
|
||||
|
||||
#if CONFIG_ESP_SPIRAM
|
||||
esp_err_t err = esp_psram_init();
|
||||
|
||||
if (err != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to Initialize SPIRAM, aborting.");
|
||||
abort();
|
||||
}
|
||||
if (esp_psram_get_size() < CONFIG_ESP_SPIRAM_SIZE) {
|
||||
ESP_EARLY_LOGE(TAG, "SPIRAM size is less than configured size, aborting.");
|
||||
abort();
|
||||
}
|
||||
|
||||
if (esp_psram_is_initialized()) {
|
||||
if (!esp_psram_extram_test()) {
|
||||
ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
memset(&_ext_ram_bss_start, 0,
|
||||
(&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start));
|
||||
|
||||
esp_init_psram();
|
||||
#endif /* CONFIG_ESP_SPIRAM */
|
||||
|
||||
esp_timer_early_init();
|
||||
|
@ -146,6 +120,16 @@ void __attribute__((section(".iram1"))) __esp_platform_start(void)
|
|||
#endif /* !CONFIG_MCUBOOT */
|
||||
|
||||
esp_intr_initialize();
|
||||
|
||||
#if CONFIG_ESP_SPIRAM
|
||||
/* Init Shared Multi Heap for PSRAM */
|
||||
int err = esp_psram_smh_init();
|
||||
|
||||
if (err) {
|
||||
printk("Failed to initialize PSRAM shared multi heap (%d)\n", err);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Start Zephyr */
|
||||
z_prep_c();
|
||||
|
||||
|
|
|
@ -19,12 +19,10 @@
|
|||
#include <sdkconfig.h>
|
||||
|
||||
#if CONFIG_ESP_SPIRAM
|
||||
#include <esp_psram.h>
|
||||
#include <esp_private/esp_psram_extram.h>
|
||||
#include "psram.h"
|
||||
#endif
|
||||
|
||||
#include <zephyr/kernel_structs.h>
|
||||
#include <string.h>
|
||||
#include <zephyr/toolchain.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/linker/linker-defs.h>
|
||||
|
@ -50,11 +48,6 @@
|
|||
|
||||
#define TAG "boot.esp32s3"
|
||||
|
||||
#if CONFIG_ESP_SPIRAM
|
||||
extern int _ext_ram_bss_start;
|
||||
extern int _ext_ram_bss_end;
|
||||
#endif
|
||||
|
||||
extern void z_prep_c(void);
|
||||
extern void esp_reset_reason_init(void);
|
||||
|
||||
|
@ -161,28 +154,7 @@ void IRAM_ATTR __esp_platform_start(void)
|
|||
esp_mmu_map_init();
|
||||
|
||||
#if CONFIG_ESP_SPIRAM
|
||||
esp_err_t err = esp_psram_init();
|
||||
|
||||
if (err != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to Initialize external RAM, aborting.");
|
||||
abort();
|
||||
}
|
||||
|
||||
if (esp_psram_get_size() < CONFIG_ESP_SPIRAM_SIZE) {
|
||||
ESP_EARLY_LOGE(TAG, "External RAM size is less than configured, aborting.");
|
||||
abort();
|
||||
}
|
||||
|
||||
if (esp_psram_is_initialized()) {
|
||||
if (!esp_psram_extram_test()) {
|
||||
ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
memset(&_ext_ram_bss_start, 0,
|
||||
(&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start));
|
||||
|
||||
esp_init_psram();
|
||||
#endif /* CONFIG_ESP_SPIRAM */
|
||||
|
||||
/* Apply SoC patches */
|
||||
|
@ -214,6 +186,15 @@ void IRAM_ATTR __esp_platform_start(void)
|
|||
|
||||
esp_intr_initialize();
|
||||
|
||||
#if CONFIG_ESP_SPIRAM
|
||||
/* Init Shared Multi Heap for PSRAM */
|
||||
int err = esp_psram_smh_init();
|
||||
|
||||
if (err) {
|
||||
printk("Failed to initialize PSRAM shared multi heap (%d)\n", err);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Start Zephyr */
|
||||
z_prep_c();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue