cortex-m处理器架构实现了多个特性,保证了OS设计的方便和高效。例如:
①影子栈指针。有两个栈指针可用,MSP用于OS内核以及中断处理,PSP则用于应用任务。
②SysTick定时器。位于处理器内部的简单定时器,使得同一个嵌入式OS可用在多种cortex-m微控制器上。
③SVC和PendSV异常。这两种异常对于嵌入式OS中的操作非常重要,如上下文切换的实现等。
④非特权执行等级。可以利用其实现一种基本安全模型,限制某些应用任务的访问权限。特权和非特权等级的分离还可同存储器保护单元一起使用,进一步提高嵌入式系统的健壮性。
⑤排他访问。排他加载和存储指令用于OS中的信号量和互斥体操作
另外,低中断等待和指令集中的各种特性还有助于嵌入式OS的高效运行。例如,低中断等待带来了较小的上下文切换开销。而且,一个名为跟踪单元(ITM)的调试特性可在多种调试工具中用于OS调试。
一、影子栈指针
cortex-m处理器中存在两个栈指针:
①主栈指针(MSP)为默认的栈指针。当CONTROL的bit[1]为0时用于线程模式,在处理模式中则总是使用。
②进程栈指针(PSP),当CONTROL的bit[1]为1时用于线程模式。
PUSH 和POP指令实现的栈操作及使用SP的多数指令都会使用当前选择的栈指针,还可以利用MRS和MSR指令直接访问MSP和PSP。对于不具有嵌入式OS或RTOS的简单应用,可以在所有操作中只使用MSP,而不用管PSP。
对于具有嵌入式OS或RTOS的系统,异常处理(包括部分OS内核)使用MSP,而应用任务则使用PSP。每个应用任务都有自己的栈空间,如下图所示。OS中的上下文切换代码在每次上下文切换时都会更新PSP。
这种设计有几个优点:
①若应用任务遇到会导致栈破坏的问题,OS内核使用的栈和其他任务的栈不会受到影响,因此可以提高系统的可靠性。
②每个任务的栈空间只需满足栈的最大需求加上一级栈帧(对于cortex-m3或无浮点单元cortex-m4,最大9个字,包括额外插入的字,或者对于具有浮点单元的cortex-m4则最大为27个字),用于ISR和嵌套中断处理的栈空间会被分配在主栈中。
③有助于创建cortex-m处理器用的高效OS.
④OS还可以利用存储器保护单元定义可以访问某个栈区域的应用任务。若某应用任务具有栈溢出的问题,MPU可以触发一次MemManage错误异常,并且避免该任务栈空间以外的存储器区域被覆盖。上电后,MSP被初始化为向量表中的数值,这也是处理器复位流程的一部分。工具链添加的C启动代码也可以执行对主栈进行初始化的其他操作。之后还可以利用MSR指令初始化PSP,并且写入CONTROL设置SPSEL,不过一般不会这么做。
初始化并使用PSP的最简单方法为(对多数OS是不适用的):
LDR R0, =PSP_TOP ;PSP_TOP为代表栈顶地址的常量
MSR PSP, R0 ;设置PSP为进程栈的顶部
MRS R0, CONTROL ;读取当前的CONTROL
ORRS R0, R0, #