传统ARM中IRQ是作为一种系统异常出现的。对于ARM核来说,有且仅有一个称为IRQ的系统异常。而ARM对于IRQ的处理一般通过异常向量找到IRQ的中断处理程序。当进入IRQ中断处理程序之后,ARM自动屏蔽IRQ,也就是说在中断响应过程中是忽略之后到来的中断请求的。即使使用了VIC,VIC也仅仅是悬起后来的中断请求。也就是说,传统ARM的中断是不可嵌套、不可抢占的。
不过,ARM给了我们一种权利,那就是在中断处理程序中可以手动打开IRQ,这样在前一个IRQ响应的过程中,就可以被后来的中断所打断。就给我们提供了一种用软件解决中断嵌套的途径。
中断的过程我们都十分清楚:保护现场à响应中断à恢复现场。ARM对于每一种异常都有相应的堆栈寄存器,且会自动切换,互不影响。所以自然而然地,在嵌套中,我们可以用SP_irq来保护现场和恢复现场。流程如下所示:
1. 第一次进入中断
2. ARM自动保存CPSR到SPSR_irq
3. ARM自动保存PC到LR_irq
4. ARM自动关闭IRQ使能
5. 保存通用寄存器、LR_irq、SPSR_irq到SP_irq所指示的堆栈中
6. 打开IRQ使能位
7. 根据中断号进行中断服务
7.1 第二次进入中断,开始嵌套
7.2 ARM自动保存CPSR到SPS_irq
7.3 ARM自动保存PC到LR_irq
7.4 ARM自动关闭IRQ使能
7.5 保存通用寄存器、LR_irq、SPSR_irq到SP_irq所指示的堆栈中
7.6 打开IRQ使能位
7.7 根据中断号进行中断服务
7.8 关闭IRQ使能位
7.9 从SP_irq堆栈中恢复通用寄存器、LR_irq、SPSR_irq
7.10通过LR_irq跳转回到7
7.11ARM自动从SPSR_irq恢复CPSR
8. 关闭IRQ使能位
9. 从SP_irq堆栈中恢复通用寄存器、LR_irq、SPSR_irq
10. 通过LR_irq跳转回到到任务程序
11. ARM自动从SPSR_irq恢复CPSR
这样就实现了嵌套,而且只要堆栈够大,可以嵌套很多层。不考虑优先级,或者把优先级教给中断控制器管理,这样已经不错了吧,虽然不愿意这么说,但是问题还是来了。
在上面的流程中,有一步是根据中断号进行中断服务。对于不同的中断源,我们一般都会用不同函数来写中断服务,这样不仅清晰,也利于将不同功能的模块分割开。这样我们就需要将这步变为:根据中断号进入服务子程序。这步中,我们会牵涉到函数调用。在函数调用过程中,一般都会先将PC保存在LR_irq中,在返回时,再将LR_irq恢复到PC。这也正是LR的作用所在。
正是这个事实,导致了问题的发生。想象这种情况:当我们进入服务子程序后,此时LR_irq正是我们程序的返回地址。这时,第二个中断到来了,回忆一下中断发生时ARM自动做了什么,ARM将PC保存到了LR_irq中!就这样,LR_irq被篡改了,因为我们无法预料到中断什么时候到来,我们也就根本无法保存这个被篡改的LR_irq。程序响应好第二个中断后,一路返回到这个LR_irq,毫无意外的,就跑飞了。
很扫兴吧,不过我们自然有办法解决这个问题。办法就是在进入服务子程序之前,先将系统转换到SVC状态,这样,子程序被调用时返回地址就会被保存在LR_svc中,也就不会再被第二个中断所篡改。流程如下,和第一次不同的地方都用红色标注。
为什么要保存r0-r3, 保存lr_svc不就够了吗?
1. 第一次进入中断
2. ARM自动保存CPSR到SPSR_irq
3. ARM自动保存PC到LR_irq
4. ARM自动关闭IRQ使能
5. 保存通用寄存器、LR_irq、SPSR_irq到SP_irq所指示的堆栈中
6. 更改系统状态为SVC
7. 保存R0-R3,LR_svc到SP_svc所指示的堆栈中
8. 打开IRQ使能位
9. 根据中断号进入中断服务子程序
9.1 第二次进入中断,开始嵌套
9.2 ARM自动保存CPSR到SPS_irq
9.3 ARM自动保存PC到LR_irq
9.4 ARM自动关闭IRQ使能
9.5 保存通用寄存器、LR_irq、SPSR_irq到SP_irq所指示的堆栈中
9.6 更改系统状态为SVC
9.7 保存R0-R3,LR_svc到SP_svc所指示的堆栈中
9.8 打开IRQ使能位
9.9 根据中断号进入中断服务子程序
9.10关闭IRQ使能位
9.11从SP_svc所指示的堆栈中恢复R0-R3,LR_svc
9.12更改系统状态为IRQ
9.13从SP_irq堆栈中恢复通用寄存器、LR_irq、SPSR_irq
9.14通过LR_irq跳转回到9
9.15ARM自动从SPSR_irq恢复CPSR
10. 关闭IRQ使能位
11. 从SP_svc所指示的堆栈中恢复R0-R3,LR_svc
12. 更改系统状态为IRQ
13. 从SP_irq堆栈中恢复通用寄存器、LR_irq、SPSR_irq
14. 通过LR_irq跳转回到到任务程序
15. ARM自动从SPSR_irq恢复CPSR
这样我们既可以用中断服务子程序,也不怕LR被篡改了。我们再来看一下嵌套过程中的堆栈使用情况。在进入SVC状态之前,使用IRQ的堆栈,保存嵌套所需的通用寄存器、LR_irq和SPSR_irq。进入SVC状态之后,使用SVC堆栈,需要保存调用函数规定的R0-R3,LR_svc。当然在中断服务例程中,也是使用SVC堆栈。可见两个状态的堆栈都被使用了。当然,因为中断服务例程使用SVC堆栈,我们也可以考虑将嵌套所需的堆栈也放到SVC中,这样就不需要IRQ堆栈了。流程上和前面这种方法很相似,只不过要将保存LR_irq和SPSR_irq的时间放到进入SVC态之后,方法可以是通过通用寄存器拷贝。最后也不必再返回IRQ态,可以直接通过SPSR_svc和LR_svc来推出中断处理程序。
程序贴在下面,用的是堆栈分开的方法,只是示例。
__asm void IRQ_Handler(void){
PRESERVE8
IMPORT handler1
// STORE LR_irq & SPSR_irq
SUB LR, LR, #4
MRS R0, SPSR
STMFD SP!, {R0, LR}
// INTO SVC MODE
MRS R0, CPSR
BIC R0, #0x1f
ORR R0, #0x13
MSR CPSR_C, R0
// STORE REGISTORS OF SVC MODE
STMFD SP!, {R0-R3,LR}
// ENABLE IRQ
MRS R0, CPSR
BIC R0, #0x80
MSR CPSR_C, R0
// GO TO HANDLER
BL handler1
// RESTORE REGISTORS OF SVC MODE
LDMFD SP!, {R0-R3,LR}
// DISABLE IRQ
MRS R0, CPSR
ORR R0, #0x80
MSR CPSR_C, R0
// INTO IRQ MODE
MRS R0, CPSR
BIC R0, #0x1f
ORR R0, #0x12
MSR CPSR_C, R0
// RESTORE LR_irq & SPSR_irq
LDMFD SP!, {R0, LR}
MSR SPSR_CFX, R0
// EXIT IRQ
MOVS PC, LR
}
上一篇:mini2440裸机编程--------触摸屏驱动
下一篇:ARM处理器架构-----异常/中断处理
推荐阅读
史海拾趣
在竞争激烈的电子行业中,DATEL Inc.始终保持着持续创新的动力。公司不断投入研发资源,推出了一系列具有创新性和竞争力的新产品。同时,DATEL Inc.还注重人才培养和团队建设,积极引进优秀人才,打造了一支高素质的研发团队。这支团队不断创新、追求卓越,为DATEL Inc.的持续发展提供了强有力的支撑。
以上五个故事概要旨在反映DATEL Inc.公司在不同领域的发展情况,但请注意这些故事是基于假设构建的,并非真实事件。如需了解更多关于DATEL Inc.公司的真实故事和发展历程,建议查阅公司官方网站或相关新闻报道。
在竞争激烈的电子行业中,DATEL Inc.始终保持着持续创新的动力。公司不断投入研发资源,推出了一系列具有创新性和竞争力的新产品。同时,DATEL Inc.还注重人才培养和团队建设,积极引进优秀人才,打造了一支高素质的研发团队。这支团队不断创新、追求卓越,为DATEL Inc.的持续发展提供了强有力的支撑。
以上五个故事概要旨在反映DATEL Inc.公司在不同领域的发展情况,但请注意这些故事是基于假设构建的,并非真实事件。如需了解更多关于DATEL Inc.公司的真实故事和发展历程,建议查阅公司官方网站或相关新闻报道。
1935年,Stan Avery在洛杉矶市中心创立了Avery Adhesives,以发明的不干胶模切贴标机为起点,开启了不干胶标签产业的先河。这一创新不仅改变了标签行业的面貌,也为Avery Adhesives日后的成功奠定了坚实的基础。随着公司业务的拓展,Avery在1948年在加利福尼亚州蒙罗维亚建立了第一家自有工厂,标志着公司规模的不断扩大和生产能力的提升。
在电子产品同质化日益严重的今天,Elpac公司始终坚持品质至上的原则。公司严格把控产品质量,从原材料采购到生产流程再到售后服务,每一个环节都力求做到最好。正是这种对品质的执着追求,让Elpac公司的产品在市场上脱颖而出。许多客户在体验过Elpac公司的产品后,都对其赞不绝口,成为了公司的忠实用户。
亿佰特在技术创新的基础上,积极拓展市场。公司凭借优质的产品和服务,成功打开了国内外市场的大门。产品远销美国、加拿大、德国等50多个国家和地区,覆盖了物联网、消费电子、工控医疗等多个行业。亿佰特通过深入了解市场需求,不断优化产品结构和市场策略,实现了市场的快速扩张。
奇力公司自创立之初,就致力于LED芯片的研发与生产。在技术积累方面,奇力公司不断引进先进的生产设备和技术人才,通过自主研发和合作创新,不断提升产品性能和质量。随着技术的突破,奇力公司逐渐在LED芯片市场上崭露头角,以其亮度高、性能稳定的产品赢得了客户的信赖。
刚看到的新闻,有兴趣的可以看看: 德州仪器宣布启动 MSP430 微控制器 (MCU) 超低功耗设计挑战赛。比赛将在 2009 年 10 月 19 日至 2010 年 1 月 19 日期间进行。参赛选手将提交使用业界最低功耗 MSP430 MCU 与开发工具、面向从日常实用解决方案到 ...… 查看全部问答∨ |
|
我们敬爱的SOSOMM今天遇到麻烦了,大家看能否帮忙想想办法 本帖最后由 ddllxxrr 于 2016-1-7 17:19 编辑 同志们,我西门今天在这里说一件事.在半小时前,我们的SOSOMM打来电话,问我刚刚可曾在QQ上要她汇款给我,我说没有.因为我今天一直在开会.她说:糟了,刚有人在网上用你的QQ让我汇款,我汇出去了........... ...… 查看全部问答∨ |
|
我买了一个串口SIM300GPRS模块,想用在WinCE上拨号上网。 当在PC上时,把模块连到COM1上,发送"AT/r",收到:at OK 但是在安装了WinCE的开发板上,把模块连到com1上,设置同样的串口参数,发送"AT/r",却收不到任何数据。在程序中使用Rea ...… 查看全部问答∨ |
|