IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 3. ARM异常处理机制 -> 正文阅读

[嵌入式]3. ARM异常处理机制

1. ARM的工作模式

图
用户模式:权限低,只能访问一部分内存资源
系统模式:权限高,能访问很多资源
异常模式:当异常出现时,能够保证cpu不挂掉而去执行异常处理程序
Supervisor:管理模式,cpu一上电被视为是一种异常,进入该模式
Undefined:cpu遇到不认识的指令时会进入该模式
Abort:终止模式,取指令或取数据时,发现地址不存在则进入该模式
IRQ:普通中断模式,中断也被视为异常
FIQ:快速中断,对速度要求高
Secure monitor:v5指令集出来后的一种模式,进入该模式后只有一部分程序能运行

2. ARM寄存器组

每一种模式有对应的能够被操作的寄存器
图
带三角形的是有专用的、独立的寄存器

r11:fp 指向每个栈的栈顶
r12:ip 用来备份sp寄存器的
r13:常用作堆栈指针SP,但这只是一种习惯用法,用户也可使用其他的寄存器作为堆栈指针,而在Thumb指令集中,某些指令强制性的要求使用r13作为堆栈指针
r14:称为子程序链接寄存器lr,当执行子程序调用指令(bl)时,r14可得到r15(程序计数器pc)的备份
r15:程序计数器pc
r16:CPSR 记录程序当前状态 高4位记录指令执行的结果,低5位记录当前工作模式。CPSR可在任何运行模式下被访问,它包括条件标志位、中断禁止位、当前处理器模式标志位,以及其他一些相关的控制和状态位。

每一种运行模式下又都有一个专用的物理状态寄存器,称为SPSR(Saved Program Status Register,备份的程序状态寄存器),当异常发生时,SPSR用于保存CPSR的当前值,从异常退出时则可由SPSR来恢复CPSR。由于用户模式和system特权模式不属于异常模式,它们没有SPSR,当在这两种模式下访问SPSR,结果是未知的

apcs规定:r0-r3一般是传递函数调用第1到第4个参数,需要手动保存,r4-r10一般是保存现场用,系统自动保存

3. 异常向量表

异常程序所放的位置,要方便cpu找到,就需要有张表来一一对应。异常向量表应运而生
图
因为不知道异常处理程序的大小,所以统一只留四个字节的空间存一条指令,这四个字节中存放的是跳转指令,可以跳转到某个内存中去执行对应的异常处理程序

0x0000 0000地址一般为iROM地址,所以异常向量表一般是通过协处理器映射到其他地址(如DDR地址)中去

4. Undefined异常实现示例

4.1 通过查手册得到负责映射的协处理器的寄存器操作指令

图

4.2 重映射异常向量表程序

_start:
	@重新映射异常向量表
	ldr r0, =0x41000000
	mcr p15, 0, r0, c12, c0, 0
	
	@打印cpsr低5位信息
	ldr r0, =str_svc
	mrs r1, cpsr
	and r1, r1, $0x1f
	mov lr, pc 			@跳转到printf函数前需要保存pc到lr,以便能够返回
	ldr pc, =0x3ff13e54
	
	@发生异常,CPU会自动跳转到0x41000000里面去执行异常处理程序
	@模拟未定义指令异常
	@1.保存返回地址到lr中
	@2.保存cpsr到spsr
	@3.修改cpsr为相应异常模式的值
	@4.修改pc指向异常向量表
	.word 0x77777777
	
	@测试能否返回
	ldr r0, =str
	mov lr, pc 			@跳转到printf函数前需要保存pc到lr,以便能够返回
	ldr pc, =0x3ff13e54
loop:
	b loop
	
str_svc:
	.asciz "hello svc mode cpsr=0x%x\n"
str:
 	.asciz "i am back\n"

	

4.3 异常处理程序

.global _start
_start:
		@开始地址是0x41000000
		b reset
		b undef
		b swi
		b abt_pre
		b abt_dat
		b reserved
		b irq
		b fiq
reset:
undef:
		ldr sp, =0x42000000 @初始化该模式下专用的sp寄存器
		
		@保存现场
		stmfd sp!, {r0-r12,lr}
		
		@打印cpsr信息
		ldr r0, =str_undef
		mrs r1, cpsr     	 @读cpsr寄存器内容
		and r1, r1, #0x1f 	 @取cpsr后五位
		mov lr, pc 		 	 @因为进入异常模式处理程序时已经自动保存返回地址到lr中 这里会覆盖掉lr
		ldr pc, =0x3ff13e54	
		
		@恢复现场
		ldmfd sp!, {r0-r12,lr}
		movs pc, lr          @+s:表示把spsr恢复到cpsr里面 因为当异常发生时,SPSR用于保存CPSR的当前值,从异常退出时则可由SPSR来恢复CPSR
swi:
abt_pre:
abt_dat:
reserved:
irq:
fiq:

str_undef:
		.asciz "hello undefine mode cpsr=0x%x\n"

4.4 运行

结果

5. swi异常处理实现

用户模式下没有权限修改CPSR,需要通过swi指令进入系统模式,通过swi指令+编号去进行系统调用,编号区分不同的系统调用函数。

5.1 重映射异常向量表程序

_start:
	@重新映射异常向量表
	ldr r0, =0x41000000
	mcr p15, 0, r0, c12, c0, 0
	
	@打印cpsr低5位信息
	ldr r0, =str_svc
	mrs r1, cpsr
	and r1, r1, $0x1f
	mov lr, pc 			@跳转到printf函数前需要保存pc到lr,以便能够返回
	ldr pc, =0x3ff13e54
	
	
	@把cpu的工作模式切换到user模式
	mrs r0, cpsr		@读cpsr寄存器内容
	bic r0, r0, #0x1f
	orr r0, r0, #0x10
	msr cpsr, r0		@设置cpsr寄存器内容
	
	@给用户模式进入到svc模式的专用指令
	@1.保存返回地址到lr中
	@2.保存cpsr到spsr
	@3.修改cpsr为相应异常模式的值
	@4.修改pc指向异常向量表
	swi 0x99
	
	@在用户模式 测试能否返回
	ldr sp, =0x420000000
	ldr r0, =str
	mov lr, pc 			@跳转到printf函数前需要保存pc到lr,以便能够返回
	ldr pc, =0x3ff13e54
loop:
	b loop
	
str_svc:
	.asciz "hello svc mode cpsr=0x%x\n"
str:
 	.asciz "in user mode: i am back\n"

5.2 异常处理程序

.global _start
_start:
		@开始地址是0x41000000
		b reset
		b undef
		b swi
		b abt_pre
		b abt_dat
		b reserved
		b irq
		b fiq
reset:
undef:
swi:
		@uboot已经初始化好该模式下的sp 所以这里不需要再初始化了
		
		@保存现场
		stmfd sp!, {r0-r12,lr}
		
		@打印cpsr信息
		ldr r0, =str_swi
		mrs r1, cpsr     	 @读cpsr寄存器内容
		and r1, r1, #0x1f 	 @取cpsr后五位 放到r1
		
		@把lr地址减4得到swi指令所在地址
		sub r3, lr,#4
		ldr r2, [r3]
		ldr r3, =0xffffff 	
		and r2, r2, r3       @取出指令后面的24位 即0x99 放到r2
		mov lr, pc 		 	 @因为进入异常模式处理程序时已经自动保存返回地址到lr中 这里会覆盖掉lr
		ldr pc, =0x3ff13e54	
		
		@恢复现场
		ldmfd sp!, {r0-r12,lr}
		movs pc, lr          @+s:表示把spsr恢复到cpsr里面 因为当异常发生时,SPSR用于保存CPSR的当前值,从异常退出时则可由SPSR来恢复
		
abt_pre:
abt_dat:
reserved:
irq:
fiq:

str_undef:
		.asciz "hello undefine mode cpsr=0x%x\n"
str_swi:
		.asciz "hello supervisor mode cpsr=0x%x swi id=0x%x\n"

5.3 运行

结果

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-16 18:59:57  更:2021-11-16 19:01:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:40:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码