找回密码
 注册
关于网站域名变更的通知
查看: 307|回复: 1
打印 上一主题 下一主题

ARM体系结构与编程学习(11)

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2021-1-28 17:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x

第九章 ARM异常中断处理

) `  C1 B/ m% r

9.1arm控制程序的执行流程

1、正常程序执行:每执行一条arm指令,PC值加4字节;每执行一条thumb指令,PC值加2字节。

2、跳转:B/BL/BLX,对于BLX,跳转到目标地址处执行,保存子程序的返回地址,根据目标地址的最低位可以将程序切换到thumb状态。

3、中断:系统先执行完当前指令,然后保存现场,之后跳转到异常中断处理程序。中断执行完后,恢复现场,程序返回到发生中断的指令的下一条指令处执行。

1 S( [2 d/ {% x: o3 m2 }

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

: D3 d/ y, z* u1 `1 e) k

9.2异常中断响应过程

8 s- F* d- N' y/ l( Q: P

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

# I3 \! }: ]/ {2 B% c

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


0 S/ o# E2 E9 l0 Y! o- y, n

处理复位中断

STMFD  SP!,{register,LR}

;...

LDMFD  SP!,{register,LR}^    ;^表示将SPSR_mode中的内容复制到CPSR


9 c. s# j5 V: T! ]1 d5 p) ^" K. n

返回

MOV  PC,LR


# q  G, u) s% E. q% j- I+ Q
# T; u2 H" T# e5 V9 M

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


# ^& z) z/ w) V! K) C5 A! i. V

处理复位中断

SUBS LR,LR,#4                    ;计算返回地址

STMFD  SP!,{register,LR}      ;保存使用到的寄存器

;...

LDMFD  SP!,{register,LR}^    ;中断返回,^表示将SPSR_mode中的内容复制到CPSR

) o6 o% d: }& {) F/ p) Q7 }/ H( O

返回

MOVS  PC,LR


. {+ z. M& y) a

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


/ Z- O2 Q1 H) ^: V

处理复位中断

SUBS LR,LR,#4                    ;计算返回地址

STMFD  SP!,{register,LR}      ;保存使用到的寄存器

;...

LDMFD  SP!,{register,LR}^    ;中断返回,^表示将SPSR_mode中的内容复制到CPSR


3 s$ g* n* E, i% b

返回

MOVS  PC,LR


; I8 i' f8 I- M5 d

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

$ K7 P  q% M( U1 [- m! L

处理复位中断

SUBS LR,LR,#4                    ;计算返回地址

STMFD  SP!,{register,LR}      ;保存使用到的寄存器

;...

LDMFD  SP!,{register,LR}^    ;中断返回,^表示将SPSR_mode中的内容复制到CPSR


! o. M7 l8 e# U" O0 |* c! A

返回

SUBS  PC,LR,#4


3 l# H, d, p  q- v

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


1 D* O' S  F3 p/ J! R8 e% F

处理复位中断

SUBS LR,LR,#4                    ;计算返回地址

STMFD  SP!,{register,LR}      ;保存使用到的寄存器

;...

LDMFD  SP!,{register,LR}^    ;中断返回,^表示将SPSR_mode中的内容复制到CPSR

7 Q' A' t' h+ m& }: g

返回

SUBS  PC,LR,#8


: ^: [9 ]  I: c& T- g: H: @

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


' f8 T5 y8 `+ G6 `8 G$ `

处理复位中断

SUBS LR,LR,#4                    ;计算返回地址

STMFD  SP!,{register,LR}      ;保存使用到的寄存器

;...

LDMFD  SP!,{register,LR}^    ;中断返回,^表示将SPSR_mode中的内容复制到CPSR

5 d5 s- F% j+ a7 x; t8 S6 E

返回

SUBS  PC,LR,#4

3 ~" @, t3 Z3 r  V! N& ?

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

1 D# x2 W- t( P( ]% S3 \0 J" t

处理复位中断

SUBS LR,LR,#4                    ;计算返回地址

STMFD  SP!,{register,LR}      ;保存使用到的寄存器

;...

LDMFD  SP!,{register,LR}^    ;中断返回,^表示将SPSR_mode中的内容复制到CPSR

6 ]$ b+ _* `) V! E: a+ Z0 E

返回

SUBS  PC,LR,#4

" ^- {  w- K6 ~% @6 _6 |

9.3 中断注册

两种方法:1、使用跳转指令将中断处理程序注册到中断向量表。简单,但是只能在32MB空间范围内跳转

              2、使用LDR指令。分两步:先将中断处理程序的绝对地址存放在距离向量表4KB范围内的存储单元中,再用LDR将该单元内容读取到PC中

% O  o1 y$ J# G( w0 o. F% c# Z

9.3.1系统复位是注册异常中断处理程序

又分为2中情况:

1、起始地址0x0处为ROM

2、起始地址0x0处为RAM


4 B9 C$ a4 t3 G: D0 @

起始地址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


2 d& k7 [% r8 z- u6 d$ x3 v

使用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


" Y7 l1 M( C9 R- a$ z* t' ~

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


& r4 U1 T. |6 k6 E

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}


) f+ ^- \% w4 q+ u9 m" N! S

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);

$ I* \3 {& m. M" Q9 m4 s

中断向量表使用数据读取指令注册

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);

5 T! _# [2 Z& `) L; u9 V2 J5 L+ b) J' a

该用户从未签到

2#
发表于 2021-1-28 18:37 | 只看该作者
ARM体系结构与编程学习(11)
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-25 04:15 , Processed in 0.078125 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表