Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RTC memory is not automatically powered down, manual toggle is difficult (IDFGH-11098) #12270

Closed
3 tasks done
0ttoman opened this issue Sep 19, 2023 · 7 comments
Closed
3 tasks done
Assignees
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally Type: Bug bugs in IDF

Comments

@0ttoman
Copy link

0ttoman commented Sep 19, 2023

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

IDF version.

(master) 3b748a6

Operating System used.

Linux

How did you build your project?

Command line with idf.py

If you are using Windows, please specify command line type.

None

Development Kit.

ESP32

Power Supply used.

USB

What is the expected behavior?

  • the esp can be configured so that ESP_PD_DOMAIN_RTC_SLOW_MEM and ESP_PD_DOMAIN_RTC_FAST_MEM are automatically disabled on deep sleep and the hibernation sleep mode is used
  • esp_sleep_pd_config() should work without panic when setting a domain to ESP_PD_OPTION_OFF without setting it to ESP_PD_OPTION_ON prior

What is the actual behavior?

Because of the reference counter introduced in the esp_sleep_pd_config function, to be able to set a domain to ESP_PD_OPTION_OFF, you now have to call esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON); before esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);. Is this anticipated? This behavior is also not documented.


When ESP_PD_DOMAIN_RTC_SLOW_MEM is left to Auto disable the function get_power_down_flags() sets ESP_PD_DOMAIN_RTC_SLOW_MEM to ESP_PD_OPTION_ON when _rtc_reserved_length > 0:

static uint32_t get_power_down_flags(void)
{
    // Where needed, convert AUTO options to ON. Later interpret AUTO as OFF.

    // RTC_SLOW_MEM is needed for the ULP, so keep RTC_SLOW_MEM powered up if ULP
    // is used and RTC_SLOW_MEM is Auto.
    // If there is any data placed into .rtc.data or .rtc.bss segments, and
    // RTC_SLOW_MEM is Auto, keep it powered up as well.

#if SOC_PM_SUPPORT_RTC_SLOW_MEM_PD && SOC_ULP_SUPPORTED
    // Labels are defined in the linker script
    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 + (size_t)&_rtc_reserved_length;
    if ((s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option == ESP_PD_OPTION_AUTO) &&
            (rtc_slow_mem_used > 0 || (s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) {
        s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option = ESP_PD_OPTION_ON;
    }
#endif

The value is referenced in esp/section.ld.in:

  .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;

esp_clk.c always declares a 24 byte struct, stored to .rtc_timer_data_in_rtc_mem

#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;

With this, _rtc_reserved_length is 24 and ESP_PD_DOMAIN_RTC_SLOW_MEM will always be powered on.

With SOC_PM_SUPPORT_RTC_FAST_MEM_PD true for my esp32,
ESP_PD_DOMAIN_RTC_FAST_MEM will always be set from ESP_PD_OPTION_AUTO to ESP_PD_OPTION_ON.

#if SOC_PM_SUPPORT_RTC_FAST_MEM_PD
#if !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
    /* RTC_FAST_MEM is needed for deep sleep stub.
       If RTC_FAST_MEM is Auto, keep it powered on, so that deep sleep stub can run.
       In the new chip revision, deep sleep stub will be optional, and this can be changed. */
    if (s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option == ESP_PD_OPTION_AUTO) {
        s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option = ESP_PD_OPTION_ON;
    }
#else
    /* If RTC_FAST_MEM is used for heap, force RTC_FAST_MEM to be powered on. */
    s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option = ESP_PD_OPTION_ON;
#endif
#endif

Steps to reproduce.

  • deep_sleep example was used
  • ULP was deactivated through menuconfig
  • hibernation mode will never be used without setting ESP_PD_DOMAINs from Auto directly to Off
  • adding esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF); before esp_deep_sleep_start(); will crash the system.
    • using the following works:
    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON);
    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_ON);
    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
    esp_deep_sleep_start();
    

Debug Logs.

No response

More Information.

old related issue

@0ttoman 0ttoman added the Type: Bug bugs in IDF label Sep 19, 2023
@espressif-bot espressif-bot added the Status: Opened Issue is new label Sep 19, 2023
@github-actions github-actions bot changed the title RTC memory is not automatically powered down, manual toggle is difficult RTC memory is not automatically powered down, manual toggle is difficult (IDFGH-11098) Sep 19, 2023
@esp-wzh
Copy link
Collaborator

esp-wzh commented Sep 21, 2023

@0ttoman Thank you for your report, in the description you are very correct in all your reasoning about the occurrence of this problem.

These behaviors are expected, the structure retain_mem_t you mentioned that has been stored in RTC_MEM is mainly used to maintain the system's timer service, and the data in it is maintained during sleep or reset, making the system's time service unaffected by sleep and reset

Considering that the power consumption of rtc_mem is very small, less than 1.5uA, we think that the importance of system timer service is much more than that, so we prohibit rtc_mem from powering down by this mechanism.

But if this 1.5uA power consumption is really important to your project, there is still a way to bypass it, you can change SOC_RTC_MEM_SUPPORTED defined in esp-idf/components/soc/esp32/include/soc/soc_caps.h to 0 and refer to the implementation for esp32c2 to use the esp32's RTC_CNTL_STORE7_REG & RTC_CNTL_STORE7_REG as RTC_FIX_US_HIGH_REG & RTC_FIX_US_LOW_REG register to store the time info. Note this also means completely abandoning the deepsleep wake stub feature.

Regards.

@espressif-bot espressif-bot added Status: Reviewing Issue is being reviewed and removed Status: Opened Issue is new labels Sep 21, 2023
@kiss81
Copy link

kiss81 commented Oct 12, 2023

Can confirm this. This assert issue is the same for all the power domains in idf 5.1.1
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF);

@esp-wzh
Copy link
Collaborator

esp-wzh commented Oct 12, 2023

@kiss81 All power domains default to ESP_PD_OPTION_AUTO, in auto mode, the sleep process will automatically power down a power domain if it determines that no module is dependent on it, so there is no need for the user to manually specify that the power domain be turned off during sleep.

@esp-wzh
Copy link
Collaborator

esp-wzh commented Oct 17, 2023

@kiss81
Thanks for the report, we will clarify the limitations of using this interface in the API documentation soon.
You can close this issue if no more questions, thanks!

@espressif-bot espressif-bot added the Awaiting Response awaiting a response from the author label Mar 4, 2024
@Sherry616
Copy link
Collaborator

Hi @kiss81, do you still have this problem? Could you please share the latest update? Thanks.

@kiss81
Copy link

kiss81 commented Mar 4, 2024

Hi @kiss81, do you still have this problem? Could you please share the latest update? Thanks.
I do use the ESP_PD_OPTION_AUTO now, which works for me!

@espressif-bot espressif-bot added Status: Done Issue is done internally Resolution: Done Issue is done internally and removed Status: Reviewing Issue is being reviewed Awaiting Response awaiting a response from the author labels Mar 5, 2024
@Alvin1Zhang
Copy link
Collaborator

Thanks for sharing the updates, feel free to reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally Type: Bug bugs in IDF
Projects
None yet
Development

No branches or pull requests

6 participants