问题描述
最近在忙公司项目的时候,要调试一个新功能,防止BootLoader的干扰,故将BootLoader屏蔽了,直接将app的中断向量表改为默认的,发现运行不了,将所有代码屏蔽掉,只留一个系统滴答定时器,和一个gpio控制灯光闪烁。发现还是运行不了。卡死在如下界面:
0xFFFFFFFE 0000 MOVS r0,r0 卡死在了这一句汇编代码。很明显这个地址已经超出了mcu内存的寻址范围。经过多次测试都是这个问题。
问题排查
反复编译验证后,发现如果将delay函数改为硬件延时同时屏蔽掉系统滴答定时器的初始化,就是工作正常。上图中的delay是调用了系统滴答定时器的计数值。
疑似跟系统定时器有关系,最终发现滴答定时器的中断怎么都进不了。换另外一块板子上的程序也改成只有一个闪灯和系统滴答定时器,然而在另外一块板子上的程序能正常运行。与硬件同事排查了晶振是否起振,都正常。
百度这个问题,也没有发现如何解决,基本分析都是指针指向了内存以外的地址,可能是野指针问题,但是,明显跟我这情况不同,我这代码不可能存在野指针(都没有用到指针)。
问题解决
排查了一圈后,发现领一块板子上的程序运行正常,且这两块板子的单片机型号是一样的,不同的是两块板子的晶振频率不一样。仅此区别,最后还是怀疑代码中哪里有问题。于是从.s文件开始查找。
单片机上电后先是调用了SystemInit函数,该函数执行完毕后,才跳转到main函数执行。找到该函数的定义。
void SystemInit(void)
{
/* FPU settings */
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 20) | (3UL << 22)); /* set CP10 and CP11 Full Access */
#endif
SystemCoreClockUpdate();
#if defined (ROM_EXT_QSPI)
SystemInit_QspiMem();
#endif /* ROM_EXT_QSPI */
/* Configure the Vector Table relocation */
SCB->VTOR = VECT_TAB_OFFSET; /* Vector Table Relocation */
}
这个函数的最后一句指定了中断向量表的地址。一般来说都是单片机运行的起始地址,对于stm32 或gd32等中断向量表默认是0x8000000,对于hc32是0x0。接着看下VECT_TAB_OFFSET发现该值不是默认值,而被改到了app的中断向量表位置。到这里虎躯一震,感觉问题找到了,立刻将改宏定义改为0x0,编译运行,一切正常,led灯按照2s的周期稳定闪烁。至此问题解决!文章来源:https://www.toymoban.com/news/detail-744423.html
吐槽:感谢前同事写的一手好代码。正常使用了bootloader后都是在main函数中,改变中断向量表的位置。而SystemInit这是系统起来前的硬件初始化,基本上不会去动它。很难想象前同事为什么要改这里。文章来源地址https://www.toymoban.com/news/detail-744423.html
到了这里,关于单片机0xFFFFFFFE死机问题解决的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!