diff --git a/components/bootloader_support/src/bootloader_common_loader.c b/components/bootloader_support/src/bootloader_common_loader.c index be85cc7044..c5103b0969 100644 --- a/components/bootloader_support/src/bootloader_common_loader.c +++ b/components/bootloader_support/src/bootloader_common_loader.c @@ -121,22 +121,6 @@ int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata, #if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC ) -#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t)) - -_Static_assert(RTC_RETAIN_MEM_ADDR >= SOC_RTC_DRAM_LOW, "rtc_retain_mem_t structure size is bigger than the RTC memory size. Consider reducing RTC reserved memory size."); - -rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)RTC_RETAIN_MEM_ADDR; - -#ifndef BOOTLOADER_BUILD -#include "heap_memory_layout.h" -/* The app needs to be told this memory is reserved, important if configured to use RTC memory as heap. - - Note that keeping this macro here only works when other symbols in this file are referenced by the app, as - this feature is otherwise 100% part of the bootloader. However this seems to happen in all apps. - */ -SOC_RESERVE_MEMORY_REGION(RTC_RETAIN_MEM_ADDR, RTC_RETAIN_MEM_ADDR + sizeof(rtc_retain_mem_t), rtc_retain_mem); -#endif - static uint32_t rtc_retain_mem_size(void) { #ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC /* A custom memory has been reserved by the user, do not consider this memory into CRC calculation as it may change without @@ -144,17 +128,19 @@ static uint32_t rtc_retain_mem_size(void) { * minus the size of everything after (including) `custom` */ return offsetof(rtc_retain_mem_t, custom); #else - return sizeof(rtc_retain_mem_t) - sizeof(rtc_retain_mem->crc); + return sizeof(rtc_retain_mem_t) - sizeof(bootloader_common_get_rtc_retain_mem()->crc); #endif } static bool check_rtc_retain_mem(void) { + rtc_retain_mem_t* rtc_retain_mem = bootloader_common_get_rtc_retain_mem(); return esp_rom_crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, rtc_retain_mem_size()) == rtc_retain_mem->crc && rtc_retain_mem->crc != UINT32_MAX; } static void update_rtc_retain_mem_crc(void) { + rtc_retain_mem_t* rtc_retain_mem = bootloader_common_get_rtc_retain_mem(); rtc_retain_mem->crc = esp_rom_crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, rtc_retain_mem_size()); } @@ -163,14 +149,14 @@ NOINLINE_ATTR void bootloader_common_reset_rtc_retain_mem(void) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Warray-bounds" - memset(rtc_retain_mem, 0, sizeof(rtc_retain_mem_t)); + memset(bootloader_common_get_rtc_retain_mem(), 0, sizeof(rtc_retain_mem_t)); #pragma GCC diagnostic pop } uint16_t bootloader_common_get_rtc_retain_mem_reboot_counter(void) { if (check_rtc_retain_mem()) { - return rtc_retain_mem->reboot_counter; + return bootloader_common_get_rtc_retain_mem()->reboot_counter; } return 0; } @@ -178,13 +164,14 @@ uint16_t bootloader_common_get_rtc_retain_mem_reboot_counter(void) esp_partition_pos_t* bootloader_common_get_rtc_retain_mem_partition(void) { if (check_rtc_retain_mem()) { - return &rtc_retain_mem->partition; + return &bootloader_common_get_rtc_retain_mem()->partition; } return NULL; } void bootloader_common_update_rtc_retain_mem(esp_partition_pos_t* partition, bool reboot_counter) { + rtc_retain_mem_t* rtc_retain_mem = bootloader_common_get_rtc_retain_mem(); if (reboot_counter) { if (!check_rtc_retain_mem()) { bootloader_common_reset_rtc_retain_mem(); @@ -206,6 +193,13 @@ void bootloader_common_update_rtc_retain_mem(esp_partition_pos_t* partition, boo rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void) { - return rtc_retain_mem; +#ifdef BOOTLOADER_BUILD + #define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t)) + static rtc_retain_mem_t *const s_bootloader_retain_mem = (rtc_retain_mem_t *)RTC_RETAIN_MEM_ADDR; + return s_bootloader_retain_mem; +#else + static __attribute__((section(".bootloader_data_rtc_mem"))) rtc_retain_mem_t s_bootloader_retain_mem; + return &s_bootloader_retain_mem; +#endif // !BOOTLOADER_BUILD } #endif // defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC ) diff --git a/components/esp_hw_support/esp_clk.c b/components/esp_hw_support/esp_clk.c index 0b90ef7cf1..f34694580b 100644 --- a/components/esp_hw_support/esp_clk.c +++ b/components/esp_hw_support/esp_clk.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #include @@ -49,9 +50,30 @@ extern uint32_t g_ticks_per_us_app; static portMUX_TYPE s_esp_rtc_time_lock = portMUX_INITIALIZER_UNLOCKED; -#if SOC_RTC_FAST_MEM_SUPPORTED -static RTC_NOINIT_ATTR uint64_t s_esp_rtc_time_us, s_rtc_last_ticks; -#endif +#if SOC_RTC_MEM_SUPPORTED +typedef struct { + uint64_t rtc_time_us; + uint64_t rtc_last_ticks; + uint32_t reserve; + uint32_t checksum; +} retain_mem_t; +_Static_assert(sizeof(retain_mem_t) == 24, "retain_mem_t must be 24 bytes"); +_Static_assert(offsetof(retain_mem_t, checksum) == sizeof(retain_mem_t) - sizeof(uint32_t), "Wrong offset for checksum field in retain_mem_t structure"); + +static __attribute__((section(".rtc_timer_data_in_rtc_mem"))) retain_mem_t s_rtc_timer_retain_mem; + +static uint32_t calc_checksum(void) +{ + uint32_t checksum = 0; + uint32_t *data = (uint32_t*) &s_rtc_timer_retain_mem; + + for (uint32_t i = 0; i < (sizeof(retain_mem_t) - sizeof(s_rtc_timer_retain_mem.checksum)) / 4; i++) { + checksum = ((checksum << 5) - checksum) ^ data[i]; + } + return checksum; +} +#define IS_RETAIN_MEM_VALID() (s_rtc_timer_retain_mem.checksum == calc_checksum()) +#endif // SOC_RTC_MEM_SUPPORTED inline static int IRAM_ATTR s_get_cpu_freq_mhz(void) { @@ -94,13 +116,24 @@ uint64_t esp_rtc_get_time_us(void) { portENTER_CRITICAL_SAFE(&s_esp_rtc_time_lock); const uint32_t cal = esp_clk_slowclk_cal_get(); -#if SOC_RTC_FAST_MEM_SUPPORTED - if (cal == 0) { - s_esp_rtc_time_us = 0; - s_rtc_last_ticks = 0; +#if SOC_RTC_MEM_SUPPORTED + static bool first_call = true; + if (cal == 0 || (first_call && !IS_RETAIN_MEM_VALID())) { + /* + If cal is 0, then this is the first power-up. Cal is keeping valid + after reboot and deepsleep. If s_rtc_timer_retain_mem is invalid, it means + that something unexpected happened (the structure was moved around + after OTA update). To keep the system time valid even after OTA we + reset the s_rtc_timer_retain_mem. But the resetting can also lead to some + drift of the system time, because only the last current calibration + value will be applied to all rtc ticks. To mitigate this effect you + might need updating of the system time (via SNTP). + */ + memset(&s_rtc_timer_retain_mem, 0, sizeof(retain_mem_t)); } + first_call = false; const uint64_t rtc_this_ticks = rtc_time_get(); - const uint64_t ticks = rtc_this_ticks - s_rtc_last_ticks; + const uint64_t ticks = rtc_this_ticks - s_rtc_timer_retain_mem.rtc_last_ticks; #else const uint64_t ticks = rtc_time_get(); #endif @@ -119,11 +152,13 @@ uint64_t esp_rtc_get_time_us(void) const uint64_t ticks_high = ticks >> 32; const uint64_t delta_time_us = ((ticks_low * cal) >> RTC_CLK_CAL_FRACT) + ((ticks_high * cal) << (32 - RTC_CLK_CAL_FRACT)); -#if SOC_RTC_FAST_MEM_SUPPORTED - s_esp_rtc_time_us += delta_time_us; - s_rtc_last_ticks = rtc_this_ticks; +#if SOC_RTC_MEM_SUPPORTED + s_rtc_timer_retain_mem.rtc_time_us += delta_time_us; + s_rtc_timer_retain_mem.rtc_last_ticks = rtc_this_ticks; + s_rtc_timer_retain_mem.checksum = calc_checksum(); + uint64_t esp_rtc_time_us = s_rtc_timer_retain_mem.rtc_time_us; portEXIT_CRITICAL_SAFE(&s_esp_rtc_time_lock); - return s_esp_rtc_time_us; + return esp_rtc_time_us; #else uint64_t esp_rtc_time_us = delta_time_us + clk_ll_rtc_slow_load_rtc_fix_us(); portEXIT_CRITICAL_SAFE(&s_esp_rtc_time_lock); @@ -137,7 +172,7 @@ void esp_clk_slowclk_cal_set(uint32_t new_cal) /* To force monotonic time values even when clock calibration value changes, * we adjust esp_rtc_time */ -#if SOC_RTC_FAST_MEM_SUPPORTED +#if SOC_RTC_MEM_SUPPORTED esp_rtc_get_time_us(); #else portENTER_CRITICAL_SAFE(&s_esp_rtc_time_lock); @@ -164,7 +199,7 @@ void esp_clk_slowclk_cal_set(uint32_t new_cal) clk_ll_rtc_slow_store_rtc_fix_us(new_fix_us); } portEXIT_CRITICAL_SAFE(&s_esp_rtc_time_lock); -#endif // SOC_RTC_FAST_MEM_SUPPORTED +#endif // SOC_RTC_MEM_SUPPORTED #endif // CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER clk_ll_rtc_slow_store_cal(new_cal); } diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 54a24c411c..4d0c0089f1 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1365,12 +1365,12 @@ static uint32_t get_power_down_flags(void) #if SOC_PM_SUPPORT_RTC_SLOW_MEM_PD && SOC_ULP_SUPPORTED // Labels are defined in the linker script - extern int _rtc_slow_length; + extern int _rtc_slow_length, _rtc_reserved_length; /** * Compiler considers "(size_t) &_rtc_slow_length > 0" to always be true. * So use a volatile variable to prevent compiler from doing this optimization. */ - volatile size_t rtc_slow_mem_used = (size_t)&_rtc_slow_length; + volatile size_t rtc_slow_mem_used = (size_t)&_rtc_slow_length + (size_t)&_rtc_reserved_length; if ((s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] == ESP_PD_OPTION_AUTO) && (rtc_slow_mem_used > 0 || (s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) { diff --git a/components/esp_system/ld/esp32/memory.ld.in b/components/esp_system/ld/esp32/memory.ld.in index 4fe39c7843..6660a28dd4 100644 --- a/components/esp_system/ld/esp32/memory.ld.in +++ b/components/esp_system/ld/esp32/memory.ld.in @@ -27,14 +27,6 @@ #define CONFIG_BTDM_RESERVE_DRAM 0 #endif -#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC -#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) -#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) -#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE) -#else -#define ESP_BOOTLOADER_RESERVE_RTC 0 -#endif - #if defined(CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE) ASSERT((CONFIG_ESP32_FIXED_STATIC_RAM_SIZE <= 0x2c200), @@ -89,24 +81,39 @@ MEMORY /* (See iram0_2_seg for meaning of 0x20 offset in the above.) */ #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS - /* RTC fast memory (executable). Persists over deep sleep. - */ + /* RTC fast memory (executable). Persists over deep sleep. */ rtc_iram_seg(RWX) : org = 0x400C0000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC - /* RTC fast memory (same block as above), viewed from data bus */ + /* RTC fast memory (same block as above, rtc_iram_seg), viewed from data bus */ rtc_data_seg(RW) : org = 0x3ff80000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC + /* We reduced the size of rtc_iram_seg and rtc_data_seg by ESP_BOOTLOADER_RESERVE_RTC value. + It reserves the amount of RTC fast memory that we use for this memory segment. + This segment is intended for keeping bootloader rtc data (s_bootloader_retain_mem, when a Kconfig option is on). + The aim of this is to keep data that will not be moved around and have a fixed address. + org = 0x3ff80000 + 0x2000 - ESP_BOOTLOADER_RESERVE_RTC == SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t) + */ + rtc_fast_reserved_seg(RW) : org = 0x3ff80000 + 0x2000 - ESP_BOOTLOADER_RESERVE_RTC, len = ESP_BOOTLOADER_RESERVE_RTC + /* RTC slow memory (data accessible). Persists over deep sleep. Start of RTC slow memory is reserved for ULP co-processor code + data, if enabled. */ #if CONFIG_ULP_COPROC_ENABLED rtc_slow_seg(RW) : org = 0x50000000 + CONFIG_ULP_COPROC_RESERVE_MEM, - len = 0x2000 - CONFIG_ULP_COPROC_RESERVE_MEM + len = 0x2000 - CONFIG_ULP_COPROC_RESERVE_MEM - RESERVE_RTC_MEM #else - rtc_slow_seg(RW) : org = 0x50000000, len = 0x2000 + rtc_slow_seg(RW) : org = 0x50000000, len = 0x2000 - RESERVE_RTC_MEM #endif // CONFIG_ULP_COPROC_ENABLED + /* We reduced the size of rtc_slow_seg by RESERVE_RTC_MEM value. + It reserves the amount of RTC slow memory that we use for this memory segment. + This segment is intended for keeping rtc timer data (s_rtc_timer_retain_mem, see esp_clk.c files). + The aim of this is to keep data that will not be moved around and have a fixed address. + org = 0x50000000 + 0x2000 - RESERVE_RTC_MEM + */ + rtc_slow_reserved_seg(RW) : org = 0x50000000 + 0x2000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM + /* external memory */ extern_ram_seg(RWX) : org = 0x3F800000, len = 0x400000 diff --git a/components/esp_system/ld/esp32/sections.ld.in b/components/esp_system/ld/esp32/sections.ld.in index 9d0c8653a0..6d04e1052b 100644 --- a/components/esp_system/ld/esp32/sections.ld.in +++ b/components/esp_system/ld/esp32/sections.ld.in @@ -109,6 +109,46 @@ SECTIONS _rtc_force_slow_end = ABSOLUTE(.); } > rtc_slow_seg + /** + * This section holds RTC FAST data that should have fixed addresses. + * The data are not initialized at power-up and are retained during deep sleep. + */ + .rtc_fast_reserved (NOLOAD): + { + . = ALIGN(4); + _rtc_fast_reserved_start = ABSOLUTE(.); + /* New data can only be added here to ensure existing data are not moved. + Because data have adhered to the end of the segment and code is relied on it. + >> put new data here << */ + KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_fast_reserved_end = ABSOLUTE(.); + } > rtc_fast_reserved_seg + + _rtc_fast_reserved_length = _rtc_fast_reserved_end - _rtc_fast_reserved_start; + ASSERT((_rtc_fast_reserved_length <= LENGTH(rtc_fast_reserved_seg)), + "RTC FAST reserved segment data does not fit.") + + /** + * This section holds RTC SLOW data that should have fixed addresses. + * The data are not initialized at power-up and are retained during deep sleep. + */ + .rtc_slow_reserved (NOLOAD): + { + . = ALIGN(4); + _rtc_slow_reserved_start = ABSOLUTE(.); + /* New data can only be added here to ensure existing data are not moved. + Because data have adhered to the end of the segment and code is relied on it. + >> put new data here << */ + + *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) + _rtc_slow_reserved_end = ABSOLUTE(.); + } > rtc_slow_reserved_seg + + _rtc_slow_reserved_length = _rtc_slow_reserved_end - _rtc_slow_reserved_start; + _rtc_reserved_length = _rtc_slow_reserved_length; + ASSERT((_rtc_slow_reserved_length <= LENGTH(rtc_slow_reserved_seg)), + "RTC SLOW reserved segment data does not fit.") + /* Get size of rtc slow data based on rtc_data_location alias */ _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) ? (_rtc_force_slow_end - _rtc_data_start) diff --git a/components/esp_system/ld/esp32c3/memory.ld.in b/components/esp_system/ld/esp32c3/memory.ld.in index aa8aabd5f8..4c62313833 100644 --- a/components/esp_system/ld/esp32c3/memory.ld.in +++ b/components/esp_system/ld/esp32c3/memory.ld.in @@ -15,14 +15,6 @@ #include "sdkconfig.h" #include "ld.common" -#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC -#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) -#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) -#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE) -#else -#define ESP_BOOTLOADER_RESERVE_RTC 0 -#endif - /** * physical memory is mapped twice to the vritual address (IRAM and DRAM). * `I_D_SRAM_OFFSET` is the offset between the two locations of the same physical memory @@ -80,7 +72,16 @@ MEMORY /** * RTC fast memory (executable). Persists over deep sleep. */ - rtc_iram_seg(RWX) : org = 0x50000000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC + rtc_iram_seg(RWX) : org = 0x50000000, len = 0x2000 - RESERVE_RTC_MEM + + /* We reduced the size of rtc_iram_seg by RESERVE_RTC_MEM value. + It reserves the amount of RTC fast memory that we use for this memory segment. + This segment is intended for keeping: + - (lower addr) rtc timer data (s_rtc_timer_retain_mem, see esp_clk.c files). + - (higher addr) bootloader rtc data (s_bootloader_retain_mem, when a Kconfig option is on). + The aim of this is to keep data that will not be moved around and have a fixed address. + */ + rtc_reserved_seg(RW) : org = 0x50000000 + 0x2000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM } /* Heap ends at top of dram0_0_seg */ diff --git a/components/esp_system/ld/esp32c3/sections.ld.in b/components/esp_system/ld/esp32c3/sections.ld.in index ac7ab6cfb8..596e23cb98 100644 --- a/components/esp_system/ld/esp32c3/sections.ld.in +++ b/components/esp_system/ld/esp32c3/sections.ld.in @@ -104,6 +104,27 @@ SECTIONS _rtc_force_slow_end = ABSOLUTE(.); } > rtc_slow_seg + /** + * This section holds RTC data that should have fixed addresses. + * The data are not initialized at power-up and are retained during deep sleep. + */ + .rtc_reserved (NOLOAD): + { + . = ALIGN(4); + _rtc_reserved_start = ABSOLUTE(.); + /* New data can only be added here to ensure existing data are not moved. + Because data have adhered to the end of the segment and code is relied on it. + >> put new data here << */ + + *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) + KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); + } > rtc_reserved_seg + + _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; + ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), + "RTC reserved segment data does not fit.") + /* Get size of rtc slow data based on rtc_data_location alias */ _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) ? (_rtc_force_slow_end - _rtc_data_start) diff --git a/components/esp_system/ld/esp32h2/memory.ld.in b/components/esp_system/ld/esp32h2/memory.ld.in index 03f45cabd9..17180bec39 100644 --- a/components/esp_system/ld/esp32h2/memory.ld.in +++ b/components/esp_system/ld/esp32h2/memory.ld.in @@ -15,14 +15,6 @@ #include "sdkconfig.h" #include "ld.common" -#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC -#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) -#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) -#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE) -#else -#define ESP_BOOTLOADER_RESERVE_RTC 0 -#endif - #define SRAM_IRAM_START 0x4037C000 #define SRAM_DRAM_START 0x3FC7C000 #define ICACHE_SIZE 0x4000 /* ICache size is fixed to 16KB on ESP32-C3 */ @@ -80,7 +72,16 @@ MEMORY /** * RTC fast memory (executable). Persists over deep sleep. */ - rtc_iram_seg(RWX) : org = 0x50000000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC + rtc_iram_seg(RWX) : org = 0x50000000, len = 0x2000 - RESERVE_RTC_MEM + + /* We reduced the size of lp_ram_seg by RESERVE_RTC_MEM value. + It reserves the amount of LP memory that we use for this memory segment. + This segment is intended for keeping: + - (lower addr) rtc timer data (s_rtc_timer_retain_mem, see esp_clk.c files). + - (higher addr) bootloader rtc data (s_bootloader_retain_mem, when a Kconfig option is on). + The aim of this is to keep data that will not be moved around and have a fixed address. + */ + rtc_reserved_seg(RW) : org = 0x50000000 + 0x2000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM } #if CONFIG_ESP32H2_USE_FIXED_STATIC_RAM_SIZE diff --git a/components/esp_system/ld/esp32h2/sections.ld.in b/components/esp_system/ld/esp32h2/sections.ld.in index de6dcbaf08..d295464e7a 100644 --- a/components/esp_system/ld/esp32h2/sections.ld.in +++ b/components/esp_system/ld/esp32h2/sections.ld.in @@ -107,6 +107,27 @@ SECTIONS _rtc_force_slow_end = ABSOLUTE(.); } > rtc_slow_seg + /** + * This section holds RTC data that should have fixed addresses. + * The data are not initialized at power-up and are retained during deep sleep. + */ + .rtc_reserved (NOLOAD): + { + . = ALIGN(4); + _rtc_reserved_start = ABSOLUTE(.); + /* New data can only be added here to ensure existing data are not moved. + Because data have adhered to the end of the segment and code is relied on it. + >> put new data here << */ + + *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) + KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); + } > rtc_reserved_seg + + _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; + ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), + "RTC reserved segment data does not fit.") + /* Get size of rtc slow data based on rtc_data_location alias */ _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) ? (_rtc_force_slow_end - _rtc_data_start) diff --git a/components/esp_system/ld/esp32s2/memory.ld.in b/components/esp_system/ld/esp32s2/memory.ld.in index 3297c8e3c8..ecf5446159 100644 --- a/components/esp_system/ld/esp32s2/memory.ld.in +++ b/components/esp_system/ld/esp32s2/memory.ld.in @@ -15,14 +15,6 @@ #include "sdkconfig.h" #include "ld.common" -#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC -#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) -#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) -#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE) -#else -#define ESP_BOOTLOADER_RESERVE_RTC 0 -#endif - #ifdef CONFIG_ESP32S2_INSTRUCTION_CACHE_8KB #define CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE 0x2000 #else @@ -92,7 +84,7 @@ MEMORY /* RTC fast memory (executable). Persists over deep sleep. */ - rtc_iram_seg(RWX) : org = 0x40070000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC + rtc_iram_seg(RWX) : org = 0x40070000, len = 0x2000 - RESERVE_RTC_MEM /* RTC slow memory (data accessible). Persists over deep sleep. @@ -105,8 +97,17 @@ MEMORY rtc_slow_seg(RW) : org = 0x50000000, len = 0x2000 #endif // CONFIG_ULP_COPROC_ENABLED - /* RTC fast memory (same block as above), viewed from data bus */ - rtc_data_seg(RW) : org = 0x3ff9e000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC + /* RTC fast memory (same block as above, rtc_iram_seg), viewed from data bus */ + rtc_data_seg(RW) : org = 0x3ff9e000, len = 0x2000 - RESERVE_RTC_MEM + + /* We reduced the size of rtc_data_seg and rtc_iram_seg by RESERVE_RTC_MEM value. + It reserves the amount of RTC fast memory that we use for this memory segment. + This segment is intended for keeping: + - (lower addr) rtc timer data (s_rtc_timer_retain_mem, see esp_clk.c files). + - (higher addr) bootloader rtc data (s_bootloader_retain_mem, when a Kconfig option is on). + The aim of this is to keep data that will not be moved around and have a fixed address. + */ + rtc_reserved_seg(RW) : org = 0x3ff9e000 + 0x2000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM /* external memory, covers the dport, dram0, dram1 cacheable address space */ extern_ram_seg(RWX) : org = 0x3F800000, diff --git a/components/esp_system/ld/esp32s2/sections.ld.in b/components/esp_system/ld/esp32s2/sections.ld.in index 5498d83c6a..661b5c9aea 100644 --- a/components/esp_system/ld/esp32s2/sections.ld.in +++ b/components/esp_system/ld/esp32s2/sections.ld.in @@ -116,6 +116,27 @@ SECTIONS _rtc_force_slow_end = ABSOLUTE(.); } > rtc_slow_seg + /** + * This section holds RTC data that should have fixed addresses. + * The data are not initialized at power-up and are retained during deep sleep. + */ + .rtc_reserved (NOLOAD): + { + . = ALIGN(4); + _rtc_reserved_start = ABSOLUTE(.); + /* New data can only be added here to ensure existing data are not moved. + Because data have adhered to the end of the segment and code is relied on it. + >> put new data here << */ + + *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) + KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); + } > rtc_reserved_seg + + _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; + ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), + "RTC reserved segment data does not fit.") + /* Get size of rtc slow data based on rtc_data_location alias */ _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) ? (_rtc_force_slow_end - _rtc_data_start) diff --git a/components/esp_system/ld/esp32s3/memory.ld.in b/components/esp_system/ld/esp32s3/memory.ld.in index 5435434763..64d6c465f0 100644 --- a/components/esp_system/ld/esp32s3/memory.ld.in +++ b/components/esp_system/ld/esp32s3/memory.ld.in @@ -14,14 +14,6 @@ #include "sdkconfig.h" #include "ld.common" -#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC -#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) -#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) -#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE) -#else -#define ESP_BOOTLOADER_RESERVE_RTC 0 -#endif - /* * 40370000 <- IRAM/Icache -> 40378000 <- D/IRAM (I) -> 403E0000 * 3FC88000 <- D/IRAM (D) -> 3FCF0000 <- DRAM/DCache -> 3FD00000 @@ -98,7 +90,16 @@ MEMORY /** * RTC fast memory (executable). Persists over deep sleep. */ - rtc_iram_seg(RWX) : org = 0x600fe000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC + rtc_iram_seg(RWX) : org = 0x600fe000, len = 0x2000 - RESERVE_RTC_MEM + + /* We reduced the size of rtc_iram_seg by RESERVE_RTC_MEM value. + It reserves the amount of RTC fast memory that we use for this memory segment. + This segment is intended for keeping: + - (lower addr) rtc timer data (s_rtc_timer_retain_mem, see esp_clk.c files). + - (higher addr) bootloader rtc data (s_bootloader_retain_mem, when a Kconfig option is on). + The aim of this is to keep data that will not be moved around and have a fixed address. + */ + rtc_reserved_seg(RW) : org = 0x600fe000 + 0x2000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM /** * RTC slow memory (data accessible). Persists over deep sleep. diff --git a/components/esp_system/ld/esp32s3/sections.ld.in b/components/esp_system/ld/esp32s3/sections.ld.in index e16f8fc108..7e3c9cb843 100644 --- a/components/esp_system/ld/esp32s3/sections.ld.in +++ b/components/esp_system/ld/esp32s3/sections.ld.in @@ -111,6 +111,27 @@ SECTIONS _rtc_force_slow_end = ABSOLUTE(.); } > rtc_slow_seg + /** + * This section holds RTC data that should have fixed addresses. + * The data are not initialized at power-up and are retained during deep sleep. + */ + .rtc_reserved (NOLOAD): + { + . = ALIGN(4); + _rtc_reserved_start = ABSOLUTE(.); + /* New data can only be added here to ensure existing data are not moved. + Because data have adhered to the end of the segment and code is relied on it. + >> put new data here << */ + + *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) + KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); + } > rtc_reserved_seg + + _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; + ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), + "RTC reserved segment data does not fit.") + /* Get size of rtc slow data based on rtc_data_location alias */ _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) ? (_rtc_force_slow_end - _rtc_data_start) diff --git a/components/esp_system/ld/ld.common b/components/esp_system/ld/ld.common index 26607f9263..7f8d0f3a58 100644 --- a/components/esp_system/ld/ld.common +++ b/components/esp_system/ld/ld.common @@ -24,3 +24,20 @@ _esp_memprot_align_size = 0; #endif _esp_mmu_block_size = (CONFIG_MMU_PAGE_SIZE); + +#if CONFIG_SOC_RTC_MEM_SUPPORTED + #if CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC + #define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) + #else + #define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE) + #endif // not CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC + + /* rtc timer data (s_rtc_timer_retain_mem, see esp_clk.c files). For rtc_timer_data_in_rtc_mem section. */ + #define RTC_TIMER_RESERVE_RTC (24) + + #if CONFIG_IDF_TARGET_ESP32 + #define RESERVE_RTC_MEM (RTC_TIMER_RESERVE_RTC) + #else + #define RESERVE_RTC_MEM (ESP_BOOTLOADER_RESERVE_RTC + RTC_TIMER_RESERVE_RTC) + #endif +#endif // SOC_RTC_MEM_SUPPORTED diff --git a/components/heap/port/esp32/memory_layout.c b/components/heap/port/esp32/memory_layout.c index 378273523d..92b23be518 100644 --- a/components/heap/port/esp32/memory_layout.c +++ b/components/heap/port/esp32/memory_layout.c @@ -173,6 +173,9 @@ SOC_RESERVE_MEMORY_REGION(SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_HIGH, spi_ram); #endif extern int _data_start, _heap_start, _iram_start, _iram_end, _rtc_force_fast_end, _rtc_noinit_end; +extern int _rtc_fast_reserved_start, _rtc_fast_reserved_end; +extern int _rtc_slow_reserved_start, _rtc_slow_reserved_end; + // Static data region. DRAM used by data+bss and possibly rodata SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start, dram_data); @@ -188,3 +191,6 @@ SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_noinit_end, rtcram_d SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_fast_end, rtcram_data); #endif #endif + +SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_fast_reserved_start, (intptr_t)&_rtc_fast_reserved_end, rtc_fast_reserved_data); +SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_slow_reserved_start, (intptr_t)&_rtc_slow_reserved_end, rtc_reserved_data); diff --git a/components/heap/port/esp32c3/memory_layout.c b/components/heap/port/esp32c3/memory_layout.c index 2cad273fe9..351f7fcbee 100644 --- a/components/heap/port/esp32c3/memory_layout.c +++ b/components/heap/port/esp32c3/memory_layout.c @@ -77,7 +77,7 @@ const soc_memory_region_t soc_memory_regions[] = { { 0x3FCC0000, (APP_USABLE_DRAM_END-0x3FCC0000), SOC_MEMORY_TYPE_DEFAULT, 0x403C0000}, //D/IRAM level3, can be used as trace memory { APP_USABLE_DRAM_END, (SOC_DIRAM_DRAM_HIGH-APP_USABLE_DRAM_END), SOC_MEMORY_TYPE_STACK_DEFAULT, MAP_DRAM_TO_IRAM(APP_USABLE_DRAM_END)}, //D/IRAM level3, can be used as trace memory (ROM reserved area) #ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP - { 0x50000000, 0x2000, SOC_MEMORY_TYPE_RTCRAM, 0}, //Fast RTC memory + { 0x50000000, 0x2000, SOC_MEMORY_TYPE_RTCRAM, 0}, //Fast RTC memory #endif }; @@ -85,6 +85,7 @@ const size_t soc_memory_region_count = sizeof(soc_memory_regions) / sizeof(soc_m extern int _data_start, _heap_start, _iram_start, _iram_end, _rtc_force_slow_end; +extern int _rtc_reserved_start, _rtc_reserved_end; /** * Reserved memory regions. @@ -106,3 +107,5 @@ SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start - I_D_OFFSET, (intptr_t)&_iram_ */ SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_slow_end, rtcram_data); #endif + +SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_reserved_start, (intptr_t)&_rtc_reserved_end, rtc_reserved_data); diff --git a/components/heap/port/esp32h2/memory_layout.c b/components/heap/port/esp32h2/memory_layout.c index e4d76aeafd..693284ce67 100644 --- a/components/heap/port/esp32h2/memory_layout.c +++ b/components/heap/port/esp32h2/memory_layout.c @@ -84,6 +84,7 @@ const size_t soc_memory_region_count = sizeof(soc_memory_regions) / sizeof(soc_m extern int _data_start, _heap_start, _iram_start, _iram_end, _rtc_force_slow_end; +extern int _rtc_reserved_start, _rtc_reserved_end; /** * Reserved memory regions. @@ -105,3 +106,5 @@ SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start - I_D_OFFSET, (intptr_t)&_iram_ */ SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_slow_end, rtcram_data); #endif + +SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_reserved_start, (intptr_t)&_rtc_reserved_end, rtc_reserved_data); diff --git a/components/heap/port/esp32s2/memory_layout.c b/components/heap/port/esp32s2/memory_layout.c index 3d003e33cf..cddc4e2dba 100644 --- a/components/heap/port/esp32s2/memory_layout.c +++ b/components/heap/port/esp32s2/memory_layout.c @@ -113,6 +113,7 @@ const size_t soc_memory_region_count = sizeof(soc_memory_regions)/sizeof(soc_mem extern int _dram0_rtos_reserved_start; extern int _data_start, _heap_start, _iram_start, _iram_end, _rtc_force_fast_end, _rtc_noinit_end; +extern int _rtc_reserved_start, _rtc_reserved_end; /* Reserved memory regions @@ -149,3 +150,5 @@ SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_noinit_end, rtcram_d SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_fast_end, rtcram_data); #endif #endif + +SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_reserved_start, (intptr_t)&_rtc_reserved_end, rtc_reserved_data); diff --git a/components/heap/port/esp32s3/memory_layout.c b/components/heap/port/esp32s3/memory_layout.c index 3566c70f2f..3932661aa6 100644 --- a/components/heap/port/esp32s3/memory_layout.c +++ b/components/heap/port/esp32s3/memory_layout.c @@ -111,6 +111,7 @@ const soc_memory_region_t soc_memory_regions[] = { const size_t soc_memory_region_count = sizeof(soc_memory_regions) / sizeof(soc_memory_region_t); extern int _data_start, _heap_start, _iram_start, _iram_end, _rtc_force_fast_end, _rtc_noinit_end; // defined in sections.ld.in +extern int _rtc_reserved_start, _rtc_reserved_end; /** * Reserved memory regions. @@ -150,3 +151,5 @@ SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_noinit_end, rtcram_d SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_fast_end, rtcram_data); #endif #endif + +SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_reserved_start, (intptr_t)&_rtc_reserved_end, rtc_reserved_data);