OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7617|回复: 6

CORTEX-M3中断的现场保护问题

[复制链接]

8

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
118
金钱
118
注册时间
2015-9-7
在线时间
8 小时
发表于 2015-12-9 18:01:46 | 显示全部楼层 |阅读模式
5金钱
Cortex-M3的内核在处理异常的时候是handler mode,此模式下必定属于“特权模式”。特权模式下的内核可以访问所有的寄存器。
在进入异常时,会自动保存R0~R3+R12+PC+LR+SP,请问为什么不用保存R4~R11呢?
我自己的猜测如下:
情况1:在进入异常后,中断服务代码经编译器编译的机器代码只使用R0~R3+R12+PC+LR+SP,而不使用R4~R11。
情况2:固件库提供的中断函数模板已经封装了对“
R4~R11的push操作”,而开发人员来说这些操作是透明的。因此在进入中断后,中断服务代码经编译器编译的机器代码可以使用所有通用寄存器
注:stm32f10x提供的中断函数模板:void xxxxx_xxxHandler(void)  {}

考虑到“MSP430单片机进入中断仅仅自动入栈了SP+SR,而没有对通用寄存器进行现场保护”的事实,因此觉得情况2的可能性更大。但是在学习uC/OS的时候觉得情况2显示是不对的。

请高手点拨一下并希望给些参考资料。

最佳答案

查看完整内容[请看2#楼]

参考Cortex-M3权威指南 136页。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

401

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1770
金钱
1770
注册时间
2015-6-11
在线时间
313 小时
发表于 2015-12-9 18:01:47 | 显示全部楼层


参考Cortex-M3权威指南 136页。
回复

使用道具 举报

8

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
118
金钱
118
注册时间
2015-9-7
在线时间
8 小时
 楼主| 发表于 2015-12-10 09:39:52 | 显示全部楼层
回复【2楼】zc123:
---------------------------------
感谢您!
回复

使用道具 举报

8

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
118
金钱
118
注册时间
2015-9-7
在线时间
8 小时
 楼主| 发表于 2015-12-10 11:15:15 | 显示全部楼层
自己把完整答案写在这里。以供他人查看。
在《Cortex-M3 Devices Generic User Guide.pdf》中介绍了异常入栈和出栈的情况,详见2.3 Exception model。Cortex-M3内核的寄存器如下。

异常发生时,入栈的寄存器是R0~R3+R12+PC+LR+SP。为啥袒护R0‐R3以及R12呢, R4‐R11就是下等公民?(摘自《Cortex-M3权威指南 》第9章)
原来,在ARM上,有一套的C函数调用标准约定(《 C/C++ rocedure Call Standard for the ARM Architecture》,AAPCS, Ref5)。个中原因就在它上面:它使得中断服务例程能用C语言编写,编译器优先使用被入栈的寄存器来保存中间结果(当然,如果程序过大也可能要用到R4‐R11,此时编译器负责生成代码来push它们。但是, ISR应该短小精悍,不要让系统如此操心——译者注)。如果读者再仔细看,会发现R0‐R3, R12是最后被压进去的。这里也有一番良苦用心:为的是可以更容易地使用SP基址来索引寻址,( 以及为了LDM等多重加载指令,因为LDM必须加载地址连续的一串数据)。参数的传递也是受益者:使之可以方便地通过压入栈的R0‐R3取出( 主要为系统软件所利用,多见于SVC与PendSV中的参数传递)。
这就是说,C编译器中断(异常)服务函数封装的这样的需求:当R0~R3+R12不够用时会使用R4‐R11,在使用R4‐R11之前会进行入栈保护;在使用完之后进行出栈恢复现场。
这也为开发人员使用汇编语言编写中断服务函数提供了借鉴。比如,在uC/OS-III移植过程中使用汇编编写任务级/中断级调度器。调度器需要触发Cortex-M3的滴答定时器中断来达到现场保护和任务切换的目的。而这个滴答定时器中断就需要使用汇编编写(详见已经移植好了的os_cpu_a.s)。
对uC/OS-III其他中断即可使用C编译器提供的模板即可:
void xxxxx_xxxHandler(void) ?
{
OSIntEnter();
…… //中断服务函数代码
OSIntExit();  
}
分析一下其过程
响应xxxxx_xxxHandler之后,保存现场R0~R3+R12+PC+LR+SP,执行OSIntEnter()和中断服务函数代码(若这期间如果通用寄存器不够用时会使用R4‐R11,使用前会先进行入栈保护,使用后出栈恢复现场),然后会在中断级调度器OSIntExit()中判定是否需要进行任务切换,如果需要则定位好待切换的任务,最后挂起由汇编编写的滴答定时器中断。这会引入“咬尾机制”直接转而去执行滴答定时器中断服务函数。

通过对C编译器封装的中断服务函数模型进行的“背地儿里”的操作,可以预见C编译器对普通函数模型封装的额外操作。至少不会比这个复杂吧....
回复

使用道具 举报

35

主题

154

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
362
金钱
362
注册时间
2014-7-30
在线时间
49 小时
发表于 2016-11-7 13:52:45 | 显示全部楼层
                                    MARK
我就是我,是颜色不一样的烟火。
回复

使用道具 举报

35

主题

154

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
362
金钱
362
注册时间
2014-7-30
在线时间
49 小时
发表于 2016-11-7 15:07:15 | 显示全部楼层
zc123 发表于 2015-12-9 18:01
参考Cortex-M3权威指南 136页。

既然编译器负责生成代码push它们,为什么PendSv中断调度里面还要自己保存R4-R11?
我就是我,是颜色不一样的烟火。
回复

使用道具 举报

28

主题

140

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
461
金钱
461
注册时间
2013-10-18
在线时间
72 小时
发表于 2016-11-25 15:05:38 | 显示全部楼层
idqiye 发表于 2016-11-7 15:07
既然编译器负责生成代码push它们,为什么PendSv中断调度里面还要自己保存R4-R11?

汇编的时候,代码都是人写的。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-26 07:44

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表