注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

一步一步写嵌入式操作系统7—中断处理2  

2011-11-19 22:24:37|  分类: ARM学习 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

一步一步写嵌入式操作系统7—中断处理2
接着上面讲,上面的中断只是一个简单的应用,而在实际的应用中,大家发现,中断是可以进行嵌套和抢占的,这个无论是在X86还是在ARM上都是一样的,中断产生的时机和由谁产生,在实际的应用环境中,这个都是未知的,举一个简单例子,有十个硬件可以进行中断工作,但可能是在整个的运行过程上一个硬件都没有产生中断,或者按次序产生,亦或者同时产生····等等,不一而足。一个个的产生中断,当然很理想,但实际情况却往往不是这样,当多个硬件同时请求中断的时候儿,怎么办呢?或者,一个中断的响应时间比较长,会是什么样子呢。
自然的会想到可以使用中断嵌套(或者优先级,这里暂不论述),也就是说,当一个中断产生时,又一个中断到来,那么就保存好正在中断的运行状态,然后对新的中断进行处理,如此递推,不很简单么,是啊,想象着确实不难,但真正使用起来,却是相当不容易的。首先是,中断在响应时,中断屏蔽位是设置的,也就是说,不会再响应新来的中断,那我们把中断屏蔽位重新设置不行么,可以是可以,但会有很多新的问题:
1、在中模式下,R14_irq是一个私有的寄存器,保存着中断时的进程返回的地址,将其压入栈中,便可以保存其并将其用来保存返回值,但如果再来一个中断,那么这个寄存器也要重复上面的动作,结果是什么,很清楚,数据没了。
2、同样SPSR_irq寄存保存了中断前 CPSR_irq状态寄存器的值,一旦重新再进入新的中断,数据也没有了。
当然,你可以用堆栈来保存状态寄存器,确实可以解决第二个问题,但第一个你怎么回避呢?一旦嵌套,第一个中断没有执行完成,返回值不知道是个啥,你保存在哪儿,只有返回去后才知道,可你的中断寄存器中存的确是第二次中断的返回值,如果你说你可以把第二次的压栈,但如果那样的话,还有什么意义呢,对吧,进程的切换(中断亦是如此)保存的是当前状态的上下文,不是下一个的。
那是不是没有办法解决了,当然不可能。要换个考虑的角度,只要把中断模式切换到其它的模式下,就可以重新的自动保存R14_irq
看代码:
.equ  DISABLE_IRQ,0x80
.equ  DISABLE_FIQ,0x40
.equ  SYS_MOD,0x1f
.equ  IRQ_MOD,0x12
.equ  FIQ_MOD,0x11
.equ  SVC_MOD,0x13
.equ  ABT_MOD,0x17
.equ  UND_MOD,0x1b
.equ  MOD_MASK,0x1f

.macro CHANGE_TO_SVC
 msr cpsr_c,#(DISABLE_FIQ|DISABLE_IRQ|SVC_MOD)
.endm

.macro CHANGE_TO_IRQ
 msr cpsr_c,#(DISABLE_FIQ|DISABLE_IRQ|IRQ_MOD)
.endm


.global __vector_undefined
.global __vector_swi
.global __vector_prefetch_abort
.global __vector_data_abort
.global __vector_reserved
.global __vector_irq
.global __vector_fiq

.text
.code 32

__vector_undefined:
 nop
__vector_swi:
 nop
__vector_prefetch_abort:
 nop
__vector_data_abort:
 nop
__vector_reserved:
 nop
__vector_irq:
 sub r14,r14,#4
 stmfd r13!,{r14}
 mrs r14,spsr
 stmfd r13!,{r14}
 CHANGE_TO_SVC
 stmfd r13!,{r0-r3}
 bl common_irq_handler
 ldmfd r13!,{r0-r3}
 CHANGE_TO_IRQ
 ldmfd r13!,{r14}
 msr spsr,r14
 ldmfd r13!,{pc}^
__vector_fiq:
 nop

这里重点讲一下两个宏:
CHANGE_TO_SVC和CHANGE_TO_IRQ
他们的定义如下:

1、.macro CHANGE_TO_SVC
 msr cpsr_c,#(DISABLE_FIQ|DISABLE_IRQ|SVC_MOD)
.endm

2、.macro CHANGE_TO_IRQ
 msr cpsr_c,#(DISABLE_FIQ|DISABLE_IRQ|IRQ_MOD)
.endm

msr这个指令我们很熟悉了,他就是为了实现指令模式的切换。
这里还多了一个disable_irq()函数:

void disable_irq(void)
{
 asm volatile(
  "mrs r4,cpsr\n\t"
  "orr r4,r4,#0x80\n\t"
  "msr cpsr,r4\n\t"
  :::"r4");
}
如果前面的理解了,这里没有什么,不过有一点儿要说明,在上面一节也说过,那个感叹号,你大可以当成一个指针的自增,这个要明白,在不同的指令下,其的含义有所不同,但基本上都是自加,有时候儿加一个字节,有时候儿加N个字节。
雨里深山雪上烟,看来容易做时难。要努力实践,努力工作,勤学不辍。

  评论这张
 
阅读(649)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017