你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

ARM CM3/4 异常进入与返回的过程

[复制链接]
qianfan 发布时间:2015-12-6 21:46
    之前在使用中断的时候,对内部的机制不是很了解。特别是相关寄存器的自动保存与恢复。在调试HardFault的时候,(见帖子https://www.stmcu.org.cn/module/forum/thread-604503-1-1.html )不明白出错的地址为什么是从PC处(更准确的说法应该是返回地址)开始找,而不是LR。因此,这里做个简单的实验分享一下。实验相关的代码在附件中可以下载。使用arm gcc进行编译,arm gdb进行调试。keil mdk虽然有不同的地方,但是原理还是相同的。

    在《嵌入式软件设计基础,基于ARM cortex-m3》一书中,介绍了进入异常处理程序和从异常处理程序返回的步骤:
  • 进入异常处理程序:
       当处理器识别出异常的时候,会通过特定序列的行为来进行自动响应。
  • 压栈:将寄存器R0-R3和R12的内容,返回地址(并不是PC),PSR和链接寄存器的内容压栈。其中,在栈中存放的顺序从低地址到高地址依次是:R0-R3,R12,LR,返回地址,PSR。
  • 在进行压栈操作的同时,处理器识别异常。将其对异常的识别结果作为PSR中的异常号记录下来,然后使用该数字从向量表中定位和拷贝对应异常处理程序的地址到PC中。
  • LR寄存器中装载除了最低的4位全1的序列,最低4位记录指向异常的处理器模式(线程模式或者异常处理模式)。(注意,LR不包含返回地址!LR中存储的值,通常为EXC_RETURN)作为特殊值由处理器识别,并用在异常处理程序返回时回复之前的模式。
  • 异常处理模式使能。
  • 异常处理程序开始执行。

    2. 从异常处理程序返回
  • 在异常处理程序将执行EXC_RETURN值装入PC时,处理器初始化返回序列。EXC RETURN通知处理器开始返回序列,确定处理器是返回线程模式还是异常处理模式。然后从栈中弹出8个字,将之恢复到R0-R3,R12,LR和PSR。并将返回地址加载到PC。

  • (注1:因为原书是基于ARM CM3讲解的,ARM CM3没有FPU,因此不必处理FPU相关的寄存器。如果是ARM CM4,这里需要保存与回复的不止这些寄存器。还有FPU相关的寄存器。)
  • (注2:这里说的栈中的返回地址和PC还是有区别的。下面还会讲解。)


    看下部分源代码:代码中添加的nop指令没有什么作用。主要是为了方便观察自动入栈的LR和PC值的不同。往0xE000ED04处写0x10000000是为了触发PendSV中断。在触发PendSV中断之后,会发生中断的自动保存。
2015-12-06 20:55:19屏幕截图.png

1. 使用arm gdb进行调试。在PendSV_Handler中断处理函数上点一个断点。之后输入continue继续运行。直到断点处停止。
2015-12-06 21:23:50屏幕截图.png

2.这时候进入了PendSV中断,并且相关的寄存器已经得到入栈保存。可以使用disassemble查看当前的汇编代码。可以发现在自动保存R0-R3,R12,LR,返回地址,PSR之后,编译器还push 了R7和LR。
2015-12-06 21:25:48屏幕截图.png

3.通过info reg查看相关的寄存器。LR的值是0xFFFFFFF9。这个数就是EXC_RETURN。更加具体的解释可以参考ARM cortex-m3权威指南。这里看到的一个比较重要的地址是sp。发生中断之后,自动保存的寄存器就在他里面。
2015-12-06 21:27:58屏幕截图.png
使用x/10xw 0x2000ffd0查看sp处连续的四个字。因为进入PendSV之后,编译器自动压入了R7和LR。所以前两个数是当前的R7和LR(数据正好和我们使用info reg读出来的吻合)。0x0000000a是R0 ... 中断发生时,自动保存的LR是0x08008637,返回地址是0x08002646。因为ARM CM3/4只能执行THUMB指令,所以LR的实际地址应该是0x08008636。(具体为什么是这样,可以查看ARM CM3权威指南)
2015-12-06 21:30:47屏幕截图.png

4.使用disassemble查看main的汇编代码:(PS:使用disassemble查看汇编代码的时候,他会一些ldr的数据当成指令来翻译。准确的翻译可以使用arm-none-eabi-objdump -d main.o来查看)。
2015-12-06 21:36:04屏幕截图.png
使用objdump查看的代码,明显的不同是对ldr数据的翻译上。
2015-12-06 21:38:09屏幕截图.png
实际触发PendSV的代码是0x08002644的那一行代码。因此从中断返回的代码也就是他的下一条指令。也就是0x08002646。这个值也就是自动保存在栈中的返回地址。
在触发中断之前,最后一条能够更新LR的指令是bl hello。他将LR的位置更新到bl hello的下一条指令。也就是0x08002636。由于是thumb指令,所以将最低位置1。因此自动保存在栈中的数值也就是0x08002637。

好了,暂时就解释这么多。更加具体的解释请参考ARM cortex-m3权威指南。
之前有朋友在社区群中问,ARM CM3权威指南中的汇编部分是不是要看。我觉得还是要看的。虽然不一定要会使用汇编写程序,但是简单的汇编代码一定要懂。这对你写程序帮助不是很大。但是对你debug确实受益匪浅。

interrupt.zip

下载

523.46 KB, 下载次数: 21

评分

参与人数 1 ST金币 +20 收起 理由
沐紫 + 20

查看全部评分

收藏 1 评论7 发布时间:2015-12-6 21:46

举报

7个回答
Paderboy 回答时间:2015-12-6 22:45:18
多谢分享,大师出手不凡。。。

STMCU-Logo.png
qianfan 回答时间:2015-12-7 16:58:07
Paderboy 发表于 2015-12-6 22:45
多谢分享,大师出手不凡。。。

stary666 回答时间:2015-12-7 17:00:06
看看,,,,,,,,,,,,,,,,
mark0668 回答时间:2015-12-7 17:02:56
多谢分享
STM32.png
埃斯提爱慕 回答时间:2015-12-7 19:57:06
提示: 作者被禁止或删除 内容自动屏蔽
moyanming2013 回答时间:2015-12-7 22:01:44

多谢分享,大师出手不凡
yanhaijian 回答时间:2015-12-10 19:31:34
学习了。

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版