From ad8e1a395cfd79e24eab5516ec9b2988fdf299a3 Mon Sep 17 00:00:00 2001 From: Armando Date: Tue, 27 Jul 2021 16:12:45 +0800 Subject: [PATCH] memory: port SPIRAM noinit segment support to master --- components/esp32/CMakeLists.txt | 87 +------------------ components/esp32/component.mk | 36 -------- components/esp_common/include/esp_attr.h | 16 ++-- .../esp_hw_support/Kconfig.spiram.common | 10 ++- .../esp_hw_support/include/soc/esp32/spiram.h | 2 +- components/esp_hw_support/port/esp32/spiram.c | 25 ++++-- .../ld/esp32/esp32.extram.noinit.ld | 14 --- components/esp_system/ld/esp32/sections.ld.in | 12 +++ components/esp_system/port/cpu_start.c | 10 +-- 9 files changed, 48 insertions(+), 164 deletions(-) delete mode 100644 components/esp_system/ld/esp32/esp32.extram.noinit.ld diff --git a/components/esp32/CMakeLists.txt b/components/esp32/CMakeLists.txt index 376de09d67..a6eaa1b31d 100644 --- a/components/esp32/CMakeLists.txt +++ b/components/esp32/CMakeLists.txt @@ -3,89 +3,10 @@ if(NOT "${target}" STREQUAL "esp32") return() endif() -idf_build_get_property(sdkconfig_header SDKCONFIG_HEADER) - -if(BOOTLOADER_BUILD) - # For bootloader, all we need from esp32 is headers - idf_component_register(INCLUDE_DIRS include REQUIRES xtensa) - target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32.peripherals.ld") -else() - # Regular app build - set(srcs - "cache_sram_mmu.c" - "dport_access.c" - "esp_himem.c" - "spiram.c" - "spiram_psram.c") - - set(include_dirs "include") - - set(requires driver efuse soc xtensa) #unfortunately rom/uart uses SOC registers directly - - # app_update is added here because cpu_start.c uses esp_ota_get_app_description() function. - # esp_timer is added here because cpu_start.c uses esp_timer - set(priv_requires app_trace app_update bootloader_support esp_system log mbedtls nvs_flash pthread - spi_flash vfs espcoredump esp_common perfmon esp_timer esp_ipc esp_pm) - - idf_component_register(SRCS "${srcs}" - INCLUDE_DIRS "${include_dirs}" - REQUIRES "${requires}" - PRIV_REQUIRES "${priv_requires}" - REQUIRED_IDF_TARGETS esp32) - - target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/esp32_out.ld") - - if(CONFIG_SPIRAM_ALLOW_NOINIT_EXTERNAL_MEMORY) - # This has to be linked before esp32.project.ld - target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32.extram.noinit.ld") - endif() - - # Process the template file through the linker script generation mechanism, and use the output for linking the - # final binary - target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/ld/esp32.project.ld.in" - PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ld/esp32.project.ld") - - target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32.peripherals.ld") - target_link_libraries(${COMPONENT_LIB} PUBLIC gcc) - target_link_libraries(${COMPONENT_LIB} INTERFACE "-u call_user_start_cpu0") - - idf_build_get_property(config_dir CONFIG_DIR) - # Preprocess esp32.ld linker script to include configuration, becomes esp32_out.ld - set(LD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ld) - add_custom_command( - OUTPUT esp32_out.ld - COMMAND "${CMAKE_C_COMPILER}" -C -P -x c -E -o esp32_out.ld -I ${config_dir} ${LD_DIR}/esp32.ld - MAIN_DEPENDENCY ${LD_DIR}/esp32.ld - DEPENDS ${sdkconfig_header} - COMMENT "Generating linker script..." - VERBATIM) - - add_custom_target(esp32_linker_script DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/esp32_out.ld) - add_dependencies(${COMPONENT_LIB} esp32_linker_script) - - if(CONFIG_SPIRAM_CACHE_WORKAROUND) - # Note: Adding as a PUBLIC compile option here causes this option to propagate to all - # components that depend on esp32. - # - # To handle some corner cases, the same flag is set in project_include.cmake - target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-issue) - # also, make sure we link with this option so correct toolchain libs are pulled in - target_link_libraries(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-issue) - # set strategy selected - # note that we don't need to set link options as the library linked is independent of this - if(CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST) - target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=dupldst) - target_link_libraries(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=dupldst) - endif() - if(CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_MEMW) - target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=memw) - target_link_libraries(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=memw) - endif() - if(CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_NOPS) - target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=nops) - target_link_libraries(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=nops) - endif() - endif() +if(NOT BOOTLOADER_BUILD) + # [refactor-todo] propagate these requirements for compatibility + # remove in the future + set(legacy_reqs driver efuse soc) endif() idf_component_register(INCLUDE_DIRS include diff --git a/components/esp32/component.mk b/components/esp32/component.mk index 1b831fd21f..ebd7a7d59b 100644 --- a/components/esp32/component.mk +++ b/components/esp32/component.mk @@ -1,39 +1,3 @@ # # Component Makefile # - -COMPONENT_SRCDIRS := . - -ifdef CONFIG_SPIRAM_ALLOW_NOINIT_EXTERNAL_MEMORY - # This linker script must come before esp32.project.ld - LINKER_SCRIPTS += esp32.extram.noinit.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. -LINKER_SCRIPTS += $(COMPONENT_BUILD_DIR)/esp32.project.ld esp32.peripherals.ld - -#ld_include_panic_highint_hdl is added as an undefined symbol because otherwise the -#linker will ignore panic_highint_hdl.S as it has no other files depending on any -#symbols in it. -COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH)/ld \ - -T esp32_out.ld \ - -u ld_include_panic_highint_hdl \ - $(addprefix -T ,$(LINKER_SCRIPTS)) \ - -# final linking of project ELF depends on all binary libraries, and -# all linker scripts (except esp32_out.ld, as this is code generated here.) -COMPONENT_ADD_LINKER_DEPS := $(addprefix ld/, $(filter-out $(COMPONENT_BUILD_DIR)/esp32.project.ld, $(LINKER_SCRIPTS))) \ - $(COMPONENT_BUILD_DIR)/esp32.project.ld - -# Preprocess esp32.ld linker script into esp32_out.ld -# -# The library doesn't really depend on esp32_out.ld, but it -# saves us from having to add the target to a Makefile.projbuild -$(COMPONENT_LIBRARY): esp32_out.ld - -esp32_out.ld: $(COMPONENT_PATH)/ld/esp32.ld ../include/sdkconfig.h - $(CC) -I ../include -C -P -x c -E $< -o $@ - -COMPONENT_EXTRA_CLEAN := esp32_out.ld $(COMPONENT_BUILD_DIR)/esp32.project.ld diff --git a/components/esp_common/include/esp_attr.h b/components/esp_common/include/esp_attr.h index 6be0d4e678..88a230b77c 100644 --- a/components/esp_common/include/esp_attr.h +++ b/components/esp_common/include/esp_attr.h @@ -72,14 +72,6 @@ extern "C" { #define EXT_RAM_ATTR #endif -#if CONFIG_SPIRAM_ALLOW_NOINIT_EXTERNAL_MEMORY -// Forces data into external memory noinit section to avoid initialization after restart. -#define EXT_RAM_NOINIT_ATTR _SECTION_ATTR_IMPL(".ext_ram.noinit", __COUNTER__) -#else -// Place in internal noinit section -#define EXT_RAM_NOINIT_ATTR __NOINIT_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. @@ -97,6 +89,14 @@ extern "C" { // Forces data into noinit section to avoid initialization after restart. #define __NOINIT_ATTR _SECTION_ATTR_IMPL(".noinit", __COUNTER__) +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY +// Forces data into external memory noinit section to avoid initialization after restart. +#define EXT_RAM_NOINIT_ATTR _SECTION_ATTR_IMPL(".ext_ram.noinit", __COUNTER__) +#else +// Place in internal noinit section +#define EXT_RAM_NOINIT_ATTR __NOINIT_ATTR +#endif + // Forces data into RTC slow memory of .noinit section. // Any variable marked with this attribute will keep its value // after restart or during a deep sleep / wake cycle. diff --git a/components/esp_hw_support/Kconfig.spiram.common b/components/esp_hw_support/Kconfig.spiram.common index adc7872332..c52071dcab 100644 --- a/components/esp_hw_support/Kconfig.spiram.common +++ b/components/esp_hw_support/Kconfig.spiram.common @@ -102,10 +102,12 @@ config SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY Note that the variables placed in SPIRAM using EXT_RAM_ATTR will be zero initialized. -config SPIRAM_ALLOW_NOINIT_EXTERNAL_MEMORY - bool "Enable placement of noinit segments in external memory" +config SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + bool "Allow .noinit segment placed in external memory" default n - depends on SPIRAM + depends on SPIRAM && IDF_TARGET_ESP32 help If enabled, noinit variables can be placed in PSRAM using EXT_RAM_NOINIT_ATTR. - If disabled, EXT_RAM_NOINIT_ATTR will act like __NOINIT_ATTR. + + Note the values placed into this section will not be initialized at startup and should keep its value + after software restart. diff --git a/components/esp_hw_support/include/soc/esp32/spiram.h b/components/esp_hw_support/include/soc/esp32/spiram.h index b931cb79b0..e58712d1fa 100644 --- a/components/esp_hw_support/include/soc/esp32/spiram.h +++ b/components/esp_hw_support/include/soc/esp32/spiram.h @@ -59,7 +59,7 @@ void esp_spiram_init_cache(void); * * @return true on success, false on failed memory test */ -bool esp_spiram_test(const void* keepout_addr_low, const void* keepout_addr_high); +bool esp_spiram_test(void); /** diff --git a/components/esp_hw_support/port/esp32/spiram.c b/components/esp_hw_support/port/esp32/spiram.c index 8c6da9afe2..d0806f16ef 100644 --- a/components/esp_hw_support/port/esp32/spiram.c +++ b/components/esp_hw_support/port/esp32/spiram.c @@ -55,7 +55,7 @@ static const char* TAG = "spiram"; #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY extern uint8_t _ext_ram_bss_start, _ext_ram_bss_end; #endif -#if CONFIG_SPIRAM_ALLOW_NOINIT_EXTERNAL_MEMORY +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY extern uint8_t _ext_ram_noinit_start, _ext_ram_noinit_end; #endif @@ -83,25 +83,32 @@ static size_t spiram_size_usable_for_malloc(void) 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. */ -bool esp_spiram_test(const void* keepout_addr_low, const void* keepout_addr_high) +bool esp_spiram_test(void) { + +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + const void *keepout_addr_low = (const void*)&_ext_ram_noinit_start; + const void *keepout_addr_high = (const void*)&_ext_ram_noinit_end; +#else + const void *keepout_addr_low = 0; + const void *keepout_addr_high = 0; +#endif + volatile int *spiram=(volatile int*)SOC_EXTRAM_DATA_LOW; size_t p; size_t s=spiram_size_usable_for_malloc(); int errct=0; int initial_err=-1; for (p=0; p<(s/sizeof(int)); p+=8) { - if ((keepout_addr_low <= (const void*)&spiram[p]) && ((const void*)&spiram[p] < keepout_addr_high)) { - continue; - } else if ((keepout_addr_low < (const void*)&spiram[p+1]) && ((const void*)&spiram[p+1] <= keepout_addr_high)) { + const void *addr = (const void *)&spiram[p]; + if ((keepout_addr_low <= addr) && (addr < keepout_addr_high)) { continue; } spiram[p]=p^0xAAAAAAAA; } for (p=0; p<(s/sizeof(int)); p+=8) { - if ((keepout_addr_low <= (const void*)&spiram[p]) && ((const void*)&spiram[p] < keepout_addr_high)) { - continue; - } else if ((keepout_addr_low < (const void*)&spiram[p+1]) && ((const void*)&spiram[p+1] <= keepout_addr_high)) { + const void *addr = (const void *)&spiram[p]; + if ((keepout_addr_low <= addr) && (addr < keepout_addr_high)) { continue; } if (spiram[p]!=(p^0xAAAAAAAA)) { @@ -192,7 +199,7 @@ esp_err_t esp_spiram_add_to_heapalloc(void) mallocable_ram_start = (intptr_t)&_ext_ram_bss_end; } #endif -#if CONFIG_SPIRAM_ALLOW_NOINIT_EXTERNAL_MEMORY +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY if (mallocable_ram_start < (intptr_t)&_ext_ram_noinit_end) { mallocable_ram_start = (intptr_t)&_ext_ram_noinit_end; } diff --git a/components/esp_system/ld/esp32/esp32.extram.noinit.ld b/components/esp_system/ld/esp32/esp32.extram.noinit.ld deleted file mode 100644 index 86c7b5341c..0000000000 --- a/components/esp_system/ld/esp32/esp32.extram.noinit.ld +++ /dev/null @@ -1,14 +0,0 @@ -/* This section is only included if CONFIG_SPIRAM_ALLOW_NOINIT_EXTERNAL_MEMORY - is set, to link some NOINIT sections in PSRAM */ - -SECTIONS -{ - /* external memory bss, from any global variable with EXT_RAM_NOINIT_ATTR attribute*/ - .ext_ram.noinit (NOLOAD) : - { - _ext_ram_noinit_start = ABSOLUTE(.); - *(.ext_ram.noinit*) - . = ALIGN(4); - _ext_ram_noinit_end = ABSOLUTE(.); - } > extern_ram_seg -} diff --git a/components/esp_system/ld/esp32/sections.ld.in b/components/esp_system/ld/esp32/sections.ld.in index b60a4a12e0..f3fb5026dd 100644 --- a/components/esp_system/ld/esp32/sections.ld.in +++ b/components/esp_system/ld/esp32/sections.ld.in @@ -197,6 +197,18 @@ SECTIONS . = ALIGN(4); } > dram0_0_seg + /** + * This section holds data that won't be initialised when startup. + * This section locates in External RAM region. + */ + .ext_ram.noinit (NOLOAD) : + { + _ext_ram_noinit_start = ABSOLUTE(.); + *(.ext_ram.noinit*) + . = ALIGN(4); + _ext_ram_noinit_end = ABSOLUTE(.); + } > extern_ram_seg + /*This section holds data that should not be initialized at power up. The section located in Internal SRAM memory region. The macro _NOINIT can be used as attribute to place data into this section. diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 3258bdbe6c..faf2a38eac 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -129,10 +129,6 @@ static const char *TAG = "cpu_start"; extern int _ext_ram_bss_start; extern int _ext_ram_bss_end; #endif -#if CONFIG_SPIRAM_ALLOW_NOINIT_EXTERNAL_MEMORY -extern int _ext_ram_noinit_start; -extern int _ext_ram_noinit_end; -#endif #ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY extern int _iram_bss_start; extern int _iram_bss_end; @@ -423,11 +419,7 @@ void IRAM_ATTR call_start_cpu0(void) #if CONFIG_SPIRAM_MEMTEST if (g_spiram_ok) { -#if CONFIG_SPIRAM_ALLOW_NOINIT_EXTERNAL_MEMORY - bool ext_ram_ok = esp_spiram_test(&_ext_ram_noinit_start, &_ext_ram_noinit_end); -#else - bool ext_ram_ok = esp_spiram_test(0, 0); -#endif + bool ext_ram_ok = esp_spiram_test(); if (!ext_ram_ok) { ESP_EARLY_LOGE(TAG, "External RAM failed memory test!"); abort();