Programming Model
The programming model of the Cortex-M processor family is highly consistent. For example, all Cortex-M processors support R0 to R15, PSR, CONTROL, and PRIMASK. Two special registers—FAULTMASK and BASEPRI—are only supported by Cortex-M3, Cortex-M4, Cortex-M7, and Cortex-M33; the floating-point register set and FPSCR (Floating Point Status and Control Register) are used by the optional floating-point unit of Cortex-M4/M7/M33.
Programming Model
The BASEPRI register allows programs to block interrupts and exceptions of a specified priority or lower. This is important for ARMv7-M, as Cortex-M3, Cortex-M4, Cortex-M7, and Cortex-M33 have a large number of priority levels, while ARMv6-M and ARMv8-M Baseline only have a limited 4 priority levels. FAULTMASK is typically used in complex error handling.
The implementation of non-privileged levels is optional for ARMv6-M processors, while it has always been supported in ARMv7-M and ARMv8-M processors. For the Cortex-M0+ processor, it is optional, and Cortex-M0 and Cortex-M1 do not support this feature. This means that the CONTROL register is slightly different across various Cortex-M processors. The configuration of the FPU also affects the CONTROL register, as shown in the figure below.
CONTROL Register
Another difference in the programming model is the details of the PSR register (Program Status Register). In all Cortex-M processors, the PSR register is further divided into Application Program Status Register (APSR), Execution Program Status Register (EPSR), and Interrupt Program Status Register (IPSR). The ARMv6-M and ARMv8-M Baseline series processors do not support the Q bit of APSR and the ICI/IT bits of EPSR. The ARMv7E-M series (Cortex-M4, Cortex-M7) and ARMv8-M Mainline (Cortex-M33 with DSP extension) support the GE bit. Additionally, the range of interrupt numbers for the IPSR of ARMv6-M series processors is very small, as shown in the figure below.
PSR Differences
Please note that the programming model of Cortex-M is different from those classic ARM processors like ARM7TDMI. Besides the difference in register sets, the definitions of “mode” and “state” in classic ARM processors are also different from those in Cortex-M. Cortex-M has only two modes: Thread mode and Handler mode, and Cortex-M processors always operate in Thumb state (ARM instructions are not supported).
Exception Handling Model and Nested Vector Interrupt Controller NVIC
All Cortex-M processors include the NVIC module, which adopts the same exception handling model. If an exception interrupt occurs, and its priority level is higher than the currently running level and is not masked by any interrupt mask registers, the processor will respond to this interrupt/exception by pushing certain registers onto the current stack. Under this stack mechanism, interrupt handlers can be written as ordinary C functions, allowing many small interrupt handling functions to respond immediately without extra stack handling overhead.
Some ARMv7-M/ARMv8-M Mainline series processors use interrupts and system exceptions that are not supported by ARMv6-M/ARMv8-M Baseline products, as shown in Figure 8. For example, the number of interrupts for Cortex-M0, M0+, and M1 is limited to less than 32, with no debug monitor exceptions, and error exceptions are limited to HardFault (for error handling details, see Section 3.4). In contrast, Cortex-M23, Cortex-M3, Cortex-M4, and Cortex-M7 processors can support up to 240 peripheral device interrupts. Cortex-M33 supports up to 480 interrupts.
Another distinction is the number of available priority levels:
➤ ARMv6-M Architecture——ARMv6-M supports 2 fixed levels (NMI and HardFault) and 4 programmable levels (represented by two bits of each priority level register) for interrupts/exceptions. This is sufficient for most microcontroller applications.
➤ ARMv7-M Architecture——ARMv7-M series processors have a range of programmable priority levels that can be configured from 8 levels (3 bits) to 256 levels (8 bits), depending on area constraints. ARMv7-M processors also have a feature called interrupt priority grouping, which can further divide the interrupt priority registers into group priority and sub-priority, allowing detailed specification of preemptive priority behavior.
➤ ARMv8-M Baseline——Similar to ARMv6-M, M23 also has a 2-bit priority level register. With the optional TrustZone security extension component, secure software can map the priority level of interrupts in non-secure environments to the lower half of the priority range, ensuring that certain interrupts/exceptions in secure environments are always higher than those in non-secure environments.
➤ ARMv8-M Mainline——Similar to ARMv7-M. It can support 8 to 256 interrupt priority levels and interrupt priority grouping. It also supports the priority adjustment features of ARMv8-M Baseline.
Cortex-M Processor Exception Interrupt Types
All Cortex-M processors rely on a vector table for exception handling. The vector table holds the starting addresses of the exception handling functions (as shown in the figure above). The starting address of the vector table is determined by a register called the Vector Table Offset Register (VTOR).
-
Cortex-M0+, Cortex-M3, and Cortex-M4 processors: by default, the vector table is located at the start of the memory map (address 0x0). Cortex-M0+, Cortex-M3, and Cortex-M4: the vector table is by default at the starting address of the storage space (address 0x0).
-
In Cortex-M7, Cortex-M23, and Cortex-M33 processors: the default value for VTOR is defined by chip designers. Cortex-M23 and Cortex-M33 processors can have two separate vector tables for Secure and Non-secure exceptions/interrupts. Cortex-M7, Cortex-M23, and Cortex-M33: the initial value of VTOR is defined by chip designers. Cortex-M23 and Cortex-M33 processors have two independent vector tables for secure and non-secure exceptions/interrupts.
-
Cortex-M0 and Cortex-M1 do not implement programmable VTOR, and the vector table starting address is always 0x00000000. Cortex-M0 and Cortex-M1 do not implement programmable VTOR; the vector table starting address is always 0x00000000.
The VTOR of Cortex-M0+ and Cortex-M23 processors is optional. If VTOR is implemented, the starting address of the vector table can be changed by setting VTOR. This feature is useful in the following situations:
-
Relocating the vector table to SRAM to dynamically change the entry point of the exception handling function.
-
Relocating the vector table to SRAM for faster vector reads (if flash memory is slow).
-
Relocating the vector table to different locations in ROM (or Flash), allowing different exception handlers for different program execution phases.
There are also additional differences in the NVIC programming model between different Cortex-M processors. The differences are summarized in the table below:
NVIC Programming Model and Feature Differences
In most cases, operations on the interrupt control features of NVIC are handled through APIs provided by CMSIS-CORE, which are included in the device driver libraries provided by microcontroller vendors. For Cortex-M3/M4/M7/M23/M33 processors, even if interrupts are enabled, their priority can be changed. ARMv6-M processors do not support dynamic priority adjustment; when you need to change the interrupt priority, you need to temporarily disable the interrupt.
Operating System Support Features
The Cortex-M processor architecture is designed with operating system support in mind. The features for operating systems include:
-
Shadow stack pointer
-
System service calls (SVC) and suspendable system call (PenSV) exceptions
-
SysTick – 24-bit decrementing timer that generates periodic exception interrupts for operating system timing and task management
-
Cortex-M0+/M3/M4/M7/M23/M33 support for non-privileged execution and memory protection unit (MPU)
The system service call (SVC) exception is triggered by the SVC instruction, which allows application tasks running in non-privileged state to invoke privileged operating system services. The suspendable system call exception is very helpful for scheduling non-critical operations like context switching in operating systems.
To fit the Cortex-M1 into very small FPGA devices, all features supporting operating systems are optional for Cortex-M1. For Cortex-M0, Cortex-M0+, and Cortex-M23 processors, the system clock SysTick is optional.
Generally, all Cortex-M processors support operating systems. Applications running on Cortex-M0+, Cortex-M3, Cortex-M4, Cortex-M7, Cortex-M23, and Cortex-M33 can operate in non-privileged runtime states and can utilize the optional memory management unit (MPU) to avoid illegal memory access. This enhances the robustness of the system.
TrustZone Security Extension
In recent years, the Internet of Things (IoT) has become a hot topic among embedded system developers. IoT system products have become more complex, and the pressure to market has increased. Embedded system products require better solutions to ensure system security while also facilitating software developers. The traditional solution is to divide software into privileged and non-privileged parts, where privileged software uses the MPU to prevent non-privileged applications from accessing critical system resources, including security-sensitive information. This solution is suitable for some IoT systems, but in some cases, a two-layer division is not enough. Especially for systems that include many complex privileged software components, a flaw in the privileged code can lead to hackers completely controlling the system.
The ARMv8-M architecture includes a security extension called TrustZone, which introduces an orthogonal division of secure and non-secure states.
-
Normal applications are in non-secure state.
-
Software components and security-related resources (e.g., secure storage, cryptographic accelerators, true random number generators (TRNG)) are in secure state.
Isolation of Secure and Non-Secure States
Non-secure state software can only access non-secure state memory and peripherals, while secure software can access all resources in both states.
With this solution, software developers can develop applications in non-secure environments in the traditional way. At the same time, they can leverage secure communication software libraries provided by chip manufacturers to execute secure IoT connections. Furthermore, even if privileged programs running in non-secure environments have vulnerabilities, the TrustZone security mechanism can prevent hackers from taking control of the entire device, limiting the impact of attacks and enabling remote recovery of the system. Additionally, the ARMv8-M architecture introduces stack boundary checks and enhanced MPU design to promote the adoption of additional security measures.
The security architecture definition also extends to the system level, where each interrupt can be set with secure or non-secure attributes. Interrupt exception handlers automatically save and restore register data in the secure environment to prevent security information leakage. Thus, the TrustZone security extension enables systems to support the requirements of real-time systems, providing a solid security foundation for IoT applications while making it easier for software developers to develop applications based on this technology.
The TrustZone module is optional for Cortex-M23 and Cortex-M33 processors.
Error Handling
A difference between ARM processors and microcontrollers of other architectures is the error handling capability. When an error is detected, an error exception handler is triggered to execute appropriate handling. Situations that trigger errors may include:
-
Undefined instruction (e.g., Flash memory corruption)
-
Accessing illegal address space (e.g., stack pointer crash) or MPU illegal access
-
Illegal operation (e.g., when the processor attempts to trigger an SVC exception while already in an interrupt with a higher priority than SVC)
The error handling mechanism enables embedded systems to respond more quickly to various issues. Otherwise, if the system crashes, the watchdog timer would take a very long time to restart the system.
In the ARMv6-M architecture, all error events trigger the HardFault handler, which has a priority of -1 (higher than all programmable exceptions but lower than non-maskable interrupts NMI). All error events are considered unrecoverable, and typically, we only run error reporting in the HardFault handler before triggering an automatic reset.
ARMv8-M Baseline architecture is similar to ARMv6-M, with only one error exception (HardFault). However, the priority of HardFault in ARMv8-M Baseline can be -1 or -3 when the TrustZone security extension is implemented.
ARMv7-M and ARMv8-M Mainline products have several configurable error exceptions in addition to HardFault:
-
Memmanage (memory management error)
-
Bus error (response error from the bus)
-
Usage error (undefined instruction or other illegal operations)
-
SecureFault (supported only by ARMv8-M Mainline products, handling secure illegal operations in TrustZone security extension)
The priority of these exceptions can be programmatically changed and can be turned on and off individually. If needed, they can also use the FAULTMASK register to raise their priority to the same level as HardFault. ARMv7-M and ARMv8-M Mainline products have additional error status registers that provide clues about the triggering error exception event and the error address register to determine the access address that triggered the error exception, making debugging easier.
Additional error handling capabilities provided by the sub-specifications of ARMv7-M and ARMv8-M Mainline products allow for flexible error handling, and the error status registers make locating and debugging error events easier. Many commercial development kits’ debuggers have embedded functionality to diagnose error events using the error status registers. Additionally, error handlers can perform some recovery actions at runtime.
Error Handling Feature Comparison Summary