ARM State and Thumb State in ARM Cortex M4 Processor : This tutorial provides a simple, beginner-friendly explanation of ARM state and Thumb state in ARM Cortex-M processors. You’ll learn what these two instruction sets are, why Cortex-M processors only use Thumb state, and how the T-bit (Thumb bit) plays a critical role in function calls, interrupt handling, and exception returns.
We break down the concepts using:
- 🧠 Real-world analogies
- 🧾 Simple C code examples
- ⚙️ Basic assembly insights
- ❌ Common pitfalls like HardFault due to wrong state
- ✅ A mini experiment showing how bit[0] of the function address affects the program flow
Whether you’re new to embedded systems or just getting started with ARM Cortex-M development, this tutorial will help you build a solid understanding of how the processor executes instructions and why Thumb state is mandatory for Cortex-M cores like M0, M3, M4, and M7.
📌 By the end of this tutorial, you’ll understand what the T-bit does, why it must always be 1, and how to avoid state-related faults in your embedded C code.
ARM State and Thumb State in ARM Cortex M4 Processor
ARM processors can execute instructions in two modes:
- ARM state
- Thumb state
These are two different instruction sets (types of machine instructions) used by ARM CPUs.
Imagine it like this:
- Think of the processor as a person who reads commands.
- There are two languages it can understand:
- ARM language (ARM state)
- Thumb language (Thumb state)
But both give the same meaning (like English and a shorthand version of English).
ARM State:
- Uses 32-bit instructions (all instructions are 4 bytes long).
- Gives more power and flexibility.
- Takes more memory to store instructions.
- Supported in ARM Cortex-A/R processors.
- ❌ Not supported in Cortex-M processors.
Thumb State:
- Uses mostly 16-bit instructions (some are 32-bit in Thumb-2).
- Smaller instructions mean:
- Uses less memory
- Faster to fetch
- Less powerful than full ARM instructions, but good for embedded systems.
- ✅ Used in all Cortex-M processors (M0, M3, M4, M7, etc.)
Analogy:
| Feature | ARM State (32-bit) | Thumb State (16-bit) |
|---|---|---|
| Instruction Size | Big (32-bit) | Small (16-bit, some 32-bit) |
| Power | Full feature set | Limited, but efficient |
| Memory usage | More | Less |
| Speed | Slower fetch (more data) | Faster fetch |
| Cortex-M usage | ❌ Not supported | ✅ Fully supported |
In Cortex-M processors:
- Only Thumb state is supported.
- That’s why the T-bit is always set to 1 to indicate Thumb state.
Switching States (in processors that support both):
In some ARM processors (like Cortex-A), you can switch between ARM and Thumb states using:
- BX instruction (Branch and Exchange)
- The LSB (least significant bit) of the target address:
- If LSB = 0 → switch to ARM state
- If LSB = 1 → switch to Thumb state
In Cortex-M, this bit must be 1, otherwise it causes a HardFault (because ARM state is not supported).
Summary:
| State | Instruction Size | Memory Usage | Supported in Cortex-M |
|---|---|---|---|
| ARM State | 32-bit | More | ❌ No |
| Thumb State | 16/32-bit | Less | ✅ Yes |
Let’s start with a simple C program:
#include <stdint.h>
void myFunction(void);
int main(void) {
myFunction(); // Call another function
while(1); // Infinite loop
}
void myFunction(void) {
// Do something
}
What happens behind the scenes?
When main() calls myFunction(), it uses a branch instruction like BL (Branch with Link). At machine level, this involves a jump to another address.
In Cortex-M, the instruction set is Thumb, and the processor must stay in Thumb state during this jump.
Key Point:
The T-bit (bit 24 in xPSR) ensures that the CPU stays in Thumb mode.
Example in Assembly (simplified)
Here’s what the processor might see when calling myFunction():
BL myFunction ; Branch to myFunction and link (Thumb instruction)
When returning:
BX LR ; Branch to the address in Link Register (LR)
Now, here’s the magic part:
The return address (in LR) has its bit 0 set to 1:
LR = 0x08000101 // <-- Bit 0 = 1 means Thumb state
If bit 0 = 0, like:
LR = 0x08000100 // <-- Bit 0 = 0 means ARM state (which is invalid on Cortex-M)
🔴 This would cause a HardFault, because Cortex-M cannot switch to ARM state.
Why is this important?
Cortex-M always works in Thumb state, so:
- When calling or returning from a function,
- When handling interrupts or exceptions,
The CPU checks the T-bit (or bit 0 of return address).
If it’s not set, the processor faults.
Let’s test this idea
Here’s a trick in C (not recommended in real use, but educational):
void myFunction(void) {
while(1);
}
int main(void) {
// Call function incorrectly (simulate wrong state)
void (*func_ptr)(void) = (void (*)(void))0x08000100; // Bit 0 = 0
func_ptr(); // ❌ This will cause a HardFault!
}
✅ But this is fine:
void (*func_ptr)(void) = (void (*)(void))0x08000101; // Bit 0 = 1
func_ptr(); // ✅ Executes in Thumb state
Summary:
| Concept | What it means |
|---|---|
| T-bit (xPSR[24]) | Indicates Thumb state (must be 1 on Cortex-M) |
| Function call/return | Needs bit 0 of address = 1 (Thumb mode) |
| Bit 0 = 0 on return | Causes HardFault on Cortex-M (invalid ARM state) |
| Cortex-M processors | Only support Thumb, not full ARM instruction set |
You can also Visit other tutorials of Embedded Prep
- What is eMMC (Embedded MultiMediaCard) memory ?
- Top 30+ I2C Interview Questions
- Bit Manipulation Interview Questions
- Structure and Union in c
- Little Endian vs. Big Endian: A Complete Guide
- Merge sort algorithm
Special thanks to @mr-raj for contributing to this article on EmbeddedPrep

Leave a Reply