You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RTC_NOINIT_ATTR与RTC_DATA_ATTR区别及深睡场景选型咨询

ESP32 RTC_NOINIT_ATTR 与 RTC_DATA_ATTR 差异及选型建议

核心差异

两者均用于将变量存入深度睡眠期间持续供电的RTC内存,核心区别在于系统启动/唤醒时的初始化逻辑和内存区域:

  • RTC_DATA_ATTR:
    • 分配在快速RTC内存(RTC FAST MEM),CPU访问速度快,容量约8KB
    • 冷启动(断电重启)时会执行变量初始化(如定义时的赋值);深度睡眠唤醒时跳过初始化,保留内存原有值
  • RTC_NOINIT_ATTR:
    • 分配在慢速RTC内存(RTC SLOW MEM),CPU访问速度较慢,容量约32KB
    • 任何启动场景(冷启动、深度睡眠唤醒)都不会执行变量初始化,内存值完全保留原始状态(冷启动时为随机值,深度睡眠唤醒时为上次睡眠前的值)

具体代码示例

1. RTC_DATA_ATTR 示例

#include "esp_system.h"
#include "esp_sleep.h"

// 快速RTC内存中的计数器
RTC_DATA_ATTR int wakeup_count = 0;

void app_main() {
    wakeup_count++;
    printf("唤醒次数:%d\n", wakeup_count);

    // 定时器深度睡眠,5秒后唤醒
    esp_sleep_enable_timer_wakeup(5000000);
    esp_deep_sleep_start();
}

运行逻辑:

  • 首次冷启动:wakeup_count被初始化为0,自增后打印1
  • 深度睡眠唤醒:系统跳过初始化,wakeup_count保留上次值,自增后依次打印2、3...
  • 断电重启(冷启动):wakeup_count重新初始化为0,计数重置

2. RTC_NOINIT_ATTR 示例

#include "esp_system.h"
#include "esp_sleep.h"

// 慢速RTC内存中的计数器,无系统初始化
RTC_NOINIT_ATTR int wakeup_count;

// 示例结构体
typedef struct {
    int temp;
    int wake_times;
    char status[16];
} SleepRecord;
RTC_NOINIT_ATTR SleepRecord record;

void app_main() {
    esp_sleep_wakeup_cause_t wake_cause = esp_sleep_get_wakeup_cause();
    // 冷启动时手动初始化变量和结构体
    if (wake_cause == ESP_SLEEP_WAKEUP_UNDEFINED) {
        wakeup_count = 0;
        record.temp = 25;
        record.wake_times = 0;
        snprintf(record.status, sizeof(record.status), "initialized");
    }

    wakeup_count++;
    record.wake_times++;
    snprintf(record.status, sizeof(record.status), "awake");
    printf("唤醒次数:%d | 记录结构体:temp=%d, wake_times=%d, status=%s\n", 
           wakeup_count, record.temp, record.wake_times, record.status);

    // 支持定时器/外部事件/WDT任意唤醒方式
    esp_sleep_enable_timer_wakeup(5000000);
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_0, 1); // 外部引脚唤醒示例
    esp_deep_sleep_start();
}

运行逻辑:

  • 首次冷启动:通过唤醒原因判断后手动初始化变量和结构体,打印初始化后的状态
  • 任意方式深度睡眠唤醒:变量和结构体完全保留上次值,更新后打印新状态
  • 断电重启:需重新手动初始化,否则变量和结构体为随机值

针对你的需求选型:选 RTC_NOINIT_ATTR

你的需求是结构体存入RTC内存后,深度睡眠无论哪种唤醒方式都能读取原有值,选择RTC_NOINIT_ATTR的原因:

  1. 无系统初始化干扰:无论定时器、外部事件还是WDT唤醒,系统都不会触碰该内存区域,确保结构体值100%保留睡眠前的状态
  2. 内存容量更充足:慢速RTC内存容量更大,适合存储结构体这类可能占用较多空间的数据
  3. 兼容性更强:不会因ESP-IDF版本的隐性初始化逻辑变更导致值被意外覆盖

唯一需要注意的是:冷启动时该结构体为随机值,需通过esp_sleep_get_wakeup_cause()判断首次启动,手动完成结构体的初始化。

内容的提问来源于stack exchange,提问作者user14665305

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:13:17