Cortex M3学习笔记 02 寄存器中断控制器.docx
《Cortex M3学习笔记 02 寄存器中断控制器.docx》由会员分享,可在线阅读,更多相关《Cortex M3学习笔记 02 寄存器中断控制器.docx(13页珍藏版)》请在冰豆网上搜索。
CortexM3学习笔记02寄存器中断控制器
CortexM3学习笔记02
寄存器,中断控制器
好像XX看了我的文章一样,上次笔记中写了一些对抱怨审核太慢的内容,结果第二天就审核好了,不知道这次速度怎么样……
一、名词定义
MSP:
主堆栈指针;
PSP:
进程堆栈指针;
二、寄存器
通用寄存器:
32位一个,不多说,一共22个。
R0~R15,其中R13是个有两个堆栈指针寄存器的功能,一共17个;另外还有5个特殊功能寄存器。
下面来理解。
a)通用寄存器
R0~R12:
用于数据操作,使用Thumb-2可以全部访问,使用Thumb只能访问R0~R7。
R13:
堆栈指针(SP):
包括主堆栈指针(MSP),进程堆栈指针(PSP)
PUSH和POP指令的用法解释:
PUSH{R0}//*(--R13)=R0;R13是long*型指针
POP{R0}//R0=*R13++
R13的最低两位强制为0,且读取同样也为0;
R14:
连接寄存器(LR):
保存子程序返回时的地址;
R15:
程序计数器(PC):
PC返回的地址是当前那指令的地址+4。
例如:
0x4000MOVR0,PC;//R0=0x4004;
当针对执行一条写入R15指令时,写入R15的地址被当成一个指令地址,程序从这个地址处开始执行,但是不更新LR寄存器,相当于引发一次跳转;
PC的LSB读回内容始终为0,不论是直接写入PC的值,还是使用分支跳转命令,都要求加载到PC的值是奇数(LSB=1),用以表明处理器是在Thumb状态下执行。
若写入0,则视为企图跳转到ARM模式,Cortex-M3将产生一个fault异常。
b)特殊功能寄存器
Ø程序状态寄存器组(PSRs);
分为:
应用状态寄存器(APSR)为[27~31];
中断状态寄存器(IPSR)为[0~8];
执行状态寄存器(EPSR)为[10~15],[24~26];
共计32位
自己画个0~31的寄存器“位”表格,很直观。
Ø中断屏蔽寄存器组(PRIMASK、FAULTMASK、BASEPRI);
PRIMASK相当于中断总开关,
当PRIMASK=1时,屏蔽所有中断(除NMI和fault外)。
FAULTMASK屏蔽错误中断。
BASEPRI优先级屏蔽寄存器中断。
Ø控制寄存器(CONTROL)。
第一.定义特权级别:
特权级线程模式,用户级线程模式;
CONTROL[0]=0是特权级;
CONTROL[0]=1是用户级;
第二.选择当前堆栈指针:
主堆栈MSP,备用堆栈。
CONTROL[1]=0是主堆栈(复位缺省);
CONTROL[1]=1是备用堆栈,
特殊功能寄存器不存在地址,只能被专用的MSR和MRS指令访问。
使用方式:
MRS,;
读特殊功能寄存器的值到通用寄存器;
MSR,;
写通用寄存器的值到特殊功能寄存器;
其中是通用寄存器,是特殊寄存器;
例如:
·MOVR0,#0x01;
MOVRPIMASK,R0;
·MOVR0,0x60;
MOVBASEPRI,R0;
三、CortexM3操作模式和特权级别
分为两种模式;两种级别:
a)操作模式:
线程模式(Threadmode),处理模式(handlermode);
线程模式:
在此模式中程序指令逐一运行;
处理模式:
在程序执行过程中,触发了一个异常后,处理器将进入到处理模式;处理结束后返回之前的状态。
b)特权级别:
特权级,用户级;
特权级:
系统开启后默认进入。
无限制。
用户级:
处理器将禁止对系统控制区域(SCS)(包含配置寄存器和调试组建的存储区域)的访问。
画个表格:
代码作用
特权级
用户级
异常handler代码
Handler模式
错误,不可操作
主应用程序代码
线程模式
(复位后默认进入的模式)
线程模式
这样可以直观的看出,处理模式下,只提供特权级的代码才能访问。
好处不多说了,保护关键区域代码安全,防止有意无意的篡改。
·思考一下,上面说过CONTROL寄存器的可以更改特权;
程序启动后,线程模式会在CONTROL的指引下进入从特权级转为用户级运行,如果在用户级下面MSR命令自然是不能更改CONTROL特权的,那么如何解决?
答案:
刚才表格中说了handler模式下肯定是特权级的,那么我们就利用handler模式来解决这个问题。
在中断处理的时候(handlermode),加入代码:
MRSR0,CONTROL;//读取CONTROL;
BIC.WR0,R0,#0x01;//清零CONTROL[0];
MSRCONTROL,R0;//将清零的内容写入CONTROL;
这样CONTROL[0]就等于0了,变成特权级;程序返回后,继续往下执行,就是在特权级下的指令执行了。
记得利用MSR+CONTROL返回用户级;如此再加上MPU设备,书上这样形容:
安全,健壮……
四、CortexM3的异常、中断及向量表
“中断”和“异常”,经常被混合使用,强调他们对主程序的执行所体现的“中断”性质。
书本不强调他们之间的区别。
若一定要区别:
可以理解“异常”由指令执行或访问存储器时产生,例如:
存储单元的值改变;
而“中断”可以理解为“中断请求信号”一般由外部产生,例如:
外设信息处理请求;
CortexM3处理器在内核水平上搭载了一个中断控制器——嵌套向量中断控制器NVIC(NestedVectoredInterruptController),可实现非常高校的异常处理。
取消FIQ(快速中断处理),取而代之的是“嵌套中断支持”和“优先级管理”。
1.嵌套中断支持,在下面的“优先级分组”中介绍。
2.向量中断支持,CortexM3会自动定位一张向量表,根据中断号从表中找出相应中断的入口地址,然后跳转过去执行。
3.异常类型,支持11种系统异常和240种外部中断输入。
其中1~15对应的是系统异常,大于等于16的则全是外部中断。
大部分异常的优先级是可编程的,出了部分固定的。
编号
类型
优先级
描述
1
复位
-3(最高)
复位
2
NMI
-2
不可屏蔽中断(来自外部NMI引脚)
3
Hardfault
-1
所有被除能的fault,都将上访(escalation)成硬fault。
只要FAULTMASK没有置位,硬fault服务例程就会被强制执行。
Fault被除能的原因包括被禁用,或者FAULTMASK被置位。
4
存储器管理fault
可编程
存储器管理fault,MPU访问违规或访问非法位置均可引发。
企图在“非执行区”取指也会引发此fault。
5
总线fault
可编程
总线错误,当AHB接口收到总线系统的错误响应时发生(也称为预取中止或是数据中止)。
6
用法fault
可编程
由于程序错误或企图访问协处理器(CortexM3不支持协处理器)导致的异常。
7~10
保留
NA
NA
11
SVCall
可编程
执行系统服务调用指令(SVC)引发的异常。
12
调试监视器
可编程
调试监视器(断点,数据观察点或外部调试请求)
13
保留
NA
NA
14
PendSV
可编程
为系统设备而设的“挂起请求”(pendablerequest)
15
SysTick
可编程
系统节拍定时器
16~255
外部中断
可编程
CortexM3内核之外产生的中断(0~239)
上边的“优先级表”中-3,-2,-1始终会高于0,所以画个数轴,就明白了“数值越小,优先级越高”的道理,但是“可编程”的优先级不存在负数……。
系统异常是CortexM3内核支持的基本异常,与具体芯片无关,而外部中断则与芯片相关,芯片厂商会根据需要和用途设计中断源数目(1~240)和优先级的位数。
例如:
NXP公司的LPC1752支持35个外部中断和32个中断优先级。
注
4.异常优先级,优先级数值越小,则级别越高(前面提过,批注A7)。
CortexM3中:
复位、NMI、硬fault是固定优先级。
5.优先级配置寄存器,理论上一个字节Bit[0~7],可以表示256个优先级,但是实际上为了精简设计芯片设计商会裁剪掉部分低端有效位。
注
例如:
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
用于表达优先级
不执行,读回为零
优先级为:
0x00(最高)、0x20、0x40、0x60、0x80、0xA0、0xC0、0xE0。
或者
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
用于表达优先级
不执行,读回为零
6.优先级分组:
·思考一下,既然中断响应的优先级已经分了,为什么还要分组呢?
书本上介绍并不详细,看了一些资料,才弄明白,这个部分其实很重要。
简单分析一下,我们知道,程序在运行时,当多个中断来的时候,根据优先级的高低来处理中断请求的。
那么问题来了,如果正在响应一个异常时,突然来了一个优先级比较高的异常,那么我们是放下当前正在响应的异常,去执行新来的这个?
还是继续响应当前的异常,直到处理完毕,再去考虑那个新异常的优先级呢?
答案:
CortexM3提供了“抢占式优先级”和“子优先级”来解决这个问题。
(有地方对“子优先级”叫做“副优先级”或“响应优先级”,无所谓叫什么,关键是通途)
看看下表,CortexM3将“优先级配置寄存器”划分为两组,这样的分组信息保存在AIRCR中。
根据上面“优先级配置寄存器”定义,来引申一下。
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
抢占优先级
子优先级
不执行,读回为零
“子优先级”至少要有1位!
!
!
!
“抢占优先级”可以没有。
优先级分组在“位4”上;
或者
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
抢占优先级
子优先级
不执行,读回为零
优先级分组在“位5”上;
也可以这样分,但是太没有意思了吧……
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
抢占优先级
抢占优先级(不执行)
子优先级
(不执行)
画个表格更直观:
分组位置
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
7
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
6
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
5
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
4
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
3
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
2
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
1
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
0
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
虽然可以这样随意分组,但是如果“优先级配置器”没有涉及到的“位”,结果还是没用……。
下面来看看,分组的作用:
以“位5”分组为例:
Bit[7]
Bit[6]
Bit[5]
Bit[4]
Bit[3]
Bit[2]
Bit[1]
Bit[0]
抢占优先级
子优先级
不执行,读回为零
假设有个正在被响应的异常,“抢占优先级”为第四级(即Bit[7]=1,Bit[6]=1),当有一个“抢占优先级”为第二级(即Bit[7]=0,Bit[6]=1)的异常产生后,不会被等待或排序,将直接挂起“第四级”,而执行“第二级”;当“第二级”执行完毕后,返回刚才“第四级”的响应。
如此一来,第一级>第二级>第三级>第四级,这样便形成了先前所说的“嵌套向量中断控制器”中“嵌套”作用。
如下图:
那么“子优先级”就好解释了,在相同“抢占等级”下,优先响应“子优先级”高的异常,而相互之间不可抢占!
也就是说“子优先级”不能再“嵌套”了。
例如:
如果系统正在响应“0x40”优先级的异常,同时出现“0x00与0x20”,那么不论她执行到哪里,都将被挂起,而优先执行“0x00与0x20”。
而0x00与0x20,必定先响应0x00。
注:
复位、NMI、硬fault是固定优先级,且无条件抢占任何优先级。
顺带提一下,“应用程序中断及复位控制寄存器(AIRCR)”:
位段
名称
类型
描述
复位值
0
VECTRESET
W
复位CortexM3处理器内核(调试逻辑除外),此复位不影响芯片上内核以外的电路
1
WECTCLRACTIVE
W
清零所有异常的活动状态信息。
通常在调试或OS从错误中恢复时使用。
2
SYSRESTREQ
W
请求芯片的控制逻辑产生一次复位
[10~8]
PRIGROUP
R/W
优先级分组
0
15
ENDIANESS
R
数据字节顺序设置:
1:
大端(BE8);0:
小端。
此位在复位时确定,不可更改。
[31~6]
VECTKEY
R/W
访问钥匙:
任何对该寄存器的写操作,都必须同时将0x05FA写入此字段,否则写操作被忽略。
读取此半字,返回0xFA05
例如:
分组设置
AIRCR=(0x05FA)|(0x05<<8);
//优先级在位5处分组;其中0x05<<8,表示数值在寄存器右移8位保存,0x05FA,在写入AIRCR数值时必须同时写入。
如果没有这个,那么在响应异常的时候,有两种可能:
第一,其余异常将会被排序并等待前面的异常处理完毕后再执行;第二,如同51芯片一样,中断优先级被固化在芯片中,可供调节的范围很小。
7.异常向量表
地址
异常编号
值(32位整数)
0x00000000
-
MSP的初始值
0x00000004
1
复位向量(PC初始值)
0x00000008
2
NMI处理函数入口地址
0x0000000C
3
硬fault处理函数入口地址
……
……
其他异常处理函数入口地址
如前面所说的,理论上中断请求有256个,这里也预留了256,缺省情况下,CortexM3中的向量表位于存储空间的零地址出,表中每个向量4个字节。
注
跳转功能和51系列很相似,CortexM3允许向量表重定位到内存的其他位置,这些位置对应区域可以使是代码区,也可以是RAM区。
当向量表位于RAM区时,允许运行中对异常服务函数进行动态修改。
结束,下次继续。