embassy-rs/embassy · critical

Unknown Cortex-M core

Error message

Unknown Cortex-M core

What it means

cpu::current() reads the CPU id register to map the executing processor to a CoreId. Only specific CPU-id values (0x4/0x7 for dual-core H7 parts) are handled; any other value panics. This means code is running on a core — or under an emulator — whose CPU id does not match any value the HAL recognizes for this chip family.

Solutions

  1. Verify the firmware is booted on the intended core (check boot address / RCC CPU boot configuration for H7 dual-core parts).
  2. Check that the selected chip features match the actual STM32 variant so the correct CPU-id mappings are compiled in.
  3. If running under an emulator, use real hardware or an emulator model with correct CPU id values.
Defensive patterns

Strategy: validation

Validate before calling

// Only use per-core APIs on the intended core; verify boot address maps
// this image to the core whose CPU id the HAL expects.
let cpu_id = /* read CPU id register */;
assert!(matches!(cpu_id, 0x4 | 0x7), "unexpected core id");

Prevention

When it happens

Trigger: Calling cpu::current() on a dual-core part (stm32h745/747/755/757, wb, wl) when the CPU id is not one of the recognized values: e.g. code linked for Core1 executing on Core0 (or vice versa), or an emulator reporting a nonstandard id.

Common situations: Running dual-core H7 firmware under QEMU/emulation with nonstandard MPIDR; feature flags not matching the actual silicon variant; a bootloader/boot RCC configuration starting the image on the wrong core.

Understand the failure class

Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/72eeb14c3e133999. Report an issue: GitHub.

Appendix: source

Thrown at embassy-stm32/src/cpu.rs:42

impl CoreId {
    /// Get the current core id
    /// This code assume that it is only executed on a Cortex-M M0+, M4 or M7 core.
    pub fn current() -> Self {
        let cpuid = unsafe { cortex_m::peripheral::CPUID::PTR.read_volatile().base.read() };
        match (cpuid & 0x000000F0) >> 4 {
            #[cfg(any(stm32wb, stm32wl))]
            0x0 => CoreId::Core1,

            #[cfg(not(any(stm32h745, stm32h747, stm32h755, stm32h757)))]
            0x4 => CoreId::Core0,

            #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
            0x4 => CoreId::Core1,

            #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
            0x7 => CoreId::Core0,
            _ => panic!("Unknown Cortex-M core"),
        }
    }

    #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757, stm32wb, stm32wl))]
    /// Get the other core id
    pub const fn other(&self) -> Self {
        match &self {
            Self::Core0 => Self::Core1,
            Self::Core1 => Self::Core0,
        }
    }

    /// Translates the core ID to an index into the interrupt registers.
    pub const fn to_index(&self) -> u8 {
        match &self {
            CoreId::Core0 => 0,
            #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757, stm32wb, stm32wl))]
            CoreId::Core1 => 1,

View on GitHub (pinned to 463a07b963)