From 46225a4026f23f453da52145345c39c676c2e74d Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Thu, 20 Feb 2025 16:16:43 +0530 Subject: [PATCH] feat(esp_psram): Add a new API to just detect and enable the PSRAM - esp_psram_chip_init() just detects and does basic initialisations of PSRAM - esp_psram_init() initialises and maps/loads the PSRAM pages --- components/esp_psram/Kconfig.spiram.common | 23 ++++++++---- .../include/esp_private/esp_psram_extram.h | 13 ++++++- components/esp_psram/include/esp_psram.h | 3 +- components/esp_psram/linker.lf | 1 + components/esp_psram/system_layer/esp_psram.c | 36 +++++++++++-------- components/esp_system/port/cpu_start.c | 22 +++++++----- components/esp_system/port/soc/esp32p4/clk.c | 2 +- 7 files changed, 67 insertions(+), 33 deletions(-) diff --git a/components/esp_psram/Kconfig.spiram.common b/components/esp_psram/Kconfig.spiram.common index 2832f1e677..f215f1d8d1 100644 --- a/components/esp_psram/Kconfig.spiram.common +++ b/components/esp_psram/Kconfig.spiram.common @@ -2,18 +2,29 @@ # # sourced into the "SPIRAM config" submenu for a specific chip. -config SPIRAM_BOOT_INIT - bool "Initialize SPI RAM during startup" - default "y" +config SPIRAM_BOOT_HW_INIT + bool "Initialise the PSRAM related hardware" + depends on SPIRAM + default "y" if SPIRAM help - If this is enabled, the SPI RAM will be enabled during initial boot. Unless you + If this is enabled, the PSRAM hardware will be initialized during startup. + Enabling this config does not ensure make sure the availability of the PSRAM for usage, + but just initialises the PSRAM hardware. + This is necessary to configure PSRAM memory protection during the boot up. + +config SPIRAM_BOOT_INIT + bool "Initialize PSRAM during startup, including the hardware and memory related configurations" + default "y" + depends on SPIRAM_BOOT_HW_INIT + help + If this is enabled, the PSRAM will be enabled during initial boot. Unless you have specific requirements, you'll want to leave this enabled so memory allocated - during boot-up can also be placed in SPI RAM. + during boot-up can also be placed in PSRAM. config SPIRAM_IGNORE_NOTFOUND bool "Ignore PSRAM when not found" default "n" - depends on SPIRAM_BOOT_INIT && !SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY && !SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + depends on SPIRAM_BOOT_HW_INIT && !SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY && !SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY help Normally, if psram initialization is enabled during compile time but not found at runtime, it is seen as an error making the CPU panic. If this is enabled, booting will complete diff --git a/components/esp_psram/include/esp_private/esp_psram_extram.h b/components/esp_psram/include/esp_private/esp_psram_extram.h index 0b44e1bfd8..3066d8c281 100644 --- a/components/esp_psram/include/esp_private/esp_psram_extram.h +++ b/components/esp_psram/include/esp_private/esp_psram_extram.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -60,6 +60,17 @@ bool esp_psram_extram_test(void); */ void esp_psram_bss_init(void); +/** + * @brief Initialize the PSRAM hardware. + * Just initialize the PSRAM hardware, does not load the XIP segments or map the PSRAM memory + * + * @return + * - ESP_OK: On success + * - ESP_FAIL: PSRAM isn't initialized successfully, potential reason would be: wrong VDDSDIO, invalid chip ID, etc. + * - ESP_ERR_INVALID_STATE: PSRAM is initialized already + */ +esp_err_t esp_psram_chip_init(void); + #if CONFIG_IDF_TARGET_ESP32 /** * @brief Force a writeback of the data in the PSRAM cache. This is to be called whenever diff --git a/components/esp_psram/include/esp_psram.h b/components/esp_psram/include/esp_psram.h index 8692aef7cf..27c7f7b4a5 100644 --- a/components/esp_psram/include/esp_psram.h +++ b/components/esp_psram/include/esp_psram.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,7 @@ extern "C" { /** * @brief Initialize PSRAM interface/hardware. + * Initializes the PSRAM hardware and load the XIP segments or maps the PSRAM memory * * @return * - ESP_OK: On success diff --git a/components/esp_psram/linker.lf b/components/esp_psram/linker.lf index 1e11799f15..65f737830e 100644 --- a/components/esp_psram/linker.lf +++ b/components/esp_psram/linker.lf @@ -20,6 +20,7 @@ entries: if SPIRAM_FLASH_LOAD_TO_PSRAM = y: esp_psram_impl_ap_hex (noflash) mmu_psram_flash_v2 (noflash) + esp_psram: esp_psram_chip_init (noflash) esp_psram: esp_psram_init (noflash) esp_psram: s_psram_chip_init (noflash) esp_psram: s_xip_psram_placement (noflash) diff --git a/components/esp_psram/system_layer/esp_psram.c b/components/esp_psram/system_layer/esp_psram.c index 003e365754..ad1b76a963 100644 --- a/components/esp_psram/system_layer/esp_psram.c +++ b/components/esp_psram/system_layer/esp_psram.c @@ -78,7 +78,8 @@ typedef struct { } psram_mem_t; typedef struct { - bool is_initialised; + bool is_chip_initialised; // if psram hardware is initialised or not + bool is_initialised; // if psram initialised with memory mapping or not and is ready to use /** * @note 1 * As we can't use heap allocator during this stage, we need to statically declare these regions. @@ -138,9 +139,9 @@ static void IRAM_ATTR s_mapping(int v_start, int size) } #endif //CONFIG_IDF_TARGET_ESP32 -static esp_err_t s_psram_chip_init(uint32_t *out_available_size) +static esp_err_t s_psram_chip_init(void) { - if (s_psram_ctx.is_initialised) { + if (s_psram_ctx.is_chip_initialised) { return ESP_ERR_INVALID_STATE; } @@ -152,7 +153,7 @@ static esp_err_t s_psram_chip_init(uint32_t *out_available_size) #endif return ret; } - s_psram_ctx.is_initialised = true; + s_psram_ctx.is_chip_initialised = true; uint32_t psram_physical_size = 0; ret = esp_psram_impl_get_physical_size(&psram_physical_size); @@ -167,13 +168,6 @@ static esp_err_t s_psram_chip_init(uint32_t *out_available_size) ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in low/high (2-core) mode."); #endif #endif - - uint32_t psram_available_size = 0; - ret = esp_psram_impl_get_available_size(&psram_available_size); - assert(ret == ESP_OK); - - *out_available_size = psram_available_size; - return ESP_OK; } @@ -349,15 +343,26 @@ static void s_psram_mapping(uint32_t psram_available_size, uint32_t start_page) #endif } +esp_err_t esp_psram_chip_init(void) +{ + return s_psram_chip_init(); +} + esp_err_t esp_psram_init(void) { esp_err_t ret = ESP_FAIL; - uint32_t psram_available_size = 0; - ret = s_psram_chip_init(&psram_available_size); - if (ret != ESP_OK) { - return ret; + + if (!s_psram_ctx.is_chip_initialised) { + ret = esp_psram_chip_init(); + if (ret != ESP_OK) { + return ret; + } } + uint32_t psram_available_size = 0; + ret = esp_psram_impl_get_available_size(&psram_available_size); + assert(ret == ESP_OK); + /** * `start_page` is the psram physical address in MMU page size. * MMU page size on ESP32S2 is 64KB @@ -382,6 +387,7 @@ esp_err_t esp_psram_init(void) cache_register_writeback(&drv); #endif + s_psram_ctx.is_initialised = true; return ESP_OK; } diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index c1b66a0930..5af3d7bbbc 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -565,19 +565,23 @@ void IRAM_ATTR call_start_cpu0(void) #endif #endif +#if CONFIG_SPIRAM_BOOT_HW_INIT + if (esp_psram_chip_init() != ESP_OK) { +#if CONFIG_SPIRAM_IGNORE_NOTFOUND + ESP_DRAM_LOGE(TAG, "Failed to init external RAM; continuing without it."); +#else + ESP_DRAM_LOGE(TAG, "Failed to init external RAM!"); + abort(); +#endif + } +#endif + #if CONFIG_SPIRAM_BOOT_INIT if (esp_psram_init() != ESP_OK) { #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY ESP_DRAM_LOGE(TAG, "Failed to init external RAM, needed for external .bss segment"); abort(); #endif - -#if CONFIG_SPIRAM_IGNORE_NOTFOUND - ESP_EARLY_LOGI(TAG, "Failed to init external RAM; continuing without it."); -#else - ESP_DRAM_LOGE(TAG, "Failed to init external RAM!"); - abort(); -#endif } #endif @@ -792,13 +796,13 @@ void IRAM_ATTR call_start_cpu0(void) } #if CONFIG_IDF_TARGET_ESP32 -#if !CONFIG_SPIRAM_BOOT_INIT +#if !CONFIG_SPIRAM_BOOT_HW_INIT // If psram is uninitialized, we need to improve some flash configuration. bootloader_flash_clock_config(&fhdr); bootloader_flash_gpio_config(&fhdr); bootloader_flash_dummy_config(&fhdr); bootloader_flash_cs_timing_config(); -#endif //!CONFIG_SPIRAM_BOOT_INIT +#endif //!CONFIG_SPIRAM_BOOT_HW_INIT #endif //CONFIG_IDF_TARGET_ESP32 #if CONFIG_SPI_FLASH_SIZE_OVERRIDE diff --git a/components/esp_system/port/soc/esp32p4/clk.c b/components/esp_system/port/soc/esp32p4/clk.c index 2475aa00db..9ca7f49cbe 100644 --- a/components/esp_system/port/soc/esp32p4/clk.c +++ b/components/esp_system/port/soc/esp32p4/clk.c @@ -414,7 +414,7 @@ __attribute__((weak)) void esp_perip_clk_init(void) REG_CLR_BIT(LP_CLKRST_HP_CLK_CTRL_REG, LP_CLKRST_HP_SDIO_PLL2_CLK_EN); REG_CLR_BIT(LP_CLKRST_HP_CLK_CTRL_REG, LP_CLKRST_HP_SDIO_PLL1_CLK_EN); REG_CLR_BIT(LP_CLKRST_HP_CLK_CTRL_REG, LP_CLKRST_HP_SDIO_PLL0_CLK_EN); -#if !CONFIG_SPIRAM_BOOT_INIT +#if !CONFIG_SPIRAM_BOOT_HW_INIT REG_CLR_BIT(LP_CLKRST_HP_CLK_CTRL_REG, LP_CLKRST_HP_MPLL_500M_CLK_EN); #endif REG_CLR_BIT(LP_SYSTEM_REG_HP_ROOT_CLK_CTRL_REG, LP_SYSTEM_REG_CPU_CLK_EN);