3、状态保存策略:保存哪些状态,如何最小化保存数据量

状态保存,说白了就是决定「什么东西要记住,什么东西可以扔掉」。

我刚开始做低功耗项目时,踩过一个坑:把所有寄存器一股脑全存了。结果呢?唤醒时间长了,功耗反而没降多少。后来才明白——存得少,才能醒得快。

3.1 三类核心状态:CPU寄存器、外设配置、内存上下文

我们把要保存的状态分成三大类。每一类的保存策略都不一样。

状态类别 典型内容 保存必要性 数据量级
CPU寄存器 PC、SP、通用寄存器、状态寄存器 必须保存,否则程序跑飞 几十字节
外设配置 GPIO模式、定时器参数、ADC配置、DMA描述符 按需保存,部分可重新初始化 几百字节到几KB
内存上下文 全局变量、堆栈数据、任务控制块 按需保存,可压缩或裁剪 几KB到几百KB

核心原则:能重新计算的,就别存。能硬件自动恢复的,就别手动存。

3.2 CPU寄存器:必须存,但可以挑着存

CPU寄存器是程序的「命根子」。不存?醒来后PC指针乱跳,系统直接崩溃。

但这里有个技巧——不是所有寄存器都需要保存。

  • PC和SP:必须存。这是程序恢复的锚点。
  • 通用寄存器(R0-R12):看情况。如果进入睡眠前已经压栈了,就不需要额外保存。
  • 状态寄存器(PSR):必须存。条件跳转全靠它。
  • 浮点寄存器:如果没用浮点运算,直接跳过。能省几十字节。

我的习惯:在进入睡眠前,先检查当前上下文。如果是在中断服务程序里进入睡眠,很多寄存器已经被硬件自动压栈了。这时候再手动保存一遍,就是浪费。

3.3 外设配置:能重配就别存

外设配置是状态保存的「大头」。一个UART的配置寄存器可能有十几个,全存下来要上百字节。

我做过一个项目,外设配置占了保存数据量的70%。后来怎么优化的?只保存「不可恢复」的部分。

  • GPIO状态:如果唤醒后需要保持输出电平,就存。否则,重新初始化。
  • 定时器计数值:如果定时器在睡眠期间继续运行,必须存。否则,清零重来。
  • DMA描述符:如果DMA正在传输,必须存。否则,重新配置。
  • ADC校准值:有些芯片的ADC校准值存在寄存器里,掉电就丢。这个必须存。

我曾经踩过的坑:某款MCU的RTC配置寄存器在深度睡眠时会复位。我以为它不会丢,结果唤醒后RTC时间全乱了。从那以后,我养成了一个习惯——看数据手册的「复位值」列。凡是复位后不是默认值的,都得存。

3.4 内存上下文:压缩、裁剪、延迟恢复

内存上下文是状态保存的「无底洞」。一个RTOS系统,任务栈、全局变量、堆数据加起来可能几十KB。

怎么最小化?三个思路:

  1. 压缩存储:用LZSS或RLE算法压缩。我试过,压缩比能达到3:1到5:1。代价是压缩/解压时间,但唤醒时间通常能接受。
  2. 裁剪无用数据:只保存「活跃」的内存页。比如,只保存当前任务栈,不保存空闲任务栈。
  3. 延迟恢复:先恢复关键数据(如任务控制块),非关键数据(如日志缓冲区)等系统跑起来后再慢慢恢复。

一个实用的经验值:对于大多数嵌入式系统,状态保存的目标是把数据量控制在1KB以内。超过这个量,唤醒时间就会明显变长。

3.5 状态保存的决策流程

说了这么多,到底怎么决定存什么、不存什么?我画了一张流程图,你看完就明白了。

状态保存决策流程图 进入睡眠准备 CPU寄存器:PC/SP/PSR必须存 外设配置:能重配就不存 内存上下文:压缩+裁剪+延迟 总数据量 < 1KB? 保存并进入睡眠 否 进一步裁剪/压缩 说明: • CPU寄存器:PC/SP/PSR必须存,通用寄存器按需存,浮点寄存器可跳过 • 外设配置:只存不可恢复的(如GPIO输出电平、DMA描述符) • 内存上下文:压缩(LZSS/RLE)+ 裁剪(只存活跃页)+ 延迟恢复

3.6 实战案例:一个BLE传感器的状态保存

说个具体的例子。我之前做的一个BLE温湿度传感器,电池供电,要求待机电流低于5μA。

状态保存清单是这样的:

状态项 是否保存 原因 数据量
CPU寄存器(PC/SP/PSR) 是 必须存 12字节
通用寄存器(R0-R12) 否 已由硬件自动压栈 0字节
BLE协议栈状态 是 连接信息不可恢复 256字节
传感器校准值 是 掉电丢失 8字节
定时器配置 否 唤醒后重新初始化 0字节
任务栈 是(压缩后) 保存当前任务上下文 512字节→180字节
日志缓冲区 否 延迟恢复 0字节

总数据量:12 + 256 + 8 + 180 = 456字节。远低于1KB的目标。

一个小技巧:我在这个项目里用了「差分保存」。每次只保存与上次不同的寄存器。比如,外设配置在初始化后基本不变,第一次保存后,后续只保存变化的部分。这样平均数据量又降了30%。

3.7 总结:状态保存的「三要三不要」

  • 要:保存CPU关键寄存器(PC/SP/PSR)
  • 要:保存不可恢复的外设状态(如DMA描述符、校准值)
  • 要:对内存上下文做压缩和裁剪
  • 不要:保存可以重新初始化的外设配置
  • 不要:保存已经由硬件自动保存的数据
  • 不要:保存非关键数据(如日志、调试信息)

嗯,状态保存策略就这些。说白了就是一句话:能不存就不存,非存不可就压缩。