Cortex-M3基础

Cortex-M3基础

寄存器组

image-20201030190843098

堆栈指针

  • R13在同一时间只有一个可见,这就是所谓的“banked”寄存器。R13 作为堆栈指针寄存器 (Stack Pointer,SP)。

  • 主堆栈指针(MSP):复位后缺省使用的堆栈指针,用于操作系统内核以及异常处理例程(包
    括中断服务例程)

  • 进程堆栈指针(PSP):由用户的应用程序代码使用。

连接寄存器

R14 作为连接寄存器 (Link Register,LR),当呼叫(调用)一个子程序时,由R14 存储返回地址。

程序计数寄存器

R15 作为程序计数器 (Program Counter,PC),指向当前的程序地址。如果修改它的值,就能改变程序的执行流。

特殊功能寄存器

image-20201030192111032

寄存器功能
xPSR记录ALU 标志(0 标志,进位标志,负数标志,溢出标志),执行状态,以及当前正服务的中断号。(保存算术与逻辑标志,例如负数标志,零结果标志,溢出标志等等)
PRIMASK除能所有的中断,不可屏蔽中断(NMI)不受影响。
FAULTMASK除能所有的fault——NMI 依然不受影响,而且被除能的faults 会“上访”,见后续章节的叙述。
BASEPRI除能所有优先级不高于某个具体数值的中断。
CONTROL定义特权状态(见后续章节对特权的叙述),并且决定使用哪一个堆栈指针。(如果是具有浮点单元的 Cortex-M4 或者 Cortex-M7,控制寄存器也用来指示浮点单元当前是否在使用)

xPSR

程序状态寄存器在其内部又被分为三个子状态寄存器:

  • 应用程序 PSR(APSR)
  • 中断号 PSR(IPSR)
  • 执行 PSR(EPSR)
    image-20201217154557648

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。

image-20201030193232853

handler mode总是使用 MSP 作为堆栈thread mode可以选择使用 MSP 或 PSP 作为堆栈,同样通过CONTROL 特殊寄存器控制。复位后,Cortex-M 默认进入线程模式、特权级、使用 MSP 堆栈。

image-20201030193654568

这可以提供一种存储器访问的保护机制,使得普通的用户程序代码不能意外地,甚至是恶意地执行涉及到要害的操作。处理器支持两种特权级,这也是一个基本的安全模型。

举例来说,操作系统的内核通常都在特权级下执行,所有没有被MPU 禁掉的存储器都可以访问。在操作系统开启了一个用户程序后,通常都会让它在用户级下执行,从而使系统不会因某个程序的崩溃或恶意破坏而受损。

内建的嵌套向量中断控制器(NVIC)

SVC和PendSV

SVC(系统服务调用,系统调用)

例如,操作系统不让用户程序直接访问硬件,而是通过提供一些系统服务函数,用户程序使用SVC 发出对系统服务函数的呼叫请求,以这种方法调用它们来间接访问硬件。因此,当用户程序想要控制特定的硬件时,它就会产生一个SVC 异常,然后操作系统提供的SVC 异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务。

优势:

  • 第一,它使用户程序从控制硬件的繁文缛节中解脱出来,而是由OS 负责控制具体的硬件。
  • 第二,OS 的代码可以经过充分的测试,从而能使系统更加健壮和可靠。
  • 第三,它使用户程序无需在特权级下执行,用户程序无需承担因误操作而瘫痪整个系统的风险。
  • 第四,通过SVC 的机制,还让用户程序变得与硬件无关,因此在开发应用程序时无需了解硬件的操作细节,从而简化了开发的难度和繁琐度,并且使应用程序跨硬件平台移植成为可能。

PendSV(可悬起系统调用)

PendSV ,它是可以像普通的中断一样被悬起的(不像SVC 那样会上访)。OS 可以利用它“缓期执行”一个异常——直到其它重要的任务完成后才执行动作。悬起PendSV 的方法是:手工往NVIC 的PendSV 悬起寄存器中写1。悬起后,如果优先级不够高,则将缓期等待执行。

PendSV 的典型使用场合是在上下文切换时(在不同任务之间切换)。例如发生中断时产生线程唤醒,中断会引发一个PendSV,在中断运行结束后,会进入PendSV在里面进行线程唤醒(线程切换)。

一些总结和个人笔记

中断的入栈出栈

  1. 进入异常服务例程时,自动压栈R0‐R3, R12, LR, PSR 和PC。
  2. 进入异常服务程序后,LR的值被自动更新为特殊的EXC_RETURN。
数值功能
0xFFFF_FFF1返回handler模式
0xFFFF_FFF9返回线程模式,并使用主堆栈(SP=MSP)
0xFFFF_FFFD返回线程模式,并使用线程堆栈(SP=PSP)
  • 如果主程序在线程模式下运行, 并且在使用MSP 时被中断, 则在服务例程中LR=0xFFFF_FFF9(主程序被打断前的LR已被自动入栈)。

  • 如果主程序在线程模式下运行, 并且在使用PSP 时被中断, 则在服务例程中LR=0xFFFF_FFFD(主程序被打断前的LR已被自动入栈)。

  1. 进入函数调用时也会压栈Rxxx寄存器作为传入参数。
  2. R0作为函数的返回值。

Cortex-M3基础
https://www.oikiou.top/2020/2651f4ca/
作者
Oikiou
发布于
2020年10月30日
许可协议