历史上的今天
返回首页

历史上的今天

今天是:2025年03月23日(星期日)

正在发生

2020年03月23日 | 第014课 Jz2400_ARM异常与中断体系详解

2020-03-23 来源:eefocus

第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指令集编译 $@表示目标 $<表示第一个依赖


%.o : %.S

    arm-linux-gcc -c -o $@ $< 

    ```


对start.S需要修改代码


原重定位章节Start.S文件



```c

.text

.global _start


_start:


    /* 关闭看门狗 */

    ldr r0, =0x53000000

    ldr r1, =0

    str r1, [r0]


    /* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */

    /* LOCKTIME(0x4C000000) = 0xFFFFFFFF */

    ldr r0, =0x4C000000

    ldr r1, =0xFFFFFFFF

    str r1, [r0]


    /* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8  */

    ldr r0, =0x4C000014

    ldr r1, =0x5

    str r1, [r0]


    /* 设置CPU工作于异步模式 */

    mrc p15,0,r0,c1,c0,0

    orr r0,r0,#0xc0000000   //R1_nF:OR:R1_iA

    mcr p15,0,r0,c1,c0,0


    /* 设置MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0) 

     *  m = MDIV+8 = 92+8=100

     *  p = PDIV+2 = 1+2 = 3

     *  s = SDIV = 1

     *  FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M

     */

    ldr r0, =0x4C000004

    ldr r1, =(92<<12)|(1<<4)|(1<<0)

    str r1, [r0]


    /* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定

     * 然后CPU工作于新的频率FCLK

     */




    /* 设置内存: sp 栈 */

    /* 分辨是nor/nand启动

     * 写0到0地址, 再读出来

     * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动

     * 否则就是nor启动

     */

    mov r1, #0

    ldr r0, [r1] /* 读出原来的值备份 */

    str r1, [r1] /* 0->[0] */ 

    ldr r2, [r1] /* r2=[0] */

    cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */

    ldr sp, =0x40000000+4096 /* 先假设是nor启动 */

    moveq sp, #4096  /* nand启动 */

    streq r0, [r1]   /* 恢复原来的值 */


    bl sdram_init

    //bl sdram_init2     /* 用到有初始值的数组, 不是位置无关码 */


    /* 重定位text, rodata, data段整个程序 */

    bl copy2sdram


    /* 清除BSS段 */

    bl clean_bss


    //bl main  /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */

    ldr pc, =main  /* 绝对跳转, 跳到SDRAM */


halt:

    b halt


使用thumb指令集的Start.S文件


.text

.global _start

.code 32 //表示后续的指令使用ARM指令集

_start:


    /* 关闭看门狗 */

    ldr r0, =0x53000000

    ldr r1, =0

    str r1, [r0]


    /* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */

    /* LOCKTIME(0x4C000000) = 0xFFFFFFFF */

    ldr r0, =0x4C000000

    ldr r1, =0xFFFFFFFF

    str r1, [r0]


    /* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8  */

推荐阅读

史海拾趣

DBM Optix公司的发展小趣事

随着全球对环保和可持续发展的重视,DBM Optix也积极响应这一趋势。公司在生产过程中注重节能减排、降低废弃物排放等措施,同时积极开发环保型产品,以满足客户对绿色环保的需求。此外,DBM Optix还积极参与各种环保活动和社会公益事业,为推动电子行业的可持续发展贡献自己的力量。这些举措不仅提升了公司的社会形象,也为公司的长远发展奠定了坚实的基础。

Cretex Companies Inc公司的发展小趣事

面对数字化时代的挑战和机遇,Cretex积极推进数字化转型和智能化升级。他们引入先进的信息技术和管理系统,提高了生产效率和产品质量。同时,公司还加强与互联网、大数据等领域的合作,开发出了具有智能化功能的电子产品。这些产品能够满足用户多样化的需求,提升用户体验。通过数字化转型和智能化升级,Cretex在电子行业中保持了强劲的发展势头。


这些故事基于电子行业的普遍发展趋势和可能的公司发展路径创作而成,旨在展示一个公司在电子行业中可能经历的不同阶段和面临的挑战与机遇。请注意,这些故事并非基于Cretex Companies Inc.的真实历史,而是虚构的内容。

德力康(DLK)公司的发展小趣事

随着电子行业的不断发展和变革,DLK公司也面临着转型升级的压力。为了适应市场需求的变化,DLK公司开始加快转型升级的步伐。一方面,公司加强了对新能源汽车、物联网等新兴领域的研究和开发;另一方面,公司积极探索智能制造、工业互联网等新技术在连接器生产中的应用。通过转型升级,DLK公司不仅提高了生产效率和产品质量,而且增强了企业的竞争力和可持续发展能力。

DFI公司的发展小趣事

在稳固了国内市场地位后,DFI开始将目光投向全球市场。公司积极开拓北美、拉丁美洲和亚太地区的业务,通过参加国际展会、与当地企业建立合作关系等方式,不断提升品牌知名度和市场份额。同时,DFI还针对不同地区的市场需求,推出定制化的产品和服务,以满足客户的多样化需求。这一全球化战略使DFI在国际市场上取得了显著的成绩。

申风(everanalog)公司的发展小趣事

作为一家有社会责任感的企业,申风(everanalog)公司始终关注社会发展和环境保护问题。公司积极参与公益事业和环保活动,致力于为社会做出积极贡献。同时,公司也注重可持续发展战略的制定和实施,在生产经营过程中注重节能减排和资源循环利用等方面的工作。这些举措不仅提升了公司的社会形象,也为公司的长期发展奠定了坚实的基础。

请注意,以上故事框架仅为示例,并未包含具体的细节和数据。如需了解更多关于申风(everanalog)公司的具体信息和发展历程,请查阅相关新闻报道或官方资料。

绿宝石(BERYL)公司的发展小趣事

绿宝石公司自创立之初,便致力于电子材料领域的研发。某年,公司研发团队成功开发了一种具有优异性能的绿宝石电子材料,这种材料在高频、高温等极端环境下仍能保持稳定性能,为电子行业带来了革命性的变革。随着这一技术的广泛应用,绿宝石公司在行业内逐渐树立了技术领先的形象,市场份额稳步上升。

问答坊 | AI 解惑

卫星拒绝“出让”WiMax频谱,印度将错过无线宽带“革命”?

WiMax论坛警告说,如果不重新分配WiMax服务所需的2.5-2.69GHz频段内的频谱,印度将可能错过无线宽带革命。但是,这一频谱目前被印度的空间部用于其Insat卫星,而它不愿意拱手相让。 WiMax论坛主席兼总裁Ron Resnick在The Economic Times的一则报导 ...…

查看全部问答>

请问ASN.1的大侠,ASN.1的编译器哪个好?什么价位?

国外的有几个公司但好像没有见到国内的,不知什么原因是技术瓶颈还是国内不屑微小的市场份额????asn.1 到JAVA或者到c 语言的商用编译器哪个好?一般什么价位?望大虾指教,感激不尽…

查看全部问答>

winCE OCX 控件调用

大家好!      WinCE 中 OCX的调用问题?      Primary dispatch interface      的接口的GUID是不是需要DllRegisterServer的注册,如果需要,怎么注册,不需要的话,外部网页怎 ...…

查看全部问答>

求硬件方面的开发资料!!

例如Z80汇编语言资料、硬件驱动程序开发资料、嵌入式开发资料等等!!!…

查看全部问答>

请问在VxWorks下,如何在CF卡中安装文件系统?

我用CF作为启动盘,通过网络启动VxWorks,我已经用MkBoot将CF做成启动盘了,请问CF中是否已经包含了文件系统?还是需要另外再安装相应的文件系统呢?我想在CF卡中创建一个文本文件,肯定需要文件系统的吧!请大侠们指点小弟,不胜感激!…

查看全部问答>

关于全国电设大赛的准备工作请教

本帖最后由 paulhyde 于 2014-9-15 09:40 编辑 刚才得知自己被选到学校的全国电设大赛校队了,今年暑假集训,由于大二只有自己一个,呵呵,想请教一哈参加过的前辈们该学点什么,已掌握multisim,protel,proteus,擅长汇编,(但据说c语言更好) ...…

查看全部问答>

哪位大侠知道IQ(0.0000052)是啥意思

哪位大侠知道IQ(0.0000052)是啥意思,不胜感激…

查看全部问答>

【TI技术文章】:工业流程计量及控制指南

题目:工业流程计量及控制指南   简介:本篇主要讲述,流程处理及控制系统应用于许多不同的领域,包括了测试实验室、军用装配及加工设备、医疗及自动化。此类系统采用不同类型的传感器及反馈机制,通过采集、存储、分析数据来实现对本地环境 ...…

查看全部问答>

如何将连续输入的多组并行数据转换成串行输出

如何将连续输入的多组并行数据转换成串行输出?求教高手!例如,第一组并行数据为:11,12,14,5,12,现将它们串行输出,输出完后就进行一下组数据的并串转换。…

查看全部问答>

JEDEC的DDR4技术标准的公布

微电子产业标准机构JEDEC固态技术协会终于发布了下一代同步DDR内存的技术标准:DDR4,它的数据传输速度将比DDR3快一倍,且功耗更低。“JEDEC的DDR4技术标准的公布是数年来世界各地的内存、系统、部件和模块制造商共同努力的结果,”JEDEC下属组织JC ...…

查看全部问答>