Cortex-M3基础
Cortex-M3基础
寄存器组
堆栈指针
R13在同一时间只有一个可见,这就是所谓的“banked”寄存器。R13 作为堆栈指针寄存器 (Stack Pointer,SP)。
主堆栈指针(MSP):复位后缺省使用的堆栈指针,用于操作系统内核以及异常处理例程(包
括中断服务例程)进程堆栈指针(PSP):由用户的应用程序代码使用。
连接寄存器
R14 作为连接寄存器 (Link Register,LR),当呼叫(调用)一个子程序时,由R14 存储返回地址。
程序计数寄存器
R15 作为程序计数器 (Program Counter,PC),指向当前的程序地址。如果修改它的值,就能改变程序的执行流。
特殊功能寄存器
寄存器 | 功能 |
---|---|
xPSR | 记录ALU 标志(0 标志,进位标志,负数标志,溢出标志),执行状态,以及当前正服务的中断号。(保存算术与逻辑标志,例如负数标志,零结果标志,溢出标志等等) |
PRIMASK | 除能所有的中断,不可屏蔽中断(NMI)不受影响。 |
FAULTMASK | 除能所有的fault——NMI 依然不受影响,而且被除能的faults 会“上访”,见后续章节的叙述。 |
BASEPRI | 除能所有优先级不高于某个具体数值的中断。 |
CONTROL | 定义特权状态(见后续章节对特权的叙述),并且决定使用哪一个堆栈指针。(如果是具有浮点单元的 Cortex-M4 或者 Cortex-M7,控制寄存器也用来指示浮点单元当前是否在使用) |
xPSR
程序状态寄存器在其内部又被分为三个子状态寄存器:
- 应用程序 PSR(APSR)
- 中断号 PSR(IPSR)
- 执行 PSR(EPSR)
PRIMASK,FAULTMASK ,BASEPRI
CM3 page.41
CONTROL 控制寄存器
位 | 功能 |
---|---|
CONTROL[1] | 堆栈指针选择 0=选择主堆栈指针MSP(复位后缺省值) 1=选择进程堆栈指针PSP 在线程或基础级(没有在响应异常——译注),可以使用PSP。在handler 模式下, 只允许使用MSP,所以此时不得往该位写1。 |
CONTROL[0] | 0=特权级的线程模式 1=用户级的线程模式 Handler 模式永远都是特权级的。 |
操作模式和特权模式
Cortex-M 引入了操作模式(handler mode、thread mode)和特权级别(特权级和用户级)的概念,如果进入异常或中断处理则进入handler mode,其他情况则为thread mode。
handler mode总是使用 MSP 作为堆栈,thread mode可以选择使用 MSP 或 PSP 作为堆栈,同样通过CONTROL 特殊寄存器控制。复位后,Cortex-M 默认进入线程模式、特权级、使用 MSP 堆栈。
这可以提供一种存储器访问的保护机制,使得普通的用户程序代码不能意外地,甚至是恶意地执行涉及到要害的操作。处理器支持两种特权级,这也是一个基本的安全模型。
举例来说,操作系统的内核通常都在特权级下执行,所有没有被MPU 禁掉的存储器都可以访问。在操作系统开启了一个用户程序后,通常都会让它在用户级下执行,从而使系统不会因某个程序的崩溃或恶意破坏而受损。
内建的嵌套向量中断控制器(NVIC)
SVC和PendSV
SVC(系统服务调用,系统调用)
例如,操作系统不让用户程序直接访问硬件,而是通过提供一些系统服务函数,用户程序使用SVC 发出对系统服务函数的呼叫请求,以这种方法调用它们来间接访问硬件。因此,当用户程序想要控制特定的硬件时,它就会产生一个SVC 异常,然后操作系统提供的SVC 异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务。
优势:
- 第一,它使用户程序从控制硬件的繁文缛节中解脱出来,而是由OS 负责控制具体的硬件。
- 第二,OS 的代码可以经过充分的测试,从而能使系统更加健壮和可靠。
- 第三,它使用户程序无需在特权级下执行,用户程序无需承担因误操作而瘫痪整个系统的风险。
- 第四,通过SVC 的机制,还让用户程序变得与硬件无关,因此在开发应用程序时无需了解硬件的操作细节,从而简化了开发的难度和繁琐度,并且使应用程序跨硬件平台移植成为可能。
PendSV(可悬起系统调用)
PendSV ,它是可以像普通的中断一样被悬起的(不像SVC 那样会上访)。OS 可以利用它“缓期执行”一个异常——直到其它重要的任务完成后才执行动作。悬起PendSV 的方法是:手工往NVIC 的PendSV 悬起寄存器中写1。悬起后,如果优先级不够高,则将缓期等待执行。
PendSV 的典型使用场合是在上下文切换时(在不同任务之间切换)。例如发生中断时产生线程唤醒,中断会引发一个PendSV,在中断运行结束后,会进入PendSV在里面进行线程唤醒(线程切换)。
一些总结和个人笔记
中断的入栈出栈
- 进入异常服务例程时,自动压栈R0‐R3, R12, LR, PSR 和PC。
- 进入异常服务程序后,LR的值被自动更新为特殊的EXC_RETURN。
数值 | 功能 |
---|---|
0xFFFF_FFF1 | 返回handler模式 |
0xFFFF_FFF9 | 返回线程模式,并使用主堆栈(SP=MSP) |
0xFFFF_FFFD | 返回线程模式,并使用线程堆栈(SP=PSP) |
如果主程序在线程模式下运行, 并且在使用MSP 时被中断, 则在服务例程中LR=0xFFFF_FFF9(主程序被打断前的LR已被自动入栈)。
如果主程序在线程模式下运行, 并且在使用PSP 时被中断, 则在服务例程中LR=0xFFFF_FFFD(主程序被打断前的LR已被自动入栈)。
- 进入函数调用时也会压栈Rxxx寄存器作为传入参数。
- R0作为函数的返回值。