3. 能量模式与功耗状态机

Silicon Labs 的 EFM32 / EFR32 系列把功耗管理抽象成一套硬件状态机,称为 Energy Mode(能量模式),从 EM0 到 EM4。理解这套状态机的关键不是记住“哪个模式最省电”,而是搞清楚三件事:进入条件(谁触发、需要满足什么)、保持与丢失(哪些资源还活着、哪些被切断)、退出条件(谁能把它唤醒、唤醒后从哪里继续执行)。这三件事决定了低功耗设计能不能真正落地。

一、五个能量模式的本质差异

EM0 是运行态,CPU 全速执行,所有外设时钟可用,功耗最高(典型几十到上百 µA/MHz 量级,具体取决于内核与主频)。EM1 关闭 CPU 时钟但保留外设与 DMA,CPU 停止取指,任何使能的中断都能把 CPU 拉回 EM0。EM2 是低功耗设计的“主战场”:关闭高频时钟(HFCLK),只保留 32.768 kHz 低频时钟(LFRCO/LFXO),外设可在低频下继续工作,典型电流在 µA 级。EM3 进一步关闭低频外设时钟,只保留部分异步外设(如 LCD、模拟比较器、看门狗),典型电流降到 1 µA 以下。EM4 是深度休眠,几乎所有电源域被切断,只有极少数唤醒引脚和复位逻辑保持供电,典型电流在 0.1~0.5 µA 量级,代价是SRAM 内容丢失、寄存器状态丢失,唤醒等同于一次复位。

这里有一个容易混淆的点:EM1/EM2/EM3 属于“睡眠”,唤醒后从进入点之后继续执行,程序上下文(栈、变量、外设配置)保持;EM4 属于“掉电式休眠”,唤醒后从复位向量重新开始,必须靠 RTC 备份寄存器或非易失存储来恢复关键状态。设计时如果误把 EM4 当成 EM3 用,就会出现“变量莫名清零”的经典问题。

EFM32/EFR32 能量模式状态机与唤醒路径 EM0 运行 CPU + 全部外设 HFCLK 开启 EM1 睡眠 CPU 停 / 外设活 任意中断唤醒 EM2 深度睡眠 仅 32kHz 低频 µA 级 / 状态保持 EM3 停止 低频外设时钟关 异步外设可唤醒 EM4 深度休眠 电源域切断 SRAM/寄存器丢失 WFI/WFE EMU_EnterEM2 EMU_EnterEM3 EMU_EnterEM4 中断唤醒 → 返回 EM0(上下文保持) EM4 唤醒 = 复位重启(状态丢失,需恢复) 典型唤醒源: GPIO 中断 · RTC 定时 · LETIMER · 模拟比较器 ACMP · ADC 完成 · I2C/SPI 从机事件 · 看门狗 · 电压比较器 · 外部复位引脚

二、进入与退出条件:谁说了算

进入 EM1/EM2/EM3 的软件入口是 EMU_EnterEM1()、EMU_EnterEM2()、EMU_EnterEM3(),或者执行 WFI/WFE 指令配合 SCR 寄存器中的 SLEEPDEEP 位。硬件层面,进入 EM2 的前提是:所有高频时钟源(HFXO、HFRCO)已关闭或不再被任何外设请求,否则 EMU 会拒绝进入并保持 EM0。这就是为什么“明明调了 EnterEM2,电流却下不去”——往往是某个外设还在请求 HFCLK。

退出条件由唤醒源决定。EM1 可被任意使能的中断唤醒;EM2 只能被在 EM2 下仍能工作的外设唤醒,例如 RTC、LETIMER、GPIO(配置为异步中断)、ACMP、I2C 从机地址匹配等;EM3 的唤醒源更少,主要是异步 GPIO、ACMP、LCD 帧中断和看门狗。EM4 只能通过特定的唤醒引脚(如 GPIO 的 EM4WU 通道)或复位唤醒,且唤醒后程序从复位向量执行。

常见误区:把普通 GPIO 中断当作 EM2 唤醒源。普通 GPIO 中断依赖 GPIO 时钟,而 EM2 下 GPIO 时钟可能已关闭。必须把引脚配置为 异步中断(GPIO_ExtIntConfig 中使能 EM4WU 或异步模式),才能在 EM2/EM3 下可靠唤醒。

三、状态保持与丢失:一张对照表

资源EM1EM2EM3EM4
CPU 寄存器 / 栈保持保持保持丢失
SRAM 内容保持保持保持丢失
外设寄存器配置保持保持保持丢失
HFCLK / HFXO可用关闭关闭关闭
LFCLK(32kHz)可用可用关闭关闭
RTC / LETIMER可用可用停止停止
唤醒后行为继续执行继续执行继续执行复位重启

这张表是设计决策的核心依据。如果应用需要在休眠期间维持一个精确的时间基准,就必须用 EM2 + LFXO + RTC,而不能用 EM3/EM4。如果应用只需要“被按键唤醒后重新初始化”,EM4 反而更省电。

四、状态转换开销:被忽视的功耗成本

每次模式切换都不是免费的。从 EM0 进入 EM2 需要关闭 HFCLK、切换时钟源,典型耗时几微秒;从 EM2 唤醒回 EM0 需要重新启动 HFXO 并稳定,典型 100~300 µs(取决于晶振启动时间)。如果每秒唤醒 100 次,仅唤醒开销就可能吃掉大量平均电流。平均电流的估算公式为:

I_avg ≈ (I_EM2 × T_sleep + I_EM0 × T_active + I_wake × T_wake) / (T_sleep + T_active + T_wake)

示例(假设值,非实测):
I_EM2 = 1.4 µA,T_sleep = 990 ms
I_EM0 = 3.0 mA,T_active = 5 ms
I_wake = 1.5 mA,T_wake = 0.2 ms
I_avg ≈ (1.4×990 + 3000×5 + 1500×0.2) / 995.2 ≈ 16.5 µA

可以看到,即使 EM2 电流只有 1.4 µA,5 ms 的活动时间就把平均电流拉到了 16.5 µA。这说明降低平均功耗的关键往往不是把 EM2 压得更低,而是缩短活动时间和唤醒次数。

五、实测方法:怎么验证真的进了 EM2

实测分两步。第一步用电流表或功耗分析仪(如 Simplicity Studio 的 Energy Profiler、Joulescope、Nordic PPK2)观察电流波形:进入 EM2 后电流应稳定在 µA 级,唤醒时出现一个 mA 级的尖峰。第二步用 GPIO 翻转做“软件打点”:在进入休眠前拉高一个空闲引脚,唤醒后拉低,用示波器测量高电平持续时间,即为实际休眠时间;同时对照 RTC 计数值验证唤醒周期是否准确。

调试技巧:如果 Energy Profiler 显示电流始终在 mA 级,先检查是否有外设未关闭(如 UART、ADC、LED 驱动),再检查是否有引脚悬空导致漏电,最后确认 EMU_EnterEM2 的返回值——EMU 在无法进入目标模式时会返回失败标志,不要忽略它。