历史上的今天
今天是:2025年04月23日(星期三)
2020年04月23日 | Arm架构异常处理流程之中断
2020-04-23 来源:eefocus
【摘要】
本文将为您介绍linux内核是如何实现arm中断处理的。缺页异常、中断和系统调用同属arm异常处理,笔者计划分三篇文档分别介绍一下,其实在汇编阶段三种处理流程有很多相通之处,不过为了阅读方便,即使相同的部分也会重新在各自文档中介绍一遍。
【写作原因】
1 了解一下linux源码是如何实现arm中断处理的。
2 对于定位一些中断有关的问题,比如中断过多等会有所帮助
【正文一】linux系统arm中断处理之汇编阶段
1 关闭和开启当前处理器上的本地中断,会产生中断信号,但不处理。
local_irq_disable()关闭中断指令:cpsid i;
local_irq_enable()开启中断指令:cpsie i;
关闭和开启中断,不会产生中断信号。
disable_irq/enable_irq
2 为了介绍方便介绍,先列出两个知识点。
2.1 linux系统为实现异常处理引入了栈帧的概念:
#define ARM_cpsr uregs[16]
#define ARM_pc uregs[15]
#define ARM_lr uregs[14]
#define ARM_sp uregs[13]
#define ARM_ip uregs[12]
#define ARM_fp uregs[11]
#define ARM_r10 uregs[10]
#define ARM_r9 uregs[9]
#define ARM_r8 uregs[8]
#define ARM_r7 uregs[7]
#define ARM_r6 uregs[6]
#define ARM_r5 uregs[5]
#define ARM_r4 uregs[4]
#define ARM_r3 uregs[3]
#define ARM_r2 uregs[2]
#define ARM_r1 uregs[1]
#define ARM_r0 uregs[0]
#define ARM_ORIG_r0 uregs[17]
2.2 Arm的几种模式介绍:
处理器模式 缩写 对应的M[4:0]编码 Privilegelevel
User usr 10000 PL0
FIQ fiq 10001 PL1
IRQ irq 10010 PL1
Supervisor svc 10011 PL1
Monitor mon 10110 PL1
Abort abt 10111 PL1
Hyp hyp 11010 PL2
Undefined und 11011 PL1
System sys 11111 PL1
2.3 ARM 异常处理总入口(entry-armv.s):
/*注释:
1)Arm架构异常处理向量表起始地址__vectors_start。
2)Arm架构定义7种异常包括中断、系统调用、缺页异常等,发生异常时处理器会跳转到相应入口。
3)异常向量表起始位置有cp15协处理器的控制寄存器c1的bit13
决定:v=0时,异常向量起始于0xffff0000;v=1时起始于0x0.
4)举例:当IRQ发生时跳转到0x18这个虚拟地址上(内核态虚拟地址)
head.s中设置了cp15寄存器器(proc-v7.s->__v7_setup()函数设置的)
*/
__vectors_start:
W(b) vector_rst
W(b) vector_und
/*
系统调用入口点:
__vectors_start + 0x1000=__stubs_start
此时pc指向系统调用异常 的处理入口:vector_swi
用户态通过swi指令产生软中断。
因为系统调用异常代码编译到其他文件,其入口地址与异常向量相隔
较远,使用b指令无法跳转过去(b指令只能相对当前pc跳转+/-32M范围)
*/
W(ldr) pc, __vectors_start + 0x1000
/* 取指令异常 */
W(b) vector_pabt
/* 数据异常--缺页异常 */
W(b) vector_dabt
W(b) vector_addrexcptn
/* 中断异常 */
W(b) vector_irq
W(b) vector_fiq
3 中断处理(vector_irq):
3.1 vector_irq : 它是通过vetcor_stub宏定义的。
/*注释:
当irq发生时,硬件完成如下操作:
1arm在irq模式下有自己的lr寄存器lr_irq ,spsr_irq,sp_irq.
r14_irq=lr_irq = address of next instruction to be executed+4;
2spsr_irq = cpsr:保存了处理器当前状态、中断屏蔽位及各条件标志位,保存后
cpsr会切换到irq模式。
3cpsr[4:0]=0b10010:设置arm为irq模式
4cpsr[4] = 0:arm状态执行。
5cpsr[7]=1:禁止irq
6pc=0xffff0018:将pc值设置成异常中断的中断向量地址,即:vector_irq地址。
之后进入下面的中断处理。
vector_stub 函数定义了vetor_irq
*/
vector_stub irq, IRQ_MODE, 4
.long __irq_usr @ 0 (USR_26 / USR_32)
.long __irq_invalid @ 1 (FIQ_26 / FIQ_32)
.long __irq_invalid @ 2 (IRQ_26 / IRQ_32)
.long __irq_svc @ 3 (SVC_26 / SVC_32)
3.2 vecotr_stub 宏定义。
1)vector_stub 宏尤为关键,arm任何异常都是通过其将r0/lr/spsr保存到异常模式的栈中。
2)vector_stub通过 vector_name实现其功能:
/*注释:
该接口负责保存异常发生前一时刻cpu寄存器到异常mode的栈中,保存r0,lr,spsr寄存器的值到sp_dabt或sp_irq上
注意:
1 此时的sp是异常状态下的sp,这个栈只有12byte大小,在cpu_init()中初始化。
2 arm在IRQ/svc/ABORT几种模式下sp是不能共用的,详见:A2.5.7
3 此时lr中保存的实际上是异常的返回地址,异常发生,切换到svc模式后,会将lr保存到svc模式栈中(pt_regs->pc)
最后从异常返回时再将pt_regs->pc加载入arm寄存器pc中,实现异常返回。
本函数只是其中一个步骤,即为将异常发生时刻lr保存到svc模式栈中(pt_regs->pc)做准备。
4 spsr是异常发生那一刻(即进入异常模式前是什么模式)的cpsr状态,如内核态下发生中断:则spsr是svc模式10111;
如用户态下发生中断,则spsr是user模式10000.
5 此时cpu正处于异常状态(如中断),此时cpsr为10010;
6 要进行真正的异常处理,需要退出异常模式进入svc模式.
*/
.macro vector_stub, name, mode, correction=0
/*强制cacheline=32byte对齐*/
.align 5
vector_name:
.ifcorrection
/*注释:
需要调整返回值,对应irq异常将lr减去4
因为异常发生时,arm将pc地址+4赋值给了lr
*/
sub lr, lr, #correction
.endif
@
@Save r0, lr_ @(parent CPSR) @spsr中保存异常发生时刻的cpsr ; book:A2.6 Exceptions; @注意此时的栈sp是异常时(abt mode或irq mode)的栈sp和svc mode里的栈sp不同 @dabt异常时的sp只有12byte大小 ;cpu_init中初始化 @save r0, lr;将r0和lr保存到异常模式的栈上[sp]=r0;[sp+4]=lr_dabt;stmia sp,{r0, lr}没有sp!,因此sp不变 @r0也要入栈,以为r0会用作传递参数(异常状态下的sp) stmia sp, {r0, lr} /*将spsr保存到异常模式的栈上[sp+8]=spsr*/ mrs lr, spsr @ read spsr to lr str lr, [sp, #8] @save spsr //sp+8=lr=(spsr_dabt) @ @Prepare for SVC32 mode. IRQs remaindisabled. @cpsr中保存的是异常模式:如中断10010;dabt10111 mrs r0, cpsr /* 注意: 1 dabt处理时:r0=r0^(0x17^0x13)=r0^0x4,bit3取反之后10011变为svc模式; 2 IRQ处理时:r0=10010=r0^(0x12^0x13)=r0^0x1=10011变为svc模式 */ eor r0, r0, #(mode ^ SVC_MODE | PSR_ISETSTATE) msr spsr_cxsf, r0 @ @the branch table must immediately follow this code @ and lr, lr, #0x0f /* 用户态(user mode)lr=0;内核态(svn mode)lr=3; */ /* r0=sp; 注意: 1此时r0中保存了异常状态下sp栈地址,这个栈上保存了r0,lr(异常返回地址), spsr(异常发生时,cpu的状态,当然异常返回时需要恢复该状态) 2之后的函数会把r0中保存的异常模式的sp上信息,加载到svc模式下的sp栈上。 异常处理返回时再将svc mode的栈加载到arm寄存器上。 */ mov r0, sp /* lr中是保存发生异常时arm的cpsr状态到spsr 1 user模式发生异常则lr=10000&0x0f;lr=pc+lr<<2pc+0时执行 __dabt_usr; 2 svc模式发生异常则lr=10011&0x0f;lr=pc+lr<<2 pc+12时执行 __data_svc lr=3时执行__dabt_svc */ ARM( ldr lr,[pc, lr, lsl #2] ) /* movs中s表示把spsr恢复给cpsr,上面可知spsr保存的是svc模式,不过此时中断还是关闭的 异常处理一定要进入svc模式原因: 1)异常处理一定要PL1特权级。2)使能嵌套中断。
下一篇:ARM 处理器 ~ 中断与异常
史海拾趣
|
【摘 要】随着城市化水平的不断提高和城市照明系统的不断扩大,节约能源并提高路灯系统的可靠性成了十分紧迫 的课题。目前很多城市的交通路灯的能源利用率不高,这不符合党中央下达的“建设节约型社会”的号召。CC2480是TI公司 生产的基于ZigBee ...… 查看全部问答> |
|
请大家帮忙,我设计的RS485总线通信线路,一共接了25个设备,驱动芯片用的RS485(有几个用了RS483),总线传输数据时干扰很大。 现在电路在每个终端处有20K的上拉和下拉电阻(分别接A和B,A上拉,B下拉),另外在A,B处跨接120欧姆的匹配电阻。不知 ...… 查看全部问答> |
|
有人说CPLD资源使用过多会发热严重,影响稳定性。 现有一项目准备做PCB了,有一EPM7128的宏单元用了88%引脚用了86%,不知对稳定性是否真的有影响?以前的项目都没用过这么多的。 请有此类经验的同仁给点意见。。。… 查看全部问答> |
|
刚开始学习PLC,遇到问题了,希望大家能帮帮忙。 用电脑(作为上位机)通过RS232口与PLC(作为下位机)连接,上位机的串口通信程序我会编写,但是下位机的程序是怎么编写的?在网上搜到手都酸了,都找不到下位机的通信 ...… 查看全部问答> |
|
最近使用stmf103做一个信号采集的实验板,觉得用usb传数据比较方便(主要是笔记本上都不带串口啊)。比较后打算用usb的虚拟串口功能比较好。有主机端的驱动程序,又有设备端的例程。 但是用起来有很多问题。因为是实时 ...… 查看全部问答> |
|
iphone5上市了以后这款貌似一个屏幕尺寸升级有限,给人们留下了不少遗憾。游戏也就罢了,看电影还是那种不爽的效果。让人恨得牙根痒痒。不过今天我们介绍的这款iphone外接装备很好的解决了看电影屏幕小的问题。它拥有一个方形喇叭外形可以让你的 iP ...… 查看全部问答> |
|
[size=0.92em]以4倍于上一代产品的操作性能和降低的功耗,本系列产品设计用于支持工业设备和其它高端应用富士通半导体(上海)有限公司今日宣布,推出首批基于ARM® Cortex™-M4处理器内核的FM4系列32位RISC 微控制器。富士通半导体本次 ...… 查看全部问答> |




