ARM处理器共有7中运转形式:
用户形式(usr) — 正常程序履行形式
|– |– 快速间断形式(fiq) — 用于高速数据传输和通道处理
特 | 异 | 外部间断形式(irq) — 用于一般的间断处理
权 –| 常 –| 管理员形式(svc) — 供操作体系运用的一种保护形式
模 | 模 | 数据拜访间断形式(abt) — 用于虚拟存储及存储保护
式 | 式 |– 未界说指令间断形式(und) — 用于支撑经过软件仿真硬件的协处理器
|– 体系形式(sys) — 用于运转特权级的操作体系使命
特权形式:fiq、irq、svc、abt、und、sys — 程序能够拜访一切的体系资源,也能够恣意切换处理器形式
反常形式:fiq、irq、svc、abt、und
ARM反常间断品种及优先级:
优先级 反常间断称号
高 复位(reset)
|| 数据拜访间断(data abort)
|| 快速间断请求(FIQ)
|| 外部间断请求(IRQ)
/||/ 指令预取间断(prefetch abort)
// 软间断(SWI)
低 未界说指令(undefined instruction)
反常向量表:
地址 反常间断称号 优先级
. .
. .
. .
0x1c FIQ 3
0x18 IRQ 4
0x14 Reserved X
0x10 Data Abort 2
0x0c Prefetch Abort 4
0x08 SWI 5
0x04 Undefined Instruction 6
0x00 Reset 1
Vector Table能够坐落0x0或许0xFFFF0000处(ARM720T、ARM9、ARM10..)
优先级为3的FIQ为什么放在地址0x1c处呢?最初这么规划应该是为了愈加快速地呼应FIQ间断,也便是说不在0x1c地
址放跳转指令,而是直接寄存最要害的FIQ处理代码在0x1c开端一段地址区域内。
反常进入及回来:
当反常发生时:
1. 复制当时形式的CPSR值到相应反常形式的SPSR_
2. 设置恰当的CPSR位:
改动处理器状况进入ARM状况
改动处理器形式进入相应的反常形式
假如需求能够设置间断制止位制止相应间断
3. 保存回来地址(pc-4)到LR_
4. 设置pc为相应的反常向量。
反常回来时,需求:
1. 从SPSR_
2. 从LR_
(只能在ARM状况下完成该回来操作)
反常回来的指令剖析:
* 运用一数据处理指令完成,该指令带“S”后缀,一起pc作为意图寄存器
* 在特权形式下不只是要更新pc,并且还要复制SPSR到CPSR
1. 从SWI和Undef反常回来:
movs pc , lr
这两种反常都会在导致反常的指令履行周期中就进入反常,没有比及下个时钟周期才进入反常,别的这两种反常都是回来到发生反常指令的下一条指令去持续履行。我从前面能够知道lr中保存的便是pc-4(该pc值是发生反常指令的下下一条指令的地址),所以能够直接将lr的值送入pc。
2. 从FIQ、IRQ和Prefect Abort回来:
subs pc , lr , #4
这三种反常都会等候发生反常的指令履行完才会进入反常,所以此时的pc现已更新,比方:
…
subs r3, r3, #1 << 26 @ 0x100
bcs 2b @ 0x104
subs r1, r1, #1 << 5 @ 0x108
bcs 1b @ 0x10b
…
假如在履行第1行地址为0x100指令时,发生了上面三种反常,此时的pc值为0x108,等第1行履行完之后,pc更新为0x10b。一起进入反常处理,在反常进入时将lr值保存为pc-4,即0x108。那么在反常回来后,需求接着履行发生反常指令的下一条指令的话就有必要将lr的值减去4才干得到正确的地址,lr-4 = 0x108 – 4 = 0x104。
3. 从数据反常(Data Abort)反常回来:
该反常也是会等候发生反常的那条指令履行完才会进入反常,状况类似于第2类的三种反常,但是有一点不同的是:数据反常回来地址不是发生反常的下一条指令,而是发生反常的那条指令,所以,它的回来指令应该是:
subs pc , lr , #8
依照上面的比如就应该回来到地址0x100处持续履行。为什么会这样,由于数据反常回来后会持续去取数据,想想缺页反常。
4. 假如lr在进入反常后被压栈的话,就需求运用下面的指令来弹出。
LDMFD sp! , {pc}^
(^一起复制SPSR到CPSR中,这儿的lr在压栈之前现已做了前面3中状况对应的处理了)
SWI反常:
履行SWI软间断指令即可发生软间断反常,进入SWI反常时会做如下动作:
CSPR保存到SPSR_svc。
改动处理器状况进入ARM状况
改动处理器形式进入相应的管理员形式(svc)
看需求制止间断
保存回来地址(pc-4)到LR_svc
设置pc为0x08或许0xFFFF0008
需求留意一点的是:假如在履行SWI指令时体系正处于svc形式时,那么将会覆盖掉本来LR_svc的值。所以
在SWI指令之前应该对LR_svc压栈保存。
SWI反常回来时,做如下动作:
从SPSR_svc康复CPSR
从LR_svc康复pc,不需求批改
在c言语中运用要害字“__swi”来界说一个软间断函数:
__swi(0x30) void my_swi(void);
void fun(void)
{
my_swi();
}
—–> 转换成汇编
fun
STMFD sp! , {lr}
swi 0x24
LDMFD sp! , {pc}
swi调用带参和swi处理函数带参:
swi调用带参:
运用swi指令时,一般有两种办法来传递参数:
1. 运用swi号
swi指令的低24bits(ARM指令集)组成或许低8bits(Thumb指令集)来指定软间断号,
其他参数经过寄存器来传递。
2. r0决议软间断号,其他参数运用相同寄存器传递。
c言语中,要害字“__swi”界说的软间断函数答应最多4个参数,运用r0~r4来传递。
swi处理函数带参:
1. 汇编中,存取调用者设置的寄存器即可
2. 传参给c,一般才用压栈的办法:
将参数压栈,给调用的函数传递一个指向这些参数的指针。
获取SWI号:
ARM core不供给直接传递软间断号到处理程序的机制,SWI处理程序有必要定位SWI指令并提取SWI指令中的常数域
1. 查看SPSR_svc的Tbit,能够确认堕入swi反常之前的指令时ARM指令集仍是Thumb指令集。
2. 然后经过LR_svc的值确认SWI指令的地址。ARM状况下是LR-4,而Thumb状况下是LR-2的方位。
3. SWI指令格局:
ARM态:
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
| Cond |1 1 1 1 | SWI number |
Thumb态
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
| 1 1 0 1 1 1 1 1| SWI number |