取个场景解释中断。
假设有个大房间里面有小房间,婴儿正在睡觉,他的妈妈在外面看书。
问:这个母亲怎么才能知道这个小孩醒?
- 过一会打开一次房门,看婴儿是否睡醒,让后接着看书
- 一直等到婴儿发出声音以后再过去查看,期间都在读书
第一种 叫做查询方式: *优点:简单 *缺点: 累 写程序如何:
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 清中断(如果是中断的话,对于其他异常不用设置)
在上节视频里说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指令集编译 $@表示目标 $
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?