ARM体系结构与编程学习(十一)
2013-03-29 15:42
316 查看
第九章 ARM异常中断处理
9.1arm控制程序的执行流程
1、正常程序执行:每执行一条arm指令,PC值加4字节;每执行一条thumb指令,PC值加2字节。
2、跳转:B/BL/BLX,对于BLX,跳转到目标地址处执行,保存子程序的返回地址,根据目标地址的最低位可以将程序切换到thumb状态。
3、中断:系统先执行完当前指令,然后保存现场,之后跳转到异常中断处理程序。中断执行完后,恢复现场,程序返回到发生中断的指令的下一条指令处执行。
9.1.2异常中断向量表及优先级
中断向量地址 异常中断类型 异常中断模式 优先级(6级最低)
0x0 复位 特权模式(SVC) 1
0x4 未定义指令中止 未定义指令中止 6
0x8 软件中断(SWI) 特权模式(SVC) 6
0x0c 指令预取中止 中止模式 5
0x10 数据访问中止 中止模式 2
0x14 保留
0x18 外部中断请求(IRQ) 外部中断模式(IRQ) 4
0x1c 快速中断请求(FIQ) 快速中断模式(FIQ) 3
异常中断模式寄存器,除FIQ外,都只有R13、R14专用寄存器,使用这些寄存器时,必须用RN来定义这些名称。
R13_svc RN R13
9.2异常中断响应过程
9.2.1 arm对异常中断的响应过程
1、保存处理器当前状态、中断屏蔽位以及各条件标志位
2、设置CPSR中相应位
3、保存返回地址到LR
4、将PC设置成中断向量地址
上述过程可以用伪指令描述为:
R14_<exception_mode>=return link
SPSR_<exception_mode>= CPSR
CPSR[4:0]=exception mode number
//运行于ARM状态
CPSR[5]=0
//禁止FIQ中断
CPSR[6]=1
//禁止IRQ中断
CPSR[7]=1
PC=exception vector address
1、响应复位异常中断
R14_svc=unpredictable value
SPSR_svc=CPSR
CPSR[4:0]=0b10011
//运行于ARM状态
CPSR[5]=0
//禁止FIQ中断
CPSR[6]=1
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 0000
else
PC=0x0000 0000
处理复位中断
STMFD SP!,{register,LR}
;...
LDMFD SP!,{register,LR}^ ;^表示将SPSR_mode中的内容复制到CPSR
返回
MOV PC,LR
2、响应未定义指令异常中断
R14_und=address of next instruction after the undefined instruction
SPSR_und=CPSR
CPSR[4:0]=0b11011
//运行于ARM状态
CPSR[5]=0
//禁止FIQ中断
CPSR[6]=1
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 0004
else
PC=0x0000 0004
处理复位中断
SUBS LR,LR,#4 ;计算返回地址
STMFD SP!,{register,LR} ;保存使用到的寄存器
;...
LDMFD SP!,{register,LR}^ ;中断返回,^表示将SPSR_mode中的内容复制到CPSR
返回
MOVS PC,LR
3、响应SWI异常中断
R14_svc=address of next instruction after the SWI instruction
SPSR_svc=CPSR
CPSR[4:0]=0b11011
//运行于ARM状态
CPSR[5]=0
//禁止FIQ中断
CPSR[6]=1
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 0008
else
PC=0x0000 0008
处理复位中断
SUBS LR,LR,#4 ;计算返回地址
STMFD SP!,{register,LR} ;保存使用到的寄存器
;...
LDMFD SP!,{register,LR}^ ;中断返回,^表示将SPSR_mode中的内容复制到CPSR
返回
MOVS PC,LR
4、响应指令预取中止异常中断
R14_abt=address of the aborted instruction +4
SPSR_abt=CPSR
CPSR[4:0]=0b10111
//运行于ARM状态
CPSR[5]=0
//CPSR[6]不变
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 000C
else
PC=0x0000 000C
处理复位中断
SUBS LR,LR,#4 ;计算返回地址
STMFD SP!,{register,LR} ;保存使用到的寄存器
;...
LDMFD SP!,{register,LR}^ ;中断返回,^表示将SPSR_mode中的内容复制到CPSR
返回
SUBS PC,LR,#4
5、响应数据访问中止异常中断
R14_abt=address of the aborted instruction +8
SPSR_abt=CPSR
CPSR[4:0]=0b10111
//运行于ARM状态
CPSR[5]=0
//
//CPSR[6]不变
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 0010
else
PC=0x0000 0010
处理复位中断
SUBS LR,LR,#4 ;计算返回地址
STMFD SP!,{register,LR} ;保存使用到的寄存器
;...
LDMFD SP!,{register,LR}^ ;中断返回,^表示将SPSR_mode中的内容复制到CPSR
返回
SUBS PC,LR,#8
6、响应IRQ异常中断
R14_irq=address of next instruction to be executed +4
SPSR_irq=CPSR
CPSR[4:0]=0b10010
//运行于ARM状态
CPSR[5]=0
//
//CPSR[6]不变
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 0018
else
PC=0x0000 0018
处理复位中断
SUBS LR,LR,#4 ;计算返回地址
STMFD SP!,{register,LR} ;保存使用到的寄存器
;...
LDMFD SP!,{register,LR}^ ;中断返回,^表示将SPSR_mode中的内容复制到CPSR
返回
SUBS PC,LR,#4
7、响应FIQ异常中断
R14_fiq=address of next instruction to be executed +4
SPSR_fiq=CPSR
CPSR[4:0]=0b10001
//运行于ARM状态
CPSR[5]=0
//禁止FIQ中断
CPSR[6]=1
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 001C
else
PC=0x0000 001C
处理复位中断
SUBS LR,LR,#4 ;计算返回地址
STMFD SP!,{register,LR} ;保存使用到的寄存器
;...
LDMFD SP!,{register,LR}^ ;中断返回,^表示将SPSR_mode中的内容复制到CPSR
返回
SUBS PC,LR,#4
9.3 中断注册
两种方法:1、使用跳转指令将中断处理程序注册到中断向量表。简单,但是只能在32MB空间范围内跳转
2、使用LDR指令。分两步:先将中断处理程序的绝对地址存放在距离向量表4KB范围内的存储单元中,再用LDR将该单元内容读取到PC中
9.3.1系统复位是注册异常中断处理程序
又分为2中情况:
1、起始地址0x0处为ROM
2、起始地址0x0处为RAM
起始地址0x0为ROM
使用跳转指令
Vector_Init_Block
BL Reset_Handler
BL Undefined_Handler
BL SWI_Handler
BL Prefetch_Handler
BL Abort_Handler
NOP
BL IRQ_Handler
BL FIQ_Handler
使用LDR指令
Vector_Init_Block
LDR PC, Reset_Addr
LDR PC, Undefined_Addr
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
Reset_Addr DCD Start_Boot
Undefined_Addr DCD Undefined_Handler
SWI_Addr DCD SWI_Handler
Prefetch_Addr DCD Prefetch_Handler
Abort_Addr DCD Abort_Handler
NOP
IRQ_Addr DCD IRQ_Handler
FIQ_Addr DCD FIQ_Handler
2地址0x0为RAM
中断向量表必须使用数据读取指令直接向PC中赋值的形式。而且必须使用下面的代码把中断向量表从ROM中复制到RAM的地址0x0处。
MOV R8, #0
ADR R9,Vector_Init_Block
;复制中断向量表(8字节)
LDMIA R9!,{R0-R7}
STMIA R8!,{R0-R7}
;复制中断处理函数地址表(8字节)
LDMIA R9!,{R0-R7}
STMIA R8!,{R0-R7}
9.3.2 在C程序中注册异常中断处理程序
中断向量表中使用跳转指令
1、读取中断处理程序的地址
2、从上一步得到的地址中减去异常中断对应的中断向量地址
3、从上一步得到的地址中减去8,以允许指令预取
4、将上一步得到的地址右移2位,得到以字为单位的偏移量
5、确保上一步得到的地址值高8位为0,因为跳转指令只允许24位的偏移量
6、将上一步得到的地址与数据0xea00 0000作逻辑或,从而得到将要写的中断向量表中的跳转指令的编码
unsigned Install_Handler (unsigned routine ,unsigned *vector)
//vector中断向量表,routine中断处理程序
//程序返回原来的中断向量
{
unsigned vec,oldvec;
vec=((routine-(unsigned)vector-0x8)>>2);
if(vec&0xff000000)
{
printf("Installation of Handler failed!");
exit(1);
}
vec=0xea00 0000|vec;
oldvec=*vector;
*vector=vec;
return oldvec;
}
//下面语句调用中断注册函数
unsigned *irqvec=(unsigned *)0x18;
Install_Handler ((unsigned)IRQHandler,irqvec);
中断向量表使用数据读取指令注册
1、读取中断处理程序的地址
2、从上一步得到的地址中减去异常中断对应的中断向量地址
3、从上一步得到的地址中减去8,以允许指令预取
4、将上一步得到的地址与数据0xe59f f000作逻辑或,从而得到将要写的中断向量表中的跳转指令的编码
unsigned Install_Handler (unsigned location ,unsigned *vector)
//vector中断向量表,location目标地址
//程序返回原来的中断向量
{
unsigned vec,oldvec;
vec=(location-(unsigned)vector-0x8) |0xe59ff000;
oldvec=*vector;
*vector=vec;
return oldvec;
}
//下面语句调用中断注册函数
unsigned *irqvec=(unsigned *)0x18;
Install_Handler ((unsigned)IRQHandler,irqvec);
9.1arm控制程序的执行流程
1、正常程序执行:每执行一条arm指令,PC值加4字节;每执行一条thumb指令,PC值加2字节。
2、跳转:B/BL/BLX,对于BLX,跳转到目标地址处执行,保存子程序的返回地址,根据目标地址的最低位可以将程序切换到thumb状态。
3、中断:系统先执行完当前指令,然后保存现场,之后跳转到异常中断处理程序。中断执行完后,恢复现场,程序返回到发生中断的指令的下一条指令处执行。
9.1.2异常中断向量表及优先级
中断向量地址 异常中断类型 异常中断模式 优先级(6级最低)
0x0 复位 特权模式(SVC) 1
0x4 未定义指令中止 未定义指令中止 6
0x8 软件中断(SWI) 特权模式(SVC) 6
0x0c 指令预取中止 中止模式 5
0x10 数据访问中止 中止模式 2
0x14 保留
0x18 外部中断请求(IRQ) 外部中断模式(IRQ) 4
0x1c 快速中断请求(FIQ) 快速中断模式(FIQ) 3
异常中断模式寄存器,除FIQ外,都只有R13、R14专用寄存器,使用这些寄存器时,必须用RN来定义这些名称。
R13_svc RN R13
9.2异常中断响应过程
9.2.1 arm对异常中断的响应过程
1、保存处理器当前状态、中断屏蔽位以及各条件标志位
2、设置CPSR中相应位
3、保存返回地址到LR
4、将PC设置成中断向量地址
上述过程可以用伪指令描述为:
R14_<exception_mode>=return link
SPSR_<exception_mode>= CPSR
CPSR[4:0]=exception mode number
//运行于ARM状态
CPSR[5]=0
//禁止FIQ中断
CPSR[6]=1
//禁止IRQ中断
CPSR[7]=1
PC=exception vector address
1、响应复位异常中断
R14_svc=unpredictable value
SPSR_svc=CPSR
CPSR[4:0]=0b10011
//运行于ARM状态
CPSR[5]=0
//禁止FIQ中断
CPSR[6]=1
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 0000
else
PC=0x0000 0000
处理复位中断
STMFD SP!,{register,LR}
;...
LDMFD SP!,{register,LR}^ ;^表示将SPSR_mode中的内容复制到CPSR
返回
MOV PC,LR
2、响应未定义指令异常中断
R14_und=address of next instruction after the undefined instruction
SPSR_und=CPSR
CPSR[4:0]=0b11011
//运行于ARM状态
CPSR[5]=0
//禁止FIQ中断
CPSR[6]=1
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 0004
else
PC=0x0000 0004
处理复位中断
SUBS LR,LR,#4 ;计算返回地址
STMFD SP!,{register,LR} ;保存使用到的寄存器
;...
LDMFD SP!,{register,LR}^ ;中断返回,^表示将SPSR_mode中的内容复制到CPSR
返回
MOVS PC,LR
3、响应SWI异常中断
R14_svc=address of next instruction after the SWI instruction
SPSR_svc=CPSR
CPSR[4:0]=0b11011
//运行于ARM状态
CPSR[5]=0
//禁止FIQ中断
CPSR[6]=1
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 0008
else
PC=0x0000 0008
处理复位中断
SUBS LR,LR,#4 ;计算返回地址
STMFD SP!,{register,LR} ;保存使用到的寄存器
;...
LDMFD SP!,{register,LR}^ ;中断返回,^表示将SPSR_mode中的内容复制到CPSR
返回
MOVS PC,LR
4、响应指令预取中止异常中断
R14_abt=address of the aborted instruction +4
SPSR_abt=CPSR
CPSR[4:0]=0b10111
//运行于ARM状态
CPSR[5]=0
//CPSR[6]不变
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 000C
else
PC=0x0000 000C
处理复位中断
SUBS LR,LR,#4 ;计算返回地址
STMFD SP!,{register,LR} ;保存使用到的寄存器
;...
LDMFD SP!,{register,LR}^ ;中断返回,^表示将SPSR_mode中的内容复制到CPSR
返回
SUBS PC,LR,#4
5、响应数据访问中止异常中断
R14_abt=address of the aborted instruction +8
SPSR_abt=CPSR
CPSR[4:0]=0b10111
//运行于ARM状态
CPSR[5]=0
//
//CPSR[6]不变
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 0010
else
PC=0x0000 0010
处理复位中断
SUBS LR,LR,#4 ;计算返回地址
STMFD SP!,{register,LR} ;保存使用到的寄存器
;...
LDMFD SP!,{register,LR}^ ;中断返回,^表示将SPSR_mode中的内容复制到CPSR
返回
SUBS PC,LR,#8
6、响应IRQ异常中断
R14_irq=address of next instruction to be executed +4
SPSR_irq=CPSR
CPSR[4:0]=0b10010
//运行于ARM状态
CPSR[5]=0
//
//CPSR[6]不变
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 0018
else
PC=0x0000 0018
处理复位中断
SUBS LR,LR,#4 ;计算返回地址
STMFD SP!,{register,LR} ;保存使用到的寄存器
;...
LDMFD SP!,{register,LR}^ ;中断返回,^表示将SPSR_mode中的内容复制到CPSR
返回
SUBS PC,LR,#4
7、响应FIQ异常中断
R14_fiq=address of next instruction to be executed +4
SPSR_fiq=CPSR
CPSR[4:0]=0b10001
//运行于ARM状态
CPSR[5]=0
//禁止FIQ中断
CPSR[6]=1
//禁止IRQ中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF 001C
else
PC=0x0000 001C
处理复位中断
SUBS LR,LR,#4 ;计算返回地址
STMFD SP!,{register,LR} ;保存使用到的寄存器
;...
LDMFD SP!,{register,LR}^ ;中断返回,^表示将SPSR_mode中的内容复制到CPSR
返回
SUBS PC,LR,#4
9.3 中断注册
两种方法:1、使用跳转指令将中断处理程序注册到中断向量表。简单,但是只能在32MB空间范围内跳转
2、使用LDR指令。分两步:先将中断处理程序的绝对地址存放在距离向量表4KB范围内的存储单元中,再用LDR将该单元内容读取到PC中
9.3.1系统复位是注册异常中断处理程序
又分为2中情况:
1、起始地址0x0处为ROM
2、起始地址0x0处为RAM
起始地址0x0为ROM
使用跳转指令
Vector_Init_Block
BL Reset_Handler
BL Undefined_Handler
BL SWI_Handler
BL Prefetch_Handler
BL Abort_Handler
NOP
BL IRQ_Handler
BL FIQ_Handler
使用LDR指令
Vector_Init_Block
LDR PC, Reset_Addr
LDR PC, Undefined_Addr
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
Reset_Addr DCD Start_Boot
Undefined_Addr DCD Undefined_Handler
SWI_Addr DCD SWI_Handler
Prefetch_Addr DCD Prefetch_Handler
Abort_Addr DCD Abort_Handler
NOP
IRQ_Addr DCD IRQ_Handler
FIQ_Addr DCD FIQ_Handler
2地址0x0为RAM
中断向量表必须使用数据读取指令直接向PC中赋值的形式。而且必须使用下面的代码把中断向量表从ROM中复制到RAM的地址0x0处。
MOV R8, #0
ADR R9,Vector_Init_Block
;复制中断向量表(8字节)
LDMIA R9!,{R0-R7}
STMIA R8!,{R0-R7}
;复制中断处理函数地址表(8字节)
LDMIA R9!,{R0-R7}
STMIA R8!,{R0-R7}
9.3.2 在C程序中注册异常中断处理程序
中断向量表中使用跳转指令
1、读取中断处理程序的地址
2、从上一步得到的地址中减去异常中断对应的中断向量地址
3、从上一步得到的地址中减去8,以允许指令预取
4、将上一步得到的地址右移2位,得到以字为单位的偏移量
5、确保上一步得到的地址值高8位为0,因为跳转指令只允许24位的偏移量
6、将上一步得到的地址与数据0xea00 0000作逻辑或,从而得到将要写的中断向量表中的跳转指令的编码
unsigned Install_Handler (unsigned routine ,unsigned *vector)
//vector中断向量表,routine中断处理程序
//程序返回原来的中断向量
{
unsigned vec,oldvec;
vec=((routine-(unsigned)vector-0x8)>>2);
if(vec&0xff000000)
{
printf("Installation of Handler failed!");
exit(1);
}
vec=0xea00 0000|vec;
oldvec=*vector;
*vector=vec;
return oldvec;
}
//下面语句调用中断注册函数
unsigned *irqvec=(unsigned *)0x18;
Install_Handler ((unsigned)IRQHandler,irqvec);
中断向量表使用数据读取指令注册
1、读取中断处理程序的地址
2、从上一步得到的地址中减去异常中断对应的中断向量地址
3、从上一步得到的地址中减去8,以允许指令预取
4、将上一步得到的地址与数据0xe59f f000作逻辑或,从而得到将要写的中断向量表中的跳转指令的编码
unsigned Install_Handler (unsigned location ,unsigned *vector)
//vector中断向量表,location目标地址
//程序返回原来的中断向量
{
unsigned vec,oldvec;
vec=(location-(unsigned)vector-0x8) |0xe59ff000;
oldvec=*vector;
*vector=vec;
return oldvec;
}
//下面语句调用中断注册函数
unsigned *irqvec=(unsigned *)0x18;
Install_Handler ((unsigned)IRQHandler,irqvec);
相关文章推荐
- ARM体系结构与编程学习(十一)
- ARM体系结构与编程学习(八)
- ARM体系结构与编程学习(九)
- ARM体系结构与编程学习(九)
- ARM体系结构与编程学习(二)
- ARM体系结构与编程学习(四)
- ARM体系结构与编程学习(五)
- ARM体系结构与编程学习(十二)
- ARM体系结构与编程学习(十)
- ARM体系结构与编程学习(五)
- ARM体系结构与编程学习(十三)
- ARM体系结构与编程学习(六)
- ARM体系结构与编程学习(一)
- ARM体系结构学习中的难点(不断更新中)
- ARM的体系结构与编程系列博客——ARM体系变种
- ARM 体系结构与编程 笔记1
- ARM的体系结构与编程系列博客——ARM体系版本
- arm体系结构学习笔记 part1--处理器模式与寄存器
- 一份好的ARM体系结构学习笔记
- arm体系结构学习笔记 part2 -- 中断相关