DIY USB 电流表番外篇:使用 PlatformIO Inspect 分析和优化固件体积

在前一篇 《DIY USB 电流表(8):绘制功率曲线》 的开发过程中,我还碰到一个额外的问题,在最终开源的代码中虽然已经解决了,但是在文章中并没有提到,这就是编译固件体积超出 Flash 限制的问题。

这里就分享一下碰到 CH32V003 固件编译后体积超过 Flash 如何查找原因、解决问题的过程。

PS. 我也还是一个初学者,如果文章中有一些错误或不足,还请多多指教。

编译后固件体积超标

在定义了功率历史数据缓存的变量,添加数据存储、屏幕画点驱动、按键检测等代码之后,照常编译一下固件,检查一下代码有没有错误,却突然发现编译出错了:

diy-usb-meter-inspect-1

一看错误原因: region 'FLASH' overflowed by 772 bytes,这就意味着编译完的固件体积已经超过了 CH32V003 的限制,毕竟CH32V003 只有 16KB 的用户代码空间。

在前几篇中编译完成也可以发现,固件体积已经快到达极限了,没想到这么快就已经超出不够用了。

排查固体体积构成

幸好 PlatformIO 提供了 Inspect 功能,可以用于分析固件编译产物中的各种资源使用情况,包括 Flash 占用、内存使用、静态代码检查等,通过这个工具,就可以快速分析固件编译完后,哪块代码或资源占用的体积最大。

PlatformIO Inspect 文档可以参考这里: https://docs.platformio.org/en/latest/home/index.html#project-inspect

使用 Inspect

要使用 PlatformIO Inspect 功能很简单,直接在 PlatformIO 侧边栏中通过菜单打开 Inspect 工具。

diy-usb-meter-inspect-2

PlatformIO 会展示 Project Inspection 选项界面,这里可以选择分析哪个项目、分析哪些内容:

diy-usb-meter-inspect-3

注意:要使用 PlatformIO Inspect,需要先保证固件能在 Inspect 环境编译通过,并且使用 Inspect 功能时,可能固件体积会相比正常编译更大,这个时候可以通过删除一部分代码来使编译通过,从而正常使用 Inspect 功能。

分析结果

在点击 Inspect 按钮后,PlatformIO 就会开始编译整个项目,并且记录项目中各种资源、符号的体积。

diy-usb-meter-inspect-4

最终 PlatformIO 会生成一个报表,包括固件的内存使用情况、Flash 使用情况以及可能存在的代码缺陷。

另外在统计界面,还可以看到主要的体积占用是哪些符号或文件导致的。

diy-usb-meter-inspect-5

在这里我们主要关注 Flash 占用情况,并且主要关注 Symbols 中的体积大小。

解决问题

排查固件大小超标元凶

进入到 Inspect 功能的 Symbols 界面,并将整个列表按 Size 倒序排列,可以看到哪些符号占用了特别大的体积。

diy-usb-meter-inspect-

在这个列表中,如果符号有对应的源代码位置,也可以直接通过符号后面的放大镜定位到代码位置。

diy-usb-meter-inspect-8

在上面的符号列表中,可以看到 __subdf3__divdf3ssd1306xled_font8x16mdos__muldf3 这几个符号的体积特别大,单个体积都超过了 1K。其中 ssd1306xled_font8x16mdos 我们可以明确知道,这个是英文字符的字体文件,没办法删除。

那么另外三个符号就很可疑了,通过搜索我们可以发现,这三个符号都是浮点计算相关的代码,并且还是软件浮点计算库。

diy-usb-meter-inspect-9

这就奇怪了,难道 CH32V003 并没有集成硬件浮点计算功能吗?通过查阅数据手册以及 RISC-V 指令集的支持情况,CH32V003 使用的指令集为 RV32EC,它并不包含浮点计算相关的指令。

找寻浮点计算源头

在我们自己编写的固件代码中,基本都没有使用浮点类型,少有的浮点数据也是从 INA219 驱动中获取的,因此就从 INA219 开始排查。

在 INA219_WE 库的代码中,可以看到大量浮点计算相关的代码,并且在我们主要使用的两个方法 setShuntSizeInOhmsgetShuntVoltage_mV 中,就有浮点计算的代码。

可以看到,在这两个方法中,分别使用除法和减法,计算了采样电阻的系数和用户设置的采样电阻电压偏移。

diy-usb-meter-inspect-10

那么我们就从这两个方法入手,优化一下看看能不能减少固件体积吧。

优化固件体积

在前面的符号表中,我们可以知道这里同样有浮点乘法的使用,并且在数据管理中,也会存在需要使用浮点乘法的情况,例如通过电压、电流计算功率。

除法换乘法

在采样电阻系数的计算中,可以看到它是按标准 100 豪欧采样电阻来计算的,它这里使用了除法来计算系数,因为乘法必不可少,这里将它换成乘法来减少除法的使用。

去掉减法

另外,我们并没有去设置采样电阻偏移校正,因此可以将 getShuntVoltage_mV 中的偏移校正直接去掉,这样就可以去掉浮点减法的使用了。

diy-usb-meter-inspect-11

当然,这只是我们的一次尝试,还需要实际检验一下,才能知道这样的优化是否有效果。

检验优化效果

再次使用 PlatformIO Inspect 工具,对固件体积进行分析。

从分析结果看,固件体积减少了 2.8KB,大大小于之前的 15.5KB。

diy-usb-meter-inspect-12

并且在 Symbols 页面中也看不到 __subdf3__divdf3 方法了。

diy-usb-meter-inspect-13

再次将固件需要的代码添加进项目,已经可以正常编译了:

diy-usb-meter-inspect-14

小结

CH32V003 的资源相当紧张,还不支持硬件浮点指令,因此在固件开发时需要额外注意资源、指令的使用情况,尽量使用整数的计算,如果需要使用浮点,也可以尽量合并,否则就要面临 Flash 不够用的问题了 😂。

从这个问题也感受了一下廉价 MCU 在开发时的局限性,作为现代移动端和桌面端软件工程师,平时也难感受到在 Flash 和内存以 KB 为单位场景中的开发体验。

USB 电流表开源地址

这个 USB 电流表所有资料已经开源,可以在以下仓库中获取,包含固件代码、PCB 生产 Gerber 文件、原理图和外壳 STL 文件。

https://github.com/ohdarling/CH32V003-USBMeter

硬件相关的源文件已经在立创开源平台开源,访问以下地址可以进行一键 PCB 下单和一键 BOM 配单操作:

https://oshwhub.com/wandaeda/ji-yu-ch32v003-de-usb-dian-liu-biao

DIY USB 电流表系列

其他 DIY 项目

30 元 DIY 一个柔性灯丝氛围灯

diy-ambient-light-1

教程地址: https://xujiwei.com/blog/2024/04/diy-ambient-light/

参考资料

发表评论?

0 条评论。

发表评论


注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>