Cortex-M3处理器支持两种模式和两种特权级别。
如下图所示,当处理器运行于Thread mode
时,它可以处于Privileged
或User
级别;而Handler mode
下,只能处于Privileged
级别。当处理器复位完毕后,处于Thread mode
。
在User
级别(Thread mode
)下,访问系统控制区域(配置寄存器和调试组件)是阻塞的,对特殊寄存器的访问(如使用MSR
指令)也是不允许的(访问APSR
寄存器除外),否则会产生一个错误异常。
处于Privileged
级别时,软件可以通过CONTROL
寄存器将程序切换到User
级别。当产生一个异常时,处理器会切换到Privileged
状态,而退出异常时,则会恢复进入异常之前的状态。
用户程序不能直接通过写CONTROL
寄存器将状态切换为Privileged
状态,而必须通过异常处理程序更改CONTROL
寄存器,以便在返回到Thread mode
时将处理器切换到Privileged
级别,如下图所示:
Privileged
和User
级别的存在可以让系统更加安全和更具鲁棒性。比如,当程序出错的时候,是修改不了NVIC的CONTROL
寄存器的。另外,如果使能了MPU(内存保护单元),还可以阻止用户程序访问特权进程的内存区域。
在简单的应用中,不需要区分Privileged
和User
级别。在这种情况下,不需要使用User
级别,也不需要更改CONTROL
寄存器。我们可以将用户程序和内核的堆栈区分开来以避免可能的程序崩溃。比如,用户程序(Thread mode
)使用PSP
堆栈,而异常处理程序使用MSP
堆栈。进入和退出异常处理程序时会自动切换这两个堆栈指针。
处理器的访问级别由CONTROL
寄存器来定义,当其bit0为0时(Privileged mode
),处理器模式将在异常发生时进行切换。
当bit0为1时(User mode
),处理器模式和访问级别都会在异常发生时切换。
CONTROL
寄存器的bit0仅在Privileged level
可编程。对于一个User level
的程序来说,要切换到Privileged mode
,它必须触发一个异常(如SVC异常),并在处理程序中修改CONTROL[0]
。
Cortex-M系列开始出现了上面这些概念,而在ARM7中没有这些模式,这里来做一个对比:
Modes and Exceptions in the ARM7 | Corresponding Modes and Exceptions in the Cortex-M3 |
---|---|
Supervisor (default) | Privileged, thread |
Supervisor (software interrupt) | Privileged, Supervisor Call (SVC) |
FIQ | Privileged, interrupt |
Interrupt request (IRQ) | Privileged, interrupt |
Abort (prefetch) | Privileged, bus fault exception |
Abort (data) | Privileged, bus fault exception |
Undefined | Privileged, usage fault exception |
System | Privileged, thread |
User | User access (nonprivileged), thread |