微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM linux的中断处理过程

ARM linux的中断处理过程

时间:11-09 来源:互联网 点击:

拷贝vector table,拷贝stub function
memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start);

kuser_init(vectors_base); ----copy kuser helper function

flush_icache_range(vectors, vectors + PAGE_SIZE * 2);
modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
}

一旦涉及代码的拷贝,我们就需要关心其编译连接时地址(link-time address)和运行时地址(run-time address)。在kernel完成链接后,__vectors_start有了其link-time address,如果link-time address和run-time address一致,那么这段代码运行时毫无压力。但是,目前对于vector table而言,其被copy到其他的地址上(对于High vector,这是地址就是0xffff00000),也就是说,link-time address和run-time address不一样了,如果仍然想要这些代码可以正确运行,那么需要这些代码是位置无关的代码。对于vector table而言,必须要位置无关。B这个branch instruction本身就是位置无关的,它可以跳转到一个当前位置的offset。不过并非所有的vector都是使用了branch instruction,对于软中断,其vector地址上指令是“W(ldr) pc, __vectors_start + 0x1000 ”,这条指令被编译器编译成ldr pc, [pc, #4080],这种情况下,该指令也是位置无关的,但是有个限制,offset必须在4K的范围内,这也是为何存在stub section的原因了。

4、中断控制器的初始化

具体可以参考GIC代码分析。

三、ARM HW对中断事件的处理

当一切准备好之后,一旦打开处理器的全局中断就可以处理来自外设的各种中断事件了。

当外设(SOC内部或者外部都可以)检测到了中断事件,就会通过interrupt requestion line上的电平或者边沿(上升沿或者下降沿或者both)通知到该外设连接到的那个中断控制器,而中断控制器就会在多个处理器中选择一个,并把该中断通过IRQ(或者FIQ,本文不讨论FIQ的情况)分发给process。ARM处理器感知到了中断事件后,会进行下面一系列的动作:

1、修改CPSR(Current Program Status Register)寄存器中的M[4:0]。M[4:0]表示了ARM处理器当前处于的模式( processor modes)。ARM定义的mode包括:

处理器模式缩写对应的M[4:0]编码Privilege level
Userusr10000PL0
FIQfiq10001PL1
IRQirq10010PL1
Supervisorsvc10011PL1
Monitormon10110PL1
Abortabt10111PL1
Hyphyp11010PL2
Undefinedund11011PL1
Systemsys11111PL1

一旦设定了CPSR.M,ARM处理器就会将processor mode切换到IRQ mode。

2、保存发生中断那一点的CPSR值(step 1之前的状态)和PC值

ARM处理器支持9种processor mode,每种mode看到的ARM core register(R0~R15,共计16个)都是不同的。每种mode都是从一个包括所有的Banked ARM core register中选取。全部Banked ARM core register包括:

UsrSystemHypSupervisorabortundefinedMonitorIRQFIQ
R0_usr
R1_usr
R2_usr
R3_usr
R4_usr
R5_usr
R6_usr
R7_usr
R8_usrR8_fiq
R9_usrR9_fiq
R10_usrR10_fiq
R11_usrR11_fiq
R12_usrR12_fiq
SP_usrSP_hypSP_svcSP_abtSP_undSP_monSP_irqSP_fiq
LR_usrLR_svcLR_abtLR_undLR_monLR_irqLR_fiq
PC
CPSR
SPSR_hypSPSR_svcSPSR_abtSPSR_undSPSR_monSPSR_irqSPSR_fiq
ELR_hyp

在IRQ mode下,CPU看到的R0~R12寄存器、PC以及CPSR是和usr mode(userspace)或者svc mode(kernel space)是一样的。不同的是IRQ mode下,有自己的R13(SP,stack pointer)、R14(LR,link register)和SPSR(Saved Program Status Register)。

CPSR是共用的,虽然中断可能发生在usr mode(用户空间),也可能是svc mode(内核空间),不过这些信息都是体现在CPSR寄存器中。硬件会将发生中断那一刻的CPSR保存在SPSR寄存器中(由于不同的mode下有不同的SPSR寄存器,因此更准确的说应该是SPSR-irq,也就是IRQ mode中的SPSR寄存器)。

PC也是共用的,由于后续PC会被修改为irq exception vector,因此有必要保存PC值。当然,与其说保存PC值,不如说是保存返回执行的地址。对于IRQ而言,我们期望返回地址是发生中断那一点执行指令的下一条指令。具体的返回地址保存在lr寄存器中(注意:这个lr寄存器是IRQ mode的lr寄存器,可以表示为lr_irq):

(1)对于thumb state,lr_irq = PC

(2)对于ARM state,lr_irq = PC - 4

为何要减去4?我的理解是这样的(不一定对)。由于ARM采用流水线结构,当CPU正在执行某一条指令的时候,其实取指的动作早

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top