历史上的今天
返回首页

历史上的今天

今天是:2024年10月20日(星期日)

正在发生

2021年10月20日 | ARM处理器架构------可嵌套中断的实现

2021-10-20 来源:eefocus

传统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来推出中断处理程序。


程序贴在下面,用的是堆栈分开的方法,只是示例。

  1. __asm void IRQ_Handler(void){  

  2.       PRESERVE8  

  3.       IMPORT handler1      

  4.        

  5.       // STORE LR_irq & SPSR_irq  

  6.       SUB             LR, LR, #4  

  7.       MRS             R0, SPSR  

  8.       STMFD           SP!, {R0, LR}  

  9.    

  10.       // INTO SVC MODE  

  11.       MRS             R0, CPSR  

  12.       BIC             R0, #0x1f  

  13.       ORR             R0, #0x13  

  14.       MSR             CPSR_C, R0  

  15.        

  16.       // STORE REGISTORS OF SVC MODE  

  17.       STMFD           SP!, {R0-R3,LR}  

  18.        

  19.       // ENABLE IRQ  

  20.       MRS             R0, CPSR  

  21.       BIC             R0, #0x80  

  22.       MSR             CPSR_C, R0  

  23.        

  24.       // GO TO HANDLER  

  25.       BL              handler1  

  26.        

  27.       // RESTORE REGISTORS OF SVC MODE  

  28.       LDMFD           SP!, {R0-R3,LR}  

  29.        

  30.       // DISABLE IRQ  

  31.       MRS             R0, CPSR  

  32.       ORR             R0, #0x80  

  33.       MSR             CPSR_C, R0        

  34.        

  35.       // INTO IRQ MODE  

  36.       MRS             R0, CPSR  

  37.       BIC             R0, #0x1f  

  38.       ORR             R0, #0x12  

  39.       MSR             CPSR_C, R0  

  40.        

  41.       // RESTORE LR_irq & SPSR_irq  

  42.       LDMFD           SP!, {R0, LR}  

  43.       MSR             SPSR_CFX, R0  

  44.        

  45.   // EXIT IRQ  

  46.       MOVS            PC, LR   

  47. }  


推荐阅读

史海拾趣

Deutronic Elektronik GmbH公司的发展小趣事

Deutronic Elektronik GmbH深知客户服务的重要性,始终将客户需求放在首位。公司建立了完善的客户服务体系,为客户提供全方位的服务支持。通过优质的产品和服务,Deutronic Elektronik GmbH赢得了客户的广泛赞誉和信任。同时,公司也注重品牌建设和提升,通过品牌推广和营销活动,进一步提升了品牌知名度和美誉度。

请注意,以上故事概要基于假设和逻辑构建,可能不完全符合Deutronic Elektronik GmbH公司的实际发展历程。如需更详细和准确的信息,请参考公司官方发布的历史资料和新闻报道。

Dongguan City Niuhang Electronics Co.LTD公司的发展小趣事

随着公司业务的不断拓展,Dongguan City Niuhang Electronics Co.LTD意识到技术创新的重要性。公司投入大量资金和技术人员,专注于芯片新技术、封装自动化的研究和开发。经过数年的努力,公司成功研发出一系列高性能的二极管、整流器等产品,其中多项技术获得国家级发明专利。这些创新产品不仅提升了公司的市场竞争力,也为公司赢得了业界的广泛认可。

Amphion Semiconductor Ltd公司的发展小趣事

为了进一步提升技术水平和市场竞争力,Dongguan City Niuhang Electronics Co.LTD积极开展国际合作与交流。公司与多家国际知名半导体企业建立了紧密的合作关系,共同开展技术研发和市场拓展。通过与国际同行的交流与合作,公司不仅学到了先进的技术和管理经验,还拓宽了国际市场渠道,为公司的长远发展奠定了坚实基础。

ENERGIZER公司的发展小趣事

随着环保意识的日益增强,ENERGIZER也积极响应环保号召,致力于研发更环保的电池产品。1988年,公司发明了无汞环保碱性电池,这一创新性的产品不仅性能优良,而且对环境友好,受到了消费者的广泛欢迎。同时,ENERGIZER还积极推广电池回收和再利用的理念,倡导绿色消费,为全球的环保事业做出了积极贡献。

科通(COMTEK)公司的发展小趣事

在多年的努力下,科通技术逐渐成长为一家具有影响力的电子企业。为了进一步提升公司的竞争力和市场地位,科通技术积极筹备IPO上市。虽然公司在上市过程中遇到了一些波折和挑战,但最终成功实现了上市目标。未来,科通技术将继续坚持创新驱动、市场导向的发展战略,不断提升自身的核心竞争力,为客户提供更加优质的产品和服务。

请注意,由于篇幅限制,上述故事仅为简要概括,并未涵盖所有细节。同时,由于信息来源的不确定性,部分故事可能无法完全还原真实情况。

Avel Lindberg公司的发展小趣事

随着公司业务的不断拓展,科通技术开始与国际知名品牌展开合作。通过与Xilinx、Intel、SanDisk等全球领先的芯片原厂建立紧密的合作关系,科通技术获得了这些品牌的产品线授权,并为其在中国市场的拓展提供了有力的支持。这些合作不仅提升了科通技术的品牌影响力,也为其带来了更多的市场机会。

问答坊 | AI 解惑

第五届全国大学生机器人

好东西!同大家分享下!…

查看全部问答>

【专贴】各位需要什么资料?

本帖最后由 paulhyde 于 2014-9-15 09:37 编辑 各位需要什么资料或者关于什么方面的内容,可以跟帖说说~~~~ 看看大家能不能帮到你~~~ (一般在需要在CNKI期刊、万方等数据库处需要付费下载的资料我都可以下载到~~~如果有看中的论文、期刊等也可 ...…

查看全部问答>

模电设计不得不看——模拟电路设计原则

主要内容: 衡量设计质量的标准 常用模拟电路设计方法 电磁兼容和认证 PCB布局布线技巧等…

查看全部问答>

请问有源晶振的输出信号 能拿100m的示波器测出来吗?

来自EEWORLD合作群:arm fpga linux 嵌入1(63762526) 群主:wangkj…

查看全部问答>

申请LM3S8962 评估套件

 希望看得见,摸得着。…

查看全部问答>

基于单片机和LM35的温度测控

我们现在在做单片机课程设计,由于是第一次做项目很多东西都还不懂,望各位大哥大姐多多指教哈。 用LM35和ADC0809基于单片机STC89C52检测室内温度,为何在数码管显示数值是乱码。…

查看全部问答>

AD637的测量范围

我用AD637测量正弦波有效值,在200K以下测的挺准的,按手册说的大于1V有效值的信号可以测到8M,但是我测2M的正弦信号就不准了,有效值越大测得也不准,我是1、3、4脚接地,8、9间接10uf,6、9相连、13脚过103的电容输入,正负15v供电。求高人指点我 ...…

查看全部问答>

学习一下,专家问答:关于电源设计几个问答题

本帖最后由 qwqwqw2088 于 2014-2-4 11:15 编辑 电源设计问题1:如何来评估一个系统的电源需求? Answer:对于一个实际的电子系统,要认真的分析它的电源需求。不仅仅是关心输入电压,输出电压和电流,还要仔细考虑总的功耗,电源实现的效率,电 ...…

查看全部问答>

振荡电路 --- 集锦

本帖最后由 dontium 于 2016-8-28 22:01 编辑 …

查看全部问答>