PM PMU
使用技术:PM PMU 驱动 | 无 sample
学习目标
- 理解 PMU——芯片电源管理核心:LDO 稳压、模块上下电、休眠唤醒
- 掌握
uapi_pmu_ldo_get_voltage/uapi_pmu_ldo_set_voltage读取和设置 LDO 电压 - 掌握
uapi_pmu_control控制模块电源开关 - 理解电压安全范围——过高损坏芯片、过低运行不稳
基本概念
PMU 做什么
PMU(Power Management Unit)是芯片的电源管理核心,负责:
- LDO 稳压:将外部供电(如 3.3V)降压为各模块所需工作电压(如 1.2V Core、1.8V IO)
- 模块电源控制:独立控制各功能模块的供电开关——不用时断电省功耗
- 休眠唤醒:与 RTC 配合实现低功耗间歇工作
flowchart TB
V[外部供电 3.3V] --> L[CORE LDO]
V --> L2[IO LDO]
V --> L3[RF LDO]
L -->|1.2V| CPU[CPU 核心]
L2 -->|1.8V| IO[GPIO/UART/SPI]
L3 -->|1.8V| RF[WiFi/BT 射频]
PMU[PMU 控制器] -->|set_voltage| L
PMU -->|set_voltage| L2
PMU -->|control on/off| CPU
PMU -->|control on/off| RF
LDO 电压范围
| LDO | 典型电压 | 范围 | 供电对象 |
|---|---|---|---|
| CORE LDO | 1.2V | 1.1V ~ 1.3V | CPU 核心、SRAM |
| IO LDO | 1.8V | 1.7V ~ 1.9V | GPIO、UART、SPI |
| RF LDO | 1.8V | 1.7V ~ 1.9V | WiFi/BT 射频前端 |
电压设定必须在芯片规格范围内——过高损坏芯片,过低运行不稳定。大多数情况下默认电压无需修改,仅在性能调优或低功耗优化时调整。
PMU Control 类型
uapi_pmu_control 是通用控制接口,type 参数决定操作类型:
| 控制类型 | 说明 | param 含义 |
|---|---|---|
| 模块电源开关 | 独立模块上电/下电 | 模块 ID + 开关值 |
| 电源域控制 | 整个电源域开关 | 域 ID + 开关值 |
| 休眠模式 | 进入/退出低功耗 | 休眠等级 |
涉及 API
| API | 用途 | 头文件 |
|---|---|---|
uapi_pmu_ldo_set_voltage(pmu_ldo_id_t id, uint8_t vset) |
设置 LDO 输出电压 | pm_pmu.h |
uapi_pmu_ldo_get_voltage(pmu_ldo_id_t id) |
读取 LDO 当前电压 | pm_pmu.h |
uapi_pmu_control(pmu_control_type_t type, uint8_t param) |
通用 PMU 控制(模块开关/休眠等) | pm_pmu.h |
pmu_ldo_id_t和pmu_control_type_t在pm_pmu_porting.h中定义——具体值取决于芯片型号。
案例说明
做什么
- 读取 CORE LDO 当前电压并打印
- 读取 IO LDO 电压验证
- 关闭空闲 RF 模块的供电以节省功耗
- 查询模块供电状态
规格与功能
| 规格项 | 说明 |
|---|---|
| 读取 LDO | CORE LDO、IO LDO |
| 典型值 | CORE = 1.2V,IO = 1.8V |
| 功耗优化 | 关闭空闲 RF 模块供电 |
| 验证 | 读取值与典型值对比 |
程序运行流程:get_voltage(CORE) → 打印 → get_voltage(IO) → 打印 → control(RF, OFF) → 打印确认。
案例流程
sequenceDiagram
participant A as 应用
participant P as PMU
participant C as CORE LDO
participant I as IO LDO
participant R as RF模块
A->>P: ldo_get_voltage CORE
P->>C: 读取电压
C->>A: 1.2V
A->>A: print CORE=1.2V
A->>P: ldo_get_voltage IO
P->>I: 读取电压
I->>A: 1.8V
A->>A: print IO=1.8V
A->>P: control RF off
P->>R: 关闭供电
Note over R: RF 模块断电
A->>A: print RF powered off
案例操作指导
第一步:编译
第二步:烧录和验证
烧录后串口打印各 LDO 电压值。用万用表(如有测试点)或功耗仪验证:RF 模块断电后整体功耗应下降。
第三步:预期输出
PMU: CORE LDO voltage = 1.20V
PMU: IO LDO voltage = 1.80V
PMU: RF module powered off (save power)
PMU: all checks passed
关键配置
| 参数 | 值 | 说明 |
|---|---|---|
| CORE 电压 | 1.1V ~ 1.3V | 典型 1.2V——不能低于 1.1V |
| IO 电压 | 1.7V ~ 1.9V | 典型 1.8V——影响 GPIO 电平 |
| 电压步进 | 取决于硬件 | 不是任意值——查询 porting 头文件 |
| 模块断电前提 | 确认空闲 | 误断正在使用的模块导致功能异常 |
电压调节的权衡
| 电压 | CPU 频率 | 功耗 | 稳定性 |
|---|---|---|---|
| 1.3V | 最高 | 最高 | 好 |
| 1.2V(默认) | 标称 | 标称 | 好 |
| 1.1V | 受限 | 最低 | 临界 |
降低 Core 电压可省电但限制最高频率——仅在降频运行时考虑。默认电压已经过芯片验证,不建议随意修改。
LDO 电压安全操作
| 操作 | 风险 | 建议 |
|---|---|---|
| 调低电压 | 芯片运行不稳定 | 仅在降频后调低 |
| 调高电压 | 芯片过热/永久损坏 | 不超过数据手册上限 |
| 关模块供电 | 模块数据丢失 | 确认无进行中的操作 |
| 关 Core 供电 | 芯片停机 | 仅在休眠流程中使用 |
代码详解
概念性代码,基于 SDK 头文件
pm_pmu.h中的 API 签名。
#include "pm_pmu.h"
#include "errcode.h"
#include "osal_printk.h"
#include "app_init.h"
/* 典型电压参考值 */
#define CORE_VOLTAGE_TYPICAL 120 /* 1.20V (单位: 10mV) */
#define IO_VOLTAGE_TYPICAL 180 /* 1.80V */
static void pm_pmu_entry(void)
{
uint8_t voltage;
errcode_t ret;
/* ---- 1. 读取 CORE LDO 电压 ---- */
voltage = uapi_pmu_ldo_get_voltage(PMU_LDO_CORE);
osal_printk("PMU: CORE LDO voltage = %u.%02uV\n",
voltage / 100, voltage % 100);
if (voltage < CORE_VOLTAGE_TYPICAL - 10 ||
voltage > CORE_VOLTAGE_TYPICAL + 10) {
osal_printk("PMU: WARNING! CORE voltage out of range!\n");
}
/* ---- 2. 读取 IO LDO 电压 ---- */
voltage = uapi_pmu_ldo_get_voltage(PMU_LDO_IO);
osal_printk("PMU: IO LDO voltage = %u.%02uV\n",
voltage / 100, voltage % 100);
if (voltage < IO_VOLTAGE_TYPICAL - 10 ||
voltage > IO_VOLTAGE_TYPICAL + 10) {
osal_printk("PMU: WARNING! IO voltage out of range!\n");
}
/* ---- 3. 关闭空闲 RF 模块供电——省电 ---- */
ret = uapi_pmu_control(PMU_CONTROL_MODULE_POWER,
PMU_MODULE_RF | PMU_POWER_OFF);
if (ret != ERRCODE_SUCC) {
osal_printk("PMU: RF power off failed: %d\n", ret);
} else {
osal_printk("PMU: RF module powered off (save power)\n");
}
/* ---- 4. 示例:调整 CORE 电压(需确认芯片支持)---- */
/* voltage = uapi_pmu_ldo_get_voltage(PMU_LDO_CORE); */
/* if (voltage >= 120) { */
/* voltage = 120; // 保持在 1.2V */
/* ret = uapi_pmu_ldo_set_voltage(PMU_LDO_CORE, voltage); */
/* if (ret != ERRCODE_SUCC) { */
/* osal_printk("PMU: set CORE voltage failed: %d\n", ret); */
/* } */
/* } */
osal_printk("PMU: all checks passed\n");
}
app_run(pm_pmu_entry);
uapi_pmu_ldo_set_voltage的vset参数单位是 10mV(即 120 = 1.20V)。具体编码方式参考芯片数据手册——不同 LDO 的编码表可能不同。PMU 配置直接影响芯片稳定性和功耗——电压设定必须在规格范围内,默认值通常是最优值。