| 一天的时间,两个好基友,一行#define预定义,这三个元素组成了今天这台戏! 公司有一个测试项目安排我来写一段测试工程。工程的技术需求明确,业务逻辑简单。抽象出来也没有多少——启动MCU,配置一些参数,再从中断函数中观察测试结果是否符合预期。 我倒是很快写完了代码,因为业务逻辑并不多,并且项目的主分支上也可以利用现成的软件环境,所以改动并不大,时间也没有花掉多少。 交付之后,我的好基友来测试验证。不久,他反馈,测试未通过!原因是由于配置参数有前置条件,上回的文档未包括。这回才补全,让我赶紧再出一版固件。 补全的内容也不多,又不影响架构。简单写了几下,程序就修改完成了,再次提交给他。 没过多久,他就反馈,仍然不通!而且,MCU貌似宕机crash了!他也坐到我工位旁边,与我一起分析 、调试! 从代码配置到堆栈溢出,从变量初始值再到MAP表。由于crash的时间正好在开启中断的那一刻,我们又对了中断线编写和中断函数列表是否有错位。文档也从业务逻辑,查到keil的帮助文档。大脑好久没有这么快的运行过了! 就当我们计划放弃另请高人的时候,我突然意识到是不是中断向量入口地址写错了!如果中断向量入口地址写错了,也就是基地址错了。中断入口函数的偏移地址即使正确,当中断触发时,同样会发生调用空指针的crash后果。在ARM Cortex-M系列的MCU中,中断向量入口地址是通过SCB->VTOR寄存器写入,是在系统进入main()函数之前由预置代码完成。 这时,倒是熟练的打开了system.c文件,查看systeminit()函数的实现。果然,我的上一位同事是直接把SCB->VTOR的预置代码修改了,如下所示: 而正确的应该为://#ifdef VECT_TAB_SRAM
    SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;
//#endif
 我git pull下来的项目代码的上一位同事,估计没有注意看预定义部分,而是上手直接修改了SCB->VTOR的实现代码。在项目中的实现与变更应该遵守项目原代码的框架设计即修改头部的预定义(官方代码也有注释说明):#ifdef VECT_TAB_SRAM
    SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;
#else
    SCB->VTOR = FMC_BASE | VECT_TAB_OFFSET;
#endif
 //#define VECT_TAB_SRAM
/* Vector Table base offset field. This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET       0x00
 也就是说,我的上一位同事应该把上面第1行的代码注释去掉即可,systeminit()函数的内容不应该修改。 这个调试bug终于解决了!我也把代码恢复了原官方架构。 我们这次的bug调试还是非常辛苦,所以,大家在团队编码的时候,一定要注意只修改,只更新属于自己负责的那部分代码。切记!切记! 
 @Gfan 参加活动了
 
 
 
 
 
 
 |