跳转至

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_tpmu_control_type_tpm_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

案例操作指导

第一步:编译

fbb build ws63-liteos-app

第二步:烧录和验证

烧录后串口打印各 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_voltagevset 参数单位是 10mV(即 120 = 1.20V)。具体编码方式参考芯片数据手册——不同 LDO 的编码表可能不同。PMU 配置直接影响芯片稳定性和功耗——电压设定必须在规格范围内,默认值通常是最优值。