查看原文
其他

关于程序总跳回启动文件的话题

Miler 茶话MCU 2022-09-10

某STM32应用客户反映:

他用STM32f407芯片开发产品,使用ADC并开启了DMA中断。中断服务函数经过反复检查并没有发现配置错误,优先级也配置得当,可为什么每次仿真时程序都跳回启动文件呢?


后面,经过进一步沟通与反馈,发现只要开启DMA中断就跳回启动文件,并死在下面位置。



一般来讲,在做STM32开发调试时,如果发现程序频繁跳进启动文件的话,可能有以下几种情况及相关特征:


1、运行程序时发生异常访问,导致硬件错误、总线错误等。

比如堆栈溢出啊、数组越界、执行非法指令、非法访问等。这时,程序指针可能会跳进启动文件里事先准备好了的相应异常服务程序,并进入死循环。比如下面这些:


2、芯片因为时钟问题、电源问题、WDG等原因,导致芯片频繁复位。

比如时钟异常、电源波动厉害、电源驱动不足、WDG未重置等,导致芯片频繁运行复位程序。此时相对比较容易发现程序频繁回到启动文件里执行复位代码以及调用SystemInit()函数。当然,类似问题在芯片复位脚上也能观察到电平频繁跳变。



3、用户没有编写中断服务程序或其函数名与启动文件里的不一致。

此时往往表现在开启了某些中断功能,但用户没有编写自己的中断服务程序,或者用户编写的中断服务函数名跟启动文件里事先定义的不一致。这样的话,当产生相关中断时,就会进入启动文件里事先使用汇编指令编写的中断服务函数,该函数除了一条原地死循环的代码外,再无其它。



在启动文件里,除了前面提到的几种特殊异常服务函数外,其它中断服务函数都共用同一执行代码,B .,即原地死循环,类似51系列MCU里的JMP $指令。


具体结合到本案例,经过多次排查、验证,发现问题就出在中断服务程序的函数名的书写上。他写的中断服务函数名跟启动文件里事先定义的就差一个字母。比如把DMA1_Stream0_IRQHandler()写错成DMA_Stream0_IRQHandler()。


该问题很隐蔽,尤其这种以为编写了中断服务函数,但中断函数名写得跟启动文件里的不一致时,编译器并不会给出任何提示,这就不容易发现问题。之前,也碰到过有人因中断函数名写得跟启动文件里定义的不一致导致中断不响应或者抱怨进不了相关中断的问题。


从客户提供的截图也可以看出,程序进入了启动文件里默认的中断服务程序,即那条死循环汇编指令  B  .


这里以基于CORTEX M4内核的STM32F4芯片为例,顺便提下基于CORTEX Mx内核的中断矢量表的话题。

在每片基于CORTEX Mx内核的芯片里,都有一张硬件中断矢量表。在这张表里按固定的顺序、以字【4个字节】为单位依次存放着各类异常响应的入口地址,其中第一个字是个例外,它存放的是栈顶地址。


下面是STM32F405/407和STM32F415/417系列芯片内部中断矢量表的一部分。其中Address是相对于该表起始地址的偏移量。该矢量表自身的地址由寄存器VTOR决定【注;M0系列没有这个寄存器】。不同的STM32系列,甚至同一系列的不同产品线【比如STM32F1系列的低容量产品线、高容量产品线、互联型产品线】,其中断矢量表的内容往往会有些差异。



当内核响应了某异常或中断后,对应的异常或中断服务程序就会得到执行。为了得到相应服务程序的入口地址,内核就使用上述的中断矢量表并建立查表机制。


通常来讲,STM32的工程项目里的启动文件已经事先帮我们预备好了所有异常及中断的服务函数,并将各个服务函数名所对应的地址按固定顺序填入到中断矢量表中。不过,这里的各个服务函数体非常简单,上面提过,就是一句原地死循环代码。



这样做的目的就是先给各异常及中断服务函数挂个号,留个地址,把中断矢量表搭建起来。真正的用户中断服务程序还得靠用户在外部具体实现,并使用与启动文件里相对应的相同函数名。毕竟,启动文件不可能知道用户在各种服务函数里需要做什么。

 

结合上面的介绍,我们知道不同的STM32产品线,其中断矢量表的内容及位置顺序都可能不同;相应地启动文件中准备的矢量表内容和顺序也就可能不一样。

 

由于STM32系列众多,产品线丰富,所以在做移植时要注意启动文件跟所选芯片型号是一致的。经常有人在做不同产品间的移植时,因忽略启动文件的差异,工程启动文件选择不合适导致中断响应方面出问题。

 

也许有人会问,启动文件里已经定义了全套各个异常及中断服务函数,用户自己再定义同名的函数不会有重复定义的问题吗?不会的。君不见,启动文件里定义的各个异常服务函数名后面都跟了[weak]弱定义符号吗?意味着在进行代码编译时它可以被其它非弱定义的同名函数覆盖取代。


 

=====================================

往期话题链接:

1、STM32开发调试受阻的二三个案例分享

2、Flash擦写操作导致USART接收丢数据的话题

3、一个涉及DMA传输的I2C通信异常的话题

4、话说STM32F4系列的总线矩阵与访问调度

5、一个关于STM8中断应用异常的话题

6、一个关于STM32 PWM输出无信号的话题

7、MCU功能严重异常的几个常见原因

8、获取ST MCU技术资料及相关支持的方式与途径

扫描或长按二维码可关注公众号



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存