关于ARM中断处理的问题----《ARM嵌入式系统开发-软件设计与优化》第九章中疑问

friendfish 2009-02-03 04:29:04
加精
各位过年好哦~
呵呵,小弟这里有点疑惑相同大家讨论讨论~,这个问题是《ARM嵌入式系统开发-软件设计与优化》一书中的见下:

第九章-中断处理
9.3.2嵌套中断
在这一节中,描述了如何处理嵌套式的中断(不能单纯的在IRQ模式下打开中断允许位),作者介绍是从IRQ模式切换到SVC模式中去处理中断,并且一如了Stack Frame的用法,书中也有相关的一点代码,对这段代码有点疑问:


Maskmd EQU 0x1f ; processor mode mask
SVC32md EQU 0x13 ; SVC mode
I_Bit EQU 0x80 ; IRQ bit

FRAME_R0 EQU 0x00
FRAME_R1 EQU FRAME_R0+4
FRAME_R2 EQU FRAME_R1+4
FRAME_R3 EQU FRAME_R2+4
FRAME_R4 EQU FRAME_R3+4
FRAME_R5 EQU FRAME_R4+4
FRAME_R6 EQU FRAME_R5+4
FRAME_R7 EQU FRAME_R6+4
FRAME_R8 EQU FRAME_R7+4
FRAME_R9 EQU FRAME_R8+4
FRAME_R10 EQU FRAME_R9+4
FRAME_R11 EQU FRAME_R10+4
FRAME_R12 EQU FRAME_R11+4
FRAME_PSR EQU FRAME_R12+4
FRAME_LR EQU FRAME_PSR+4
FRAME_PC EQU FRAME_LR+4
FRAME_SIZE EQU FRAME_PC+4

IRQ_Entry ; instruction state : comment
SUB r14,r14,#4 ; 2 :
STMDB r13!,{r0-r3,r12,r14} ; 2 : save context
<service interrupt>
BL read_RescheduleFlag ; 3 : more processing
CMP r0,#0 ; 3 : if processing?
LDMNEIA r13!,{r0-r3,r12,pc}ˆ ; 4 : else return
MRS r2,spsr ; 5 : copy spsr_irq
MOV r0,r13 ; 5 : copy r13_irq
ADD r13,r13,#6*4 ; 5 : reset stack
MRS r1,cpsr ; 6 : copy cpsr
BIC r1,r1,#Maskmd ; 6 :
ORR r1,r1,#SVC32md ; 6 :
MSR cpsr_c,r1 ; 6 : change to SVC
SUB r13,r13,#FRAME_SIZE-FRAME_R4 ; 7 : make space
STMIA r13,{r4-r11} ; 7 : save r4-r11
LDMIA r0,{r4-r9} ; 7 : restore r4-r9
BIC r1,r1,#I_Bit ; 8 :
MSR cpsr_c,r1 ; 8 : enable IRA
STMDB r13!,{r4-r7} ; 9 : save r4-r7 SVC
STR r2,[r13,#FRAME_PSR] ; 9 : save PSR
STR r8,[r13,#FRAME_R12] ; 9 : save r12
STR r9,[r13,#FRAME_PC] ; 9 : save pc
STR r14,[r13,#FRAME_LR] ; 9 : save lr
<complete interrupt service routine>
LDMIA r13!,{r0-r12,r14} ; 11 : restore context
MSR spsr_cxsf,r14 ; 11 : restore spsr
LDMIA r13!,{r14,pc}ˆ ; 11 : return


为什么要在Frame Stack未创建完成时打开中断呢?此时r4-r7,r2,r8,r9,r14都还没保存,如果有中断发生,岂不是会覆盖这么寄存器(重要的是会覆盖r9)导致中断服务程序不能正常返回。

各位有何高见~
...全文
2597 57 打赏 收藏 转发到动态 举报
写回复
用AI写文章
57 条回复
切换为时间正序
请发表友善的回复…
发表回复
decentraland 2011-11-24
  • 打赏
  • 举报
回复
[Quote=引用 37 楼 singlerace 的回复:]

仔细看了看,这段代码没有问题。如果刚打开irq时再次发生中断,r2中断在入口处会被再次保存。
r14_svc只有LDMIA r13!,{r0-r12,r14}这句会被改写,但是这句的前面r14_svc进栈了,后面又恢复了,所以也是安全的。
比较奇妙的是r4-r9确实没有保护,但是如果你仔细看的话r4-r9也是安全的。因为再次进入中断到STMIA r13, {r4-r11}这句之前r4-r9没……
[/Quote]

这段代码确实是没问题的,楼主也理解了其中的一些深层的规则。读懂这些细节确实需要比较多的基础知识。
好帖留名。
endlesswings 2011-10-23
  • 打赏
  • 举报
回复
说句负责任的话,这段程序中由于作者的失误,这两行程序放错位置了:
BIC r1,r1,#I_Bit ; 8 :
MSR cpsr_c,r1 ; 8 : enable IRA
具体放哪边我就不提醒了,非常明显。

gzc1017 2010-10-27
  • 打赏
  • 举报
回复
谢谢,学习到了很多!
zzbbing 2010-10-02
  • 打赏
  • 举报
回复
恩,支持十四楼,只要是有备份的寄存器(如sp不用压栈,异常下都是有另外一个sp的)都不用保存,没备份要备份,只有中断后又有要子程序执行要备份lr
Neophy 2010-09-27
  • 打赏
  • 举报
回复
看看14楼和19楼说的,已经很详细了
kuishanpark 2010-08-18
  • 打赏
  • 举报
回复
终于找到了
arm_lr 2010-04-22
  • 打赏
  • 举报
回复
好东西 值得品味啊
beijiexi 2010-03-22
  • 打赏
  • 举报
回复
受教了
yuweixian 2010-03-20
  • 打赏
  • 举报
回复
学习中
sfengsheng 2010-01-30
  • 打赏
  • 举报
回复
学习中
friendfish 2009-02-18
  • 打赏
  • 举报
回复
终于弄明白了,忽略了STMIA r13,{r4-r11} ; 7 : save r4-r11就是保存,唉,搞混了
谢谢singlerace大侠了~

终于可以结贴了~
gooogleman 2009-02-18
  • 打赏
  • 举报
回复
[Quote=引用 45 楼 singlerace 的回复:]
1,IRQ模式的r4-r9和SVC模式的r4-r9是同一组寄存器。
2,LDMIA r0,{r4-r9} ; 7 : restore r4-r9
这句之前是:STMIA r13,{r4-r11} ; 7 : save r4-r11
这一句把上一次的r4-r9保存了。
之后,LDMIA r13!,{r0-r12,r14} ; 11 : restore context
这一句又把r4-r9恢复了。
你自己画个SVC模式的栈空间变化图仔细想想。
[/Quote]

赞,书上的确是这么说的。
singlerace 2009-02-18
  • 打赏
  • 举报
回复
1,IRQ模式的r4-r9和SVC模式的r4-r9是同一组寄存器。
2,LDMIA r0,{r4-r9} ; 7 : restore r4-r9
这句之前是:STMIA r13,{r4-r11} ; 7 : save r4-r11
这一句把上一次的r4-r9保存了。
之后,LDMIA r13!,{r0-r12,r14} ; 11 : restore context
这一句又把r4-r9恢复了。
你自己画个SVC模式的栈空间变化图仔细想想。
friendfish 2009-02-17
  • 打赏
  • 举报
回复
[Quote=引用 43 楼 singlerace 的回复:]
LDMIA r0,{r4-r9} ; 7 : restore r4-r9
中断在第8阶段才打开,这句在重新打开中断之前。
[/Quote]
恩,是阿,但是如果在第一次中断的处理中(已经从IRQ转入SVC)打开中断(这里是第一次中断),也就是在

MSR cpsr_c,r1 ; 8 : enable IRA

之后,如果此时有中断进入(第二次中断),那么IRQ部分的代码会重新再执行,而此时保存在R14_IRQ的返回地址是返回到SVC模式下第一次中断的处理中(因为第一次中断还未处理完).
等到执行到

LDMIA r0,{r4-r9} ; 7 : restore r4-r9

注:上面的代码是在SVC模式下的,也就是说SVC模式下的R4-R9.而SVC模式下的R9保存的就是第一次中断的返回地址(返回到USER模式).
上面的这条指令会将IRQ堆栈(R0保存的是R13_IRQ)中保存的寄存器恢复到SVC模式下的R4-R9.而IRQ模式中保存的是R0-R3,R12,R14_IRQ.这样会将R4-R9中的值覆盖掉.

虽然
LDMIA r0,{r4-r9} ; 7 : restore r4-r9
在打开中断之前,但此时已经是第二次中断的处理了.
明鉴~

singlerace 2009-02-17
  • 打赏
  • 举报
回复
[Quote=引用 40 楼 friendfish 的回复:]
引用 37 楼 singlerace 的回复:
仔细看了看,这段代码没有问题。如果刚打开irq时再次发生中断,r2中断在入口处会被再次保存。
r14_svc只有LDMIA r13!,{r0-r12,r14}这句会被改写,但是这句的前面r14_svc进栈了,后面又恢复了,所以也是安全的。
比较奇妙的是r4-r9确实没有保护,但是如果你仔细看的话r4-r9也是安全的。因为再次进入中断到STMIA r13, {r4-r11}这句之前r4-r9没有使用,也就是说r4-r9没有被破坏,是安全的;另一方…
[/Quote]
LDMIA r0,{r4-r9} ; 7 : restore r4-r9
中断在第8阶段才打开,这句在重新打开中断之前。
singlerace 2009-02-17
  • 打赏
  • 举报
回复
[Quote=引用 41 楼 clementzhao 的回复:]
SVC模式禁止有irq中断的
[/Quote]
svc模式可以被中断。
clementzhao 2009-02-17
  • 打赏
  • 举报
回复
SVC模式禁止有irq中断的
friendfish 2009-02-17
  • 打赏
  • 举报
回复
[Quote=引用 37 楼 singlerace 的回复:]
仔细看了看,这段代码没有问题。如果刚打开irq时再次发生中断,r2中断在入口处会被再次保存。
r14_svc只有LDMIA r13!,{r0-r12,r14}这句会被改写,但是这句的前面r14_svc进栈了,后面又恢复了,所以也是安全的。
比较奇妙的是r4-r9确实没有保护,但是如果你仔细看的话r4-r9也是安全的。因为再次进入中断到STMIA r13, {r4-r11}这句之前r4-r9没有使用,也就是说r4-r9没有被破坏,是安全的;另一方面,如果中断处理调用到其他子函数…
[/Quote]
等了好久,终于有人深入研究了,感激不尽~

我觉得还有有问题,问题就处在R9_SVC上。

[Quote=引用 37 楼 singlerace 的回复:]
比较奇妙的是r4-r9确实没有保护,但是如果你仔细看的话r4-r9也是安全的。因为再次进入中断到STMIA r13, {r4-r11}这句之前r4-r9没有使用,也就是说r4-r9没有被破坏,是安全的;
[/Quote]
在STMIA r13, {r4-r11}这句之前,R4-R9(这里指的是SVC模式下)但是下一句,确实致命的:

LDMIA r0,{r4-r9} ; 7 : restore r4-r9

这里回复的是IRQ堆栈里的“R0,R1,R2,R3,R12,R14_IRQ”
因为这些是在IRQ里保存过的:

STMDB r13!,{r0-r3,r12,r14} ; 2 : save context


现在我们假设IRQ中断再次发生,那么,R14_IRQ保存的将是返回到SVC模式下的地址。(因为第二次中断发生了,也就是说第二次中断先要返回到SVC模式,然后再返回USER模式)
但是执行完

LDMIA r0,{r4-r9} ; 7 : restore r4-r9

致命的错误发生了,第二次中断的返回地址覆盖了返回到USER模式的地址。

我最大的怀疑是在这里。明鉴~

gooogleman 2009-02-11
  • 打赏
  • 举报
回复
[Quote=引用 37 楼 singlerace 的回复:]
仔细看了看,这段代码没有问题。如果刚打开irq时再次发生中断,r2中断在入口处会被再次保存。
r14_svc只有LDMIA r13!,{r0-r12,r14}这句会被改写,但是这句的前面r14_svc进栈了,后面又恢复了,所以也是安全的。
比较奇妙的是r4-r9确实没有保护,但是如果你仔细看的话r4-r9也是安全的。因为再次进入中断到STMIA r13, {r4-r11}这句之前r4-r9没有使用,也就是说r4-r9没有被破坏,是安全的;另一方面,如果中断处理调用到其他子函数,那么ARM的ATPCS调用规则要求子函数自己要保证不破坏r4-r9,换句话说子函数要么不使用r4-r9,要么在使用之前把r4-r9进栈,返回前再恢复,因此也是安全的。当然如果你自己写的子函数不遵循ATPCS调用规则那么r4-r9确实会被破坏,但这是你的责任;另一方面C等高级语言的编译器会保证遵循ATPCS调用规则,所以中断处理调用C语言写的子函数也是没问题的。
[/Quote]

ATPCS,有空找来看看才行,在很多地方提到。
singlerace 2009-02-11
  • 打赏
  • 举报
回复
[Quote=引用 36 楼 gooogleman 的回复:]
看了,我觉得这样做不合理。

还有,他的书不一定是对的,别信它。总之wince下的内核代码能运行的才是最好参考。
[/Quote]
这本书非常权威,犯错的可能性很小,何况是这么重要的错误。
加载更多回复(36)
这本最畅销的计算机组成书籍经过全面更新,关注现今发生在计算机体系结构领域的革命性变革:从单处理器发展到多核微处理器。此外,出版这本书的ARM版是为了强调嵌入式系统对于全亚洲计算行业的重要性,并采用ARM处理器来讨论实际计算机的指令集和算术运算,因为ARM是用于嵌入式设备的最流行的指令集架构,而全世界每年约销售40亿个嵌入式设备。与前几版一样,本书采用了一个MIPS处理器来展示计算机硬件技术、流水线、存储器层次结构以及I/O等基本功能。此外,本书还包括一些关于x86架构的介绍。   本书主要特点   ·采用ARMv6(ARM11系列)为主要架构来展示指令系统和计算机算术运算的基本功能。   ·覆盖从串行计算到并行计算的革命性变革,新增了关于并行化的一章,并且每章还有一些强调并行硬件和软件主题的小节。   ·新增一个由NVIDIA的首席科学家和架构主管撰写的附录,介绍了现代GPU的出现和重要性,首次详细描述了这个针对可视计算进行了优化的高度并行化、多线程、多核的处理器。   ·描述一种度量多核性能的独特方法——“Roofline model”,自带benchmark测试和分析AMD Opteron X4、Intel Xeon 5000、Sun UltraSPARC T2和 IBM Cell的性能。   ·涵盖了一些关于闪存和虚拟机的新内容。   ·提供了大量富有启发性的练习题,内容达200多页。   ·将AMD Opteron X4和Intel Nehalem作为贯穿本书的实例。   ·用SPEC CPU2006组件更新了所有处理器性能实例。

19,503

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 嵌入开发(WinCE)
社区管理员
  • 嵌入开发(WinCE)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧