mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/support_bss_on_psram' into 'master'
psram: support .bss on psram on esp32s3 Closes IDF-4814, IDF-4396, IDFGH-7148, and IDFGH-7153 See merge request espressif/esp-idf!17557
This commit is contained in:
commit
5bb59b00e7
@ -195,9 +195,14 @@ menu "ESP32S2-specific"
|
|||||||
bool "20Mhz clock speed"
|
bool "20Mhz clock speed"
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
config SPIRAM_SPEED
|
||||||
|
int
|
||||||
|
default 80 if SPIRAM_SPEED_80M
|
||||||
|
default 40 if SPIRAM_SPEED_40M
|
||||||
|
default 40 if SPIRAM_SPEED_26M
|
||||||
|
default 40 if SPIRAM_SPEED_20M
|
||||||
|
|
||||||
# insert non-chip-specific items here NOERROR
|
source "$IDF_PATH/components/esp_hw_support/Kconfig.spiram.common" #insert non-chip-specific items here
|
||||||
source "$IDF_PATH/components/esp_hw_support/Kconfig.spiram.common"
|
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
@ -66,9 +66,19 @@ extern "C" {
|
|||||||
|
|
||||||
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
// Forces bss variable into external memory. "
|
// Forces bss variable into external memory. "
|
||||||
#define EXT_RAM_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__)
|
#define EXT_RAM_BSS_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__)
|
||||||
#else
|
#else
|
||||||
#define EXT_RAM_ATTR
|
#define EXT_RAM_BSS_ATTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated Macro for putting .bss on PSRAM
|
||||||
|
*/
|
||||||
|
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
|
// Forces bss variable into external memory. "
|
||||||
|
#define EXT_RAM_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__) _Pragma ("GCC warning \"'EXT_RAM_ATTR' macro is deprecated, please use `EXT_RAM_BSS_ATTR`\"")
|
||||||
|
#else
|
||||||
|
#define EXT_RAM_ATTR _Pragma ("GCC warning \"'EXT_RAM_ATTR' macro is deprecated, please use `EXT_RAM_BSS_ATTR`\"")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Forces data into RTC slow memory. See "docs/deep-sleep-stub.rst"
|
// Forces data into RTC slow memory. See "docs/deep-sleep-stub.rst"
|
||||||
|
@ -116,8 +116,8 @@ TEST_CASE_MULTIPLE_STAGES("Spiram test noinit memory", "[spiram]", write_spiram_
|
|||||||
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
#define TEST_BSS_NUM 256
|
#define TEST_BSS_NUM (256 * 1024)
|
||||||
static EXT_RAM_ATTR uint32_t s_bss_buffer[TEST_BSS_NUM];
|
static EXT_RAM_BSS_ATTR uint32_t s_bss_buffer[TEST_BSS_NUM];
|
||||||
|
|
||||||
TEST_CASE("Test variables placed in external .bss segment", "[ld]")
|
TEST_CASE("Test variables placed in external .bss segment", "[ld]")
|
||||||
{
|
{
|
||||||
|
@ -92,15 +92,15 @@ config SPIRAM_MALLOC_RESERVE_INTERNAL
|
|||||||
config SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
config SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
bool "Allow .bss segment placed in external memory"
|
bool "Allow .bss segment placed in external memory"
|
||||||
default n
|
default n
|
||||||
depends on SPIRAM && (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2) # ESP32-S3 IDF-1974
|
depends on SPIRAM
|
||||||
select ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
select ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
help
|
help
|
||||||
If enabled, variables with EXT_RAM_ATTR attribute will be placed in SPIRAM instead of internal DRAM.
|
If enabled, variables with EXT_RAM_BSS_ATTR attribute will be placed in SPIRAM instead of internal DRAM.
|
||||||
BSS section of `lwip`, `net80211`, `pp`, `bt` libraries will be automatically placed
|
BSS section of `lwip`, `net80211`, `pp`, `bt` libraries will be automatically placed
|
||||||
in SPIRAM. BSS sections from other object files and libraries can also be placed in SPIRAM through
|
in SPIRAM. BSS sections from other object files and libraries can also be placed in SPIRAM through
|
||||||
linker fragment scheme `extram_bss`.
|
linker fragment scheme `extram_bss`.
|
||||||
|
|
||||||
Note that the variables placed in SPIRAM using EXT_RAM_ATTR will be zero initialized.
|
Note that the variables placed in SPIRAM using EXT_RAM_BSS_ATTR will be zero initialized.
|
||||||
|
|
||||||
config SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
|
config SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
|
||||||
bool "Allow .noinit segment placed in external memory"
|
bool "Allow .noinit segment placed in external memory"
|
||||||
|
@ -12,17 +12,22 @@
|
|||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_memory_utils.h"
|
#include "esp_memory_utils.h"
|
||||||
|
#include "esp_private/spiram_private.h"
|
||||||
|
|
||||||
|
|
||||||
//TODO: IDF-4855, replace PSRAM related address region into PSRAM private APIs
|
|
||||||
|
|
||||||
bool esp_ptr_dma_ext_capable(const void *p)
|
bool esp_ptr_dma_ext_capable(const void *p)
|
||||||
{
|
{
|
||||||
#ifdef SOC_PSRAM_DMA_CAPABLE
|
#if !SOC_PSRAM_DMA_CAPABLE
|
||||||
return (intptr_t)p >= SOC_DMA_EXT_LOW && (intptr_t)p < SOC_DMA_EXT_HIGH;
|
return false;
|
||||||
|
#endif //!SOC_PSRAM_DMA_CAPABLE
|
||||||
|
#if CONFIG_SPIRAM
|
||||||
|
intptr_t vaddr_start = 0;
|
||||||
|
intptr_t vaddr_end = 0;
|
||||||
|
esp_spiram_get_mapped_range(&vaddr_start, &vaddr_end);
|
||||||
|
return (intptr_t)p >= vaddr_start && (intptr_t)p < vaddr_end;
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif //CONFIG_SPIRAM
|
||||||
}
|
}
|
||||||
|
|
||||||
bool esp_ptr_byte_accessible(const void *p)
|
bool esp_ptr_byte_accessible(const void *p)
|
||||||
@ -37,27 +42,36 @@ bool esp_ptr_byte_accessible(const void *p)
|
|||||||
r |= (ip >= SOC_RTC_DRAM_LOW && ip < SOC_RTC_DRAM_HIGH);
|
r |= (ip >= SOC_RTC_DRAM_LOW && ip < SOC_RTC_DRAM_HIGH);
|
||||||
#endif
|
#endif
|
||||||
#if CONFIG_SPIRAM
|
#if CONFIG_SPIRAM
|
||||||
#if CONFIG_SPIRAM_SIZE != -1 // Fixed size, can be more accurate
|
intptr_t vaddr_start = 0;
|
||||||
r |= (ip >= SOC_EXTRAM_DATA_LOW && ip < (SOC_EXTRAM_DATA_LOW + CONFIG_SPIRAM_SIZE));
|
intptr_t vaddr_end = 0;
|
||||||
#else
|
esp_spiram_get_mapped_range(&vaddr_start, &vaddr_end);
|
||||||
r |= (ip >= SOC_EXTRAM_DATA_LOW && ip < (SOC_EXTRAM_DATA_HIGH));
|
r |= (ip >= vaddr_start && ip < vaddr_end);
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool esp_ptr_external_ram(const void *p) {
|
bool esp_ptr_external_ram(const void *p)
|
||||||
#if SOC_SPIRAM_SUPPORTED
|
{
|
||||||
return ((intptr_t)p >= SOC_EXTRAM_DATA_LOW && (intptr_t)p < SOC_EXTRAM_DATA_HIGH);
|
#if !SOC_SPIRAM_SUPPORTED
|
||||||
|
return false;
|
||||||
|
#endif //!SOC_SPIRAM_SUPPORTED
|
||||||
|
#if CONFIG_SPIRAM
|
||||||
|
intptr_t vaddr_start = 0;
|
||||||
|
intptr_t vaddr_end = 0;
|
||||||
|
esp_spiram_get_mapped_range(&vaddr_start, &vaddr_end);
|
||||||
|
return (intptr_t)p >= vaddr_start && (intptr_t)p < vaddr_end;
|
||||||
#else
|
#else
|
||||||
return false; // SoC has no external RAM
|
return false;
|
||||||
#endif
|
#endif //CONFIG_SPIRAM
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|
#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|
||||||
bool esp_stack_ptr_in_extram(uint32_t sp)
|
bool esp_stack_ptr_in_extram(uint32_t sp)
|
||||||
{
|
{
|
||||||
|
intptr_t vaddr_start = 0;
|
||||||
|
intptr_t vaddr_end = 0;
|
||||||
|
esp_spiram_get_mapped_range(&vaddr_start, &vaddr_end);
|
||||||
//Check if stack ptr is in between SOC_EXTRAM_DATA_LOW and SOC_EXTRAM_DATA_HIGH, and 16 byte aligned.
|
//Check if stack ptr is in between SOC_EXTRAM_DATA_LOW and SOC_EXTRAM_DATA_HIGH, and 16 byte aligned.
|
||||||
return !(sp < SOC_EXTRAM_DATA_LOW + 0x10 || sp > SOC_EXTRAM_DATA_HIGH - 0x10 || ((sp & 0xF) != 0));
|
return !(sp < vaddr_start + 0x10 || sp > vaddr_end - 0x10 || ((sp & 0xF) != 0));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ESP_SPIRAM_SIZE_16MBITS = 0, /*!< SPI RAM size is 16 MBits */
|
||||||
|
ESP_SPIRAM_SIZE_32MBITS = 1, /*!< SPI RAM size is 32 MBits */
|
||||||
|
ESP_SPIRAM_SIZE_64MBITS = 2, /*!< SPI RAM size is 64 MBits */
|
||||||
|
ESP_SPIRAM_SIZE_INVALID, /*!< SPI RAM size is invalid */
|
||||||
|
} esp_spiram_size_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the size of the attached SPI RAM chip selected in menuconfig
|
||||||
|
*
|
||||||
|
* @return Size in bytes, or 0 if no external RAM chip support compiled in.
|
||||||
|
*/
|
||||||
|
size_t esp_spiram_get_size(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the psram mapped vaddr range
|
||||||
|
*
|
||||||
|
* @param[out] out_vstart PSRAM virtual address start
|
||||||
|
* @param[out] out_vend PSRAM virtual address end
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - ESP_ERR_INVALID_STATE PSRAM is not initialized successfully
|
||||||
|
*/
|
||||||
|
esp_err_t esp_spiram_get_mapped_range(intptr_t *out_vstart, intptr_t *out_vend);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the psram alloced vaddr range
|
||||||
|
*
|
||||||
|
* @param[out] out_vstart PSRAM virtual address start
|
||||||
|
* @param[out] out_vend PSRAM virtual address end
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK On success
|
||||||
|
* - ESP_ERR_INVALID_STATE PSRAM is not initialized successfully
|
||||||
|
*/
|
||||||
|
esp_err_t esp_spiram_get_alloced_range(intptr_t *out_vstart, intptr_t *out_vend);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -17,20 +17,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
//TODO: IDF-4382, unify `target/spiram.h`, update migration guide as well
|
||||||
ESP_SPIRAM_SIZE_16MBITS = 0, /*!< SPI RAM size is 16 MBits */
|
|
||||||
ESP_SPIRAM_SIZE_32MBITS = 1, /*!< SPI RAM size is 32 MBits */
|
|
||||||
ESP_SPIRAM_SIZE_64MBITS = 2, /*!< SPI RAM size is 64 MBits */
|
|
||||||
ESP_SPIRAM_SIZE_INVALID, /*!< SPI RAM size is invalid */
|
|
||||||
} esp_spiram_size_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief get SPI RAM size
|
|
||||||
* @return
|
|
||||||
* - ESP_SPIRAM_SIZE_INVALID if SPI RAM not enabled or not valid
|
|
||||||
* - SPI RAM size
|
|
||||||
*/
|
|
||||||
esp_spiram_size_t esp_spiram_get_chip_size(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize spiram interface/hardware. Normally called from cpu_start.c.
|
* @brief Initialize spiram interface/hardware. Normally called from cpu_start.c.
|
||||||
@ -67,15 +54,6 @@ bool esp_spiram_test(void);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_spiram_add_to_heapalloc(void);
|
esp_err_t esp_spiram_add_to_heapalloc(void);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the size of the attached SPI RAM chip selected in menuconfig
|
|
||||||
*
|
|
||||||
* @return Size in bytes, or 0 if no external RAM chip support compiled in.
|
|
||||||
*/
|
|
||||||
size_t esp_spiram_get_size(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Force a writeback of the data in the SPI RAM cache. This is to be called whenever
|
* @brief Force a writeback of the data in the SPI RAM cache. This is to be called whenever
|
||||||
* cache is disabled, because disabling cache on the ESP32 discards the data in the SPI
|
* cache is disabled, because disabling cache on the ESP32 discards the data in the SPI
|
||||||
|
@ -29,13 +29,6 @@ esp_err_t esp_spiram_init(void);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_spiram_add_to_heapalloc(void);
|
esp_err_t esp_spiram_add_to_heapalloc(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the size of the attached SPI RAM chip selected in menuconfig
|
|
||||||
*
|
|
||||||
* @return Size in bytes, or 0 if no external RAM chip support compiled in.
|
|
||||||
*/
|
|
||||||
size_t esp_spiram_get_size(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Force a writeback of the data in the SPI RAM cache. This is to be called whenever
|
* @brief Force a writeback of the data in the SPI RAM cache. This is to be called whenever
|
||||||
* cache is disabled, because disabling cache on the ESP32 discards the data in the SPI
|
* cache is disabled, because disabling cache on the ESP32 discards the data in the SPI
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __ESP_SPIRAM_H
|
#pragma once
|
||||||
#define __ESP_SPIRAM_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -24,43 +23,11 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_spiram_init(void);
|
esp_err_t esp_spiram_init(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Configure Cache/MMU for access to external SPI RAM.
|
|
||||||
*
|
|
||||||
* Normally this function is called from cpu_start, if CONFIG_SPIRAM_BOOT_INIT
|
|
||||||
* option is enabled. Applications which need to enable SPI RAM at run time
|
|
||||||
* can disable CONFIG_SPIRAM_BOOT_INIT, and call this function later.
|
|
||||||
*
|
|
||||||
* @attention this function must be called with flash cache disabled.
|
|
||||||
*/
|
|
||||||
void esp_spiram_init_cache(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Memory test for SPI RAM. Should be called after SPI RAM is initialized and
|
|
||||||
* (in case of a dual-core system) the app CPU is online. This test overwrites the
|
|
||||||
* memory with crap, so do not call after e.g. the heap allocator has stored important
|
|
||||||
* stuff in SPI RAM.
|
|
||||||
*
|
|
||||||
* @return true on success, false on failed memory test
|
|
||||||
*/
|
|
||||||
bool esp_spiram_test(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add the initialized SPI RAM to the heap allocator.
|
* @brief Add the initialized SPI RAM to the heap allocator.
|
||||||
*/
|
*/
|
||||||
esp_err_t esp_spiram_add_to_heapalloc(void);
|
esp_err_t esp_spiram_add_to_heapalloc(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the available physical size of the attached SPI RAM chip
|
|
||||||
*
|
|
||||||
* @note If ECC is enabled, the available physical size would be smaller than the physical size. See `CONFIG_SPIRAM_ECC_ENABLE`
|
|
||||||
*
|
|
||||||
* @return Size in bytes, or 0 if no external RAM chip support compiled in.
|
|
||||||
*/
|
|
||||||
size_t esp_spiram_get_size(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Force a writeback of the data in the SPI RAM cache. This is to be called whenever
|
* @brief Force a writeback of the data in the SPI RAM cache. This is to be called whenever
|
||||||
* cache is disabled, because disabling cache on the ESP32 discards the data in the SPI
|
* cache is disabled, because disabling cache on the ESP32 discards the data in the SPI
|
||||||
@ -160,5 +127,3 @@ int rodata_flash2spiram_offset(void);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "hal/cpu_hal.h"
|
#include "hal/cpu_hal.h"
|
||||||
#include "compare_set.h"
|
#include "compare_set.h"
|
||||||
|
#include "soc/soc.h"
|
||||||
|
|
||||||
#if __XTENSA__
|
#if __XTENSA__
|
||||||
#include "xtensa/xtruntime.h"
|
#include "xtensa/xtruntime.h"
|
||||||
@ -36,6 +37,19 @@ typedef struct {
|
|||||||
NEED_VOLATILE_MUX uint32_t count;
|
NEED_VOLATILE_MUX uint32_t count;
|
||||||
}spinlock_t;
|
}spinlock_t;
|
||||||
|
|
||||||
|
#if (CONFIG_ESP32_SPIRAM_SUPPORT)
|
||||||
|
/**
|
||||||
|
* @brief Check if the pointer is on external ram
|
||||||
|
* @param p pointer
|
||||||
|
* @return true: on external ram; false: not on external ram
|
||||||
|
*/
|
||||||
|
static inline bool __attribute__((always_inline)) spinlock_ptr_external_ram(const void *p)
|
||||||
|
{
|
||||||
|
//On esp32, this external virtual address rergion is for psram
|
||||||
|
return ((intptr_t)p >= SOC_EXTRAM_DATA_LOW && (intptr_t)p < SOC_EXTRAM_DATA_HIGH);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize a lock to its default state - unlocked
|
* @brief Initialize a lock to its default state - unlocked
|
||||||
* @param lock - spinlock object to initialize
|
* @param lock - spinlock object to initialize
|
||||||
@ -95,7 +109,7 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
|
|||||||
result = core_id;
|
result = core_id;
|
||||||
|
|
||||||
#if defined(CONFIG_ESP32_SPIRAM_SUPPORT)
|
#if defined(CONFIG_ESP32_SPIRAM_SUPPORT)
|
||||||
if (esp_ptr_external_ram(lock)) {
|
if (spinlock_ptr_external_ram(lock)) {
|
||||||
compare_and_set_extram(&lock->owner, SPINLOCK_FREE, &result);
|
compare_and_set_extram(&lock->owner, SPINLOCK_FREE, &result);
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,7 +15,7 @@ entries:
|
|||||||
spiram_psram (noflash)
|
spiram_psram (noflash)
|
||||||
if SPIRAM_MODE_OCT = y:
|
if SPIRAM_MODE_OCT = y:
|
||||||
opiram_psram (noflash)
|
opiram_psram (noflash)
|
||||||
if IDF_TARGET_ESP32S2 = y:
|
if IDF_TARGET_ESP32S2 = y && SPIRAM:
|
||||||
mmu_psram (noflash)
|
mmu_psram (noflash)
|
||||||
if PERIPH_CTRL_FUNC_IN_IRAM = y:
|
if PERIPH_CTRL_FUNC_IN_IRAM = y:
|
||||||
periph_ctrl: periph_module_reset (noflash)
|
periph_ctrl: periph_module_reset (noflash)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp32/spiram.h"
|
#include "esp32/spiram.h"
|
||||||
|
#include "esp_private/spiram_private.h"
|
||||||
#include "esp32/rom/cache.h"
|
#include "esp32/rom/cache.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_himem.h"
|
#include "esp_himem.h"
|
||||||
|
@ -17,6 +17,7 @@ we add more types of external RAM memory, this can be made into a more intellige
|
|||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp32/spiram.h"
|
#include "esp32/spiram.h"
|
||||||
|
#include "esp_private/spiram_private.h"
|
||||||
#include "spiram_psram.h"
|
#include "spiram_psram.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
@ -55,6 +56,12 @@ extern uint8_t _ext_ram_bss_start, _ext_ram_bss_end;
|
|||||||
extern uint8_t _ext_ram_noinit_start, _ext_ram_noinit_end;
|
extern uint8_t _ext_ram_noinit_start, _ext_ram_noinit_end;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//These variables are in bytes
|
||||||
|
static intptr_t s_allocable_vaddr_start;
|
||||||
|
static intptr_t s_allocable_vaddr_end;
|
||||||
|
static intptr_t s_mapped_vaddr_start;
|
||||||
|
static intptr_t s_mapped_vaddr_end;
|
||||||
|
|
||||||
static bool spiram_inited=false;
|
static bool spiram_inited=false;
|
||||||
|
|
||||||
|
|
||||||
@ -132,6 +139,9 @@ void IRAM_ATTR esp_spiram_init_cache(void)
|
|||||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DRAM1);
|
DPORT_CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DRAM1);
|
||||||
cache_sram_mmu_set(1, 0, SOC_EXTRAM_DATA_LOW, 0, 32, (size / 1024 / 32));
|
cache_sram_mmu_set(1, 0, SOC_EXTRAM_DATA_LOW, 0, 32, (size / 1024 / 32));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
s_mapped_vaddr_start = (intptr_t)SOC_EXTRAM_DATA_LOW;
|
||||||
|
s_mapped_vaddr_end = s_mapped_vaddr_start + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_spiram_size_t esp_spiram_get_chip_size(void)
|
esp_spiram_size_t esp_spiram_get_chip_size(void)
|
||||||
@ -155,6 +165,7 @@ esp_spiram_size_t esp_spiram_get_chip_size(void)
|
|||||||
|
|
||||||
esp_err_t esp_spiram_init(void)
|
esp_err_t esp_spiram_init(void)
|
||||||
{
|
{
|
||||||
|
assert(!spiram_inited);
|
||||||
esp_err_t r;
|
esp_err_t r;
|
||||||
r = psram_enable(PSRAM_SPEED, PSRAM_MODE);
|
r = psram_enable(PSRAM_SPEED, PSRAM_MODE);
|
||||||
if (r != ESP_OK) {
|
if (r != ESP_OK) {
|
||||||
@ -189,20 +200,50 @@ esp_err_t esp_spiram_add_to_heapalloc(void)
|
|||||||
{
|
{
|
||||||
//Add entire external RAM region to heap allocator. Heap allocator knows the capabilities of this type of memory, so there's
|
//Add entire external RAM region to heap allocator. Heap allocator knows the capabilities of this type of memory, so there's
|
||||||
//no need to explicitly specify them.
|
//no need to explicitly specify them.
|
||||||
intptr_t mallocable_ram_start = (intptr_t)SOC_EXTRAM_DATA_LOW;
|
s_allocable_vaddr_start = (intptr_t)SOC_EXTRAM_DATA_LOW;
|
||||||
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
if (mallocable_ram_start < (intptr_t)&_ext_ram_bss_end) {
|
if (s_allocable_vaddr_start < (intptr_t)&_ext_ram_bss_end) {
|
||||||
mallocable_ram_start = (intptr_t)&_ext_ram_bss_end;
|
s_allocable_vaddr_start = (intptr_t)&_ext_ram_bss_end;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
|
#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
|
||||||
if (mallocable_ram_start < (intptr_t)&_ext_ram_noinit_end) {
|
if (s_allocable_vaddr_start < (intptr_t)&_ext_ram_noinit_end) {
|
||||||
mallocable_ram_start = (intptr_t)&_ext_ram_noinit_end;
|
s_allocable_vaddr_start = (intptr_t)&_ext_ram_noinit_end;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
intptr_t mallocable_ram_end = (intptr_t)SOC_EXTRAM_DATA_LOW + spiram_size_usable_for_malloc() - 1;
|
s_allocable_vaddr_end = (intptr_t)SOC_EXTRAM_DATA_LOW + spiram_size_usable_for_malloc() - 1;
|
||||||
ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (mallocable_ram_end - mallocable_ram_start)/1024);
|
ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (s_allocable_vaddr_end - s_allocable_vaddr_start)/1024);
|
||||||
return heap_caps_add_region(mallocable_ram_start, mallocable_ram_end);
|
return heap_caps_add_region(s_allocable_vaddr_start, s_allocable_vaddr_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t IRAM_ATTR esp_spiram_get_mapped_range(intptr_t *out_vstart, intptr_t *out_vend)
|
||||||
|
{
|
||||||
|
if (!out_vstart || !out_vend) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!spiram_inited) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_vstart = s_mapped_vaddr_start;
|
||||||
|
*out_vend = s_mapped_vaddr_end;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_spiram_get_alloced_range(intptr_t *out_vstart, intptr_t *out_vend)
|
||||||
|
{
|
||||||
|
if (!out_vstart || !out_vend) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!spiram_inited) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_vstart = s_allocable_vaddr_start;
|
||||||
|
*out_vend = s_allocable_vaddr_end;
|
||||||
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,10 +17,11 @@ if(NOT BOOTLOADER_BUILD)
|
|||||||
"esp_hmac.c"
|
"esp_hmac.c"
|
||||||
"esp_crypto_lock.c"
|
"esp_crypto_lock.c"
|
||||||
"esp_ds.c"
|
"esp_ds.c"
|
||||||
"dport_access.c"
|
"dport_access.c")
|
||||||
"spiram.c"
|
|
||||||
"mmu_psram.c"
|
if(CONFIG_SPIRAM)
|
||||||
"spiram_psram.c")
|
list(APPEND srcs "spiram.c" "mmu_psram.c" "spiram_psram.c")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
|
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/xtensa_api.h"
|
#include "freertos/xtensa_api.h"
|
||||||
#include "esp_heap_caps_init.h"
|
#include "esp_heap_caps_init.h"
|
||||||
|
#include "esp_private/spiram_private.h"
|
||||||
#include "esp32s2/spiram.h"
|
#include "esp32s2/spiram.h"
|
||||||
#include "esp_private/mmu_psram.h"
|
#include "esp_private/mmu_psram.h"
|
||||||
#include "spiram_psram.h"
|
#include "spiram_psram.h"
|
||||||
@ -44,47 +45,48 @@ extern uint8_t _ext_ram_bss_end;
|
|||||||
#endif //#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
#endif //#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
|
|
||||||
//These variables are in bytes
|
//These variables are in bytes
|
||||||
static uint32_t s_allocable_vaddr_start;
|
static intptr_t s_allocable_vaddr_start;
|
||||||
static uint32_t s_allocable_vaddr_end;
|
static intptr_t s_allocable_vaddr_end;
|
||||||
|
static intptr_t s_mapped_vaddr_start;
|
||||||
|
static intptr_t s_mapped_vaddr_end;
|
||||||
|
|
||||||
static bool spiram_inited=false;
|
static bool s_spiram_inited;
|
||||||
static const char* TAG = "spiram";
|
static const char* TAG = "spiram";
|
||||||
|
|
||||||
bool esp_spiram_test(uint32_t v_start, uint32_t size);
|
static bool esp_spiram_test(uint32_t v_start, uint32_t size);
|
||||||
|
|
||||||
|
|
||||||
esp_err_t esp_spiram_init(void)
|
esp_err_t esp_spiram_init(void)
|
||||||
{
|
{
|
||||||
esp_err_t r;
|
assert(!s_spiram_inited);
|
||||||
r = psram_enable(PSRAM_SPEED, PSRAM_MODE);
|
esp_err_t ret;
|
||||||
if (r != ESP_OK) {
|
ret = psram_enable(PSRAM_SPEED, PSRAM_MODE);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
|
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
|
||||||
ESP_EARLY_LOGE(TAG, "SPI RAM enabled but initialization failed. Bailing out.");
|
ESP_EARLY_LOGE(TAG, "SPI RAM enabled but initialization failed. Bailing out.");
|
||||||
#endif
|
#endif
|
||||||
return r;
|
return ret;
|
||||||
}
|
}
|
||||||
|
s_spiram_inited = true;
|
||||||
|
|
||||||
spiram_inited = true;
|
uint32_t psram_physical_size = 0;
|
||||||
|
ret = psram_get_physical_size(&psram_physical_size);
|
||||||
|
assert(ret == ESP_OK);
|
||||||
|
|
||||||
//TODO IDF-4380
|
|
||||||
size_t spiram_size = esp_spiram_get_size();
|
|
||||||
#if (CONFIG_SPIRAM_SIZE != -1)
|
#if (CONFIG_SPIRAM_SIZE != -1)
|
||||||
if (spiram_size != CONFIG_SPIRAM_SIZE) {
|
if (psram_physical_size != CONFIG_SPIRAM_SIZE) {
|
||||||
ESP_EARLY_LOGE(TAG, "Expected %dKiB chip but found %dKiB chip. Bailing out..", CONFIG_SPIRAM_SIZE/1024, spiram_size/1024);
|
ESP_EARLY_LOGE(TAG, "Expected %dMB chip but found %dMB chip. Bailing out..", CONFIG_SPIRAM_SIZE / 1024 / 1024, psram_physical_size / 1024 / 1024);
|
||||||
return ESP_ERR_INVALID_SIZE;
|
return ESP_ERR_INVALID_SIZE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
ESP_EARLY_LOGI(TAG, "Found %dMBit SPI RAM device", psram_physical_size / (1024 * 1024));
|
||||||
|
ESP_EARLY_LOGI(TAG, "Speed: %dMHz", CONFIG_SPIRAM_SPEED);
|
||||||
|
|
||||||
ESP_EARLY_LOGI(TAG, "Found %dMBit SPI RAM device",
|
uint32_t psram_available_size = 0;
|
||||||
(spiram_size*8)/(1024*1024));
|
ret = psram_get_available_size(&psram_available_size);
|
||||||
ESP_EARLY_LOGI(TAG, "SPI RAM mode: %s", PSRAM_SPEED == PSRAM_CACHE_S40M ? "sram 40m" : \
|
assert(ret == ESP_OK);
|
||||||
PSRAM_SPEED == PSRAM_CACHE_S80M ? "sram 80m" : "sram 20m");
|
|
||||||
ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in %s mode.", \
|
|
||||||
(PSRAM_MODE==PSRAM_VADDR_MODE_EVENODD)?"even/odd (2-core)": \
|
|
||||||
(PSRAM_MODE==PSRAM_VADDR_MODE_LOWHIGH)?"low/high (2-core)": \
|
|
||||||
(PSRAM_MODE==PSRAM_VADDR_MODE_NORMAL)?"normal (1-core)":"ERROR");
|
|
||||||
|
|
||||||
uint32_t psram_available_size = spiram_size;
|
__attribute__((unused)) uint32_t total_available_size = psram_available_size;
|
||||||
/**
|
/**
|
||||||
* `start_page` is the psram physical address in MMU page size.
|
* `start_page` is the psram physical address in MMU page size.
|
||||||
* MMU page size on ESP32S2 is 64KB
|
* MMU page size on ESP32S2 is 64KB
|
||||||
@ -99,8 +101,8 @@ esp_err_t esp_spiram_init(void)
|
|||||||
|
|
||||||
//------------------------------------Copy Flash .text to PSRAM-------------------------------------//
|
//------------------------------------Copy Flash .text to PSRAM-------------------------------------//
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
r = mmu_config_psram_text_segment(start_page, spiram_size, &used_page);
|
ret = mmu_config_psram_text_segment(start_page, total_available_size, &used_page);
|
||||||
if (r != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_EARLY_LOGE(TAG, "No enough psram memory for instructon!");
|
ESP_EARLY_LOGE(TAG, "No enough psram memory for instructon!");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -111,8 +113,8 @@ esp_err_t esp_spiram_init(void)
|
|||||||
|
|
||||||
//------------------------------------Copy Flash .rodata to PSRAM-------------------------------------//
|
//------------------------------------Copy Flash .rodata to PSRAM-------------------------------------//
|
||||||
#if CONFIG_SPIRAM_RODATA
|
#if CONFIG_SPIRAM_RODATA
|
||||||
r = mmu_config_psram_rodata_segment(start_page, spiram_size, &used_page);
|
ret = mmu_config_psram_rodata_segment(start_page, total_available_size, &used_page);
|
||||||
if (r != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_EARLY_LOGE(TAG, "No enough psram memory for rodata!");
|
ESP_EARLY_LOGE(TAG, "No enough psram memory for rodata!");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -121,10 +123,10 @@ esp_err_t esp_spiram_init(void)
|
|||||||
ESP_EARLY_LOGV(TAG, "after copy .rodata, used page is %d, start_page is %d, psram_available_size is %d B", used_page, start_page, psram_available_size);
|
ESP_EARLY_LOGV(TAG, "after copy .rodata, used page is %d, start_page is %d, psram_available_size is %d B", used_page, start_page, psram_available_size);
|
||||||
#endif //#if CONFIG_SPIRAM_RODATA
|
#endif //#if CONFIG_SPIRAM_RODATA
|
||||||
|
|
||||||
//Map the PSRAM physical range to MMU
|
//----------------------------------Map the PSRAM physical range to MMU-----------------------------//
|
||||||
static DRAM_ATTR uint32_t vaddr_start = 0;
|
static DRAM_ATTR uint32_t vaddr_start = 0;
|
||||||
mmu_map_psram(MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(start_page) + psram_available_size, &vaddr_start);
|
mmu_map_psram(MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(start_page) + psram_available_size, &vaddr_start);
|
||||||
if (r != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_EARLY_LOGE(TAG, "MMU PSRAM mapping wrong!");
|
ESP_EARLY_LOGE(TAG, "MMU PSRAM mapping wrong!");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -141,6 +143,8 @@ esp_err_t esp_spiram_init(void)
|
|||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
* After mapping, we DON'T care about the PSRAM PHYSICAL ADDRESSS ANYMORE!
|
* After mapping, we DON'T care about the PSRAM PHYSICAL ADDRESSS ANYMORE!
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
s_mapped_vaddr_start = vaddr_start;
|
||||||
|
s_mapped_vaddr_end = vaddr_start + psram_available_size;
|
||||||
s_allocable_vaddr_start = vaddr_start;
|
s_allocable_vaddr_start = vaddr_start;
|
||||||
s_allocable_vaddr_end = vaddr_start + psram_available_size;
|
s_allocable_vaddr_end = vaddr_start + psram_available_size;
|
||||||
|
|
||||||
@ -157,35 +161,58 @@ esp_err_t esp_spiram_init(void)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the PSRAM available region to heap allocator. Heap allocator knows the capabilities of this type of memory,
|
||||||
|
* so there's no need to explicitly specify them.
|
||||||
|
*/
|
||||||
esp_err_t esp_spiram_add_to_heapalloc(void)
|
esp_err_t esp_spiram_add_to_heapalloc(void)
|
||||||
{
|
{
|
||||||
return heap_caps_add_region(s_allocable_vaddr_start, s_allocable_vaddr_end - 1);
|
ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (s_allocable_vaddr_end - s_allocable_vaddr_start) / 1024);
|
||||||
|
return heap_caps_add_region(s_allocable_vaddr_start, s_allocable_vaddr_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *dma_heap;
|
esp_err_t IRAM_ATTR esp_spiram_get_mapped_range(intptr_t *out_vstart, intptr_t *out_vend)
|
||||||
|
|
||||||
esp_err_t esp_spiram_reserve_dma_pool(size_t size) {
|
|
||||||
if (size==0) return ESP_OK; //no-op
|
|
||||||
ESP_EARLY_LOGI(TAG, "Reserving pool of %dK of internal memory for DMA/internal allocations", size/1024);
|
|
||||||
dma_heap=heap_caps_malloc(size, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
|
|
||||||
if (!dma_heap) return ESP_ERR_NO_MEM;
|
|
||||||
uint32_t caps[]={MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_8BIT|MALLOC_CAP_32BIT};
|
|
||||||
return heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap+size-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO IDF-4380
|
|
||||||
size_t esp_spiram_get_size(void)
|
|
||||||
{
|
{
|
||||||
if (!spiram_inited) {
|
if (!out_vstart || !out_vend) {
|
||||||
ESP_EARLY_LOGE(TAG, "SPI RAM not initialized");
|
return ESP_ERR_INVALID_ARG;
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
psram_size_t size=psram_get_size();
|
if (!s_spiram_inited) {
|
||||||
if (size==PSRAM_SIZE_16MBITS) return 2*1024*1024;
|
return ESP_ERR_INVALID_STATE;
|
||||||
if (size==PSRAM_SIZE_32MBITS) return 4*1024*1024;
|
}
|
||||||
if (size==PSRAM_SIZE_64MBITS) return 8*1024*1024;
|
|
||||||
return CONFIG_SPIRAM_SIZE;
|
*out_vstart = s_mapped_vaddr_start;
|
||||||
|
*out_vend = s_mapped_vaddr_end;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_spiram_get_alloced_range(intptr_t *out_vstart, intptr_t *out_vend)
|
||||||
|
{
|
||||||
|
if (!out_vstart || !out_vend) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s_spiram_inited) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_vstart = s_allocable_vaddr_start;
|
||||||
|
*out_vend = s_allocable_vaddr_end;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_spiram_reserve_dma_pool(size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0) {
|
||||||
|
return ESP_OK; //no-op
|
||||||
|
}
|
||||||
|
ESP_EARLY_LOGI(TAG, "Reserving pool of %dK of internal memory for DMA/internal allocations", size/1024);
|
||||||
|
uint8_t *dma_heap = heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||||
|
if (!dma_heap) {
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
uint32_t caps[] = {MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT};
|
||||||
|
return heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -206,7 +233,7 @@ void IRAM_ATTR esp_spiram_writeback_cache(void)
|
|||||||
*/
|
*/
|
||||||
bool esp_spiram_is_initialized(void)
|
bool esp_spiram_is_initialized(void)
|
||||||
{
|
{
|
||||||
return spiram_inited;
|
return s_spiram_inited;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t esp_spiram_get_cs_io(void)
|
uint8_t esp_spiram_get_cs_io(void)
|
||||||
@ -219,7 +246,7 @@ uint8_t esp_spiram_get_cs_io(void)
|
|||||||
true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been
|
true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been
|
||||||
initialized (in a two-core system) or after the heap allocator has taken ownership of the memory.
|
initialized (in a two-core system) or after the heap allocator has taken ownership of the memory.
|
||||||
*/
|
*/
|
||||||
bool esp_spiram_test(uint32_t v_start, uint32_t size)
|
static bool esp_spiram_test(uint32_t v_start, uint32_t size)
|
||||||
{
|
{
|
||||||
volatile int *spiram = (volatile int *)v_start;
|
volatile int *spiram = (volatile int *)v_start;
|
||||||
|
|
||||||
|
@ -34,8 +34,6 @@
|
|||||||
#include "driver/spi_common.h"
|
#include "driver/spi_common.h"
|
||||||
#include "esp_private/periph_ctrl.h"
|
#include "esp_private/periph_ctrl.h"
|
||||||
#include "bootloader_common.h"
|
#include "bootloader_common.h"
|
||||||
|
|
||||||
#if CONFIG_SPIRAM
|
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
|
|
||||||
static const char* TAG = "psram";
|
static const char* TAG = "psram";
|
||||||
@ -378,20 +376,6 @@ static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode)
|
|||||||
s_psram_cs_io = psram_io.psram_cs_io;
|
s_psram_cs_io = psram_io.psram_cs_io;
|
||||||
}
|
}
|
||||||
|
|
||||||
psram_size_t psram_get_size(void)
|
|
||||||
{
|
|
||||||
if ((PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_64MBITS) || PSRAM_IS_64MBIT_TRIAL(s_psram_id)) {
|
|
||||||
return PSRAM_SIZE_64MBITS;
|
|
||||||
} else if (PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_32MBITS) {
|
|
||||||
return PSRAM_SIZE_32MBITS;
|
|
||||||
} else if (PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_16MBITS) {
|
|
||||||
return PSRAM_SIZE_16MBITS;
|
|
||||||
} else {
|
|
||||||
return PSRAM_SIZE_MAX;
|
|
||||||
}
|
|
||||||
return PSRAM_SIZE_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
//used in UT only
|
//used in UT only
|
||||||
bool psram_is_32mbit_ver0(void)
|
bool psram_is_32mbit_ver0(void)
|
||||||
{
|
{
|
||||||
@ -542,4 +526,36 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
|
|||||||
|
|
||||||
CLEAR_PERI_REG_MASK(SPI_MEM_MISC_REG(0), SPI_MEM_CS1_DIS_M); //ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM)
|
CLEAR_PERI_REG_MASK(SPI_MEM_MISC_REG(0), SPI_MEM_CS1_DIS_M); //ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM)
|
||||||
}
|
}
|
||||||
#endif // CONFIG_SPIRAM
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------
|
||||||
|
* Following APIs are not required to be IRAM-Safe
|
||||||
|
*
|
||||||
|
* Consider moving these to another file if this kind of APIs grows dramatically
|
||||||
|
*-------------------------------------------------------------------------------*/
|
||||||
|
esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
|
||||||
|
{
|
||||||
|
if (!out_size_bytes) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_64MBITS) || PSRAM_IS_64MBIT_TRIAL(s_psram_id)) {
|
||||||
|
*out_size_bytes = PSRAM_SIZE_8MB;
|
||||||
|
} else if (PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_32MBITS) {
|
||||||
|
*out_size_bytes = PSRAM_SIZE_4MB;
|
||||||
|
} else if (PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_16MBITS) {
|
||||||
|
*out_size_bytes = PSRAM_SIZE_2MB;
|
||||||
|
} else {
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is to get the available physical psram size in bytes.
|
||||||
|
* On ESP32S2, all of the PSRAM physical region are available
|
||||||
|
*/
|
||||||
|
esp_err_t psram_get_available_size(uint32_t *out_size_bytes)
|
||||||
|
{
|
||||||
|
return psram_get_physical_size(out_size_bytes);
|
||||||
|
}
|
||||||
|
@ -4,13 +4,20 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#ifndef _PSRAM_H
|
|
||||||
#define _PSRAM_H
|
|
||||||
#include "soc/spi_mem_reg.h"
|
#include "soc/spi_mem_reg.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PSRAM_SIZE_2MB (2 * 1024 * 1024)
|
||||||
|
#define PSRAM_SIZE_4MB (4 * 1024 * 1024)
|
||||||
|
#define PSRAM_SIZE_8MB (8 * 1024 * 1024)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PSRAM_CACHE_S80M = 1,
|
PSRAM_CACHE_S80M = 1,
|
||||||
PSRAM_CACHE_S40M,
|
PSRAM_CACHE_S40M,
|
||||||
@ -19,12 +26,6 @@ typedef enum {
|
|||||||
PSRAM_CACHE_MAX,
|
PSRAM_CACHE_MAX,
|
||||||
} psram_cache_mode_t;
|
} psram_cache_mode_t;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PSRAM_SIZE_16MBITS = 0,
|
|
||||||
PSRAM_SIZE_32MBITS = 1,
|
|
||||||
PSRAM_SIZE_64MBITS = 2,
|
|
||||||
PSRAM_SIZE_MAX,
|
|
||||||
} psram_size_t;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
See the TRM, chapter PID/MPU/MMU, header 'External RAM' for the definitions of these modes.
|
See the TRM, chapter PID/MPU/MMU, header 'External RAM' for the definitions of these modes.
|
||||||
@ -40,12 +41,20 @@ typedef enum {
|
|||||||
} psram_vaddr_mode_t;
|
} psram_vaddr_mode_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get psram size
|
* @brief To get the physical psram size in bytes.
|
||||||
* @return
|
*
|
||||||
* - PSRAM_SIZE_MAX if psram not enabled or not valid
|
* @param[out] out_size_bytes physical psram size in bytes.
|
||||||
* - PSRAM size
|
|
||||||
*/
|
*/
|
||||||
psram_size_t psram_get_size(void);
|
esp_err_t psram_get_physical_size(uint32_t *out_size_bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief To get the available physical psram size in bytes.
|
||||||
|
*
|
||||||
|
* @note On ESP32S2, all of the PSRAM physical region are available
|
||||||
|
*
|
||||||
|
* @param[out] out_size_bytes availabe physical psram size in bytes.
|
||||||
|
*/
|
||||||
|
esp_err_t psram_get_available_size(uint32_t *out_size_bytes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief psram cache enable function
|
* @brief psram cache enable function
|
||||||
@ -74,5 +83,3 @@ esp_err_t esp_spiram_wrap_set(spiram_wrap_mode_t mode);
|
|||||||
* @return psram CS IO
|
* @return psram CS IO
|
||||||
*/
|
*/
|
||||||
uint8_t psram_get_cs_io(void);
|
uint8_t psram_get_cs_io(void);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -16,15 +16,17 @@ if(NOT BOOTLOADER_BUILD)
|
|||||||
"dport_access.c"
|
"dport_access.c"
|
||||||
"esp_hmac.c"
|
"esp_hmac.c"
|
||||||
"esp_ds.c"
|
"esp_ds.c"
|
||||||
"esp_crypto_lock.c"
|
"esp_crypto_lock.c")
|
||||||
"spiram.c")
|
|
||||||
|
|
||||||
if(CONFIG_SPIRAM_MODE_QUAD)
|
if(CONFIG_SPIRAM)
|
||||||
list(APPEND srcs "spiram_psram.c")
|
list(APPEND srcs "spiram.c")
|
||||||
elseif(CONFIG_SPIRAM_MODE_OCT)
|
|
||||||
list(APPEND srcs "opiram_psram.c")
|
if(CONFIG_SPIRAM_MODE_QUAD)
|
||||||
|
list(APPEND srcs "spiram_psram.c")
|
||||||
|
elseif(CONFIG_SPIRAM_MODE_OCT)
|
||||||
|
list(APPEND srcs "opiram_psram.c")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
|
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
|
||||||
|
@ -25,8 +25,6 @@
|
|||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "driver/spi_common.h"
|
#include "driver/spi_common.h"
|
||||||
#include "esp_private/periph_ctrl.h"
|
#include "esp_private/periph_ctrl.h"
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_MODE_OCT
|
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "esp_private/spi_flash_os.h"
|
#include "esp_private/spi_flash_os.h"
|
||||||
|
|
||||||
@ -383,6 +381,10 @@ static void s_config_psram_spi_phases(void)
|
|||||||
*-------------------------------------------------------------------------------*/
|
*-------------------------------------------------------------------------------*/
|
||||||
esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
|
esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
|
||||||
{
|
{
|
||||||
|
if (!out_size_bytes) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
*out_size_bytes = s_psram_size;
|
*out_size_bytes = s_psram_size;
|
||||||
return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE);
|
return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE);
|
||||||
}
|
}
|
||||||
@ -393,6 +395,10 @@ esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
|
|||||||
*/
|
*/
|
||||||
esp_err_t psram_get_available_size(uint32_t *out_size_bytes)
|
esp_err_t psram_get_available_size(uint32_t *out_size_bytes)
|
||||||
{
|
{
|
||||||
|
if (!out_size_bytes) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_ECC_ENABLE
|
#if CONFIG_SPIRAM_ECC_ENABLE
|
||||||
*out_size_bytes = s_psram_size * 15 / 16;
|
*out_size_bytes = s_psram_size * 15 / 16;
|
||||||
#else
|
#else
|
||||||
@ -400,5 +406,3 @@ esp_err_t psram_get_available_size(uint32_t *out_size_bytes)
|
|||||||
#endif
|
#endif
|
||||||
return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE);
|
return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //#if CONFIG_SPIRAM_MODE_OCT
|
|
||||||
|
@ -1,45 +1,35 @@
|
|||||||
/*
|
|
||||||
Abstraction layer for spi-ram. For now, it's no more than a stub for the spiram_psram functions, but if
|
|
||||||
we add more types of external RAM memory, this can be made into a more intelligent dispatcher.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------------------------
|
||||||
|
* Abstraction layer for PSRAM. PSRAM device related registers and MMU/Cache related code shouls be
|
||||||
|
* abstracted to lower layers.
|
||||||
|
*
|
||||||
|
* When we add more types of external RAM memory, this can be made into a more intelligent dispatcher.
|
||||||
|
*----------------------------------------------------------------------------------------------------*/
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_heap_caps_init.h"
|
||||||
|
#include "esp_private/spiram_private.h"
|
||||||
#include "esp32s3/spiram.h"
|
#include "esp32s3/spiram.h"
|
||||||
#include "spiram_psram.h"
|
#include "spiram_psram.h"
|
||||||
#include "esp_log.h"
|
#include "hal/mmu_hal.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "hal/cache_ll.h"
|
||||||
#include "freertos/xtensa_api.h"
|
|
||||||
#include "soc/soc.h"
|
|
||||||
#include "esp_heap_caps_init.h"
|
|
||||||
#include "soc/soc_memory_layout.h"
|
|
||||||
#include "soc/dport_reg.h"
|
|
||||||
#include "esp32s3/rom/cache.h"
|
|
||||||
#include "soc/ext_mem_defs.h"
|
|
||||||
#include "soc/extmem_reg.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @note consider abstract these cache register operations, so as to make `spiram.c` not needed to be IRAM-SAFE.
|
|
||||||
* This file only contains abstract operations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
|
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
|
||||||
|
|
||||||
#define MMU_PAGE_SIZE 0x10000
|
#define MMU_PAGE_SIZE 0x10000
|
||||||
|
#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||||
#if CONFIG_SPIRAM
|
|
||||||
|
|
||||||
static const char *TAG = "spiram";
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_SPEED_40M
|
#if CONFIG_SPIRAM_SPEED_40M
|
||||||
#define PSRAM_SPEED PSRAM_CACHE_S40M
|
#define PSRAM_SPEED PSRAM_CACHE_S40M
|
||||||
@ -47,79 +37,171 @@ static const char *TAG = "spiram";
|
|||||||
#define PSRAM_SPEED PSRAM_CACHE_S80M
|
#define PSRAM_SPEED PSRAM_CACHE_S80M
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool s_spiram_inited = false;
|
|
||||||
|
static const char *TAG = "spiram";
|
||||||
|
static bool s_spiram_inited;
|
||||||
|
|
||||||
//These variables are in bytes
|
//These variables are in bytes
|
||||||
static uint32_t s_allocable_vaddr_start;
|
static intptr_t s_allocable_vaddr_start;
|
||||||
static uint32_t s_allocable_vaddr_end;
|
static intptr_t s_allocable_vaddr_end;
|
||||||
static DRAM_ATTR uint32_t s_mapped_vaddr_start;
|
static intptr_t s_mapped_vaddr_start;
|
||||||
static DRAM_ATTR uint32_t s_mapped_size;
|
static intptr_t s_mapped_vaddr_end;
|
||||||
|
|
||||||
/**
|
|
||||||
* Initially map all psram physical address to virtual address.
|
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
* If psram physical size is larger than virtual address range, then only map the virtual address range.
|
extern uint8_t _ext_ram_bss_start;
|
||||||
*/
|
extern uint8_t _ext_ram_bss_end;
|
||||||
void IRAM_ATTR esp_spiram_init_cache(void)
|
#endif //#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
|
|
||||||
|
|
||||||
|
static bool esp_spiram_test(uint32_t v_start, uint32_t size);
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t esp_spiram_init(void)
|
||||||
{
|
{
|
||||||
esp_err_t ret = psram_get_available_size(&s_mapped_size);
|
assert(!s_spiram_inited);
|
||||||
|
esp_err_t ret;
|
||||||
|
uint32_t psram_physical_size = 0;
|
||||||
|
ret = psram_enable(PSRAM_SPEED, PSRAM_MODE);
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
abort();
|
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
|
||||||
|
ESP_EARLY_LOGE(TAG, "SPI RAM enabled but initialization failed. Bailing out.");
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
if ((SOC_EXTRAM_DATA_HIGH - SOC_EXTRAM_DATA_LOW) < s_mapped_size) {
|
s_spiram_inited = true;
|
||||||
|
|
||||||
|
ret = psram_get_physical_size(&psram_physical_size);
|
||||||
|
assert(ret == ESP_OK);
|
||||||
|
|
||||||
|
#if (CONFIG_SPIRAM_SIZE != -1)
|
||||||
|
if (psram_physical_size != CONFIG_SPIRAM_SIZE) {
|
||||||
|
ESP_EARLY_LOGE(TAG, "Expected %dMB chip but found %dMB chip. Bailing out..", (CONFIG_SPIRAM_SIZE / 1024 / 1024), (psram_physical_size / 1024 / 1024));
|
||||||
|
return ESP_ERR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ESP_EARLY_LOGI(TAG, "Found %dMB SPI RAM device", psram_physical_size / (1024 * 1024));
|
||||||
|
ESP_EARLY_LOGI(TAG, "Speed: %dMHz", CONFIG_SPIRAM_SPEED);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO IDF-4318
|
||||||
|
* Add these feature here:
|
||||||
|
* - Copy Flash text into PSRAM
|
||||||
|
* - Copy Flash rodata into PSRAM
|
||||||
|
*/
|
||||||
|
//----------------------------------Map the PSRAM physical range to MMU-----------------------------//
|
||||||
|
uint32_t vaddr_start = 0;
|
||||||
|
extern uint32_t _rodata_reserved_end;
|
||||||
|
uint32_t rodata_end_aligned = ALIGN_UP_BY((uint32_t)&_rodata_reserved_end, MMU_PAGE_SIZE);
|
||||||
|
vaddr_start = rodata_end_aligned;
|
||||||
|
ESP_EARLY_LOGV(TAG, "rodata_end_aligned is 0x%x bytes", rodata_end_aligned);
|
||||||
|
|
||||||
|
uint32_t psram_available_size = 0;
|
||||||
|
ret = psram_get_available_size(&psram_available_size);
|
||||||
|
assert(ret == ESP_OK);
|
||||||
|
|
||||||
|
if (vaddr_start + psram_available_size > DRAM0_CACHE_ADDRESS_HIGH) {
|
||||||
//Decide these logics when there's a real PSRAM with larger size
|
//Decide these logics when there's a real PSRAM with larger size
|
||||||
ESP_EARLY_LOGE(TAG, "Virtual address not enough for PSRAM!");
|
ESP_EARLY_LOGE(TAG, "Virtual address not enough for PSRAM!");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
s_mapped_vaddr_start = SOC_EXTRAM_DATA_HIGH - s_mapped_size;
|
|
||||||
|
|
||||||
Cache_Suspend_DCache();
|
//On ESP32S3, MMU is shared for both of the cores. Note this when porting `spiram.c`
|
||||||
Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, s_mapped_vaddr_start, 0, 64, s_mapped_size >> 16, 0);
|
uint32_t actual_mapped_len = 0;
|
||||||
REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS);
|
mmu_hal_map_region(0, MMU_TARGET_PSRAM0, vaddr_start, 0, psram_available_size, &actual_mapped_len);
|
||||||
|
ESP_EARLY_LOGV(TAG, "actual_mapped_len is 0x%x bytes", actual_mapped_len);
|
||||||
|
|
||||||
|
cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, vaddr_start, actual_mapped_len);
|
||||||
|
cache_ll_l1_enable_bus(0, bus_mask);
|
||||||
#if !CONFIG_FREERTOS_UNICORE
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS);
|
bus_mask = cache_ll_l1_get_bus(1, vaddr_start, actual_mapped_len);
|
||||||
|
cache_ll_l1_enable_bus(1, bus_mask);
|
||||||
#endif
|
#endif
|
||||||
Cache_Resume_DCache(0);
|
|
||||||
|
|
||||||
//Currently no non-heap stuff on ESP32S3
|
#if CONFIG_SPIRAM_MEMTEST
|
||||||
s_allocable_vaddr_start = s_mapped_vaddr_start;
|
//After mapping, simple test SPIRAM first
|
||||||
s_allocable_vaddr_end = SOC_EXTRAM_DATA_HIGH;
|
bool ext_ram_ok = esp_spiram_test(vaddr_start, psram_available_size);
|
||||||
|
if (!ext_ram_ok) {
|
||||||
|
ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif //#if CONFIG_SPIRAM_MEMTEST
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* After mapping, we DON'T care about the PSRAM PHYSICAL ADDRESSS ANYMORE!
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
s_mapped_vaddr_start = vaddr_start;
|
||||||
|
s_mapped_vaddr_end = vaddr_start + psram_available_size;
|
||||||
|
s_allocable_vaddr_start = vaddr_start;
|
||||||
|
s_allocable_vaddr_end = vaddr_start + psram_available_size;
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------Configure .bss in PSRAM-------------------------------------//
|
||||||
|
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
|
//should never be negative number
|
||||||
|
uint32_t ext_bss_size = ((intptr_t)&_ext_ram_bss_end - (intptr_t)&_ext_ram_bss_start);
|
||||||
|
ESP_EARLY_LOGV(TAG, "_ext_ram_bss_start is 0x%x, _ext_ram_bss_start is 0x%x, ext_bss_size is 0x%x bytes", &_ext_ram_bss_start, &_ext_ram_bss_end, ext_bss_size);
|
||||||
|
|
||||||
|
s_allocable_vaddr_start += ext_bss_size;
|
||||||
|
#endif //#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
|
|
||||||
|
ESP_EARLY_LOGV(TAG, "s_allocable_vaddr_start is 0x%x, s_allocable_vaddr_end is 0x%x", s_allocable_vaddr_start, s_allocable_vaddr_end);
|
||||||
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Simple RAM test. Writes a word every 32 bytes. Takes about a second to complete for 4MiB. Returns
|
* Add the PSRAM available region to heap allocator. Heap allocator knows the capabilities of this type of memory,
|
||||||
true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been
|
* so there's no need to explicitly specify them.
|
||||||
initialized (in a two-core system) or after the heap allocator has taken ownership of the memory.
|
*/
|
||||||
*/
|
esp_err_t esp_spiram_add_to_heapalloc(void)
|
||||||
bool esp_spiram_test(void)
|
|
||||||
{
|
{
|
||||||
volatile int *spiram = (volatile int *)s_mapped_vaddr_start;
|
ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (s_allocable_vaddr_end - s_allocable_vaddr_start) / 1024);
|
||||||
|
return heap_caps_add_region(s_allocable_vaddr_start, s_allocable_vaddr_end);
|
||||||
|
}
|
||||||
|
|
||||||
size_t s = s_mapped_size;
|
esp_err_t IRAM_ATTR esp_spiram_get_mapped_range(intptr_t *out_vstart, intptr_t *out_vend)
|
||||||
size_t p;
|
{
|
||||||
int errct = 0;
|
if (!out_vstart || !out_vend) {
|
||||||
int initial_err = -1;
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
for (p = 0; p < (s / sizeof(int)); p += 8) {
|
if (!s_spiram_inited) {
|
||||||
spiram[p] = p ^ 0xAAAAAAAA;
|
return ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
for (p = 0; p < (s / sizeof(int)); p += 8) {
|
|
||||||
if (spiram[p] != (p ^ 0xAAAAAAAA)) {
|
*out_vstart = s_mapped_vaddr_start;
|
||||||
errct++;
|
*out_vend = s_mapped_vaddr_end;
|
||||||
if (errct == 1) {
|
return ESP_OK;
|
||||||
initial_err = p * 4;
|
}
|
||||||
}
|
|
||||||
if (errct < 4) {
|
esp_err_t esp_spiram_get_alloced_range(intptr_t *out_vstart, intptr_t *out_vend)
|
||||||
ESP_EARLY_LOGE(TAG, "SPI SRAM error@%08x:%08x/%08x \n", &spiram[p], spiram[p], p ^ 0xAAAAAAAA);
|
{
|
||||||
}
|
if (!out_vstart || !out_vend) {
|
||||||
}
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
if (errct) {
|
|
||||||
ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s / 32, initial_err + SOC_EXTRAM_DATA_LOW);
|
if (!s_spiram_inited) {
|
||||||
return false;
|
return ESP_ERR_INVALID_STATE;
|
||||||
} else {
|
|
||||||
ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK");
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*out_vstart = s_allocable_vaddr_start;
|
||||||
|
*out_vend = s_allocable_vaddr_end;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_spiram_reserve_dma_pool(size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
ESP_EARLY_LOGI(TAG, "Reserving pool of %dK of internal memory for DMA/internal allocations", size / 1024);
|
||||||
|
uint8_t *dma_heap = heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||||
|
if (!dma_heap) {
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
uint32_t caps[] = {MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT};
|
||||||
|
return heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO IDF-4318
|
//TODO IDF-4318
|
||||||
@ -222,81 +304,6 @@ int IRAM_ATTR rodata_flash2spiram_offset(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
esp_err_t esp_spiram_init(void)
|
|
||||||
{
|
|
||||||
esp_err_t r;
|
|
||||||
uint32_t psram_physical_size = 0;
|
|
||||||
r = psram_enable(PSRAM_SPEED, PSRAM_MODE);
|
|
||||||
if (r != ESP_OK) {
|
|
||||||
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
|
|
||||||
ESP_EARLY_LOGE(TAG, "SPI RAM enabled but initialization failed. Bailing out.");
|
|
||||||
#endif
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
s_spiram_inited = true;
|
|
||||||
|
|
||||||
r = psram_get_physical_size(&psram_physical_size);
|
|
||||||
if (r != ESP_OK) {
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
#if (CONFIG_SPIRAM_SIZE != -1)
|
|
||||||
if (psram_physical_size != CONFIG_SPIRAM_SIZE) {
|
|
||||||
ESP_EARLY_LOGE(TAG, "Expected %dMB chip but found %dMB chip. Bailing out..", (CONFIG_SPIRAM_SIZE / 1024 / 1024), (psram_physical_size / 1024 / 1024));
|
|
||||||
return ESP_ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ESP_EARLY_LOGI(TAG, "Found %dMB SPI RAM device", psram_physical_size / (1024 * 1024));
|
|
||||||
ESP_EARLY_LOGI(TAG, "Speed: %dMHz", CONFIG_SPIRAM_SPEED);
|
|
||||||
ESP_EARLY_LOGI(TAG, "Initialized, cache is in %s mode.", \
|
|
||||||
(PSRAM_MODE == PSRAM_VADDR_MODE_EVENODD) ? "even/odd (2-core)" : \
|
|
||||||
(PSRAM_MODE == PSRAM_VADDR_MODE_LOWHIGH) ? "low/high (2-core)" : \
|
|
||||||
(PSRAM_MODE == PSRAM_VADDR_MODE_NORMAL) ? "normal (1-core)" : "ERROR");
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add entire external RAM region to heap allocator. Heap allocator knows the capabilities of this type of memory,
|
|
||||||
* so there's no need to explicitly specify them.
|
|
||||||
*/
|
|
||||||
esp_err_t esp_spiram_add_to_heapalloc(void)
|
|
||||||
{
|
|
||||||
ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (s_allocable_vaddr_end - s_allocable_vaddr_start) / 1024);
|
|
||||||
return heap_caps_add_region(s_allocable_vaddr_start, s_allocable_vaddr_end - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint8_t *dma_heap;
|
|
||||||
|
|
||||||
esp_err_t esp_spiram_reserve_dma_pool(size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0) {
|
|
||||||
return ESP_OK; //no-op
|
|
||||||
}
|
|
||||||
ESP_EARLY_LOGI(TAG, "Reserving pool of %dK of internal memory for DMA/internal allocations", size / 1024);
|
|
||||||
dma_heap = heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
|
||||||
if (!dma_heap) {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
uint32_t caps[] = {MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT};
|
|
||||||
return heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap + size - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t esp_spiram_get_size(void)
|
|
||||||
{
|
|
||||||
if (!s_spiram_inited) {
|
|
||||||
ESP_EARLY_LOGE(TAG, "SPI RAM not initialized");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t size = 0; //in bytes
|
|
||||||
esp_err_t ret = psram_get_available_size(&size);
|
|
||||||
if (ret == ESP_OK) {
|
|
||||||
return size;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
|
Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
|
||||||
otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
|
otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
|
||||||
@ -323,4 +330,39 @@ uint8_t esp_spiram_get_cs_io(void)
|
|||||||
return psram_get_cs_io();
|
return psram_get_cs_io();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
/*
|
||||||
|
Simple RAM test. Writes a word every 32 bytes. Takes about a second to complete for 4MiB. Returns
|
||||||
|
true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been
|
||||||
|
initialized (in a two-core system) or after the heap allocator has taken ownership of the memory.
|
||||||
|
*/
|
||||||
|
static bool esp_spiram_test(uint32_t v_start, uint32_t size)
|
||||||
|
{
|
||||||
|
volatile int *spiram = (volatile int *)v_start;
|
||||||
|
|
||||||
|
size_t s = size;
|
||||||
|
size_t p;
|
||||||
|
int errct = 0;
|
||||||
|
int initial_err = -1;
|
||||||
|
|
||||||
|
for (p = 0; p < (s / sizeof(int)); p += 8) {
|
||||||
|
spiram[p] = p ^ 0xAAAAAAAA;
|
||||||
|
}
|
||||||
|
for (p = 0; p < (s / sizeof(int)); p += 8) {
|
||||||
|
if (spiram[p] != (p ^ 0xAAAAAAAA)) {
|
||||||
|
errct++;
|
||||||
|
if (errct == 1) {
|
||||||
|
initial_err = p * 4;
|
||||||
|
}
|
||||||
|
if (errct < 4) {
|
||||||
|
ESP_EARLY_LOGE(TAG, "SPI SRAM error@%08x:%08x/%08x \n", &spiram[p], spiram[p], p ^ 0xAAAAAAAA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errct) {
|
||||||
|
ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s / 32, initial_err + SOC_EXTRAM_DATA_LOW);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
/*
|
|
||||||
Driver bits for PSRAM chips (at the moment only the ESP-PSRAM32 chip).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2013-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2013-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
@ -35,8 +31,6 @@
|
|||||||
#include "driver/spi_common.h"
|
#include "driver/spi_common.h"
|
||||||
#include "esp_private/periph_ctrl.h"
|
#include "esp_private/periph_ctrl.h"
|
||||||
#include "bootloader_common.h"
|
#include "bootloader_common.h"
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_MODE_QUAD
|
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "esp_private/spi_flash_os.h"
|
#include "esp_private/spi_flash_os.h"
|
||||||
|
|
||||||
@ -409,6 +403,10 @@ static void config_psram_spi_phases(void)
|
|||||||
*-------------------------------------------------------------------------------*/
|
*-------------------------------------------------------------------------------*/
|
||||||
esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
|
esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
|
||||||
{
|
{
|
||||||
|
if (!out_size_bytes) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
*out_size_bytes = s_psram_size;
|
*out_size_bytes = s_psram_size;
|
||||||
return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE);
|
return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE);
|
||||||
}
|
}
|
||||||
@ -421,7 +419,10 @@ esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
|
|||||||
*/
|
*/
|
||||||
esp_err_t psram_get_available_size(uint32_t *out_size_bytes)
|
esp_err_t psram_get_available_size(uint32_t *out_size_bytes)
|
||||||
{
|
{
|
||||||
|
if (!out_size_bytes) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
*out_size_bytes = s_psram_size;
|
*out_size_bytes = s_psram_size;
|
||||||
return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE);
|
return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE);
|
||||||
}
|
}
|
||||||
#endif // CONFIG_SPIRAM
|
|
||||||
|
@ -9,16 +9,16 @@
|
|||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PSRAM_SIZE_2MB (2 * 1024 * 1024)
|
#define PSRAM_SIZE_2MB (2 * 1024 * 1024)
|
||||||
#define PSRAM_SIZE_4MB (4 * 1024 * 1024)
|
#define PSRAM_SIZE_4MB (4 * 1024 * 1024)
|
||||||
#define PSRAM_SIZE_8MB (8 * 1024 * 1024)
|
#define PSRAM_SIZE_8MB (8 * 1024 * 1024)
|
||||||
#define PSRAM_SIZE_16MB (16 * 1024 * 1024)
|
#define PSRAM_SIZE_16MB (16 * 1024 * 1024)
|
||||||
#define PSRAM_SIZE_32MB (32 * 1024 * 1024)
|
#define PSRAM_SIZE_32MB (32 * 1024 * 1024)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PSRAM_CACHE_S80M = 1,
|
PSRAM_CACHE_S80M = 1,
|
||||||
PSRAM_CACHE_S40M,
|
PSRAM_CACHE_S40M,
|
||||||
|
@ -116,7 +116,7 @@ static esp_err_t esp_sleep_tagmem_pd_low_init(bool enable)
|
|||||||
uint32_t data_size = (uint32_t)(_rodata_reserved_end - _rodata_start);
|
uint32_t data_size = (uint32_t)(_rodata_reserved_end - _rodata_start);
|
||||||
#else
|
#else
|
||||||
uint32_t data_start = SOC_DROM_LOW;
|
uint32_t data_start = SOC_DROM_LOW;
|
||||||
uint32_t data_size = (SOC_EXTRAM_DATA_HIGH-SOC_EXTRAM_DATA_LOW) + (SOC_DROM_HIGH-SOC_DROM_LOW);
|
uint32_t data_size = SOC_EXTRAM_DATA_SIZE;
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGI(TAG, "Code start at %08x, total %.2f KiB, data start at %08x, total %.2f KiB",
|
ESP_LOGI(TAG, "Code start at %08x, total %.2f KiB, data start at %08x, total %.2f KiB",
|
||||||
code_start, (float)code_size/1024, data_start, (float)data_size/1024);
|
code_start, (float)code_size/1024, data_start, (float)data_size/1024);
|
||||||
|
@ -14,17 +14,27 @@
|
|||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
|
#include "esp_private/spiram_private.h"
|
||||||
#if CONFIG_SPIRAM
|
#if CONFIG_SPIRAM
|
||||||
#include "spiram.h"
|
#include "spiram.h"
|
||||||
|
|
||||||
const static char *TAG = "PSRAM";
|
const static char *TAG = "PSRAM";
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_MODE_OCT
|
#if CONFIG_SPIRAM_MODE_OCT
|
||||||
#define TEST_ALLOC_SIZE (4 * 1024 * 1024)
|
#define TEST_ALLOC_SIZE (4 * 1024 * 1024)
|
||||||
#else
|
#else
|
||||||
#define TEST_ALLOC_SIZE (1 * 1024 * 1024)
|
#define TEST_ALLOC_SIZE (1 * 1024 * 1024)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool s_check_valid_psram_alloced_range(const void *p)
|
||||||
|
{
|
||||||
|
intptr_t vaddr_start = 0;
|
||||||
|
intptr_t vaddr_end = 0;
|
||||||
|
esp_spiram_get_alloced_range(&vaddr_start, &vaddr_end);
|
||||||
|
return (intptr_t)p >= vaddr_start && (intptr_t)p < vaddr_end;
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("test psram heap allocable","[psram]")
|
TEST_CASE("test psram heap allocable","[psram]")
|
||||||
{
|
{
|
||||||
uint32_t *ext_buffer = (uint32_t *)heap_caps_calloc(TEST_ALLOC_SIZE, 1, MALLOC_CAP_SPIRAM);
|
uint32_t *ext_buffer = (uint32_t *)heap_caps_calloc(TEST_ALLOC_SIZE, 1, MALLOC_CAP_SPIRAM);
|
||||||
@ -32,9 +42,8 @@ TEST_CASE("test psram heap allocable","[psram]")
|
|||||||
|
|
||||||
uintptr_t start = (uintptr_t)ext_buffer;
|
uintptr_t start = (uintptr_t)ext_buffer;
|
||||||
uintptr_t end = (uintptr_t)ext_buffer + TEST_ALLOC_SIZE;
|
uintptr_t end = (uintptr_t)ext_buffer + TEST_ALLOC_SIZE;
|
||||||
ESP_LOGI(TAG, "test ext buffer start addr is %x, end addr is %x", start, end);
|
ESP_LOGI(TAG, "test ext buffer start addr is 0x%x, end addr is 0x%x", start, end);
|
||||||
TEST_ASSERT((start >= SOC_EXTRAM_DATA_LOW) && (end <= SOC_EXTRAM_DATA_HIGH));
|
TEST_ASSERT(s_check_valid_psram_alloced_range((void *)start) && s_check_valid_psram_alloced_range((void *)end));
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < TEST_ALLOC_SIZE / sizeof(uint32_t); i++) {
|
for (int i = 0; i < TEST_ALLOC_SIZE / sizeof(uint32_t); i++) {
|
||||||
ext_buffer[i] = (i + 1) ^ 0xaaaaaaaa;
|
ext_buffer[i] = (i + 1) ^ 0xaaaaaaaa;
|
||||||
@ -47,6 +56,7 @@ TEST_CASE("test psram heap allocable","[psram]")
|
|||||||
free(ext_buffer);
|
free(ext_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "esp32s3/rom/spi_flash.h"
|
#include "esp32s3/rom/spi_flash.h"
|
||||||
|
@ -223,7 +223,7 @@ SECTIONS
|
|||||||
_noinit_end = ABSOLUTE(.);
|
_noinit_end = ABSOLUTE(.);
|
||||||
} > dram0_0_seg
|
} > dram0_0_seg
|
||||||
|
|
||||||
/* external memory bss, from any global variable with EXT_RAM_ATTR attribute*/
|
/* external memory bss, from any global variable with EXT_RAM_BSS_ATTR attribute*/
|
||||||
.ext_ram.bss (NOLOAD) :
|
.ext_ram.bss (NOLOAD) :
|
||||||
{
|
{
|
||||||
_ext_ram_bss_start = ABSOLUTE(.);
|
_ext_ram_bss_start = ABSOLUTE(.);
|
||||||
|
@ -233,7 +233,7 @@ SECTIONS
|
|||||||
_noinit_end = ABSOLUTE(.);
|
_noinit_end = ABSOLUTE(.);
|
||||||
} > dram0_0_seg
|
} > dram0_0_seg
|
||||||
|
|
||||||
/* external memory bss, from any global variable with EXT_RAM_ATTR attribute*/
|
/* external memory bss, from any global variable with EXT_RAM_BSS_ATTR attribute*/
|
||||||
.ext_ram.bss (NOLOAD) :
|
.ext_ram.bss (NOLOAD) :
|
||||||
{
|
{
|
||||||
_ext_ram_bss_start = ABSOLUTE(.);
|
_ext_ram_bss_start = ABSOLUTE(.);
|
||||||
@ -249,7 +249,6 @@ SECTIONS
|
|||||||
{
|
{
|
||||||
. = ALIGN (8);
|
. = ALIGN (8);
|
||||||
_bss_start = ABSOLUTE(.);
|
_bss_start = ABSOLUTE(.);
|
||||||
*(.ext_ram.bss*)
|
|
||||||
|
|
||||||
mapping[dram0_bss]
|
mapping[dram0_bss]
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ MEMORY
|
|||||||
|
|
||||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
/* Flash mapped constant data */
|
/* Flash mapped constant data */
|
||||||
drom0_0_seg (R) : org = 0x3C000020, len = 0x800000-0x20
|
drom0_0_seg (R) : org = 0x3C000020, len = 0x2000000-0x20
|
||||||
|
|
||||||
/* (See iram0_2_seg for meaning of 0x20 offset in the above.) */
|
/* (See iram0_2_seg for meaning of 0x20 offset in the above.) */
|
||||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
@ -115,6 +115,11 @@ MEMORY
|
|||||||
#else
|
#else
|
||||||
rtc_slow_seg(RW) : org = 0x50000000 , len = 0x2000
|
rtc_slow_seg(RW) : org = 0x50000000 , len = 0x2000
|
||||||
#endif // CONFIG_ULP_COPROC_ENABLED
|
#endif // CONFIG_ULP_COPROC_ENABLED
|
||||||
|
/**
|
||||||
|
* `extern_ram_seg` and `drom0_0_seg` share the same bus and the address region.
|
||||||
|
* A dummy section is used to avoid overlap. See `.ext_ram.dummy` in `sections.ld.in`
|
||||||
|
*/
|
||||||
|
extern_ram_seg(RWX) : org = 0x3c000020 , len = 0x2000000-0x20
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE
|
#if CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE
|
||||||
|
@ -231,7 +231,6 @@ SECTIONS
|
|||||||
{
|
{
|
||||||
. = ALIGN (8);
|
. = ALIGN (8);
|
||||||
_bss_start = ABSOLUTE(.);
|
_bss_start = ABSOLUTE(.);
|
||||||
*(.ext_ram.bss*)
|
|
||||||
|
|
||||||
mapping[dram0_bss]
|
mapping[dram0_bss]
|
||||||
|
|
||||||
@ -292,7 +291,7 @@ SECTIONS
|
|||||||
*/
|
*/
|
||||||
.flash_rodata_dummy (NOLOAD):
|
.flash_rodata_dummy (NOLOAD):
|
||||||
{
|
{
|
||||||
_flash_rodata_dummy_start = .;
|
_flash_rodata_dummy_start = ABSOLUTE(.);
|
||||||
/* Start at the same alignment constraint than .flash.text */
|
/* Start at the same alignment constraint than .flash.text */
|
||||||
. = ALIGN(ALIGNOF(.flash.text));
|
. = ALIGN(ALIGNOF(.flash.text));
|
||||||
/* Create an empty gap as big as .flash.text section */
|
/* Create an empty gap as big as .flash.text section */
|
||||||
@ -381,6 +380,25 @@ SECTIONS
|
|||||||
mapping[rodata_noload]
|
mapping[rodata_noload]
|
||||||
} > default_rodata_seg
|
} > default_rodata_seg
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This section is required to skip flash rodata sections, because `extern_ram_seg`
|
||||||
|
* and `drom0_0_seg` are on the same bus
|
||||||
|
*/
|
||||||
|
.ext_ram.dummy (NOLOAD):
|
||||||
|
{
|
||||||
|
. = ORIGIN(extern_ram_seg) + (_rodata_reserved_end - _flash_rodata_dummy_start);
|
||||||
|
. = ALIGN (0x10000);
|
||||||
|
} > extern_ram_seg
|
||||||
|
|
||||||
|
/* This section holds .ext_ram.bss data, and will be put in PSRAM */
|
||||||
|
.ext_ram.bss (NOLOAD) :
|
||||||
|
{
|
||||||
|
_ext_ram_bss_start = ABSOLUTE(.);
|
||||||
|
mapping[extern_ram]
|
||||||
|
. = ALIGN(4);
|
||||||
|
_ext_ram_bss_end = ABSOLUTE(.);
|
||||||
|
} > extern_ram_seg
|
||||||
|
|
||||||
/* Marks the end of IRAM code segment */
|
/* Marks the end of IRAM code segment */
|
||||||
.iram0.text_end (NOLOAD) :
|
.iram0.text_end (NOLOAD) :
|
||||||
{
|
{
|
||||||
|
@ -389,12 +389,10 @@ void IRAM_ATTR call_start_cpu0(void)
|
|||||||
bootloader_init_mem();
|
bootloader_init_mem();
|
||||||
#if CONFIG_SPIRAM_BOOT_INIT
|
#if CONFIG_SPIRAM_BOOT_INIT
|
||||||
if (esp_spiram_init() != ESP_OK) {
|
if (esp_spiram_init() != ESP_OK) {
|
||||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
|
||||||
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
ESP_EARLY_LOGE(TAG, "Failed to init external RAM, needed for external .bss segment");
|
ESP_EARLY_LOGE(TAG, "Failed to init external RAM, needed for external .bss segment");
|
||||||
abort();
|
abort();
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
|
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
|
||||||
ESP_EARLY_LOGI(TAG, "Failed to init external RAM; continuing without it.");
|
ESP_EARLY_LOGI(TAG, "Failed to init external RAM; continuing without it.");
|
||||||
@ -405,11 +403,11 @@ void IRAM_ATTR call_start_cpu0(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
//TODO: IDF-4382
|
//TODO: IDF-4382
|
||||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
if (g_spiram_ok) {
|
if (g_spiram_ok) {
|
||||||
esp_spiram_init_cache();
|
esp_spiram_init_cache();
|
||||||
}
|
}
|
||||||
#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3, //TODO: IDF-4382
|
#endif //#if CONFIG_IDF_TARGET_ESP32, //TODO: IDF-4382
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||||
@ -439,7 +437,7 @@ void IRAM_ATTR call_start_cpu0(void)
|
|||||||
|
|
||||||
#if CONFIG_SPIRAM_MEMTEST
|
#if CONFIG_SPIRAM_MEMTEST
|
||||||
//TODO: IDF-4382
|
//TODO: IDF-4382
|
||||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
if (g_spiram_ok) {
|
if (g_spiram_ok) {
|
||||||
bool ext_ram_ok = esp_spiram_test();
|
bool ext_ram_ok = esp_spiram_test();
|
||||||
if (!ext_ram_ok) {
|
if (!ext_ram_ok) {
|
||||||
@ -447,7 +445,7 @@ void IRAM_ATTR call_start_cpu0(void)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif //CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3, //TODO: IDF-4382
|
#endif //CONFIG_IDF_TARGET_ESP32, //TODO: IDF-4382
|
||||||
#endif //CONFIG_SPIRAM_MEMTEST
|
#endif //CONFIG_SPIRAM_MEMTEST
|
||||||
|
|
||||||
//TODO: IDF-4382
|
//TODO: IDF-4382
|
||||||
|
@ -87,6 +87,8 @@ enum tlsf_config
|
|||||||
FL_INDEX_MAX = 23, //Each pool can have up 8MB
|
FL_INDEX_MAX = 23, //Each pool can have up 8MB
|
||||||
#elif (TLSF_MAX_POOL_SIZE <= (16 * 1024 * 1024))
|
#elif (TLSF_MAX_POOL_SIZE <= (16 * 1024 * 1024))
|
||||||
FL_INDEX_MAX = 24, //Each pool can have up 16MB
|
FL_INDEX_MAX = 24, //Each pool can have up 16MB
|
||||||
|
#elif (TLSF_MAX_POOL_SIZE <= (32 * 1024 * 1024))
|
||||||
|
FL_INDEX_MAX = 25, //Each pool can have up 32MB
|
||||||
#else
|
#else
|
||||||
#error "Higher TLSF pool sizes should be added for this new config"
|
#error "Higher TLSF pool sizes should be added for this new config"
|
||||||
#endif
|
#endif
|
||||||
|
@ -185,7 +185,7 @@
|
|||||||
#define SOC_RTC_DATA_LOW 0x50000000
|
#define SOC_RTC_DATA_LOW 0x50000000
|
||||||
#define SOC_RTC_DATA_HIGH 0x50002000
|
#define SOC_RTC_DATA_HIGH 0x50002000
|
||||||
|
|
||||||
#define SOC_EXTRAM_DATA_LOW 0x3D000000
|
#define SOC_EXTRAM_DATA_LOW 0x3C000000
|
||||||
#define SOC_EXTRAM_DATA_HIGH 0x3E000000
|
#define SOC_EXTRAM_DATA_HIGH 0x3E000000
|
||||||
#define SOC_IROM_MASK_LOW 0x40000000
|
#define SOC_IROM_MASK_LOW 0x40000000
|
||||||
#define SOC_IROM_MASK_HIGH 0x4001A100
|
#define SOC_IROM_MASK_HIGH 0x4001A100
|
||||||
|
@ -91,7 +91,7 @@ If a suitable block of preferred internal/external memory is not available, the
|
|||||||
|
|
||||||
Because some buffers can only be allocated in internal memory, a second configuration item :ref:`CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL` defines a pool of internal memory which is reserved for *only* explicitly internal allocations (such as memory for DMA use). Regular ``malloc()`` will not allocate from this pool. The :ref:`MALLOC_CAP_DMA <dma-capable-memory>` and ``MALLOC_CAP_INTERNAL`` flags can be used to allocate memory from this pool.
|
Because some buffers can only be allocated in internal memory, a second configuration item :ref:`CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL` defines a pool of internal memory which is reserved for *only* explicitly internal allocations (such as memory for DMA use). Regular ``malloc()`` will not allocate from this pool. The :ref:`MALLOC_CAP_DMA <dma-capable-memory>` and ``MALLOC_CAP_INTERNAL`` flags can be used to allocate memory from this pool.
|
||||||
|
|
||||||
.. only:: esp32 or esp32s2
|
.. only:: SOC_SPIRAM_SUPPORTED
|
||||||
|
|
||||||
.. _external_ram_config_bss:
|
.. _external_ram_config_bss:
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ Because some buffers can only be allocated in internal memory, a second configur
|
|||||||
|
|
||||||
If enabled, a region of the address space starting from {IDF_TARGET_PSRAM_ADDR_START} will be used to store zero-initialized data (BSS segment) from the lwIP, net80211, libpp, and bluedroid ESP-IDF libraries.
|
If enabled, a region of the address space starting from {IDF_TARGET_PSRAM_ADDR_START} will be used to store zero-initialized data (BSS segment) from the lwIP, net80211, libpp, and bluedroid ESP-IDF libraries.
|
||||||
|
|
||||||
Additional data can be moved from the internal BSS segment to external RAM by applying the macro ``EXT_RAM_ATTR`` to any static declaration (which is not initialized to a non-zero value).
|
Additional data can be moved from the internal BSS segment to external RAM by applying the macro ``EXT_RAM_BSS_ATTR`` to any static declaration (which is not initialized to a non-zero value).
|
||||||
|
|
||||||
It is also possible to place the BSS section of a component or a library to external RAM using linker fragment scheme ``extram_bss``.
|
It is also possible to place the BSS section of a component or a library to external RAM using linker fragment scheme ``extram_bss``.
|
||||||
|
|
||||||
@ -129,8 +129,8 @@ External RAM use has the following restrictions:
|
|||||||
|
|
||||||
* When flash cache is disabled (for example, if the flash is being written to), the external RAM also becomes inaccessible; any reads from or writes to it will lead to an illegal cache access exception. This is also the reason why ESP-IDF does not by default allocate any task stacks in external RAM (see below).
|
* When flash cache is disabled (for example, if the flash is being written to), the external RAM also becomes inaccessible; any reads from or writes to it will lead to an illegal cache access exception. This is also the reason why ESP-IDF does not by default allocate any task stacks in external RAM (see below).
|
||||||
|
|
||||||
* External RAM cannot be used as a place to store DMA transaction descriptors or as a buffer for a DMA transfer to read from or write into. Therefore when External RAM is enabled, any buffers that will be used in combination with DMA must be allocated using ``heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL)`` and can be freed using a standard ``free()`` call.
|
* External RAM cannot be used as a place to store DMA transaction descriptors or as a buffer for a DMA transfer to read from or write into. Therefore when External RAM is enabled, any buffer that will be used in combination with DMA must be allocated using ``heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL)`` and can be freed using a standard ``free()`` call.
|
||||||
|
|
||||||
.. only:: SOC_PSRAM_DMA_CAPABLE
|
.. only:: SOC_PSRAM_DMA_CAPABLE
|
||||||
|
|
||||||
Note, although {IDF_TARGET_NAME} has hardware support for DMA to/from external RAM, this is not yet supported in ESP-IDF.
|
Note, although {IDF_TARGET_NAME} has hardware support for DMA to/from external RAM, this is not yet supported in ESP-IDF.
|
||||||
|
@ -16,9 +16,9 @@ DRAM (Data RAM)
|
|||||||
|
|
||||||
Non-constant static data (.data) and zero-initialized data (.bss) is placed by the linker into Internal SRAM as data memory. The remaining space in this region is used for the runtime heap.
|
Non-constant static data (.data) and zero-initialized data (.bss) is placed by the linker into Internal SRAM as data memory. The remaining space in this region is used for the runtime heap.
|
||||||
|
|
||||||
.. only:: esp32 or esp32s2
|
.. only:: SOC_SPIRAM_SUPPORTED
|
||||||
|
|
||||||
By applying the ``EXT_RAM_ATTR`` macro, zero-initialized data can also be placed into external RAM. To use this macro, the :ref:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY` needs to be enabled. See :ref:`external_ram_config_bss`.
|
By applying the ``EXT_RAM_BSS_ATTR`` macro, zero-initialized data can also be placed into external RAM. To use this macro, the :ref:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY` needs to be enabled. See :ref:`external_ram_config_bss`.
|
||||||
|
|
||||||
.. only:: esp32
|
.. only:: esp32
|
||||||
|
|
||||||
|
@ -41,10 +41,21 @@ ESP HW Support
|
|||||||
- The header file ``esp_intr.h`` has been deleted. Please include ``esp_intr_alloc.h`` to allocate and manipulate interrupts.
|
- The header file ``esp_intr.h`` has been deleted. Please include ``esp_intr_alloc.h`` to allocate and manipulate interrupts.
|
||||||
- The header file ``esp_panic.h`` has been deleted. ESP-IDF developers should include ``esp_private/panic_reason.h`` to get supported panic reasons. And should include ``esp_debug_helpers.h`` to use any debug related helper functions, e.g. print backtrace.
|
- The header file ``esp_panic.h`` has been deleted. ESP-IDF developers should include ``esp_private/panic_reason.h`` to get supported panic reasons. And should include ``esp_debug_helpers.h`` to use any debug related helper functions, e.g. print backtrace.
|
||||||
- The header file ``soc_log.h`` is now renamed to ``esp_hw_log.h`` and all logging macros have been updated from ``SOC_LOGx`` to ``ESP_HW_LOGx``. ESP-IDF users must use the later form.
|
- The header file ``soc_log.h`` is now renamed to ``esp_hw_log.h`` and all logging macros have been updated from ``SOC_LOGx`` to ``ESP_HW_LOGx``. ESP-IDF users must use the later form.
|
||||||
- The header file ``esp_spiram.h`` file is deleted. Users should use the ``<target>/spiram.h`` file instead.
|
|
||||||
- The header file ``esp32/himem.h`` file is deleted. Users should use the esp_himem.h file instead.
|
|
||||||
- The header files ``spinlock.h``, ``clk_ctrl_os.h`` and ``rtc_wdt.h`` must now be included without the ``soc`` prefix. Eg:- ``#include "spinlock.h"``.
|
- The header files ``spinlock.h``, ``clk_ctrl_os.h`` and ``rtc_wdt.h`` must now be included without the ``soc`` prefix. Eg:- ``#include "spinlock.h"``.
|
||||||
|
|
||||||
|
PSRAM
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
- The header file ``esp_spiram.h`` file has been deleted. Users should use the ``<target>/spiram.h`` file instead.
|
||||||
|
- The header file ``esp32/himem.h`` file has been deleted. Users should use the esp_himem.h file instead.
|
||||||
|
- `esp_spiram_get_chip_size` has been deleted.
|
||||||
|
- `esp_spiram_get_size` has been moved to `esp_private/spiram_private.h`
|
||||||
|
|
||||||
|
ESP Common
|
||||||
|
----------
|
||||||
|
|
||||||
|
- `EXT_RAM_ATTR` is deprecated. Use this new macro `EXT_RAM_BSS_ATTR` to put .bss on PSRAM.
|
||||||
|
|
||||||
ESP System
|
ESP System
|
||||||
----------
|
----------
|
||||||
- The header files ``esp_random.h``, ``esp_mac.h`` and ``esp_chip_info.h``, which were all previously indirectly included via the header file ``esp_system.h``, must now be included directly. These headers are removed from ``esp_system.h``.
|
- The header files ``esp_random.h``, ``esp_mac.h`` and ``esp_chip_info.h``, which were all previously indirectly included via the header file ``esp_system.h``, must now be included directly. These headers are removed from ``esp_system.h``.
|
||||||
|
@ -91,7 +91,7 @@ ESP-IDF 启动过程中,片外 RAM 被映射到以 {IDF_TARGET_PSRAM_ADDR_STAR
|
|||||||
|
|
||||||
由于有些内存缓冲器仅可在内部存储器中分配,因此需要使用第二个配置项 :ref:`CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL` 定义一个内部内存池,仅限显式的内部存储器分配使用(例如用于 DMA 的存储器)。常规 ``malloc()`` 将不会从该池中分配,但可以使用 :ref:`MALLOC_CAP_DMA <dma-capable-memory>` 和 ``MALLOC_CAP_INTERNAL`` 标志从该池中分配存储器。
|
由于有些内存缓冲器仅可在内部存储器中分配,因此需要使用第二个配置项 :ref:`CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL` 定义一个内部内存池,仅限显式的内部存储器分配使用(例如用于 DMA 的存储器)。常规 ``malloc()`` 将不会从该池中分配,但可以使用 :ref:`MALLOC_CAP_DMA <dma-capable-memory>` 和 ``MALLOC_CAP_INTERNAL`` 标志从该池中分配存储器。
|
||||||
|
|
||||||
.. only:: esp32 or esp32s2
|
.. only:: SOC_SPIRAM_SUPPORTED
|
||||||
|
|
||||||
.. _external_ram_config_bss:
|
.. _external_ram_config_bss:
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ ESP-IDF 启动过程中,片外 RAM 被映射到以 {IDF_TARGET_PSRAM_ADDR_STAR
|
|||||||
|
|
||||||
启用该选项后,从 {IDF_TARGET_PSRAM_ADDR_START} 起始的地址空间将用于存储来自 lwip、net80211、libpp 和 bluedroid ESP-IDF 库中零初始化的数据(BSS 段)。
|
启用该选项后,从 {IDF_TARGET_PSRAM_ADDR_START} 起始的地址空间将用于存储来自 lwip、net80211、libpp 和 bluedroid ESP-IDF 库中零初始化的数据(BSS 段)。
|
||||||
|
|
||||||
``EXT_RAM_ATTR`` 宏应用于任何静态声明(未初始化为非零值)之后,可以将附加数据从内部 BSS 段移到片外 RAM。
|
``EXT_RAM_BSS_ATTR`` 宏应用于任何静态声明(未初始化为非零值)之后,可以将附加数据从内部 BSS 段移到片外 RAM。
|
||||||
|
|
||||||
也可以使用链接器片段方案 ``extram_bss`` 将组件或库的 BSS 段放到片外 RAM 中。
|
也可以使用链接器片段方案 ``extram_bss`` 将组件或库的 BSS 段放到片外 RAM 中。
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ DRAM(数据 RAM)
|
|||||||
|
|
||||||
非常量静态数据(.data 段)和零初始化数据(.bss 段)由链接器放入内部 SRAM 作为数据存储。此区域中的剩余空间可在程序运行时用作堆。
|
非常量静态数据(.data 段)和零初始化数据(.bss 段)由链接器放入内部 SRAM 作为数据存储。此区域中的剩余空间可在程序运行时用作堆。
|
||||||
|
|
||||||
.. only:: esp32 or esp32s2
|
.. only:: SOC_SPIRAM_SUPPORTED
|
||||||
|
|
||||||
通过应用 ``EXT_RAM_ATTR`` 宏,零初始化数据也可以放入外部 RAM。使用这个宏需要启用 :ref:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY`。详情请见 :ref:`external_ram_config_bss`。
|
通过应用 ``EXT_RAM_BSS_ATTR`` 宏,零初始化数据也可以放入外部 RAM。使用这个宏需要启用 :ref:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY`。详情请见 :ref:`external_ram_config_bss`。
|
||||||
|
|
||||||
.. only:: esp32
|
.. only:: esp32
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user