杰理 SDK 文档中心
首页
首页
  • 入门指南

    • SDK 概述与芯片平台
    • 环境搭建与开发工具链
    • 编译、烧录与快速开始
  • 应用层开发

    • 语音玩具应用 voice_toy
    • 扩音器应用 voice_enhanced
    • 语音功能状态机 voice_func
    • 应用公共框架与配置
  • 音频子系统

    • 音频解码器与 MIDI 播放
    • 音频编码与录音
    • 音效算法(ANS、变调、变声、混响)
    • 音频输出、功放与硬件重采样
  • 存储与文件系统

    • 文件系统层(FAT、NOR_FS、SYDF 等)
    • 存储设备与设备管理
    • 参数存储 VM 与保留区
  • 系统机制

    • 消息与事件机制
    • 电源管理与低功耗
    • 固件升级机制
    • 外设驱动(按键、红外、SPI、USB)
    • 实时时钟与定时器
  • 构建系统与工具

    • 构建系统(Makefile 与 Code::Blocks)
    • 编译后处理与语音资源打包
  • 硬件平台与文档

    • 芯片平台与启动流程
    • 硬件文档、规格书与原理图

电源管理与低功耗

本文档介绍 AD24N SDK 的电源管理与低功耗机制:从应用层的电池电压检测、低电告警(app_power_mg),到 PMU 电源框架(power_api)中的 sleep/deep-sleep/soft-off 三种低功耗模式、电源控制命令、参数配置与回调钩子,说明整个电源子系统的端到端工作方式。

Purpose and Scope

本页面覆盖 AD24N(SH58 系列 CPU)电源管理子系统的完整实现:

  • 应用层电源管理:app_power_mg.c/.h 的 VBAT 采样、低电检测与 MSG_LOW_POWER 消息上报;
  • 电源框架:power_api.h 定义的电源初始化、power_control() 命令集、低功耗使能/关闭 API、soft-off 流程;
  • PMU 平台实现:power_app.c 中的进入/退出低功耗回调、软关机回调与 power_early_flowing() 启动流程;
  • 关键数据结构:_power_param、_power_pdata、VDDIO_KEEP_TYPE、LOWPOWER_OSC_TYPE 等。

以下内容属于兄弟页面范畴,本页仅作引导、不展开:RTC/时钟与晶振配置(见时钟管理)、GPIO 唤醒配置(见 GPIO 驱动)、VM 参数存储、按键长按复位等。

Overview

AD24N 是杰理科技(Jieli-Tech)的低功耗音频 MCU(SH58 内核)。其电源管理子系统解决两个核心问题:

  1. 运行时的电源健康监控——通过 PMU 内置 ADC 通道 ADC_CH_PMU_VBAT 周期性采样电池电压,连续多次低于阈值后向应用层投递 MSG_LOW_POWER 消息,触发低电提醒/关机策略。
  2. 空闲时的功耗优化——当系统(含蓝牙协议栈)空闲时,由 FreeRTOS 的 vPortSuppressTicksAndSleep() 或显式的 sys_power_down() 进入低功耗(sleep/deep-sleep),或由 sys_softoff() 进入 soft-off(软关机),在保持唤醒能力的同时把整机功耗压到最低。

整个框架的设计意图是把"硬件电源细节"与"应用策略"解耦:硬件相关的电压挡位、晶振选择、IO 保持策略通过 power_control() 命令接口和 _power_param 配置注入;应用只关心"检测电压、判断低电、发消息"和"空闲时请求睡眠",以及通过回调感知进入/退出低功耗的时刻。

Architecture

flowchart TD
    subgraph sg_App["应用层 (sdk/app/bsp/common)"]
        AppPM["app_power_mg.c<br/>VBAT采样/低电告警"]
        MSG["MSG_LOW_POWER 消息"]
        AppPM -->|"post_msg"| MSG
    end

    subgraph sg_PMU["电源框架 (include_lib/cpu/sh58/asm/power)"]
        API["power_api.h<br/>power_control / lowpower_init / sys_power_down"]
        PARAM["_power_param 配置<br/>osc_type / vddiom_lev / config"]
    end

    subgraph sg_Platform["平台实现 (sdk/app/bsp/cpu/sh58/power)"]
        APP["power_app.c<br/>power_early_flowing / 回调"]
        CALLBACK["sleep_enter_callback<br/>sleep_exit_callback<br/>power_soff_callback"]
    end

    subgraph sg_HW["硬件资源"]
        ADC["PMU ADC 通道<br/>ADC_CH_PMU_VBAT"]
        LDO["VDDIOM / VDDIOW LDO"]
        OSC["LRC / BT_OSC 低功耗晶振"]
    end

    AppPM -->|"adc_get_voltage"| ADC
    AppPM -->|"低电检测"| MSG
    API -->|"进入/退出"| CALLBACK
    API -->|"配置"| PARAM
    API -->|"控制LDO/晶振"| LDO
    API -->|"唤醒计时"| OSC
    APP -->|"power_early_init(gpio_config)"| API
    APP -->|"实现钩子"| CALLBACK

架构分四层:

  • 应用层:app_power_mg.c 只做两件事——启动时连续采样 VBAT 得到稳定的开机电压值;周期扫描中连续 10 次电压低于阈值时打印告警并 post_msg(1, MSG_LOW_POWER)。阈值来源由 LVD_WARNING_FOR_LOW_POWER 宏决定(默认用 LVD 警告电压 + 200mV,而非固定 3.3V),这保证低电检测与硬件复位点(LVD)保持合理余量。
  • 电源框架:power_api.h 是 PMU 库对外契约,定义初始化序列(power_early_init → power_later_init → power_init)、power_control() 命令集、低功耗开关(lowpower_init/lowpower_uninit)与睡眠/关机入口(vPortSuppressTicksAndSleep/sys_power_down/sys_softoff)。
  • 平台实现:power_app.c 把"进入睡眠前把 USB IO 置高阻、退出后恢复 DIR"、"软关机前关闭平台 uninit 流程并配置 GPIO 为软关机状态"等板级细节以回调形式挂入框架,并通过 power_early_flowing() 在启动早期加载低功耗代码段(overlay)、保护调试打印口、再调用 power_early_init((u32)gpio_config)。
  • 硬件资源:PMU ADC、双 LDO 挡位、低功耗晶振(LRC 或蓝牙 24M 晶振)与唤醒计时器,均由框架按 _power_param 配置驱动。

低功耗模式与状态

power_api.h 定义了三种电源策略,由 _power_param.config 字段(宏 LOWPOWER_CLOSE / SLEEP_EN / DEEP_SLEEP_EN)选择:

stateDiagram-v2
    [*] --> RUN: power_early_init + 系统运行
    RUN --> SLEEP: 空闲 && SLEEP_EN<br/>vPortSuppressTicksAndSleep/sys_power_down
    SLEEP --> RUN: 定时器/IO唤醒 (sleep_exit_callback)
    RUN --> DEEPSLEEP: 空闲 && DEEP_SLEEP_EN
    DEEPSLEEP --> RUN: 唤醒源触发
    RUN --> SOFF: sys_softoff / 低电关机策略
    SOFF --> [*]: power_soff_callback<br/>GPIO软关机
  • SLEEP(睡眠):SLEEP_EN 使能,系统空闲时按 usec 定时睡眠,通过 LRC/BT_OSC 计时,唤醒后自动恢复;FreeRTOS 通过 vPortSuppressTicksAndSleep(usec) 把 tick 中断与硬件睡眠对齐,保证调度器时间不漂移(配合 low_power_trace_drift 校正)。
  • DEEP_SLEEP(深睡):DEEP_SLEEP_EN 使能,进一步关闭更多外设电源域,唤醒延迟更大、功耗更低。
  • SOFF(软关机):sys_softoff() 触发,power_soff_callback() 执行平台 uninit、mask 软标志(sfc_fast_boot = 0)、gpio_config_soft_poweroff() 配置关机态 IO,最终整机进入极低功耗待机,靠开机键/充电检测唤醒。

应用层电源管理实现(app_power_mg)

低电检测阈值的选择

app_power_mg.h 通过编译期宏 LVD_WARNING_FOR_LOW_POWER 决定低电阈值来源,这是"硬件复位余量"设计意图的直接体现:如果低电告警阈值与 LVD(低压检测,硬件强制复位点)太接近,软件来不及保存状态系统就被复位;如果太远,则电池容量利用不足。

#define LVD_WARNING_FOR_LOW_POWER   1//1:使用LVD警告电压作低电提醒 0:使用固定值作低电提醒

#if LVD_WARNING_FOR_LOW_POWER
#define LOW_POWER_VOL		    lvd_warning_voltage
#define LOW_POWER_LOG           "Warning!!! Vbat is near to lvd!\n"
#define low_power_warning_init()  lvd_warning_init()
#else
#define LOW_POWER_VOL		    3300//3.3v
#define LOW_POWER_LOG           "low power\n"
#define low_power_warning_init()
#endif

Source: app_power_mg.h

默认路径(LVD_WARNING_FOR_LOW_POWER = 1)下,阈值在运行时从 efuse/寄存器读取的 LVD 电压加 200mV 得到,确保告警先于硬件复位发生:

static void lvd_warning_init(void)
{
    u16 lvd_voltage = get_lvd_vol();
    lvd_warning_voltage = lvd_voltage + 200;
}

Source: app_power_mg.c

初始化与上电电压采样

app_power_init() 注册 VBAT 采样通道后,通过 adc_kick_start() 连续触发 10 次采样(回调自嵌套),直到拿到稳定电压值才返回。这样开机阶段就能得到可信的电池电压(4 倍放大换算:PMU 内部电阻分压后软件乘 4 还原实际电压):

static volatile u8 powerup_kick_start_cnt = 0;
static void app_power_powerup_kick_start(void)
{
    if (powerup_kick_start_cnt++ < 10) {
        adc_kick_start(app_power_powerup_kick_start);
        return;
    }
    log_info("vbat value:%d \n", app_power_get_vbat());
}

void app_power_init(void)
{
    low_power_warning_init();
    adc_add_sample_ch(ADC_CH_PMU_VBAT);
    adc_kick_start(app_power_powerup_kick_start);
    while (powerup_kick_start_cnt < 10);
}

u32 app_power_get_vbat(void)
{
    u32 vol = adc_get_voltage(ADC_CH_PMU_VBAT);
    if (-1 != vol) {
        vol *= 4;
    }
    return vol;
}

Source: app_power_mg.c

周期扫描与低电消息

app_power_scan() 是去抖式的低电检测:只有连续 10 次扫描(约 10 个扫描周期)都低于阈值才判定为低电,避免电池电压因负载波动瞬时跌落造成的误报。一旦确认低电,立即 post_msg(1, MSG_LOW_POWER) 通知应用层(应用据此弹低电提醒、降频或执行关机策略)。若按键为 GPIO 直连(非 AD/矩阵按键),扫描末尾主动 adc_kick_start(NULL) 维持 ADC 采样链路:

void app_power_scan(void)
{
    static u16 low_power_cnt = 0;
    u32 vol = adc_get_voltage(ADC_CH_PMU_VBAT);

    if (-1 != vol) {
        vol = vol * 4;
        if (vol <= LOW_POWER_VOL) {
            low_power_cnt++;
            if (low_power_cnt == 10) {
                log_error(LOW_POWER_LOG);
                post_msg(1, MSG_LOW_POWER);
            }
        } else {
            low_power_cnt = 0;
        }
    }

#if (!(KEY_AD_EN || KEY_MATRIX_EN))
    adc_kick_start(NULL);
#endif
}

Source: app_power_mg.c

端到端低电检测时序

sequenceDiagram
    participant App as 应用任务
    participant ADC as PMU ADC (ADC_CH_PMU_VBAT)
    participant PM as app_power_mg
    participant MSG as 消息队列

    App->>PM: app_power_init()
    PM->>ADC: adc_add_sample_ch + adc_kick_start ×10
    ADC-->>PM: 稳定 VBAT (×4)
    loop 周期扫描 app_power_scan()
        PM->>ADC: adc_get_voltage
        alt vol <= LOW_POWER_VOL
            PM->>PM: low_power_cnt++ (连续10次)
            PM->>MSG: post_msg(1, MSG_LOW_POWER)
        else vol > LOW_POWER_VOL
            PM->>PM: low_power_cnt = 0 (复位去抖计数)
        end
    end

电源框架 API 详解(power_api.h)

低功耗代码段放置

框架把"进出低功耗必须驻留"的驱动代码显式放入专用内存段,保证睡眠期间 DDR/Flash 掉电后代码仍可执行(overlay 段在低功耗期间保持有效):

#define AT_VOLATILE_RAM_POWER       	AT(.power_driver.data)
#define AT_VOLATILE_RAM_BSS_POWER     	AT(.power_driver.data.bss)
#define AT_VOLATILE_RAM_CODE_POWER      AT(.power_driver.text.cache.L1)

#define AT_VOLATILE_RAM_LOWPOWER        AT(.power_driver.data.overlay)
#define AT_VOLATILE_RAM_BSS_LOWPOWER    AT(.power_driver.data.bss.overlay)
#define AT_VOLATILE_RAM_CODE_LOWPOWER	AT(.power_driver.text.cache.L1.overlay)

Source: power_api.h

电源参数结构

_power_param 是平台电源配置的载体,分"睡眠"与"电源"两组:睡眠组描述低功耗晶振(btosc_hz 默认 24M、osc_type、预留的 t1~t4/lptmr_flow);电源组描述工作态与低功耗态的 LDO 挡位(vddiom_lev 工作电压、vddiow_lev 低功耗电压)以及 config 选择的低功耗模式。osc_delay_us 预留低功耗晶振起振延时,说明框架对晶振稳定时间有显式建模:

struct _power_param {
    //sleep
    u32 btosc_hz;		//蓝牙晶振频率(默认使用24M)
    u32 osc_delay_us;		//低功耗晶振起振延时,为预留配置。
    u32 t1;				//低功耗参数,预留配置
    u32 t2;				//低功耗参数,预留配置
    u32 t3;				//低功耗参数,预留配置
    u32 t4;				//低功耗参数,预留配置

    //power
    u8 vddiom_lev;		//vddiom,系统工作时使用vddiom ldo(使用enum VDDIOM_VOL配置)
    u8 vddiow_lev;		//vddiow,系统低功耗时使用vddiow ldo(使用enum VDDIOW_VOL配置)

    //sleep
    u8 config;			//低功耗使能(使用LOWPOWER_CONFIG配置)
    u8 osc_type;		//低功耗晶振类型(使用enum LOWPOWER_OSC_TYPE配置)
    u8 lptmr_flow;		//低功耗参数由用户配置
};

Source: power_api.h

VDDIO 保持策略

进出低功耗时 VDDIOW 的供电策略通过 VDDIO_KEEP_TYPE 枚举表达,覆盖四种典型场景:使用配置值、沿用工作态 VDDIOM 挡位、使用 trim 校准值、或完全保持 VDDIOM 不关。PCONTROL_PD_VDDIO_KEEP / PCONTROL_SF_VDDIO_KEEP 两个命令分别控制 sleep 与 soft-off 的切换流程:

enum VDDIO_KEEP_TYPE {
    VDDIO_KEEP_TYPE_NULL,		//vddiow使用配置值
    VDDIO_KEEP_TYPE_NORMAL,		//vddiow使用配置值使用vddiom挡位,即vddiom_lev
    VDDIO_KEEP_TYPE_TRIM,		//vddiow使用trim值
    VDDIO_KEEP_TYPE_PG,             //保持vddiom不关闭
};

Source: power_api.h

power_control 命令集

power_control() 是平台电源行为的统一配置入口,命令按功能域分组(0x100 电源、0x200/0x300/0x400 预留子模块)。这种"命令字 + 参数"设计让 PMU 库与具体板级差异解耦:同一份库代码可通过不同命令参数适配 DCVDD 是否外挂电容、Flash 供电引脚类型、RTC 晶振类型、供电方式(IOVDD/VPWR)等硬件变体:

enum PCONTROL_CMD {
    PCONTROL_POWER_DRIVER_RESERVE = 0,
    PCONTROL_P_PUTBYTE,			//串口调试函数

    //power
    PCONTROL_POWER_MODE = 0x100,
    PCONTROL_DCVDD_CAP_SW,			//0:DCVDD上没有外挂电容 1:DCVDD上有外挂电容
    PCONTROL_FLASH_PG_VDDIO,		//0:FLASH电源引脚使用IO 1:FLASH电源引脚没有使用IO
    PCONTROL_RTC_CLK,			//RTC_CLK类型,配置开机、关机晶振流程
    PCONTROL_POWER_SUPPLY,			//供电方式,0:IOVDD供电,1:VPWR供电

    //sleep
    PCONTROL_PD_VDDIO_KEEP,			//pdown vddio切换流程(使用enum VDDIO_KEEP_TYPE配置)
    PCONTROL_PD_WDVDD_LEV,			//pdown wvdd挡位
    PCONTROL_PD_DVDD_LEV,			//pdown dvdd挡位
    PCONTROL_PD_KEEP_LPCTMU,		//pdown 触摸是否保持 0:不保持 1:保持

    //soff
    PCONTROL_SF_KEEP_LRC,			//soff lrc是否保持 0:不保持 1:保持
    PCONTROL_SF_VDDIO_KEEP,			//soff vddio切换流程(使用enum VDDIO_KEEP_TYPE配置)
    PCONTROL_SF_KEEP_NVDD,			//soff nvdd是否保持 0:不保持 1:保持
    PCONTROL_SF_KEEP_PVDD,			//soff pvdd是否保持 0:不保持 1:保持

    //以下配置为对应子模块的预留配置
    PCONTROL_PHW_RESERVE = 0x100,
    PCONTROL_P33_RESERVE = 0x200,
    PCONTROL_P11_RESERVE = 0x300,
    PCONTROL_LP_FLOW_IC_RESERVE = 0x400,
};

Source: power_api.h

低功耗入口与初始化序列

框架暴露两组关键接口:

  • 初始化:power_early_init(arg)(启动最早,仅带 gpio_config 参数,见 power_early_flowing)→ power_later_init(arg) → power_init(pdata)(携带 _power_pdata 即 _power_param 指针)。分阶段初始化保证:先建立最小电源环境(LDO/晶振),再在后期接入完整参数与平台策略。
  • 低功耗开关:lowpower_init()/lowpower_uninit() 控制 overlay 代码段与低功耗驱动是否可用;low_power_sys_request(priv) 供系统空闲时请求睡眠;low_power_trace_drift(usec) 校正睡眠期间 FreeRTOS tick 漂移;low_power_reset_osc_type / low_power_get_osc_type / low_power_get_default_osc_type 管理低功耗晶振类型。
  • 睡眠/关机入口:vPortSuppressTicksAndSleep(usec) 由 FreeRTOS 调度器在 idle 任务调用,sys_power_down(usec) 供非 RTOS 场景直接使用,sys_softoff() 进入软关机。
void power_early_init(u32 arg);
void power_later_init(u32 arg);
void power_init(struct _power_pdata *pdata);
u32 power_control(enum PCONTROL_CMD cmd, u32 arg);
void lowpower_init();
void lowpower_uninit();
void low_power_sys_request(void *priv);
s32 low_power_trace_drift(u32 usec);
void low_power_reset_osc_type(u8 type);
u8 low_power_get_default_osc_type(void);
u8 low_power_get_osc_type(void);
void lowpower_dump();
void vPortSuppressTicksAndSleep(u32 usec);
void sys_power_down(u32 usec);
void sys_softoff(void);

Source: power_api.h

平台实现与回调机制(power_app.c)

进入/退出低功耗回调

power_app.c 以回调方式把板级动作注入框架。sleep_enter_callback(step) 在关中断、单核环境下执行(注释明确要求"禁止添加打印、勿做耗时操作"):打印 '<' 标记、保存 USB IO 方向寄存器(调试口在 DP/DM 时)、把 USB 口置高阻防止睡眠漏电;sleep_exit_callback(usec) 则恢复 USB IO 方向并打印 '>'。这里的 USB IO 特殊处理体现了调试口保护与低功耗的权衡——睡眠期间打印口必须高阻,退出后再恢复:

static u32 usb_io_con = 0;
void sleep_enter_callback(u8 step)
{
    /* 此函数禁止添加打印 */
    int putchar(int a);
    putchar('<');

    //USB IO打印引脚特殊处理
    if (libs_debug) {
#if ((CONFIG_UART_DEBUG_PORT == IO_PORT_DP) || (CONFIG_UART_DEBUG_PORT == IO_PORT_DM))
        usb_io_con = JL_PORTUSB->DIR;
#endif
    }
    usb_high_res();
}

void sleep_exit_callback(u32 usec)
{
    //USB IO打印引脚特殊处理
    if (libs_debug) {
#if ((CONFIG_UART_DEBUG_PORT == IO_PORT_DP) || (CONFIG_UART_DEBUG_PORT == IO_PORT_DM))
        JL_PORTUSB->DIR = usb_io_con;
#endif
    }
    int putchar(int a);
    putchar('>');
}

Source: power_app.c

软关机回调

power_soff_callback() 是 soft-off 前的最后一站:执行平台 uninit、清除快速开机软标志(sfc_fast_boot = 0,保证下次上电走完整启动而非快速启动)、把 IO 配置为软关机态。mask_softflag_config 写软标志说明 soft-off 后仍可由特定事件(充电插入/开机键)唤醒并继续执行:

static void __mask_io_cfg()
{
    struct app_soft_flag_t app_soft_flag = {0};
    app_soft_flag.sfc_fast_boot = 0;
    mask_softflag_config(&app_soft_flag);
}

u8 power_soff_callback()
{
    DO_PLATFORM_UNINITCALL();
    __mask_io_cfg();
    gpio_config_soft_poweroff();
    GPIO_CONFIG_UNINIT();
    return 0;
}

Source: power_app.c

开机电源早期流程

power_early_flowing() 是上电后电源子系统的最早执行序列,顺序本身即设计意图:先 lowpower_init() 把低功耗代码加载进 overlay 段(保证后续即使进入睡眠也有驻留代码可用)→ 初始化 boot ROM 与端口表 → 若开启调试则在电源初始化前用 PORT_PROTECT 保护打印口(否则电源初始化会把打印口置高阻导致日志丢失)→ 最后 power_early_init((u32)gpio_config) 把 GPIO 配置传给 PMU 驱动:

void power_early_flowing()
{
    /*默认把低功耗部分代码加载到power overlay段*/
    lowpower_init();

    PORT_TABLE(g);
    init_boot_rom();

    //开打印则开机需要保护打印口,否则初始化完打印后面电源初始化会被设置成高阻
    if (libs_debug) {
        PORT_PROTECT(UART_OUTPUT_CH_PORT);
    }

    power_early_init((u32)gpio_config);
}

Source: power_app.c

核心流程:一次完整的低功耗睡眠周期

sequenceDiagram
    participant RTOS as FreeRTOS idle 任务
    participant PM as 电源框架 (power_api)
    participant CB as power_app 回调
    participant HW as 硬件 (LDO/晶振/定时器)

    RTOS->>PM: vPortSuppressTicksAndSleep(usec)
    PM->>PM: low_power_trace_drift(usec) 校正tick漂移
    PM->>CB: sleep_enter_callback(step)
    CB->>HW: USB IO置高阻 + 保存DIR
    PM->>HW: 切换VDDIOW挡位(PD_VDDIO_KEEP)<br/>保持/关闭外设电源域
    PM->>HW: 切换到低功耗晶振(OSC_TYPE_LRC/BT_OSC)<br/>启动lptmr计时
    HW-->>PM: 计时到/唤醒源触发
    PM->>HW: 恢复工作晶振与LDO挡位
    PM->>CB: sleep_exit_callback(usec)
    CB->>HW: 恢复USB IO方向
    PM->>PM: 补偿睡眠期间的tick
    PM-->>RTOS: 返回,继续调度

流程要点:

  1. FreeRTOS 的 idle 钩子通过 vPortSuppressTicksAndSleep(usec) 请求睡眠,usec 由调度器根据下一个定时事件计算——睡眠时长被精确限制,不会错过任务唤醒点。
  2. 框架先做 low_power_trace_drift tick 漂移校正,再进入硬件睡眠,保证醒来后系统时间连续。
  3. sleep_enter_callback 在关中断的单核环境下执行板级收尾(USB 高阻),随后框架切换 VDDIOW 挡位、保持策略(VDDIO_KEEP_TYPE)、低功耗晶振并启动 lptmr。
  4. 唤醒后按逆序恢复:晶振/LDO → sleep_exit_callback 恢复 IO → tick 补偿 → 返回调度器。整个进出过程对应用任务透明。

配置选项

以下配置项分布于板级配置与电源框架,供开发者按硬件变体调整:

配置项类型默认/可选值说明
LVD_WARNING_FOR_LOW_POWER宏1 (0/1)1:低电阈值用 LVD 警告电压+200mV;0:固定 3300mV
LOW_POWER_VOL宏/变量lvd_warning_voltage 或 3300低电判定阈值(mV)
_power_param.configu8LOWPOWER_CLOSE(0) / SLEEP_EN(1) / DEEP_SLEEP_EN(2)低功耗模式使能
_power_param.osc_typeu8OSC_TYPE_LRC(0) / OSC_TYPE_BT_OSC(1) / OSC_TYPE_NULL(2)低功耗晶振类型
_power_param.btosc_hzu3224M 默认蓝牙晶振频率
_power_param.osc_delay_usu32预留低功耗晶振起振延时
_power_param.vddiom_levu8VDDIOM_VOL 枚举工作态 VDDIOM LDO 挡位
_power_param.vddiow_levu8VDDIOW_VOL 枚举低功耗态 VDDIOW LDO 挡位
_power_param.lptmr_flowu8用户配置低功耗参数(预留)
PCONTROL_DCVDD_CAP_SW命令参数0/1DCVDD 是否外挂电容
PCONTROL_FLASH_PG_VDDIO命令参数0/1Flash 电源引脚是否使用 IO
PCONTROL_RTC_CLK命令参数类型值RTC_CLK 类型,决定开/关机晶振流程
PCONTROL_POWER_SUPPLY命令参数0/10:IOVDD 供电;1:VPWR 供电
PCONTROL_PD_VDDIO_KEEP / PCONTROL_SF_VDDIO_KEEP命令参数VDDIO_KEEP_TYPE 枚举sleep/soff 的 VDDIO 切换流程
PCONTROL_PD_KEEP_LPCTMU命令参数0/1睡眠时触摸通道是否保持
PCONTROL_SF_KEEP_LRC命令参数0/1软关机时 LRC 是否保持
CONFIG_UART_DEBUG_PORT宏TCFG_UART0_TX_PORT 或 -1调试口端口,决定 USB IO 保护逻辑

API 参考

void app_power_init(void)

应用层电源初始化:初始化低电阈值(LVD+200mV)、注册 ADC_CH_PMU_VBAT 采样通道并阻塞采样 10 次直到拿到稳定 VBAT。

void app_power_scan(void)

周期扫描函数(通常由定时任务周期调用):读取 VBAT,连续 10 次低于 LOW_POWER_VOL 时打印告警并 post_msg(1, MSG_LOW_POWER);非 AD/矩阵按键配置下主动 adc_kick_start(NULL) 维持采样。

u32 app_power_get_vbat(void)

返回当前电池电压(mV),内部将 ADC 采样值乘 4 还原分压;采样无效时返回 -1(即 0xFFFFFFFF)。

void power_early_init(u32 arg) / power_later_init(u32 arg) / void power_init(struct _power_pdata *pdata)

电源三段式初始化:早期(携带 gpio_config)建立最小电源环境;后期完成平台策略;power_init 注入 _power_param 参数。注意:power_early_init 由 power_early_flowing() 调用,必须先 lowpower_init() 并保护调试口。

u32 power_control(enum PCONTROL_CMD cmd, u32 arg)

  • 参数:cmd 为 PCONTROL_CMD 命令字(0x100 电源 / sleep / soff 分组);arg 为对应命令参数(如 VDDIO_KEEP_TYPE 或 0/1)。
  • 返回:执行结果/状态值。

void lowpower_init(void) / void lowpower_uninit(void)

加载/卸载低功耗 overlay 代码段与驱动,必须在进入低功耗能力前调用 lowpower_init()。

void vPortSuppressTicksAndSleep(u32 usec) / void sys_power_down(u32 usec) / void sys_softoff(void)

  • vPortSuppressTicksAndSleep:FreeRTOS 低功耗 tickless 入口,睡眠 usec 微秒。
  • sys_power_down:非 RTOS 场景直接睡眠入口。
  • sys_softoff:软关机入口,触发 power_soff_callback() 后整机待机。

s32 low_power_trace_drift(u32 usec)

  • 参数:usec 计划睡眠时长。
  • 返回:s32 漂移校正值,用于补偿睡眠期间 FreeRTOS tick 误差。

回调契约(平台实现)

回调触发时机约束
void sleep_enter_callback(u8 step)进入睡眠前单核、关中断;禁止打印/耗时操作
void sleep_exit_callback(u32 usec)退出睡眠后恢复 IO 方向等板级状态
u8 power_soff_callback(void)soft-off 前平台 uninit + GPIO 软关机态配置

故障模式、边界情况与并发

低电检测的误报与漏报

  • 误报抑制:app_power_scan() 采用连续 10 次计数去抖。电池在播放/射频大电流瞬间电压跌落不会立刻触发告警,只有持续低压才判定低电。设计权衡:计数阈值过小易误报,过大则告警滞后。
  • 漏报风险:阈值 lvd_warning_voltage = lvd_voltage + 200 依赖 get_lvd_vol() 正确读取 efuse/寄存器。若 LVD 配置缺失,应回退到 LVD_WARNING_FOR_LOW_POWER = 0 的固定 3300mV 方案。
  • 采样失败:adc_get_voltage 返回 -1 时 app_power_get_vbat() 与 app_power_scan() 均直接跳过,不会用脏数据触发低电。

睡眠时序与并发约束

  • sleep_enter_callback 运行于关中断单核环境,任何耗时操作(如打印、阻塞 IO)都会拉长中断关闭窗口,可能导致蓝牙协议栈超时——源码注释明确"此函数禁止添加打印"。
  • vPortSuppressTicksAndSleep(usec) 的 usec 由调度器约束,睡眠期间不可调度;low_power_trace_drift 用于消除 tick 计数漂移,若未校正会导致任务唤醒时刻整体偏移。
  • overlay 代码段是低功耗正确性的前提:若 lowpower_init() 未在 power_early_flowing() 中执行,睡眠恢复后代码可能因 Flash/DDR 掉电而取指失败。

soft-off 与快速启动的相互作用

power_soff_callback() 通过 mask_softflag_config 把 sfc_fast_boot 清零,保证软关机唤醒后走完整启动流程(重新初始化外设而非快速恢复)。若应用依赖快速启动语义,需自行管理软标志,否则软关机后的启动路径会与预期不符。

USB 调试口与低功耗冲突

当 CONFIG_UART_DEBUG_PORT 为 DP/DM 时,睡眠前必须保存 JL_PORTUSB->DIR 并置高阻,退出后恢复。若省略该处理,睡眠期间 USB 口漏电会显著抬高整机功耗;若恢复逻辑缺失,调试口在唤醒后失效。

性能与运维考量

  • 低功耗收益:sleep 模式保留 LRC/BT_OSC 计时与快速唤醒路径,适合蓝牙耳机等频繁空闲唤醒场景;deep-sleep 关闭更多电源域,唤醒延迟增大;soft-off 功耗最低但需外部事件唤醒。三档功耗/延迟权衡由 _power_param.config 与 PCONTROL_* 命令组合决定。
  • 开机电压稳定化:app_power_init() 阻塞采样 10 次,保证应用拿到稳定 VBAT;app_power_powerup_kick_start 自嵌套回调避免了启动瞬间 ADC 未就绪的无效读数。
  • 调试技巧:sleep_enter_callback/sleep_exit_callback 的 '<'/'>' 字符输出可作为睡眠进出频率的低成本观测手段;lowpower_dump() 可导出低功耗内部状态用于问题定位。
  • ADC 采样维持:非 AD/矩阵按键方案下 app_power_scan() 末尾主动 adc_kick_start(NULL),保证下次扫描时已有最新采样结果,避免扫描周期与采样周期错位。

扩展点

  1. 板级电源策略:通过 _power_param(vddiom/vddiow 挡位、osc_type、config)与 power_control(PCONTROL_*, arg) 适配不同硬件:DCVDD 电容、Flash 供电、供电方式(IOVDD/VPWR)、触摸保持、soff 时 LRC/NVDD/PVDD 保持。
  2. 低功耗回调:在 power_app.c 的 sleep_enter_callback / sleep_exit_callback / power_soff_callback 中挂接板级动作(如矩阵按键行 IO 拉低、外设掉电)。注意回调运行环境约束(关中断、禁耗时操作)。
  3. 晶振选择:low_power_reset_osc_type / low_power_get_osc_type 允许运行时切换 LRC 与 BT_OSC,适合不同唤醒精度/功耗需求的动态策略。
  4. 低电策略:MSG_LOW_POWER 消息由应用自行消费,可扩展为"降频 → 停止功能 → 关机"的多级策略(SDK 仅负责检测与上报)。

相关文件与链接

  • app_power_mg.h — 应用层电源宏与接口
  • app_power_mg.c — VBAT 采样与低电检测实现
  • power_api.h — 电源框架 API 与参数结构
  • power_app.c — 平台回调与启动流程
  • power_config.c — 板级电源参数配置
  • power_interface.h — 电源接口汇总
  • power_wakeup.h — 唤醒源定义
  • lib_power_config.c — 库级电源配置

相关主题指引:唤醒源与 GPIO 配置见 GPIO 驱动文档;RTC/晶振流程见时钟管理;VM 参数存储(mask_softflag_config 等软标志)见系统参数文档。

Prev
消息与事件机制
Next
固件升级机制