Cortex-M · 24 pages
- Core lineup
- Architecture family compared
- Cortex-M0
- Cortex-M0+
- Cortex-M3
- Cortex-M4
- Cortex-M7
- Cortex-M23v8-M
- Cortex-M33v8-M
- Cortex-M55Helium
- Cortex-M85Helium
- NVIC overview
- NVIC registers
- NVIC priority & preemption
- Tail-chain & late-arrival
- Vector table
- SysTick & timing
- SCB — System Control Block
- MPU on Cortex-M
- FPU on Cortex-M
- Cache & TCM (M7/M55/M85)
- DWT / ITM / ETM
- CoreSight
- Low-power modes
Cortex-M33
ARMv8-M Mainline — the modern mid-tier Cortex. TrustZone-M, optional FPU and DSP, MPU, 3-stage pipeline. The default pick for new secure IoT and industrial designs.
The Cortex-M33 is the workhorse of the ARMv8-M generation. It picks up where the M3 and M4 left off — same general performance envelope, same code-density, same toolchain — and adds TrustZone-M, an updated MPU, and a cleaner ISA. For a vendor designing a new mid-tier MCU in 2024 or later, the M33 is the default core. STMicroelectronics, NXP, Nordic, Renesas, Microchip, and Infineon (Cypress PSoC 6) all ship M33-based product lines.
The M33's design centers on modular optional features. The base core is small and resembles a beefed-up M3. Vendors then license, in any combination: FPU (single or double precision), DSP saturating extensions, TrustZone-M, and the MPU. STM32U5 ships with all four; PSoC 6 has FPU + DSP + MPU but no TrustZone-M on some variants; Nordic nRF5340 ships dual M33s (one for the application processor, one for the radio) with TrustZone-M on the application core.
- Architecture
- ARMv8-M Mainline
- Pipeline
- 3-stage in-order, with branch speculation on direct branches
- TrustZone-M
- Optional — same security model as M23, plus per-region MPU and SAU
- FPU
- Optional — FPv5-SP (single precision only). No double-precision option on M33.
- DSP
- Optional — saturating arithmetic (QADD/QSUB), SIMD on packed 16-bit/8-bit data
- MPU
- Optional, ARMv8-M MPU, up to 16 regions per security state
- Co-processor interface
- Up to 8 user-defined co-processors via CP0–CP7 (CDP/MRC/MCR instructions)
- NVIC
- Up to 480 IRQs, 8 priority bits (16 levels typical in silicon)
- DMIPS/MHz
- 1.50 (Dhrystone 2.1)
- CoreMark/MHz
- ~4.02
- Typical clock
- 64–160 MHz silicon, headroom to ~250 MHz on modern processes
- Typical parts
- STM32U5, STM32L5, STM32H5, Nordic nRF5340 / nRF9160, Infineon PSoC 6, Renesas RA6M5
Pipeline and microarchitecture
Three stages: fetch, decode, execute. Direct branches are speculatively predicted as taken or not-taken based on a small static predictor (forward = not-taken, backward = taken — the standard cheap heuristic). The branch penalty is 0 cycles on correctly-predicted direct branches and 2 cycles on mispredict or indirect branch. Loads are 2 cycles to use unless the result lands in a different pipeline slot; load-use stalls show up but rarely.
The M33's IPC is about 1.0 for typical control code, drifting up to 1.2 on hot loops where the static predictor wins. Compared to the M3 (which the M33 is positionally replacing), the IPC is essentially identical — the win is on the ISA side (more compact code, faster division) and on the system side (TrustZone, better MPU).
Bus interfaces
The M33 has multiple bus master ports:
- I-bus — instruction fetches
- D-bus — data accesses
- S-bus — system accesses (to peripheral region, PPB)
This Harvard-style split means an instruction fetch and a data access can happen in the same cycle. Vendors typically route I-bus and D-bus to flash (with an instruction cache buffer) and to SRAM. The PPB is always on a dedicated channel — accesses to NVIC, SCB, MPU, and SysTick go through the S-bus and don't contend with code or data.
Some vendors add TCMs (tightly-coupled memory) — the M33 doesn't have native TCM support (that's an M7/M55/M85 feature) but vendors can put low-latency SRAM at conventional addresses to mimic the effect. STM32U5 has 192 KB of "SRAM4" at single-cycle latency for performance-critical code.
TrustZone-M on the M33
The TrustZone implementation is identical to the M23, but with the M33's wider feature set everything compounds: the FPU has banked state per security domain (FPCCR.S/FPCCR.NS), the MPU has separate region tables per state, the NVIC banks priorities per state. This makes the M33 a credible target for security-certified products — the partition is enforceable from boot through every interrupt.
The flow looks like this. Boot starts in secure state. The Secure boot code:
- Programs the SAU and IDAU (vendor-specific) to define which regions are S, NS, and NSC.
- Sets up the MPU for secure state.
- Configures FPU and any DSP-relevant state.
- Sets
SCB->NSACR(Non-Secure Access Control Register) to grant or deny non-secure access to the FPU and any co-processors. - Configures interrupt targeting (NVIC->ITNS — bit per IRQ, 0=secure, 1=non-secure).
- Sets up the non-secure MSP and vector table.
- Branches to non-secure code via
BLXNSorBXNS.
From this point, non-secure code runs the application, and secure code is only reachable through SG gateways. See TrustZone-M architecture.
// Boot: configure SAU
SAU->RNR = 0;
SAU->RBAR = 0x0C000000; // NSC region base
SAU->RLAR = 0x0C00FFFF | SAU_RLAR_NSC_Msk | SAU_RLAR_ENABLE_Msk;
SAU->RNR = 1;
SAU->RBAR = 0x08040000; // Non-secure flash
SAU->RLAR = 0x080FFFFF | SAU_RLAR_ENABLE_Msk;
SAU->CTRL = SAU_CTRL_ENABLE_Msk;
__DSB(); __ISB();FPU — FPv5-SP
If licensed, the M33's FPU is FPv5-SP: single-precision IEEE 754 only. 32 single-precision registers (s0..s31), or equivalently 16 doubles when paired (d0..d15) — but actual double-precision ops are not implemented on M33; doubles must go through software helpers. Operations include add, subtract, multiply, multiply-accumulate, divide, square-root, and conversions. Latencies are mostly 1–3 cycles; divide and sqrt are 14 cycles non-pipelined.
Lazy stacking on exception entry: the FPU registers are not pushed unless the handler actually uses the FPU. This saves up to 17 stack words on every interrupt for code that doesn't touch floats. See FPU page for the FPCCR.LSPEN bit and the lazy stacking dance.
DSP extensions
Optional. The DSP extensions add the same SIMD-on-packed-data instructions the M4 had: SADD16, SSUB16, SADD8, SSUB8 (parallel add/sub on packed halves), QADD, QSUB (saturating), SMLAD, SMLSD (dual MAC), USAT/SSAT (saturate to N bits), and pack/extract operations. The CMSIS-DSP library is heavily optimized around these and gives 4–8× speedup for FIR filters, FFTs, and complex-arithmetic kernels versus pure scalar C.
DSP-extension-equipped M33s show "Cortex-M33F" or "Cortex-M33D" in some vendor datasheets — though the official ARM nomenclature is just "Cortex-M33 with DSP extension."
NVIC and exceptions
Up to 480 external IRQs (most parts ship 100–200), priority bits up to 8 (most ship 3 or 4). With TrustZone-M, every IRQ is targetable: NVIC_ITNS bit chooses whether the IRQ runs in secure or non-secure state. SysTick is banked — there are two SysTicks, one per state, with independent reload values and counters.
Exception entry preserves security state. A secure exception entered from non-secure context pushes an extended stack frame that includes a security signature (a hash of the stack contents), and on return the hardware verifies the signature to detect tampering. The hardware also pushes additional registers when crossing security boundaries to prevent secure state from leaking into non-secure registers.
Memory protection
The MPU is the ARMv8-M MPU — up to 16 regions per security state, non-power-of-two sizes, MAIR-indexed attributes. With TrustZone, the secure MPU and non-secure MPU are independent. The secure side typically locks down the entire chip, hands out a few permissions through NSC gateways, and lets the non-secure side configure its own MPU as it pleases.
Stack overflow detection works the same way as on M7/M4 — guard region with no-access. The M33 adds a hardware Stack Limit register (MSPLIM, PSPLIM, plus secure variants) that triggers a UsageFault if SP drops below the limit, without needing an MPU region. This is much cheaper for stack overflow detection — one comparison per push instead of a full MPU check — and is on by default in CMSIS startup files when configured.
__set_MSPLIM((uint32_t)&_estack_limit);
__set_PSPLIM((uint32_t)&_task_stack_limit);Representative parts
| Part | Vendor | Highlights |
|---|---|---|
| STM32U5 | STMicro | Best mainstream M33 — 160 MHz, full TZ, OCTOSPI, large flash, 1.5 µA in Stop2 |
| STM32L5 | STMicro | Predecessor to U5 — 110 MHz, TZ, USB, broader peripheral set |
| STM32H5 | STMicro | High-perf M33 — 250 MHz, similar peripheral set to H7 |
| nRF5340 | Nordic | Dual M33 — 128 MHz application core + 64 MHz network core, BLE 5.x, Thread, Matter |
| nRF9160 | Nordic | LTE-M / NB-IoT, M33 with TZ, GPS |
| PSoC 6 | Infineon | Dual-core M33+M0+ (or M4+M0+ on older variants), programmable analog/digital fabric |
| RA6M5 | Renesas | 200 MHz, 2 MB flash, TZ, Ethernet, CAN-FD |
When to choose Cortex-M33
The M33 is the default for new designs in the 64–250 MHz range that need any of:
- Hardware security (TrustZone-M)
- FPU for sensor fusion or DSP
- Mid-tier performance with low active-mode power
- A modern ISA with v8-M memory ordering
Step down to M23 only when BoM cost is brutal. Step up to M55 when you need ML inference (Helium MVE), or M7/M85 when you need 400+ MHz pure throughput. Avoid the old M4 for new designs — same performance, no TrustZone, older ISA, vendor support is shrinking.
Cross-references
- Cortex-M23 — Baseline counterpart
- Cortex-M55 — adds Helium MVE for ML
- Cortex-M85 — highest-performance Cortex-M
- TrustZone-M architecture
- FPU on Cortex-M
- MPU
- ARMv8-M Architecture Reference Manual (DDI 0553)