Open-source project
rust-embedded/cortex-m avatar
rust-embedded/cortex-m

The cortex-m crates are the bottom layer of Rust on a microcontroller

Low level access to Cortex-M processors

1,011 stars201 forksRustApache-2.0

At a glance

What is it?
This repository holds the crates that make a Cortex-M microcontroller programmable from Rust: the cortex-m crate for CPU peripheral access and intrinsics, cortex-m-rt for startup code and interrupt handling, cortex-m-semihosting for semihosting debugging, cortex-m-interrupt-number for the shared interrupt trait, and two panic handlers that send messages over ITM and over semihosting. The whole thing is developed by the Arm team of the Rust Embedded Working Group and is tested in QEMU.
Who is it for?
cortex-m is the right foundation if you are writing no-std Rust for a Cortex-M part, because it is the layer that owns the reset vector, the vector table and the panic path, and because the interrupt number trait is the seam that the generated peripheral crates plug into. It is the wrong crate to reach for if you need the peripherals themselves, since the peripheral access crates live outside this repository and the shared trait is the contract between them.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Six crates, and each one owns a different job

The README lists the crates and the split is the design. The cortex-m crate gives CPU peripheral access and intrinsics, which is the set of instructions the core offers beyond the general instruction set, the ones a compiler cannot emit for you. The cortex-m-rt crate is startup code and interrupt handling, so the reset behaviour, the vector table and the interrupt entry points. The cortex-m-semihosting crate is support for semihosting debugging, which is the mechanism where the target host talks to the device over the debug probe instead of a real UART. The cortex-m-interrupt-number crate is a shared trait for interacting with peripheral access crates, which is the seam between the core and the generated peripheral definitions. And two panic handlers, panic-itm which sends messages over the ITM and SWO output, and panic-semihosting which sends messages over semihosting. The repository tree also holds cortex-m-types, which is not in the README list but is a workspace member, so the picture is a family of small crates with a clear division of labour.

The runtime crate owns the reset vector and the vector table

cortex-m-rt is the crate that decides what happens when the chip comes out of reset, and it is where most of the invisible complexity of embedded Rust lives. The top-level tree shows the two files that describe the memory layout, memory.x and device.x, and they are the linker script and the device description that the runtime uses. Because the crate owns startup code, it also owns interrupt handling, which means the vector table, the handler entry and the priority mechanics are its business rather than the application's. That is a good division, because those parts are the same on every Cortex-M part and getting them subtly wrong is the classic embedded failure. The crate has its own macros directory, cortex-m-rt/macros, which is a workspace member in its own right, and the macro layer is where the vector table entries get generated for a developer.

Two ways to get a panic message off the chip

A panic on a microcontroller is a special case, because there is no operating system to print the message and no exit. The two panic handler crates solve the same problem with different transports, and having both is the point. panic-itm sends messages over the ITM and SWO output, which is the Instrumentation Trace Macrocell path, and it works with the debug probe that is probably already attached because that is how you flashed the firmware. panic-semihosting sends messages over semihosting, which uses the same debug probe channel but through the semihosting protocol, and it is the one that pairs with the cortex-m-semihosting crate. The practical consequence is that choosing a panic handler is choosing how you will see a crash, and the choice is made once at link time by depending on one crate rather than the other, which is why they are separate crates rather than one crate with a feature.

The test suite runs the code in QEMU

The justfile at the repository root is two targets, and they are the whole of the test story. One runs the test suite for a Cortex-M3 target and the other for a Cortex-M0 target:

bash
cargo test --features qemu --target thumbv7em-none-eabihf
cargo test --features qemu --target thumbv6m-none-eabi --release

The Cortex-M3 target, thumbv7em-none-eabihf, is the Thumb-2 instruction set with the hardware divide extension, and the Cortex-M0 target, thumbv6m-none-eabi, is the smallest and most constrained of the family, which is why the M0 run is in release mode. Running the suite under the qemu feature means the tests execute on an emulated processor rather than on hardware, so the crate's own behaviour, the startup path and the interrupt handling are all exercised without a board on the desk. The testsuite/ directory is excluded from the workspace, so it has its own dependency set, and the xtask/ directory holds the automation for the repository itself.

A workspace that keeps the crates honest

The root Cargo.toml is a workspace with the resolver set to version 3, and the members are the crates themselves, including the two macro directories, cortex-m/macros and cortex-m-rt/macros, plus cortex-m-types, cortex-m-semihosting, panic-itm, panic-semihosting and xtask. The testsuite is excluded rather than being a member, which is a deliberate way of keeping the library crates from depending on the test dependencies. There is a .cargo/ directory in the tree, which is where per-repository cargo configuration lives, and the .github/ directory holds the workflows. The build is driven by a justfile rather than a Makefile, which is the current convention in the Rust embedded ecosystem and means the commands are the recipes. The release history shows how the crates version separately, with cortex-m v0.7.9 and v0.7.8 both published on 2026-09-02, and cortex-m-rt v0.7.7 on 2026-09-24, which is the practical thing to know before you write a dependency block, because the two crates are not on the same number.

Where this repository stops

The boundary is the processor, and the README is explicit that the crates are for Cortex-M microcontrollers with the no-std tag on the repository. The peripherals themselves are not here, which the description of cortex-m-interrupt-number makes clear, since it is a shared trait for interacting with peripheral access crates, and those generated crates live in their own projects. So a project on a Cortex-M part pulls the core crates from here and the peripheral definitions from somewhere else, and the trait is the contract that makes them work together. The second boundary is the toolchain, since this is Rust on a target that has no standard library, and everything about the crates assumes that, so the setup work of getting a no-std build working belongs to the project and not to this repository. The third is the language version, since these crates track the Rust embedded working group's conventions and the way they are maintained, with the Arm team of the Embedded Devices Working Group as the maintainer, is a hint that the design follows that group's decisions rather than the Rust core team's. The licensing is generous, with LICENSE-APACHE and LICENSE-MIT files in the tree, and the contribution note says that unless you explicitly state otherwise, any contribution is dual licensed as above without any additional terms or conditions.

Editorial conclusion

cortex-m is the right foundation if you are writing no-std Rust for a Cortex-M part, because it is the layer that owns the reset vector, the vector table and the panic path, and because the interrupt number trait is the seam that the generated peripheral crates plug into. It is the wrong crate to reach for if you need the peripherals themselves, since the peripheral access crates live outside this repository and the shared trait is the contract between them. Before you start, check the version of each crate rather than assuming they move together, because cortex-m and cortex-m-rt were released on different days in September 2026 with different version numbers, and read the memory.x and device.x files, since the linker script and the memory layout they describe are where most first-time bring-up problems come from.

Frequently asked questions

What is in the rust-embedded cortex-m repository?

Crates for writing Rust programs on Cortex-M microcontrollers: cortex-m for CPU peripheral access and intrinsics, cortex-m-rt for startup code and interrupt handling, cortex-m-semihosting for semihosting debugging, cortex-m-interrupt-number for the shared trait used with peripheral access crates, panic-itm and panic-semihosting as panic handlers, plus cortex-m-types in the workspace.

How is the cortex-m test suite run?

Through the justfile, with cargo test --features qemu --target thumbv7em-none-eabihf for a Cortex-M3 target and cargo test --features qemu --target thumbv6m-none-eabi --release for a Cortex-M0 target, so the tests execute on an emulated processor rather than on hardware.

Which panic handler should an embedded Rust project use?

panic-itm sends panic messages over the ITM and SWO output and panic-semihosting sends them over semihosting, and both rely on the debug probe that is already attached. The choice is made by depending on one crate rather than the other, and cortex-m-semihosting provides the semihosting support the second one uses.

What licence are the cortex-m crates under?

Dual licensed, with LICENSE-APACHE and LICENSE-MIT in the repository root, and the contribution note states that unless you explicitly state otherwise any contribution is dual licensed as above without any additional terms or conditions. The project is developed and maintained by the Arm team of the Embedded Devices Working Group.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. rust-embedded/cortex-m on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rust-embedded-cortex-m.svg)](https://hysenlabs.com/projects/rust-embedded-cortex-m)

Was this useful?