中断与异常

筅森魡賤 提交于 2020-02-08 16:06:02

arm对异常(中断)处理过程

1 初始化:
:: a 设置中断源,让它可以产生中断
:: b 设置中断控制器(可以屏蔽某个中断,优先级)
:: c 设置CPU总开关,(使能中断)

2 执行其他程序:正常程序

3 产生中断:按下按键--->中断控制器--->CPU

4 cpu每执行完一条指令都会检查有无中断/异常产生

5 发现有中断/异常产生,开始处理。对于不同的异常,跳去不同的地址执行程序。这地址上,只是一条跳转指令,跳去执行某个函数(地址),这个就是异常向量。如下就是异常向量表,对于不同的异常都有一条跳转指令。  (3-5都是硬件强制做的)

6 这些函数做什么事情?
:: 软件做的:
:: a 保存现场(各种寄存器)
:: b 处理异常(中断):
:::: 分辨中断源
:::: 再调用不同的处理函数
:: c 恢复现场

--------------------------------------异常向量表-------------------------------------

.globl _start
_start: b   reset
    ldr pc, _undefined_instruction
    ldr pc, _software_interrupt
    ldr pc, _prefetch_abort
    ldr pc, _data_abort
    ldr pc, _not_used
    ldr pc, _irq //发生中断时,CPU跳到这个地址执行该指令 **假设地址为0x18**
    ldr pc, _fiq
//我们先在0x18这里放 ldr pc ,__irq,于是cpu最终会跳去执行__irq代码
//保护现场,调用处理函数,恢复现场

思考:为什么不用b指令实现中断的跳转?

 

软中断程序:

示例一:

.text
    
    @异常向量表
    b     reset        @0x00 reset
    nop                @0x04 udef
    b    swi_handler   @0x08 swi
    nop                @0x0c prefetch abort 指令预取终止
    nop                @0x10 data abort 数据访问终止
    nop                @0x14 reserved   保留
    nop                @0x18 irq
    nop                @0x1c fiq
                       @nop 占空地址;0x00-1c为异常向量表所用,不可被其他语句所占
swi_handler:
    stmfd sp!,{r0,lr} @将r0,lr进栈,保护现场,sp为堆栈指针
    mov r0,#6
    ldmfd sp!,{r0,pc} @将原值出栈到r0,pc,恢复现场

reset:
    mov r0,#3
    swi 2
    
    mov r1,r0
    b   reset
    

执行压栈和出栈指令后报错

 

 所以在压栈之前,要令堆栈指针sp重新指向一个空间

    .text
    
    @异常向量表
    b     reset      @0x00 reset
    nop             @0x04 udef
    b    swi_handler @0x08 swi
    nop                @0x0c prefetch abort 指令预取终止
    nop                @0x10 data abort 数据访问终止
    nop                @0x14 reserved   保留
    nop                @0x18 irq
    nop                @0x1c fiq
                    @nop 占空地址;0x00-1c为异常向量表所用,不可被其他语句所占
swi_handler:
    stmfd  sp!,{r0,lr} @将r0,lr进栈,保护现场,sp为堆栈指针
    mov    r0,#6
    ldmfd  sp!,{r0,pc} @将原值出栈到r0,pc,恢复现场

reset:
    ldr    sp,=stack_base
    mov    r0,#3
    swi    2
    mov    r1,r0
    b      reset
    
    .data
buf:
    .space    32   @定义内存空间,将空间末地址赋给sp
stack_base:      @开始压栈,sp递减,入栈sp递增,又会回到此位置

    .end

软中断主要用于系统调用,用于从用户空间到内核空间的切换。user--->svc

@异常向量表
    b     reset           @0x00 reset 指令机器码存放的地址空间大小有限制,可以如下单独构造4字节的空间存放
    ldr  pc,_udef        @0x04 udef
    ldr     pc,_swi         @0x08 swi   不使用b而使用ldr跳转以突破32M空间限制
    ldr  pc,_prefetch     @0x0c prefetch abort 指令预取终止
    ldr  pc,_data_abort     @0x10 data abort 数据访问终止
    nop                     @0x14 reserved   保留
    ldr  pc,_irq         @0x18 irq
    ldr  pc,_fiq         @0x1c fiq
                         @nop 占空地址;0x00-1c为异常向量表所用,不可被其他语句所占

_udef:
    .word    udef_handler
_swi:                     @此标号为地址
    .word    swi_handler  @里面存放了一个数,此数存放了地址,通过ldr将函数地址赋给PC以实现跳转
_prefetch:
    .word   prefetch_handler  @未实现
_data_abort:
    .word   data_abort_handler
_irq:
    .word   irq_handler
_fiq:
    .word   fiq_handler
swi_handler:
    stmfd  sp!,{r0,lr}   @将r0,lr进栈,保护现场,sp为堆栈指针
    sub       r0,lr,#4
    ldr    r0,[r0]
    bic    r0,#0xff000000
    bl     swi_num_handler
    ldmfd  sp!,{r0,pc}^  @将原值出栈到r0,pc,恢复现场

swi_num_handler:
    @swith(num)
    @case 2:
    @  .....
    @case 3:
    @  .....
    

reset:
    ldr    sp,=stack_base
    @切换到应用程序空间
    msr    cpsr,#0x10
    mov    r0,#3
    @ open  read  write  ioctl ...通过系统调用访问内核数据
    @  2     4      6      7      软中断号  
    swi    2     @跳转到异常向量表的软中断入口
                 @保存返回的地址到LR
                 @切换到SVC模式
    mov    r1,r0
    b      reset
    
    .data
buf:
    .space    32   @定义内存空间,将空间末地址赋给sp
stack_base:      @开始压栈,sp递减,入栈sp递增,又会回到此位置


    .end

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!