Search code examples
esp32arduino-esp32sleep-mode

RTC_NOINIT_ATTR vs RTC_DATA_ATTR (slow vs fast memory)


I am trying to understand the difference between RTC_NOINIT_ATTR vs RTC_DATA_ATTR (slow vs fast memory) but cannot see a clear definition and examples when to use which - not even on the original espressif websites: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/memory-types.html

Can anyone clarify it using concrete examples?

In my case, I need to store a struct into RTC memory before going to deep sleep and the same struct values should be available after waking up (regardless whether it was based on the timers or external events or WDT). Which one shall I use RTC_NOINIT_ATTR or RTC_DATA_ATTR and why?


Solution

  • I think the documentation on that page is a bit misleading/incomplete. It needs to be read in conjunction with the the page about deep sleep stubs and even then, that seems to disagree with what the SDK source file espattr.h, where these prefixes are defined, says about them.

    Let's look at the available prefixes for targeting RTC memory, and what the sources and the docs say:

    Prefix espattr.h says Documentation says
    RTC_DATA_ATTR Slow Fast or Slow depending on menuconfig options CONFIG_ESP32_RTCDATA_IN_FAST_MEM and CONFIG_FREERTOS_UNICORE. Default is Slow.
    RTC_FAST_ATTR Fast Fast
    RTC_IRAM_ATTR Fast Fast (used for Wake Stub functions, not variables)
    RTC_NOINIT_ATTR Slow Slow
    RTC_RODATA_ATTR Doesn't say, just "RTC" Same as RTC_DATA_ATTR (but readonly)
    RTC_SLOW_ATTR Slow Slow

    All of these will keep their previous values across a normal deep sleep / wake cycle. What is additional with NOINIT compared to SLOW or DATA, is that it is not initialised at cold boot. Whether that means it can keep its value across a Watchdog restart or crash (or even a restart after firmware upgrade), I'm not sure - you can do those experiments if that's what you really need.

    Personally I think it's better for everything to be reset when a watchdog reset or crash happens, because it seems safer to start with a clean slate. Otherwise, you would need some sort of check that the data is valid, as the lack of initialisation even at inital powerup means there's a good chance you'll be reading garbage.

    If you really want to ensure data is kept in all possible scenarios, I'd say you should be saving it to flash or external battery-backed SRAM (such as found in some RTCs like the DS1307 and DS3232), and restoring it from there on a cold boot.

    These are the specific rules:

    • A Deep Sleep Wake Stub uses RTC Fast Memory (but can access variables in RTC Slow Memory)

    • The ULP can only access RTC Slow Memory - its code and data must be in there.

    • RTC Fast memory is only accessible to the "PRO" core (#0), so on a dual-core ESP32 any FreeRTOS tasks running on the "APP" core (#1) cannot use it. This means if you are using the Arduino framework where the main code runs on the APP core, you can really only use Slow (except for Wake Stubs) and RTC_DATA_ATTR works fine for that.