Hello! Welcome back to your preparation for the embedded driver development interview.
In our first lesson, we established a high-level view of the ARM processor landscape, comparing the Cortex-M and Cortex-R families and their roles in automotive systems. Now, we will peel back the next layer of the onion and look at the core from a programmer's perspective.
This lesson focuses on the internal state of a Cortex-M processor. We will cover the fundamental building blocks you interact with when writing low-level code: the register set, the two processor modes (Thread and Handler), and the two privilege levels (Privileged and Unprivileged). Understanding these concepts is non-negotiable for anyone writing bare-metal drivers, developing for an RTOS, or working on safety-critical software, as they define the rules of what your code can and cannot do at any given moment.
1. The Programmer's Model: A High-Level View
Before we dissect each component, let's get a unified overview of how these concepts fit together. The Cortex-M architecture provides a consistent programmer's model that balances simplicity with the features needed for robust and secure systems.
To start, watch this brief segment from an Arm official video. It introduces the core registers and the concepts of execution modes and privilege levels.
How to Choose your ARM Cortex-M Processor
The video 'How to Choose your ARM Cortex-M Processor' by Arm provides an excellent introduction to the baseline programmer's model.
Please watch from 03:40 to 06:01. Focus on the descriptions of the 16 core registers (especially R13, R14, R15), the distinction between Thread and Handler modes, and the purpose of Privileged versus Unprivileged levels.
As the video explained, the processor's state is defined by three key aspects at any point in time:
- The values in its registers.
- The execution mode it is in (Thread or Handler).
- The privilege level at which it is operating (Privileged or Unprivileged).
Let's explore each of these in more detail.
2. The ARM Cortex-M Register Set
When you debug using Trace32, the register window is your primary view into the processor's soul. Understanding what each register does is crucial. We can group them into three categories.
To guide this section, we'll refer to an excellent technical article from Memfault, which provides the level of detail you'll appreciate.
ARM Cortex-M RTOS Context Switching | Interrupt - Memfault
The article 'ARM Cortex-M RTOS Context Switching' provides a detailed breakdown of the Cortex-M register set.
First, read the section 'Registers', focusing on the subsections 'Core Registers' and 'Special Registers'. Then, read the section 'Stack Pointers'. Pay attention to the table of core registers and the description of the CONTROL register bits.
General-Purpose Registers (GPRs): R0-R12
- R0-R3: These are primarily used as argument/scratch registers. According to the ARM Procedure Call Standard (AAPCS), which we'll cover in a future lesson, they are used to pass the first four arguments to a function and to return a result from a function.
- R4-R11: These are "callee-saved" variable registers. A function must preserve the values of these registers for its caller.
- R12 (IP): The Intra-Procedure-call scratch register. It's a special scratch register that can be used by the linker for veneers (small code stubs to handle long branches), but is otherwise a general-purpose scratch register.
Special-Purpose Core Registers: R13-R15
These registers have roles assigned by the hardware itself.
-
R13 (SP - Stack Pointer): This register holds the current address of the top of the stack. A key feature of Cortex-M is that the stack pointer is banked. This means there are two physical stack pointer registers:
- Main Stack Pointer (MSP): The default stack pointer, used by the OS kernel and exception handlers.
- Process Stack Pointer (PSP): Used by user application code or RTOS tasks.
This hardware separation is fundamental for RTOS design, as it provides a clean way to isolate the kernel's stack from each task's stack. The processor automatically uses the MSP when it enters an exception handler.
-
R14 (LR - Link Register): When a function is called using a Branch with Link (
BLorBLX) instruction, the hardware automatically saves the return address (the address of the next instruction) into the LR. It is also used in exceptions to hold a specialEXC_RETURNvalue that tells the processor how to return from the exception. -
R15 (PC - Program Counter): This always holds the address of the next instruction to be fetched from memory. Directly writing to the PC causes a branch.
Special Registers
Beyond the core registers, a set of special-purpose registers configures and reports on the processor's state. They are accessed using the special MSR (Move to Special Register) and MRS (Move from Special Register) instructions. The most important one for our current topic is the CONTROL register.
The CONTROL register has two critical bits for managing state:
nPRIV(bit 0): Controls the privilege level in Thread mode.0: Thread mode is Privileged.1: Thread mode is Unprivileged.
SPSEL(bit 1): Selects the active stack pointer in Thread mode.0: Use the Main Stack Pointer (MSP).1: Use the Process Stack Pointer (PSP).
In Handler mode, the processor ignores these bits and always operates as Privileged, using the MSP.
3. Processor Modes and Privilege Levels
Now, let's formalize the concepts of modes and levels. An excellent article from EmbeddedPrep breaks this down clearly.
Understanding Thread Mode, Handler Mode, Privileged & ...
The article 'Understanding Thread Mode, Handler Mode, Privileged & Unprivileged Modes' provides a clear, practical explanation of these concepts.
Read the sections from 'What is Thread Mode?' down to 'Why Are These Modes Important?'. Pay special attention to the summary table that brings all the concepts together.
Let's synthesize this information with the state diagram below.

Here’s how to interpret the diagram and the concepts from the article:
- Reset: After a reset, the processor starts in Privileged Thread Mode, using the MSP. This allows the startup code to have full control to initialize the hardware (clocks, memory, etc.).
- Thread Mode: This is the processor's normal operating state. It executes your
main()function and general application logic. It can be:- Privileged: Full access to all memory and special registers. Ideal for an RTOS kernel or bare-metal system.
- Unprivileged: Access is restricted. For example, it cannot change interrupt masks or access certain system control registers. This is perfect for sandboxing user tasks in an RTOS.
- Handler Mode: The processor automatically enters Handler Mode whenever an exception (like an interrupt or a system fault) occurs.
- Handler Mode is always Privileged. This is a critical security and stability feature, ensuring that an interrupt service routine (ISR) has the necessary rights to manage the system, regardless of what the application code was doing.
- Transitions:
- Privileged Thread -> Unprivileged Thread: This is a software-controlled transition. You do it by setting the
nPRIVbit in theCONTROLregister, as we saw earlier. - Any State -> Privileged Handler: An exception occurs. The hardware automatically saves key registers onto the current stack, loads the PC with the address of the handler, and enters Privileged Handler mode.
- Privileged Handler -> Any Thread State: This occurs upon an exception return. The special
EXC_RETURNvalue loaded into the LR during the exception tells the processor which mode and stack pointer to return to. - Unprivileged Thread -> Privileged Thread: This transition cannot be made directly. An unprivileged application cannot simply grant itself more privileges. It must trigger an exception, such as a Supervisor Call (
SVCinstruction), to enter Handler Mode. The privileged SVC handler can then perform the requested action on behalf of the application or choose to return to Privileged Thread mode. This is the fundamental mechanism for system calls in an OS.
- Privileged Thread -> Unprivileged Thread: This is a software-controlled transition. You do it by setting the
Test your understanding!
An application task running in an RTOS needs to disable all interrupts globally to perform a time-critical update to a shared data structure. The task itself is running in Unprivileged Thread mode. Can the task code directly write to the PRIMASK register to disable interrupts? If not, how would this be achieved?
Show answer
No, the task cannot directly write to PRIMASK. The PRIMASK register is a special register that can only be modified from a privileged level. An attempt to execute MSR PRIMASK, R0 from unprivileged code would be ignored by the hardware.
To achieve this, the RTOS would provide a system call API, for example, taskEnterCritical(). When the application calls this function, it executes an SVC instruction. This causes an exception, transitioning the processor to Privileged Handler Mode to run the RTOS's SVC handler. This privileged handler then disables the interrupts by writing to PRIMASK on the application's behalf before returning.
4. A Practical Code Example
Theory is essential, but seeing it in action solidifies the concepts. The same EmbeddedPrep article provides a full bare-metal code example that demonstrates these transitions.
Understanding Thread Mode, Handler Mode, Privileged & ...
Let's examine the 'Full Code Example' from the EmbeddedPrep article.
Please review the C code provided. Trace the execution flow described in the comments and match it to the 'What You Just Learned' summary table. Also, note the 'Bonus Tip' about how this applies in an RTOS context.
The code demonstrates the following flow, which is a textbook example of how privilege levels are used:
- Start:
main()begins in Privileged Thread Mode. It has full access to configure GPIOs. - Demotion: The code explicitly switches to Unprivileged Thread Mode by writing to the
CONTROLregister using inline assembly. Now, it has restricted access. - System Call: The code triggers a software interrupt, which is a form of exception. The CPU automatically transitions to Privileged Handler Mode to execute the
EXTI3_IRQHandler. - Return: After the ISR finishes, the CPU returns to the
mainloop, which is still in Unprivileged Thread Mode.
This example perfectly illustrates the secure boundary between application code and system/driver code, which is a cornerstone of reliable embedded systems and a direct application of your ISO 26262 experience at the hardware level.
Interview Corner
Be prepared to discuss these topics clearly and concisely.
-
"Can you describe the core registers of an ARM Cortex-M processor and their primary roles?"
- Hint: Group your answer: GPRs (R0-R12 for arguments and variables), and Special-Purpose Core Registers (SP, LR, PC). Mention the banked stack pointers (MSP/PSP) and their use with an RTOS.
-
"What is the difference between Thread mode and Handler mode?"
- Hint: Thread mode is for normal execution; Handler mode is for exceptions/interrupts. Handler mode is always privileged. The transition to Handler mode is automatic on an exception.
-
"Explain the concept of privileged versus unprivileged execution. How does an RTOS leverage this feature?"
- Hint: Privileged mode has full system access; unprivileged is restricted. This creates a secure sandbox. An RTOS runs its kernel in privileged mode to manage hardware and tasks, while running user application tasks in unprivileged mode to prevent them from interfering with the kernel or each other.
-
"How does a processor transition from an unprivileged level to a privileged one?"
- Hint: It cannot do so directly. It must trigger an exception (like an interrupt or an
SVCinstruction). This causes an automatic, secure transition into privileged Handler mode.
- Hint: It cannot do so directly. It must trigger an exception (like an interrupt or an
Conclusion
Great job. We've moved from the high-level architecture of ARM families down into the core's internal state machine. This is the foundation upon which all low-level software is built.
Key Takeaways:
- The Cortex-M programmer's model consists of 16 core registers, including special-purpose
SP,LR, andPC. - The Stack Pointer (SP) is banked, with a Main Stack Pointer (MSP) for the kernel/handlers and a Process Stack Pointer (PSP) for user tasks.
- The processor operates in one of two modes: Thread Mode for normal code and Handler Mode for exceptions.
- Execution occurs at one of two levels: Privileged (full access) or Unprivileged (restricted). Handler mode is always privileged.
- Transitions between levels are tightly controlled by the hardware, forming the basis for secure system calls in an RTOS. The
CONTROLspecial register is key to software management of these states.
Next Lesson Preview:
Now that we understand the processor's state, the next logical step is to understand how it executes instructions. In the next lesson, we will explore the ARM instruction pipeline and its impact on execution timing. This will help you understand why certain instruction sequences can be faster than others and introduce concepts like data hazards and branch prediction, which are important for performance optimization.