Skip to content

Commit

Permalink
soc: espressif: psram as shared multi heap
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
LucasTambor committed Aug 13, 2024
1 parent 6a101ae commit d54c7e5
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 89 deletions.
3 changes: 3 additions & 0 deletions include/zephyr/multi_heap/shared_multi_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ enum shared_multi_heap_attr {
/** non-cacheable */
SMH_REG_ATTR_NON_CACHEABLE,

/** external Memory */
SMH_REG_ATTR_EXTERNAL,

/** must be the last item */
SMH_REG_ATTR_NUM,
};
Expand Down
2 changes: 2 additions & 0 deletions soc/espressif/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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_library_sources_ifdef(CONFIG_ESP_SPIRAM psram.c)
10 changes: 1 addition & 9 deletions soc/espressif/common/Kconfig.spiram
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,14 @@ if SOC_SERIES_ESP32 || SOC_SERIES_ESP32S2 || SOC_SERIES_ESP32S3
config ESP_SPIRAM
bool "Support for external, SPI-connected RAM"
default n if MCUBOOT
select SHARED_MULTI_HEAP
help
This enables support for an external SPI RAM chip, connected in
parallel with the main SPI flash chip.

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
Expand Down
10 changes: 10 additions & 0 deletions soc/espressif/common/include/psram.h
Original file line number Diff line number Diff line change
@@ -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);
57 changes: 57 additions & 0 deletions soc/espressif/common/psram.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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);
}

int esp_init_psram(void)
{
esp_err_t err = esp_psram_init();

if (err != ESP_OK) {
ets_printf("Failed to Initialize external RAM, aborting.\n");
return err;
}

if (esp_psram_get_size() < CONFIG_ESP_SPIRAM_SIZE) {
ets_printf("External RAM size is less than configured, aborting.\n");
return err;
}

if (esp_psram_is_initialized()) {
if (!esp_psram_extram_test()) {
ets_printf("External RAM failed memory test!");
return err;
}
}

memset(&_ext_ram_bss_start, 0,
(&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start));

return 0;
}
34 changes: 9 additions & 25 deletions soc/espressif/esp32/soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -42,11 +41,6 @@

#include <zephyr/sys/printk.h>

#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);

Expand Down Expand Up @@ -152,26 +146,9 @@ void IRAM_ATTR __esp_platform_start(void)
#endif

#if CONFIG_ESP_SPIRAM
esp_err_t err = esp_psram_init();

if (err != ESP_OK) {
printk("Failed to Initialize SPIRAM, aborting.\n");
if (esp_init_psram()) {
abort();
}
if (esp_psram_get_size() < CONFIG_ESP_SPIRAM_SIZE) {
printk("SPIRAM size is less than configured size, aborting.\n");
abort();
}

if (esp_psram_is_initialized()) {
if (!esp_psram_extram_test()) {
printk("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));
#endif /* CONFIG_ESP_SPIRAM */

/* Scheduler is not started at this point. Hence, guard functions
Expand All @@ -187,6 +164,13 @@ void IRAM_ATTR __esp_platform_start(void)

esp_intr_initialize();

#if CONFIG_ESP_SPIRAM
/* Init Shared Multi Heap for PSRAM */
if (esp_psram_smh_init()) {
abort();
}
#endif

/* Start Zephyr */
z_prep_c();

Expand Down
36 changes: 10 additions & 26 deletions soc/espressif/esp32s2/soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -41,11 +40,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
Expand Down Expand Up @@ -107,27 +101,9 @@ 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) {
printk("Failed to Initialize SPIRAM, aborting.\n");
if (esp_init_psram()) {
abort();
}
if (esp_psram_get_size() < CONFIG_ESP_SPIRAM_SIZE) {
printk("SPIRAM size is less than configured size, aborting.\n");
abort();
}

if (esp_psram_is_initialized()) {
if (!esp_psram_extram_test()) {
printk("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));

#endif /* CONFIG_ESP_SPIRAM */

esp_timer_early_init();
Expand All @@ -143,6 +119,14 @@ void __attribute__((section(".iram1"))) __esp_platform_start(void)
#endif /* !CONFIG_MCUBOOT */

esp_intr_initialize();

#if CONFIG_ESP_SPIRAM
/* Init Shared Multi Heap for PSRAM */
if (esp_psram_smh_init()) {
abort();
}
#endif

/* Start Zephyr */
z_prep_c();

Expand Down
37 changes: 9 additions & 28 deletions soc/espressif/esp32s3/soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -47,11 +45,6 @@

#include <zephyr/sys/printk.h>

#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);

Expand Down Expand Up @@ -158,28 +151,9 @@ 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) {
printk("Failed to Initialize external RAM, aborting.\n");
if (esp_init_psram()) {
abort();
}

if (esp_psram_get_size() < CONFIG_ESP_SPIRAM_SIZE) {
printk("External RAM size is less than configured, aborting.\n");
abort();
}

if (esp_psram_is_initialized()) {
if (!esp_psram_extram_test()) {
printk("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));

#endif /* CONFIG_ESP_SPIRAM */

/* Apply SoC patches */
Expand Down Expand Up @@ -211,6 +185,13 @@ void IRAM_ATTR __esp_platform_start(void)

esp_intr_initialize();

#if CONFIG_ESP_SPIRAM
/* Init Shared Multi Heap for PSRAM */
if (esp_psram_smh_init()) {
abort();
}
#endif

/* Start Zephyr */
z_prep_c();

Expand Down
2 changes: 1 addition & 1 deletion west.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ manifest:
groups:
- hal
- name: hal_espressif
revision: e2902b60bc8b540b49f1012e6d45f8eef067f5bb
revision: pull/312/head
path: modules/hal/espressif
west-commands: west/west-commands.yml
groups:
Expand Down

0 comments on commit d54c7e5

Please sign in to comment.