如何解决单片机0xFFFFFFFE死机问题

问题描述

最近在忙公司项目的时候,要调试一个新功能,防止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 */
}

![在这里插入图片描述](https://i3.wp.com/img-blog.csdnimg.cn/9fd1acb8d76046cdb86897e58ac94dee.png
这个函数的最后一句指定了中断向量表的地址。一般来说都是单片机运行的起始地址,对于stm32 或gd32等中断向量表默认是0x8000000,对于hc32是0x0。接着看下VECT_TAB_OFFSET发现该值不是默认值,而被改到了app的中断向量表位置。到这里虎躯一震,感觉问题找到了,立刻将改宏定义改为0x0,编译运行,一切正常,led灯按照2s的周期稳定闪烁。至此问题解决!

吐槽:感谢前同事写的一手好代码。正常使用了bootloader后都是在main函数中,改变中断向量表的位置。而SystemInit这是系统起来前的硬件初始化,基本上不会去动它。很难想象前同事为什么要改这里。

物联沃分享整理
物联沃-IOTWORD物联网 » 如何解决单片机0xFFFFFFFE死机问题

发表评论