Merge branch 'feature/bss_seg_in_external_memory' into 'master'

memory:   support .bss segment can be in psram

See merge request idf/esp-idf!2236
This commit is contained in:
Angus Gratton 2018-10-10 14:40:21 +08:00
commit 31cf117404
10 changed files with 82 additions and 7 deletions

View File

@ -75,8 +75,14 @@ else()
endif()
target_linker_script(esp32 "${CMAKE_CURRENT_BINARY_DIR}/esp32_out.ld")
if(CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY)
# This has to be linked before esp32.common.ld
target_linker_script(esp32 "ld/esp32.extram.bss.ld")
endif()
target_linker_script(esp32 "ld/esp32.common.ld")
target_linker_script(esp32
"ld/esp32.common.ld"
"ld/esp32.rom.ld"
"ld/esp32.peripherals.ld"
"ld/esp32.rom.libgcc.ld"
@ -113,6 +119,7 @@ else()
MAIN_DEPENDENCY ${LD_DIR}/esp32.ld ${SDKCONFIG_H}
COMMENT "Generating linker script..."
VERBATIM)
add_custom_target(esp32_linker_script DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/esp32_out.ld)
add_dependencies(esp32 esp32_linker_script)

View File

@ -41,7 +41,7 @@ config SPIRAM_BOOT_INIT
config SPIRAM_IGNORE_NOTFOUND
bool "Ignore PSRAM when not found"
default "n"
depends on SPIRAM_BOOT_INIT
depends on SPIRAM_BOOT_INIT && !SPIRAM_ALLOW_BSS_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 ESP32 panic. If this is enabled, the ESP32 will keep on
@ -172,6 +172,15 @@ config SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
ROM code in any way (no direct calls, but also no Bluetooth/WiFi), you can try to disable this and use
xTaskCreateStatic to create the tasks stack in external memory.
config SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
bool "Allow .bss segment placed in external memory"
default n
depends on SPIRAM_SUPPORT
help
If enabled the option,and add EXT_RAM_ATTR defined your variable,then your variable will be placed
in PSRAM instead of internal memory, and placed most of variables of lwip,net802.11,pp,bluedroid library
to external memory defaultly.
endmenu
config MEMMAP_TRACEMEM

View File

@ -8,6 +8,11 @@ ifndef CONFIG_NO_BLOBS
LIBS += core rtc net80211 pp wpa smartconfig coexist wps wpa2 espnow phy mesh
endif
ifdef CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
# This linker script must come before esp32.common.ld
LINKER_SCRIPTS += esp32.extram.bss.ld
endif
#Linker scripts used to link the final application.
#Warning: These linker scripts are only used when the normal app is compiled; the bootloader
#specifies its own scripts.

View File

@ -93,6 +93,10 @@ extern int _bss_start;
extern int _bss_end;
extern int _rtc_bss_start;
extern int _rtc_bss_end;
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
extern int _ext_ram_bss_start;
extern int _ext_ram_bss_end;
#endif
extern int _init_start;
extern void (*__init_array_start)(void);
extern void (*__init_array_end)(void);
@ -154,6 +158,11 @@ void IRAM_ATTR call_start_cpu0()
#if CONFIG_SPIRAM_BOOT_INIT
esp_spiram_init_cache();
if (esp_spiram_init() != ESP_OK) {
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
ESP_EARLY_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.");
s_spiram_okay = false;
@ -207,7 +216,9 @@ void IRAM_ATTR call_start_cpu0()
}
}
#endif
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
memset(&_ext_ram_bss_start, 0, (&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start));
#endif
/* Initialize heap allocator. WARNING: This *needs* to happen *after* the app cpu has booted.
If the heap allocator is initialized first, it will put free memory linked list items into
memory also used by the ROM. Starting the app cpu will let its ROM initialize that memory,

View File

@ -39,6 +39,13 @@
// Forces code into RTC fast memory. See "docs/deep-sleep-stub.rst"
#define RTC_IRAM_ATTR __attribute__((section(".rtc.text")))
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
// Forces bss variable into external memory. "
#define EXT_RAM_ATTR __attribute__((section(".ext_ram.bss")))
#else
#define EXT_RAM_ATTR
#endif
// Forces data into RTC slow memory. See "docs/deep-sleep-stub.rst"
// Any variable marked with this attribute will keep its value
// during a deep sleep / wake cycle.

View File

@ -229,6 +229,7 @@ SECTIONS
{
. = ALIGN (8);
_bss_start = ABSOLUTE(.);
*(.ext_ram.bss*)
_bt_bss_start = ABSOLUTE(.);
*libbt.a:(.bss .bss.* COMMON)
. = ALIGN (4);

View File

@ -0,0 +1,17 @@
/* This section is only included if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
is set, to link some sections to BSS in PSRAM */
SECTIONS
{
/* external memory bss, from any global variable with EXT_RAM_ATTR attribute*/
.ext_ram.bss (NOLOAD) :
{
_ext_ram_bss_start = ABSOLUTE(.);
*(.ext_ram.bss*)
*libnet80211.a:(.dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON)
*libpp.a:(.dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON)
*liblwip.a:(.dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON)
*libbt.a:(EXCLUDE_FILE (libbtdm_app.a) .dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON)
_ext_ram_bss_end = ABSOLUTE(.);
} > extern_ram_seg
}

View File

@ -71,6 +71,10 @@ MEMORY
*/
rtc_slow_seg(RW) : org = 0x50000000 + CONFIG_ULP_COPROC_RESERVE_MEM,
len = 0x1000 - CONFIG_ULP_COPROC_RESERVE_MEM
/* external memory ,including data and text */
extern_ram_seg(RWX) : org = 0x3F800000,
len = 0x400000
}
/* Heap ends at top of dram0_0_seg */

View File

@ -59,7 +59,9 @@ static const char* TAG = "spiram";
#error "FLASH speed can only be equal to or higher than SRAM speed while SRAM is enabled!"
#endif
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
extern int _ext_ram_bss_start, _ext_ram_bss_end;
#endif
static bool spiram_inited=false;
@ -145,11 +147,16 @@ esp_err_t esp_spiram_init()
esp_err_t esp_spiram_add_to_heapalloc()
{
ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", CONFIG_SPIRAM_SIZE/1024);
{
//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.
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (CONFIG_SPIRAM_SIZE - (&_ext_ram_bss_end - &_ext_ram_bss_start))/1024);
return heap_caps_add_region((intptr_t)&_ext_ram_bss_end, (intptr_t)SOC_EXTRAM_DATA_LOW + CONFIG_SPIRAM_SIZE-1);
#else
ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", CONFIG_SPIRAM_SIZE/1024);
return heap_caps_add_region((intptr_t)SOC_EXTRAM_DATA_LOW, (intptr_t)SOC_EXTRAM_DATA_LOW + CONFIG_SPIRAM_SIZE-1);
#endif
}

View File

@ -46,6 +46,9 @@ ESP-IDF fully supports integrating external memory use into your applications. E
``heap_caps_malloc(size, MALLOC_CAP_SPIRAM)``. This memory can be used and subsequently freed using a normal ``free()`` call.
* Initialize RAM, add it to the capability allocator and add memory to the pool of RAM that can be returned by ``malloc()``. This allows
any application to use the external RAM without having to rewrite the code to use ``heap_caps_malloc``.
* Initialize RAM, use a region start from 0x3F800000 for storing zero initialized data(BSS segment) of lwip,net802.11,pp,bluedroid library
by enabling :ref: `CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY` in menuconfig,this way can save some internal memorybecause the BSS segment
originally stored in internal memoryand the rest of external RAM can be add the capability allocator and add memory to the pool of RAM as above way
All these options can be selected from the menuconfig menu.
@ -67,7 +70,11 @@ The use of external RAM has a few restrictions:
for stack and task TCBs and xTaskCreateStatic-type functions will check if the buffers passed are internal. However, for tasks not calling
on code in ROM in any way, directly or indirectly, the menuconfig option :ref:`CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY` will eliminate
the check in xTaskCreateStatic, allowing task stack in external RAM. Using this is not advised, however.
* External RAM initialized failed can not be ignored if enabled :ref:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY`; because of this, some BSS segment
can not be placed into external memory if PSRAM can't work normally and can not be moved to internal memory at runtime because the address of
them is defined by linkfile, the :ref:`CONFIG_SPIRAM_IGNORE_NOTFOUND` can't handle this situation,if you want to enable :ref:
`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY` the :ref:`CONFIG_SPIRAM_IGNORE_NOTFOUND` will be disabled, and if initialize SPIRAM failed,the system
will invoke abort.
Because there are a fair few situations that have a specific need for internal memory, but it is also possible to use malloc() to exhaust
internal memory, there is a pool reserved specifically for requests that cannot be resolved from external memory; allocating task