功耗调试指导
📎 原始文档:https://www.kdocs.cn/l/ciTwhq957Pci 功耗调试指导
一、蓝牙功耗调试
- 参考《701N_WATCH_SDK_介绍》第七章5、6节 使用开关经典蓝牙接口,在待机情况下可以根据需求选择是否关闭经典蓝牙。

- 修改BLE广播间隔 客户可以根据 自身需求调用相关接口并配合手机 app 来控制经典蓝牙的开关以及调整
BLE 的广播和通讯间隔,以达到功耗的进一步缩小。
二、待机功耗调试(各手表穿戴系列通用)
- 影响功耗的因素
样机待机功耗偏大主要有以下几方面原因:
1、传感器模块、TP、屏幕等没有成功进入休眠。
2、某些IO状态不对,导致的漏电。
3、系统没有进SLEEP或者系统起来太频繁,比如定时器小于500ms,传感器频繁起中断唤醒主系统、蓝牙频繁唤醒等。
4、模块没有进入IDEL;
针对707补充两点:
a、RAM内存不足70KB(RAM内存 - 静态推屏内存 = 满足系统进入低功耗的RAM内存大小) ;
b、TCFG_LOWPOWER_LOWPOWER_SEL 没有置位2,(低功耗模式);
.......
DP、DM打印会增加300uA:
如果使用USB口DP、DM打印调试,需要注意此功耗会增加300uA,也就是说用DP打印调试功耗时要算上300多uA功耗是DP打印耗掉的,剩下的才是整机应用的功耗,调试完成后关闭DP打印再测量,才能得出最终的功耗。
判断线程是否进入空闲模式:
// 判断模块有没有进入IDEL:
void user_test_sleep(void)
{
struct lp_target *p;
list_for_each_lp_target(p){
printf("name:%s level:%d is_idle:%d",
p->name,
(p->level)?p->level():-1,
(p->is_idle)?p->is_idle():-1);
}
}
//注意:当所有模块都进入了IDLE,系统还没有进入低功耗,或者没有打印低功耗的S<>或D<>,那可能是开启了DUT模式。
判断IO口是否进入高阻态:
- 701
void io_mem_printf(void *priv)
{
mem_stats();
JL_PORT_FLASH_TypeDef *PO[] = {JL_PORTA,JL_PORTB,JL_PORTC,JL_PORTD,JL_PORTE,JL_PORTG,JL_PORTP};
char * str[] = {"JL_PORTA","JL_PORTB","JL_PORTC","JL_PORTD","JL_PORTE","JL_PORTG","JL_PORTP"};
u8 bit = 0;
u8 num = 0;
JL_PORT_FLASH_TypeDef *PORT = NULL;
for(num=0;num<sizeof(PO)/sizeof(JL_PORT_FLASH_TypeDef*);num++){
PORT=PO[num];
printf("IO状态仅供参考===> %d %s", num,str[num]);
for(bit=0;bit<16;bit++){
if((PORT->DIR &BIT(bit))==0){
if((PORT->OUT &BIT(bit)) && (PORT->PD &BIT(bit))){
printf("输出内部PD漏电,FLASH引脚除外");
}
if(!(PORT->OUT &BIT(bit)) && (PORT->PU &BIT(bit))){
printf("输出内部PU漏电,FLASH引脚除外");
}
}
if((PORT->DIR &BIT(bit))){
if((PORT->IN &BIT(bit)) && (PORT->PD &BIT(bit))){
printf("输入外部PD漏电,DIE置0不准");
}
if(!(PORT->IN &BIT(bit)) && (PORT->PU &BIT(bit))){
printf("输入内部PU漏电,DIE置0不准");
}
}
printf("%d DIR-%d PU-%d PD-%d DIE-%d DIEH-%d HD0-%d HD-%d OUT-%d IN-%d",
bit,
(PORT->DIR &BIT(bit))?1:0,
(PORT->PU &BIT(bit))?1:0,
(PORT->PD &BIT(bit))?1:0,
(PORT->DIE &BIT(bit))?1:0,
(PORT->DIEH &BIT(bit))?1:0,
(PORT->HD0 &BIT(bit))?1:0,
(PORT->HD &BIT(bit))?1:0,
(PORT->OUT &BIT(bit))?1:0,
(PORT->IN &BIT(bit))?1:0
);
}
}
}
- 707
//707判断是否进入低功耗:
static void low_power_level_test(void)
{
#include "power/power_manager.h"
const struct lp_target *p;
enum LOW_POWER_LEVEL level = LOW_POWER_MODE_DEEP_SLEEP;
list_for_each_lp_target(p) {
if ((p->level != NULL) && (p->level() < level)) {
printf("[LP_DEBUG]%s name:%s level:%d",__func__,p->name,p->level());
level = p->level();
if (level == LOW_POWER_MODE_LIGHT_SLEEP) {
break;
}
}
}
printf("[LP_DEBUG]%s LEVEL:%d",__func__,level);
if (level == LOW_POWER_MODE_LIGHT_SLEEP) {
putchar('L');
} else if (level == LOW_POWER_MODE_SLEEP) {
putchar('S');
} else if (level == LOW_POWER_MODE_DEEP_SLEEP) {
putchar('D');
}
}
//打印内存: mem_defrag()
- 系统完全进入深度睡眠状态的底电流 调试空闲状态下的底电流,尽量让整机的底电流降低
在代码上添加开机一段时间后调用bt_direct_close、step_stop()、heart_rate_stop();
关闭所有sensor以及蓝牙功能,等待息屏后就能使用万用表测量出整机底电流的一个状态,701正常参考功耗能达到160-200uA左右的(板子上带msa310、hrs3300、9307屏幕、cst816d触摸)。
测试程序:
现象:开机成功等待10S后进入息屏,系统就会进入休眠状态,8s唤醒一次,因为唤醒频率很低,所有可使用万用表直接测量低电流。
3. 关机电流 7012A板子上接msa310、hrs3300、9307屏幕、cst816d触摸、AW8155,5个模块由vddio供电,博雅flash PC8供电,关机正常最终测得参考电流28.93uA。如若关机电流比较大,建议分析:
①是否有模块没有进入休眠:一般模块上电是默认处于待机电流,并非完全是休眠,所以要确保所有模块都能响应到休眠指令
排查方法可以通过屏蔽模块休眠指令的代码,如果测量带休眠指令的代码比不带休眠指令时功耗要低,说明此模块休眠指令响应到了。
②IO状态不对导致的漏电:某个模块的IO口高阻状态受干扰、状态不对与内部上下拉电阻形成漏电回路等。
4. 待机状态的电流
其中图示的打印“<”、“>”是用于查看CPU是否进休眠状态的,此符号打印频率和状态与功耗是有相关性,频率越高功耗越大。另外也可以通过设置APP_IO_DEBUG_1/0某个IO输出波形,用示波器观察,高电平为CPU工作状态,低电平为CPU休眠状态。
蓝牙通讯、定时器到时间点、中断唤醒、P11到主核消息响应都会唤醒CPU退出深度睡眠进入工作,待程序处理完成所有模块空闲了再次进入深度睡眠,深度睡眠状态下主核CPU会完全掉电。
若出现不能进入睡眠状态,打开以下打印 查看是否有线程卡住不让进低功耗
SDK\apps\soundbox\log_config\lib_driver_config.c
const char log_tag_const_v_PMU AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE);
const char log_tag_const_i_PMU AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE);
const char log_tag_const_d_PMU AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE);
const char log_tag_const_w_PMU AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE);
const char log_tag_const_e_PMU AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE);
const char log_tag_const_c_PMU AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE);
系统检测各个模块是否空闲,若所有模块都为空闲状态,系统才会进入睡眠状态,可参考以下代码可在自己的模块上注册回调函数控制是否允许系统进低功耗:
SDK\apps\common\device\key\key_drive.c
//按键检测中活动中 is_key_active有值,不允许进低功耗
//按键检测非活动 is_key_active = 0,允许进低功耗,不一定是进低功耗
static u8 key_idle_query(void)
{
return !is_key_active;
}
#if !TCFG_LP_TOUCH_KEY_ENABLE
REGISTER_LP_TARGET(key_lp_target) = {
.name = "key",
.is_idle = key_idle_query,
};