记录一下bootloader升级Bug分析及复现最后解决的整个过程

描述

前言

这几天遇到一个bootloader升级的奇怪问题,分析问题的过程使用了一些常用的分析工具和方法觉得很有普遍性,这里记录一下Bug分析、复现最后解决的整个过程,希望能给大家带来一些启发。

正文

环境描述

ECU使用瑞萨公司的RH850芯片,bootloader支持应用的双分区刷写。

测试用例

当前程序处于A分区 --> 开始升级,跳入bootloader  --> 升级A分区程序 --> 故障注入,跳过升级的0x34服务,直接开始0x36服务传输升级包程序

bootloader

图1:Bootloader故障注入测试

bootloader

图2:Bootloader升级常用的UDS服务ID

期望结果

Bootloader升级失败,0x11 01软件复位后Bootloader校验A分区失败(默认跳到A分区),程序跳到B分区,正常运行B分区程序。

bootloader

图3:A分区升级失败后跳到B分区期望正常通信状态

实际结果

Bootloader升级失败,0x11 01软件复位后Bootloader校验A分区失败(默认跳到A分区),程序跳到B分区,程序的通信都异常(每次重启后只发出一帧报文,间隔很久又会发出一帧报),但是诊断功能是OK的。

bootloader

图4:A分区升级失败后跳到B分区实际异常通信状态

问题分析

1)诊断功能OK的,说明程序没有跑死,上电只发一帧报文很像是应用满足条件关闭通信了。ECU在以下三个状态下会关闭通信。

. IGOFF

.低电压(低于6.5V)

.低功耗模式 && 没有处于EOL(End Of Line,下线模式)

第一个和第二个条件直接测试外部硬件输入可以确定不可能满足。第三个条件需要诊断触发,理论上是不可能满足条件。

初步结论1:不是外部硬件输入状态导致关闭通信,也不是诊断时间关闭通信。

2)尝试各种正常情况下的刷写操作

. 处于A分区,刷A分区

. 处于A分区,刷B分区

. 处于B分区,刷A分区

. 处于B分区,刷B分区

结果,无论最后是在A分区还是B分区,通信都是正常的。

初步结论2:正常情况下的程序刷写都成功,且通信正常。

3)问题发生后ECU就一直处于故障状态了,这个时候可以考虑使用调试器的热插拔功能(Hot Plug-in,不重新Download程序到ECU当中,直接进入调试模式,ECU中运行的还是故障状态下的程序)。

调试上位机:RH850提供的CS+

调试仿真器:瑞萨专用的E2

bootloader

图5:CS+的热插拔选项

bootloader

图6:CS+的调试器E2配置

图7:程序进入了低功耗状态下关闭通信的分支

按照1)中的分析,程序不可能进入低功耗状态下关闭通信的分支,除非是进行分支判断的全局变量被异常篡改了。

初步结论3:启动模式的全局变量被异常篡改,导致程序进入到低功耗模式下关闭通信了。

全局变量被异常篡改,一般是数组越界或者是指向全局变量的指针操作异常导致的,但是如果是这样的话,和升级没啥关系,无论最后跳到A分区还是B分区都会出现异常,所以应该不是程序本身的问题。

4)让测试同事在B分区进行故障注入测试。

. 当前处于B分区

. 升级B分区

. 跳过0x34开始传输数据服务

最后升级B分区失败,跳到A分区,A分区的通信是正常的。

初步结论4:B分区升级B分区进行故障注入后跳到A分区是正常的。

5)尝试自己复现问题。测试同事的测试用例是跳过0x34服务后开始传输数据,其实也就是A分区被擦除后升级失败,跳到了B分区。那么理论上我复现问题的时候,只要满足以下条件就能复现文:

. 当前处于A分区

. 开始升级程序

. 擦除完A分区数据

. 还没升级完A分区程序就断开物理连接,确保A分区升级失败

最后确实升级A分区失败,跳到了B分区,但是B分区的通信却是正常的。为什么自己的测试结果和测试同事的测试结果不一样了?-- 分析测试同事的测试用例:

. 开始升级

. 跳过0x34服务

. 0x36开始传输数据

和上面我的复现步骤对比,测试同学的测试用例因为跳过了0x34服务,所以ECU的A分区是完全被擦除的状态,我的操作是在程序刷写了一部分的情况下断开物理连接,所以A分区被擦除后又被写入部分数据。

6)模拟测试同事的测试步骤。

擦除完A分区数据后还没开始传输A分区的数据就立马断开物理连接。

成功复现问题!!!

分析5)和6)两种操作,不同点就是擦除完A分区后数据后又往A分区写入了部分数据。写入的部分数据影响了A分区程序的运行。

7)使用瑞莎公司提供的RFPV(Renesas Flash Programmer)将5)和6)两种操作后的程序都读出来进行对比。

bootloader

图8:读取两种操作下的Flash中的程序

bootloader

图9:使用hexview工具对比B分区通信异常和B分区通信正常下的程序

异常情况下的程序从0x40000开始处数据是被擦除的,正常情况下的程序的0x40000开始的程序是有数据的。

为啥A分区0x40000处开始的数据会影响B分区的程序运行?

8)查看A分区和B分区的链接文件

bootloader

图10:A分区链接文件

bootloader

图11:B分区链接文件

找到问题,A分区和B分区的标定数据用的是同一块Flash地址!

9)修改B分区链接文件

bootloader

图12:修改B分区链接文件的标定量起始地址

最后上板验证通过,问题解决。

10)为啥标定量的数据被擦除后会影响到通信?-- 猜测是标定段数据被擦除后标定相关的协议数据读写异常,最后导致进行分支判断的全局变量被异常篡改了。目前还未想到验证猜想的办法。

总结

这个问题分析了足足一天,分析问题的过程很具有代表性:发现问题 --> 推测原因 -->验证猜想 --> 验证失败 -->对比分析推测-->猜测验证 -->成功解决,逐步抽丝剥茧,层层递进,最后解决问题。

希望对各位看官有所启示。中间还用到了调试器的热插拔功能,编程器的读取ECU程序的功能,hexview对比Hex文件的功能,这些功能在分析问题中经常用到。






审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分