您当前的位置: 首页 >  ar

韦东山

暂无认证

  • 0浏览

    0关注

    506博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

第014课 Jz2400_ARM异常与中断体系详解

韦东山 发布时间:2018-02-28 10:36:52 ,浏览量:0

第001节_概念引入与处理流程

取个场景解释中断。

假设有个大房间里面有小房间,婴儿正在睡觉,他的妈妈在外面看书。

问:这个母亲怎么才能知道这个小孩醒?

  • 过一会打开一次房门,看婴儿是否睡醒,让后接着看书
  • 一直等到婴儿发出声音以后再过去查看,期间都在读书

第一种 叫做查询方式: *优点:简单 *缺点: 累 写程序如何:


while(1)
{
    1 read book(读书)
    2 open door(开门)
    if(睡)
        return(read book)
    else
        照顾小孩

}

第二种叫中断方式:

  • 优点:不累
  • 缺点:复杂

写程序:


while(1)
{
    read book
    中断服务程序()//如何被调用?
    {
    处理照顾小孩
    }
}

我们看看母亲被小孩哭声打断如何照顾小孩?

母亲的处理过程:

1 平时看书

2 发生了各种声音,如何处理这些声音 :: 有远处的猫叫(听而不闻,忽略) :: 门铃声有快递(开门收快递) :: 小孩哭声(打开房门,照顾小孩) 3 母亲的处理 :: 只会处理门铃声和小孩哭声 :: a 现在书中放入书签,合上书(保存现场) :: b 去处理 (调用对应的中断服务程序) :: c 继续看书(恢复现场)

不同情况,不同处理:

a 对于门铃:开门取快件

b 对于哭声:照顾小孩

我们将母亲的处理过程抽象化——母亲的头脑相当于CPU

耳朵听到声音会发送信号给脑袋,声音来源有很多种,有远处的猫叫,门铃声,小孩哭声。这些声音传入耳朵,再由耳朵传给大脑,除了这些可以中断母亲的看书,还有其他情况,比如身体不舒服,有只蜘蛛掉下来,对于特殊情况无法回避,必须立即处理

对比我们的arm系统 这里写图片描述

有CPU,有中断控制器。

中断控制器可以发信号给CPU告诉它发生了那些紧急情况

中断源有按键、定时器、有其它的(比如网络数据)

这些信号都可以发送信号给中断控制器,再由中断控制器发送信号给CPU表明有这些中断产生了,这些成为中断(属于一种异常)

还有什么可以中断CPU运行?

指令不对,数据访问有问题

reset信号,这些都可以中断CPU 这些成为异常中断

重点在于保存现场以及恢复现场

处理过程

a 保存现场(各种寄存器)

b 处理异常(中断属于一种异常)

c 恢复现场

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

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

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

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

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

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

.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代码
//保护现场,调用处理函数,恢复现场

(3-5都是硬件强制做的)

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

对比母亲的处理过程来比较arm中断的处理过程。

中断处理程序怎么被调用?

CPU—>0x18 –跳转到其他函数-> :: 做保护现场 :: 调用函数 :::: 分辨中断源 :::: 调用对应函数 :: 恢复现场

cpu到0x18是由硬件决定的,跳去执行更加复杂函数(由软件决定)

第002节CPU模式(Mode)状态(State)与寄存器

这节课我们来讲CPU的工作模式(Mode) 状态(State)寄存器

7种Mode:

 usr/sys
 undefined(und)
 Supervisor(svc)
 Abort(abt)
 IRQ(irq)
 FIQ(fiq)

2种State:

 ARM state
 Thumb state

寄存器: 通用寄存器 备份寄存器(banked register) 当前程序状态寄存器(Current Program Status Register);CPSR CPSR的备份寄存器:SPSR(Save Program Status Register)

我们仍然以这个母亲为例讲解这个CPU模式 这个母亲无压力看书 –>(正常模式) 要考试,看书—>(兴奋模式) 生病—->(异常模式)

可以参考书籍 《ARM体系结构与编程》作者:杜春雷

对于ARM CPU有7种模式:

1 usr :类比 正常模式

2 sys :类比的话兴奋模式

3 5种异常模式:(2440用户手册72页) :: 3.1 und :未定义模式 :: 3.2 svc :管理模式 :: 3.3 abt :终止模式 :::: a 指令预取终止(读写某条错误的指令导致终止运行) :::: b 数据访问终止 (读写某个地址,这个过程出错) :::: 都会进入终止模式 :: 3.4 IRQ: 中断模式 :: 3.5 FIQ: 快中断模式

我们可以称以下6种为特权模式 und :未定义模式 svc :管理模式 abt :终止模式 IRQ :中断模式 FIQ :快中断模式 sys :系统模式

usr用户模式(不可直接进入其他模式) 可以编程操作CPSR直接进入其他模式 这里写图片描述

这个图是有关各个模式下能访问寄存器的,再讲这个图之前我们先引入 2种state

CPU有两种state:

  • 1 ARM state:使用ARM指令集,每个指令4byte
  • 2 Thumb state:使用的是Thumb指令集,每个指令2byte

比如同样是:

mov R0, R1 编译后

对于ARM指令集要占据4个字节:机器码

对于Thumb指令集占据2个字节:机器码

引入Thumb减少存储空间

ARM指令集与Thumb指令集的区别:

Thumb 指令可以看作是 ARM 指令压缩形式的子集,是针对代码密度的问题而提出的,它具有 16 位的代码密度但是它不如ARM指令的效率高 .

Thumb 不是一个完整的体系结构,不能指望处理只执行Thumb 指令而不支持 ARM 指令集.

因此,Thumb 指令只需要支持通用功能,必要时可以借助于完善的 ARM 指令集,比如,所有异常自动进入 ARM 状态.在编写 Thumb 指令时,先要使用伪指令 CODE16 声明,而且在 ARM 指令中要使用 BX指令跳转到 Thumb 指令,以切换处理器状态.编写 ARM 指令时,则可使用伪指令 CODE32声明.

下节课会演示使用Thumb指令集编译,看是否生成的bin文件会变小很多 这里写图片描述

在每种模式下都有R0 ~ R15

在这张图注意到有些寄存器画有灰色的三角形,表示访问该模式下访问的专属寄存器 比如 mov R0, R8 mov R0, R8 在System 模式下访问的是R0 ~ R8,在所有模式下访问R0都是同一个寄存器 mov R0,R8_fiq 但是在FIQ模式下,访问R8是访问的FIQ模式专属的R8寄存器,不是同一个物理上的寄存器

在这五种异常模式中每个模式都有自己专属的R13 R14寄存器,R13用作SP(栈) R14用作LR(返回地址) LR是用来保存发生异常时的指令地址

为什么快中断(FIQ)有那么多专属寄存器,这些寄存器称为备份寄存器

回顾一下中断的处理过程 * 1 保存现场(保存被中断模式的寄存器)

就比如说我们的程序正在系统模式/用户模式下运行,当你发生中断时,需要把R0 ~ R14这些寄存器全部保存下来,让后处理异常,最后恢复这些寄存器

但如果是快中断,那么我就不需要保存 系统/用户模式下的R8 ~ R12这几个寄存器,在FIQ模式下有自己专属的R8 ~ R12寄存器,省略保存寄存器的时间,加快处理速度

但是在Linux中并不会使用FIQ模式

  • 2 处理

  • 3 恢复现场

CRSR当前程序状态寄存器,这是一个特别重要的寄存器

SPSR保存的程序状态寄存器,他们格式如下: 这里写图片描述

首先 M4 ~ M0 表示当前CPU处于哪一种模式(Mode);

我们可以读取这5位来判断CPU处于哪一种模式,也可以修改这一种模式位,让其修改这种模式;

假如你当前处于用户模式下,是没有权限修改这些位的;

M4 ~ M0对应什么值,会有说明: 这里写图片描述

查看其他位 Bit5 State bits表示CPU工作与Thumb State还是ARM State用的指令集是什么 Bit6 FIQ disable当bit6等于1时,FIQ是不工作的 Bit7 IRQ disable当bit5等于1时,禁止所有的IRQ中断,这个位是IRQ的总开关 Bit8 ~ Bit27是保留位 Bite28 ~ Bit31是状态位,

什么是状态位,比如说执行一条指令 cmp R0, R1 如果R0 等于 R1 那么zero位等于1,这条指令影响 Z 位,如果R0 == R1,则Z = 1

beq跳转到xxx这条指令会判断Bit30是否为1,是1的话则跳转,不是1的话则不会跳转 使用 Z 位,如果 Z 位等于1 则跳转,这些指令是借助状态位实现的

SPSR保存的程序状态寄存器: 表示发生异常时这个寄存器会用来保存被中断的模式下他的CPSR

就比如我我的程序在系统模式下运行 CPSR是某个值,当发生中断时会进入irq模式,这个CPSR_irq就保存系统模式下的CPSR

我们来看看发生异常时CPU是如何协同工作的:

进入异常的处理流程(硬件) 这里写图片描述

我们来翻译一下:

发生异常时,我们的CPU会做什么事情

  • 1把下一条指令的地址保存在LR寄存器里(某种异常模式的LR等于被中断的下一条指令的地址)

它有可能是PC + 4有可能是PC + 8,到底是那种取决于不同的情况

  • 2 把CPSR保存在SPSR里面(某一种异常模式下SPSR里面的值等于CPSR)

  • 3 修改CPSR的模式为进入异常模式(修改CPSR的M4 ~ M0进入异常模式)

  • 4 跳到向量表

退出异常怎么做? 这里写图片描述

  • 1 让LR减去某个值,让后赋值给PC(PC = 某个异常LR寄存器减去 offset) 减去什么值呢?

也就是我们怎么返回去继续执行原来的程序,根据下面这个表来取值 这里写图片描述

如果发生的是SWI可以把 R14_svc复制给PC

如果发生的是IRQ可以把R14_irq的值减去4赋值给PC

  • 2 把CPSR的值恢复(CPSR 值等于 某一个一场模式下的SPSR)

  • 3 清中断(如果是中断的话,对于其他异常不用设置)

第003节_不重要_Thumb指令集程序示例

在上节视频里说ARMCPU有两种状态

ARM State 每条指令会占据4byte

Thumb State 每条指令占据2byte

我们说过Thumb指令集并不重要,本节演示把一个程序使用Thumb指令集来编译它

使用上一章节的重定位代码,打开Makefile和Start.S

Makefile文件


all:
    arm-linux-gcc -c -o led.o led.c
    arm-linux-gcc -c -o uart.o uart.c
    arm-linux-gcc -c -o init.o init.c
    arm-linux-gcc -c -o main.o main.c
    arm-linux-gcc -c -o start.o start.S
    #arm-linux-ld -Ttext 0 -Tdata 0x30000000  start.o led.o uart.o init.o main.o -o sdram.elf
    arm-linux-ld -T sdram.lds start.o led.o uart.o init.o main.o -o sdram.elf
    arm-linux-objcopy -O binary -S sdram.elf sdram.bin
    arm-linux-objdump -D sdram.elf > sdram.dis
clean:
    rm *.bin *.o *.elf *.dis

   ```


对于使用Thumb指令集
```c
all:
    arm-linux-gcc -mthumb -c -o led.o led.c//只需要在arm-linux-gcc加上 mthumb命令即可
    arm-linux-gcc -c -o uart.o uart.c
    arm-linux-gcc -c -o init.o init.c
    arm-linux-gcc -c -o main.o main.c
    arm-linux-gcc -c -o start.o start.S
    #arm-linux-ld -Ttext 0 -Tdata 0x30000000  start.o led.o uart.o init.o main.o -o sdram.elf
    arm-linux-ld -T sdram.lds start.o led.o uart.o init.o main.o -o sdram.elf
    arm-linux-objcopy -O binary -S sdram.elf sdram.bin
    arm-linux-objdump -D sdram.elf > sdram.dis
clean:
    rm *.bin *.o *.elf *.dis
 ```  


改进
  ```c 
all: led.o uart.o init.o main.o start.o //all依赖led.o uart.o init.o main.o start.o
    #arm-linux-ld -Ttext 0 -Tdata 0x30000000  start.o led.o uart.o init.o main.o -o sdram.elf
    arm-linux-ld -T sdram.lds start.o led.o uart.o init.o main.o -o sdram.elf
    arm-linux-objcopy -O binary -S sdram.elf sdram.bin
    arm-linux-objdump -D sdram.elf > sdram.dis
clean:
    rm *.bin *.o *.elf *.dis

%.o : %.c
    arm-linux-gcc -mthumb -c -o $@ $< //对于所有的.c文件使用规则就可以使用thumb指令集编译 $@表示目标 $            
关注
打赏
1658827356
查看更多评论
0.0425s