ESP32中RTC_NOINIT_ATTR修饰int变量出现未定义行为如何解决
ESP32 RTC_NOINIT_ATTR变量初始随机值解决方案
问题根因
RTC_NOINIT_ATTR标记的变量会被分配到RTC慢内存的.noinit段,系统启动流程会直接跳过该段的初始化操作,你代码中写的int counter2 = 0初始赋值会被编译器忽略,因此首次上电时该变量的值为RTC内存上电后的随机值,只有软重启(esp_restart()触发)、深睡唤醒等场景才会保留修改后的值。
可行解决方案
最常用且官方推荐的方案是添加魔术字校验逻辑,仅首次上电时初始化NOINIT变量,后续重启不会重写变量值,代码修改示例如下:
#include <Arduino.h> // 定义自定义魔术字,可随意替换为其他固定32位值 #define RTC_INIT_MAGIC 0xA5B6C7D8 RTC_DATA_ATTR int counter1 = 0; // 新增魔术字校验变量,同样用RTC_NOINIT_ATTR修饰 RTC_NOINIT_ATTR uint32_t rtc_check_magic; RTC_NOINIT_ATTR int counter2; void setup() { Serial.begin(115200); // 启动时先校验魔术字,不匹配则说明是首次上电,初始化NOINIT变量 if (rtc_check_magic != RTC_INIT_MAGIC) { rtc_check_magic = RTC_INIT_MAGIC; counter2 = 0; } Serial.printf("RTC programme running, counter1 = %d; counter2 = %d\n",counter1,counter2); delay(3000); counter1++; counter2++; esp_restart(); } void loop() { // 此处无需编写代码 }
方案说明
- 首次上电时RTC内存的
rtc_check_magic为随机值,和自定义魔术字不匹配,会自动把counter2初始化为0,同时把校验变量设置为正确的魔术字 - 后续所有软重启、深睡唤醒场景下,
rtc_check_magic的值会一直保留为正确的魔术字,不会再触发初始化逻辑,counter2的累加值会正常保留 - 该方案仅额外占用4字节RTC内存,逻辑简单无额外依赖,完全满足必须使用
RTC_NOINIT_ATTR的需求
内容的提问来源于stack exchange,提问作者R Spandit
相关产品推荐
相关产品推荐

