4、电源管理单元(PMU)配置:电压调节器模式、电源域划分、内核电压与IO电压管理
好,咱们接着聊PMU。这东西说白了就是芯片的“供电大脑”。你想想看,一个嵌入式系统里,CPU要电、内存要电、外设也要电,谁来决定什么时候给谁送电、送多少?就是PMU。
我刚开始做低功耗项目时,总觉得PMU配置就是设几个寄存器的事。后来被现实狠狠教育了一回——板子待机电流死活降不下来,查了三天,发现是电压调节器模式没配对。从那以后,我对PMU的敬畏心就上来了。
4.1 电压调节器的工作模式
电压调节器(Voltage Regulator)是PMU的核心。它负责把电池或外部电源的电压,转换成芯片需要的稳定电压。常见的模式有这么几种:
| 模式 | 特点 | 适用场景 |
|---|---|---|
| PWM模式 | 纹波小、效率高(重载时) | CPU全速运行、大数据传输 |
| PFM模式 | 轻载效率高、纹波稍大 | 待机、浅睡眠、低负载 |
| Bypass模式 | 直接旁路、压降极小 | 深度睡眠、RTC供电 |
| LDO模式 | 低噪声、效率较低 | 模拟电路、RF前端 |
我个人习惯在系统全速运行时用PWM模式,这时候负载大,PWM的效率优势很明显。一旦进入空闲状态,我会立刻切到PFM模式。为什么?因为PFM在轻载下能省下30%-50%的调节器自身功耗。
4.2 电源域划分的艺术
电源域(Power Domain)划分,说白了就是把芯片的不同功能模块,接到不同的供电网络上。这样你可以单独关掉某个区域的电源,而不影响其他区域。
典型的划分方式是这样的:
- Always-on域: RTC、唤醒逻辑、部分GPIO。永远不断电。
- Core域: CPU核心、Cache、内部总线。性能敏感,电压可调。
- IO域: 外部接口、GPIO bank。电压通常固定(1.8V/3.3V)。
- Memory域: SRAM、Flash。可独立保持或断电。
- Analog域: ADC、DAC、PLL。对噪声敏感,通常单独供电。
嗯,这里要注意:电源域划分不是越多越好。每个域都需要独立的电源开关和电平转换器,这些都会增加面积和成本。我见过一个项目分了12个电源域,结果光电源开关就占了芯片面积的15%,得不偿失。
4.3 内核电压的动态管理
内核电压(Vcore)是给CPU核心供电的。这块的功耗占整个芯片的大头,所以是优化的重点。
常用的技术是DVFS(动态电压频率调整)。说白了就是:任务重时,电压和频率都拉高;任务轻时,降下来。公式很简单:
P ∝ C × V² × f
你看,功耗和电压的平方成正比。所以降一点电压,效果非常明显。我在一个项目中,把Vcore从1.2V降到1.0V,频率从400MHz降到200MHz,功耗直接降了60%。而用户根本感觉不到卡顿,因为大部分时间CPU都在闲着。
但要注意,电压不能无限降。每个芯片都有一个最低工作电压(Vmin),低于这个值,逻辑门就可能出错。我建议的做法是:
- 先做芯片的电压-频率特性测试,找到每个频率点对应的Vmin。
- 留出5%-10%的余量,防止温度变化导致失效。
- 在固件中实现自适应电压调节,根据温度实时微调。
4.4 IO电压的管理策略
IO电压(Vccio)是给外部接口供电的。常见的有1.8V、2.5V、3.3V。这块的管理相对简单,但坑也不少。
首先,IO电压通常不支持动态调节。因为外部设备(传感器、存储器)对电压有固定要求。你这边一变,那边可能就烧了。
但我们可以做的是:
- IO bank独立供电: 不同的外设接到不同的IO bank,不用的bank直接断电。
- 电平转换: 内核用低压(0.9V-1.2V),IO用高压(1.8V-3.3V),中间加电平转换器。
- IO保持: 进入睡眠时,把IO引脚设为高阻或固定电平,避免漏电。
我记得有个项目,待机电流总是比预期高0.5mA。查来查去,发现是一个GPIO在睡眠时被拉到了中间电平,导致IO buffer里的PMOS和NMOS同时导通,形成了贯通电流。解决办法很简单:睡眠前把那个引脚拉到确定的电平。
4.5 实际配置示例
下面是一个典型的PMU初始化代码(伪代码风格),展示如何配置电压调节器模式和电源域:
// 1. 初始化Always-on域
PMU_ALWAYS_ON_ENABLE();
// 2. 配置Core域电压调节器为PWM模式
PMU_SET_REGULATOR_MODE(REGULATOR_CORE, MODE_PWM);
PMU_SET_VOLTAGE(REGULATOR_CORE, 1200); // 1.2V
// 3. 配置IO域电压为3.3V
PMU_SET_VOLTAGE(REGULATOR_IO, 3300);
// 4. 关闭未使用的电源域
PMU_POWER_DOMAIN_OFF(PD_ANALOG);
PMU_POWER_DOMAIN_OFF(PD_MEMORY_BANK2);
// 5. 进入低功耗前的切换
void enter_sleep_mode() {
// 先降频
CPU_SET_FREQ(100); // 100MHz
// 再降压
PMU_SET_VOLTAGE(REGULATOR_CORE, 900); // 0.9V
// 切到PFM模式
PMU_SET_REGULATOR_MODE(REGULATOR_CORE, MODE_PFM);
// 最后关掉不用的IO bank
PMU_IO_BANK_OFF(IO_BANK_3);
PMU_IO_BANK_OFF(IO_BANK_4);
}
你看,顺序很重要。先降频再降压,否则可能因为电压不足导致指令执行出错。先切模式再关IO,避免切换瞬间的电流冲击。
4.6 总结一下
PMU配置这件事,说白了就是三个字:管好电。管好了,待机电流从mA级降到μA级不是梦;管不好,电池半天就没了。
最后分享一个我自己的检查清单,每次做PMU配置时我都会过一遍:
- ☐ 电压调节器模式是否根据负载动态切换?
- ☐ 电源域划分是否合理?有没有不必要的域?
- ☐ 内核电压是否做了DVFS?低温补偿加了没?
- ☐ IO电压是否稳定?睡眠时引脚电平确定吗?
- ☐ 切换顺序是否正确?(先降频再降压,先升压再升频)
嗯,做到这几点,你的PMU配置基本就稳了。下一章咱们聊聊时钟管理,那个也是低功耗的重头戏。