本帖最后由 woshiyaohaoki 于 2023-2-2 10:00 编辑
一、 问题描述
最近工作遇到一个问题,手头一个项目,X定制协议版本的静态运行功耗比常规程序大2uA。
已接近警戒值。
二、 问题分析
a) 大前提:
该产品所有定制版本使用同一源码,通过协议宏配置,基础功能可复用,定制版本额外拥有定制化功能。
b) 初步排查
测试三套最新程序的功耗 分别是常规180,定制X180,定制Y180。
常规180 功耗正常
定制X 180 功耗异常
定制Y 180 功耗正常
发现有且仅有X功耗异常,大2uA,比对源码 X定制拥有状态机上报模式(登陆帧,数据帧,下线帧),此时怀疑状态机上报模式影响功耗,继续测试同样拥有状态机上报模式的定制X1
定制X1 功耗异常。
定制X1 定制X 关闭状态机上报模式后,功耗正常。
如下图:
c) 状态机上报模式排查
进一步对状态机上报模式产生了怀疑,该功能为X定制首版程序新增,测试常规160,定制X 160,功耗均正常。如此也排除单一功能的影响。
d) 定制X 各版本比对排查
比对定制X 160与定制X 181源码,定制化源码部分,修改增加了设备地址变长功能(此功能设备地址长度可通过上位机进行设置,由此新增一个全局变量进行地址数据存储)。
一点点剥离该代码,发现去除该功能后,功耗正常。
后尝试将此全部变量从custom_X.h定制挪到custom_com.h中。功耗竟奇迹般的正常了。
到此基本治标了,但是根本性原因依然未知,探索依然在继续。
e) 代码记录排查
根据记录一点点更新代码并进行测试。
在增加日志功能后功耗异常,该功能为通用性功能,20多个定制版本都在使用均未出现功耗问题。规律类似之前状态机上报模式,
定制X 关闭日志功能 功耗正常
定制X 打开日志功能 功耗异常
常规 关闭日志功能 功耗正常
常规 打开日志功能 功耗正常
关于日志功能,与定制协议未有一丝耦合,理论上不应该出现此问题,于是重点检查日志功能。
f) 日志功能排查
日志功能一共有两部分组成
日志记录API logBuf,
日志打印任务 Log_Handle。日志功能需要上位机开启才会进行工作,默认是全关闭状态,未进行功能时功耗依然异常。 因为设备串口有限,本地串口为四路通道共用一个串口,主要目的为通讯通道,基本其他路功能交互报文,为避免日志丢失,故日志功能拥有1024字节数据缓存。
g) 综合分析
此时综合以上分析,一共发现三点线索:
比对debug中map文件,发现如下规律
栈区位置不同导致了功耗异常。
此规律适用线索1,2,3。接下去阅读cmd源码可知,栈区会在RAM和RAM2中进行分配。当分配到RAM2中功耗将会异常。
大致会出现三种情况,故保证栈区处于RAM中即可。因bss段连续原则,故保证bss大小就可保证栈区分配于RAM中
2. 原因概述:
a) 随着功能越来越复杂,RAM区占用越来越多,此次正好处于临界状态,多一个功能就超,少一个功能就不超。
b) 前人魔改cmd文件,未考虑栈区分配影响功耗。
3. 现状:
带来的影响是:
l 栈区分配不可控:栈区分配于何处无法从应用代码进行控制,也没编译提示,影响开发效率。
小结:若问题不得到解决,随着后续功能增加,所有程序功耗均会异常。
三、 寻找解决方案
1. 方案可行性分析
考虑从以下几方面作为软件识别方案的切入点:
a) bss区处理
需避免bss区占用过大。
操作1:将日志功能 1024字节数据缓存 28字节状态缓存 存入data区(定义时进行初始化即可)
操作2:去除串口冗余缓冲区保护,节约1100字节。
b) cmd文件处理:
修改cmd文件,避免栈区误分配到RAM2,中增加编译错误提示。
如下修改后,当栈区只可存入RAM中,否则编译报错
四、 总结输出
1. 有时候问题不仅仅是出在应用代码上,当排除一个接一个之后真像将会越来越近。
2. 发现根本性原因更为重要,并从根源上避免该问题出现(依靠编译器报错)。
3. 此问题进度为 0%-> 0.001%-> 0.002%->99.999%,有时候灵感也很重要。
|