一、ARM CPU的工作7种模式:
1、usr :正常程序或app执行的状态(需手动编程阻止程序访问硬件)。需使用swi xxx软中断命令切换到 swi 模式(不可直接操作 cpsr)。
2、sys :系统模式。运行具有特权的操作系统任务,效率很高。
3、und :未定义模式。执行未定义指令时进入。指令需参考第一章的指令表。
4、svc :管理模式。操作系统使用的保护模式。
5、abt :终止模式。终止数据访问 (读写地址时出错) 或指令预取 (读写了错误的指令导致终止运行) 时进入。
6、irq: 中断模式。
7、fiq: 快中断模式。

二、模式简介:
1、模式②到⑦属于特权模式,而③到⑦属于异常模式。大多数程序运行在用户模式,进入特权模式是为了处理中断、异常或访问被保护的系统资源。除了发生相应的异常造成工作模式切换,还可以用软件操作cpsr寄存器进入其他模式。
2、CPU上电或复位后处于管理模式(svc),正常运行功能代码前要手动切换到 usr 模式。发生异常后,需在相应模式初始化其独立的栈空间,并手动保存特定模式下公用寄存器和 lr 。之后再手动恢复。每种模式初始化完毕后,其余代码最好都在 sdram 中执行。
三、各个模式下的寄存器:
灰色寄存器是特定模式下所特有的,不是同一个物理寄存器,只是访问地址一样。一般Linux里不使用fiq模式。

四、异常与中断:
1、中断可分为异常中断和普通中断(属于异常的一种),异常中断无法屏蔽。
指令错误、数据访问有问题、reset信号等为异常中断,中断控制器发出的中断信号则视为普通中断。
中断控制器接收按键、定时器等发出的中断信号,再传给CPU。进入退出异常由硬件实现。
中断程序一般只做简单功能(改变标志位、转换高低电平等)。
2、异常触发后CPU 处理步骤如下:
①、保存下一条指令地址到 lr(r14)。它有可能是 pc+4 或 pc+8,取决于不同的情况。
②、把当前模式的cpsr保存在将跳转到的异常模式的spsr里。
③、修改cpsr模式中的m4-m0,进入异常模式。
④、跳转到向量表。
3、异常的处理和退出步骤如下:
①、保存现场:
Ⅰ、设置特定模式下的栈寄存器 sp 地址。 一般使用命令 ldr sp, =xxxx
Ⅱ、保存非专属寄存器,同时保存计算机已经保存好的 lr 寄存器(返回地址),以防之后代码使用时修改。此时的 lr 的值需要参考退出异常步骤表(下图右)。一般用命令 sdmdb sp!, { rx-ry, lr },确保与ADS兼容。
②、处理异常:一般使用C语言。中断模式下需要清中断,其他异常不用设置。一般使用C语言。
③、恢复现场:回写非专属寄存器,回写 lr 到 pc (返回地址)。一般使用命令 ldmia sp!, { rx-ry, pc }^,确保与ADS兼容。" ^ "表示恢复 spsr 的值到 cpsr。

五、ARM 下七种异常:
1、CPU处理完每条指令后,都会检测是否有中断/异常产生。有则处理中断。同一时间只能处理一种中断。不同异常跳去不同的地址执行程序。每个地址上存有一条跳转指令,跳去其地址执行函数 (异常向量)。如下就是异常向量表,对于不同的异常都有一条跳转指令:
①、Reset : 处理器工作时,按下重启键就会触发该异常。0x00
②、Undefined instructions : 处理器无法识别指令的异常。使用时用 0xedeadc0de 表示。此时进入 und 未定义模式。0x04
③、Software interrupt (SWI) : 软中断。软件打断处理器工作。此时进入 svc 管理模式。0x08
④、Prefetch Abort (instruction fetch memory abort) : 预取指令失败。ARM 在执行指令的过程中, 会先预取指令准备执行。0x0c
⑤、Data Abort (data access memory abort) : 读取数据失败。0x10
⑥、IRQ (interrupt) : 普通中断。地址是0x18。0x14位置保留
⑦、FIQ (fast interrupt) : 快速中断。响应速度比普通中断快。0x1c
2、异常向量表:
①、在汇编入口位置定义定义异常向量表。
②、保险起见,除reset之外,其余异常跳转使用 ldr 直接跳到 sdram 执行,尽量不使用 b 。以防之后使用相对跳转命令时,跳转地址在4k之外导致出错。(上电已经重定位过)
③、ldr 伪指令不使用" = "。这样可以 跳转到内存中 其符号标识的 .word 定义的 字段的地址,执行指令。

六、配置中断:
1、初始化:
①、设置 CPU 中断开关:上电后处于 svc 管理模式时即可设置。一般在汇编文件,与切换模式时的 cpsr 设置操作合并。cpsr 中的 I 位设为 0,即 bit7 。
②、设置中断控制器:屏蔽某个中断,让其可以传递中断信号到CPU。必须在 sdram 初始化后进行。一般使用C语言。
③、设置中断源:让其可以产生中断到控制器。复杂系统中,在不同模块初始化的时候配置。一般使用C语言。
Ⅰ、配置硬件接的 gpio 成中断模式。
Ⅱ、设置中断触发方式(上升/下降/双边沿)。
Ⅲ、设置中断屏蔽寄存器。某些gpio需要配置此寄存器才能使能信号。有些中断信号能直达中断控制器,无需设置。
2、中断处理:
①、分辨中断源:通过读寄存器的值区分。
②、根据不同中断源,调用不同中断处理函数 isr 。isr 还分 hisr 和 lisr。
3、清中断:从中断源开始,依次清理寄存器。(中断源 ==> 中断控制器)

网友评论