资源冲突导致启动黑屏问题
问题记录:资源冲突导致启动黑屏问题
1. 问题发生
终端客户反馈:上电后中控没有启动,仍为黑屏;
进一步获取信息如下:
- 836版本软件6台机器进行自动化开关机实验测试,其中3台出现此问题;
- 客户同样方式煲机9台(Debug版本),一晚上未出现问题;
- 客户将其中6台机替换为836版本软件,测试5小时,4台出现此现象;
- HW排查异常机器,晶振没有工作,MCU有正常给AP供电;
2. 问题分析
2.1 排除board 影响
由于HW排查出现晶振没有工作的情况,担心board存在问题,立即到现场进行处理,首先排除board设计问题:
- 将两台机器连接串口打印,进行开关机测试;
- 其中机器A在10分钟左右出现问题,此时量取晶振,是有在工作的
说明并非board 晶振不振导致系统停止工作,而是其他原因导致异常,而后系统不再工作,需要分析log情况,进一步确认问题点;
2.2 排查方向
根据当前所了解到的信息排查方向如下:
- 根据log信息正面排查,确认异常逻辑;
- 从获取信息来看,debug版本和user版本表现有差异,可以进行交叉对比实验缩小范围;
2.3 具体分析
反复测试多次,log基本都卡在相同位置:
从这个位置来看存在几种可能性:
- 异常环节在lk中,从这个log信息来看,还没有进入kernel;
需要打开lk中log信息进一步确认;
- 异常环节在kernel中,由于kernel在uart初始化完成之前将log信息存储在内存中,如果这个阶段出现block,可能也是卡在这个位置的;
需要打开early console打印kernel中log确认;
- 异常环节在tee中,由于客户会修改这部分使用,所以也存在这种可能性(较小);
由于debug版本没有此问题,可以交叉替换tee.img测试
2.3.1 打开log操作
-
Kernel 打开early console,并设置默认输出log:
kernel-4.9/arch/arm/configs/$(Device)_defconfig 添加 CONFIG_SERIAL_MTK_EARLY_CONSOLE=y
drivers/tty/serial/ 中添加 mtk_earlycon.c
将disable_uart设置为0 -
LK打开log分析,目前怀疑这部分的可能性比较大:
/vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/$Project/default.mak 设置CFG_UART_DYNAMIC_SWITCH :=0
/vendor/mediatek/proprietary/bootable/bootloader/lk/project/$Project.mk DEBUG:=1 这里会控制log的打印,默认0的情况会把loglevel设置为2:
2.3.2 实验排除部分可能性
- Tee 初始化时还没有运行到客户修改的部分,理论上这部分可能性比较小;
- 机器A出现问题后烧录Debug版本测试未出现问题,存在两种可能性:
- Format all操作将emmc清空后重新烧录,即format all操作修复问题;
- 烧录为新的image,修复问题;
- 测试2小时后还是出现问题,则上述怀疑点排除;
- 由于烧录image有verify限制,所以需要首先替换preloader,替换为对应disable verify版本
- 机器A在683版本上烧录preloader_disable debug版本tee.img,半小时后复现到了问题,排除tee部分影响;
- 机器A在683版本上烧录上述添加log后的 preloader、lk、boot三个分区
- 将lk和preloader替换为原来683异常版本,半小时内出现问题
此实验得出结论:为preloader + lk影响
2.3.3 跟踪改动宏部分逻辑
由于lk & preloader使用为683版本,仅为进行了上述操作问题消失,则存在如下两种可能性:
- 为打开log影响;
- 上述宏的开关还会影响到其他部分;
源码目录搜索该宏,可以看到只有如下部分有使用:
- 在platform.h中定义了一个变量:log_dynamic_switch:
- Print.c中定义了一个变量g_log_switch,在set_log_switch将其设置为1:
- 推测启动过程中一定会用到这个变量来进行操作,依次查看这几个宏控制位置,我们需要找到的是控制lk log的位置,主要怀疑这个位置:platform_set_boot_args_by_atag,字面意思是通过这里往lk继续传递参数,tags->u.log_com.log_dynamic_switch = (u8)get_log_switch()
实验验证:
- 将宏仍然设置为0,然后将这个参数配置为1,结果可以正常输出lk log信息,说明就是这里控制的;
- 将宏设置为1,这里参数配置为0,结果无法输出lk log信息,并且很快复现到一次问题;
则这部分实验说明:
- Lk部分log控制实际就是tags->u.log_com.log_dynamic_switch
- 问题大概率是由log触发的
进一步在lk部分查看这个变量的作用:
从流程上来看仅仅是管控log信息,但是为了保险起见我们继续做两个实验:
- Log_dynamic_switch设置为1,然后uart两个判断直接返回;
- Log_dynamic_switch设置为0,然后uart两个判断强制执行;
结果:实验2的情况下有log打印,且未测到异常现象;实验1无log输出,且可以复测到问题;
则经过上述几个对比实验,说明问题受是lk部分的log信息打印影响,这也进一步佐证了为什么debug版本无问题而user版本有问题,而log信息对于系统的影响主要是时序,所以接下来两个方向排查:
- 对比lk部分的改动,是否有可能造成系统block的可能性
- 逐步关闭log信息排查,缩小范围;
结果比较顺利,对于lk部分的改动内容较少,I2C部分的改动非常值得怀疑,由于将其去除后短时间内如果测试不到问题,则很难说明问题,所以反向测试,在添加log信息的情况下将这部分对I2C的操作修改为循环处理持续2分钟:
结果必现问题,则说明确实为lk中添加的I2C操作影响,由于I2C部分在ARM9中也有操作,则同时操作同一组I2C的时候会出现资源冲突问题;
抓取相关波形证明问题:
3. 问题处理
经过上述分析,确认问题原因为ARM9 与 A53在lk阶段同时操作I2C模块,导致系统崩溃,block住10分钟后系统不再工作;
由于存在两个核之间同时操作某IP的可能性,建议客户将对于I2C操作均放在ARM9中,避免在LK中使用,修改后安排9台机器煲机两天未出现此问题;
4. 整理
上述过程中获取如下信息:
- Lk部分的log信息管理是如何进行的,相关控制关键位置;
- 由于ARM9会对UART I2C SPI等接口进行通信,需要限制资源竞争冲突,避免出现此类问题;
- log打印会影响到时序进而影响程序结果;