NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #2905 most downloaded on crates.io
Low level access to Cortex-M processors
Last release 1 months ago
19 Aug 2026
Ships unpredictably
gaps range from 8 days to 3.6 years
Most releases are documented
notes for 42 of 47 stable releases
11 versions withdrawn
withdrawn after publishing
10 years old
59 releases · first in 2016
SCB::enable_icache and SCB::enable_dcache now build the CCR address with movw / movt instead of ldr = , fixing "out of range pc-relative fixup value"
SCB::enable_icache and SCB::enable_dcache now build the CCR address withmovw/movt instead of ldr =, fixing "out of range pc-relative fixup value"basepri, basepri_max and faultmask register modules are now availableSoundness fix (breaking change)
The singleton! macro now requires the user to supply a critical-section implementation. The
previous behavior was to disable interrupts in the current core, which is unsound on multicore chips. By using critical-section the user can set
the implementation that's sound for their chip.
Not supplying an implementation will result in a linker error like rust-lld: error: undefined symbol: _critical_section_1_0_acquire.
To supply one, do either one of:
critical-section-single-core in the cortex-m crate. This implementation disables interrupts in the current core and is equivalent to the behavior in previous versions.critical-section-impl or similar.Library crates generally should not enable a critical section implementation, only the end user (who is building the final binary) should.
inline-asm feature is now a currently a no-op, will be removed in a future major versionenter_unprivileged function to switch to unprivileged mode (on the Process Stack, or PSP)asm::delay() to guarantee that theSCB::vect_active() now reads ICSR with a volatile access, preventing the load from being narrowedOne column per quarter.
Align the default _stext to the alignment required by the .text section. Fixes the lld warning address (...) of section .text is not a multiple of ali
_stext to the alignment required by the .text section. Fixesaddress (...) of section .text is not a multiple of alignment (...).
_stext is not auto-aligned if it's explicitly overridden by the user. It's their responsibility to align it, else the warning will show.syn v3.Full Changelog: v0.7.6...v0.7.7
critical-section-single-core feature added
in v0.7.6.Added critical-section-single-core feature which provides an implementation for the critical-section crate for single-core systems, based on disabling
critical-section-single-core feature which provides an implementation for the critical-section crate for single-core systems, based on disabling all interrupts. (#448).vector_table by @korken89 in #582#[unsafe(link_section = )] for Rust 2024 edition by @yutannihilation in #596pre_init as deprecated by @romancardenas in #598cortex-m-rt: Fix build command in docs by @mfil in #611Full Changelog: c-m-rt-v0.7.5...c-m-rt-v0.7.6
the ptr() function on all peripherals register blocks in favor of the associated constant PTR (#386).
ptr() function on all peripherals register blocks in favor of
the associated constant PTR (#386).inline-asm feature no longer requires a nightly Rust compiler, but
does require Rust 1.59 or above.singleton!() statics sometimes ending up in .data instead of .bss (#364, #380).
(Backported from upcoming 0.8 release).DWT::get_cycle_count has been deprecated in favor of DWT::cycle_count. This change was made for consistency with the [C-GETTER] convention.
DWT.set_cycle_count (#347).cm7 to enable access to these (#352).delay::Delay::with_source, a constructor that lets you specify
the SysTick clock source (#374).DWT::get_cycle_count has been deprecated in favor of DWT::cycle_count.
This change was made for consistency with the C-GETTER convention. (#349)Fixed compilation for native targets on non-x86 host systems (#336, #337).
Delay struct now offers direct delay_us() and delay_ms() methods
without having to go through the embedded-hal traits (#344).Fixed a bug where calling asm::delay() with an argument of 0 or 1 would underflow, leading to a very long delay.
asm::delay() with an argument of 0 or 1 would
underflow, leading to a very long delay.msp::write has been deprecated in favor of asm::bootstrap. It was not possible to use msp::write without causing Undefined Behavior, so all existing u…
asm::semihosting_syscall, asm::bootstrap, and
asm::bootload.msp::write has been deprecated in favor of asm::bootstrap. It was not
possible to use msp::write without causing Undefined Behavior, so all
existing users are encouraged to migrate.asm::delay which could lead to incorrect codegen and
infinite loops.asm::delay on multiple-issue CPU cores.Peripherals struct is now non-exhaustive, so fields may be added in future non-breaking changes
InterruptNumber trait is now required on interrupt arguments to the
various NVIC functions, replacing the previous use of Nr from bare-metal.
For backwards compatibility, InterruptNumber is implemented for types
which are Nr + Copy, but this will be removed in a future version.PTR is introduced to Core Peripherals to
eventually replace the existing ptr() API.asm/lib.rs documentation for more details.inline-asm feature enabled used pre-built
objects which were built by a GCC compiler, while inline-asm enabled the
use of llvm_asm! calls. The asm system has been replaced with a new
technique which generates Rust static libs for stable calling, and uses the
new asm! macro with inline-asm. See the asm/lib.rs documentation for
more details.ptr() methods are now const.SCB::invalidate_dcache and related methods are now unsafe, see #188Peripherals struct is now non-exhaustive, so fields may be added in future
non-breaking changesaligned dependencyNVIC::clear_pendingNVIC::disableNVIC::enableNVIC::set_pendingSCB::system_resetbasepri, basepri_max, and faultmask registers from thumbv8m.baseFixed missing peripheral::itm reexport.
peripheral::itm reexport.Fixed missing ITM reexport on thumbv8m.base targets.
thumbv8m.base targets.This release is forwards-compatible with cortex-m 0.7, and depends on and re-exports many types from that version. Both 0.6.5 and 0.7 may co-exist in
Nothing published for this version
MSRV bumped to 1.36.0 due to aligned dependency.
aligned dependency.Initial Cortex-M Security Extension support for armv8m
UDF intrinsicasm::delay not updating status clobber flagsllvm_asm! to support inline assembly on new nightliesis_fifo_ready improved to support armv8Deprecated incorrectly included registers (BASPRI, BASEPRI_MAX, FAULTMASK) on thumbv8.base
CONTROL register via register::control::writeDWT::unlock() for a safe way to unlock the DWTBASPRI, BASEPRI_MAX, FAULTMASK) on thumbv8.basesystem_reset is deprecated in favor of sys_reset
Debug, PartialEq and Eq for more typesdelay function is fixed for Cortex-M0 MCUssystem_reset as system_reset2links = "cortex-m" to not link multiple versions of the crateNVIC::{mask,unmask}{M,P}SPLIM access is now possible on ARMv8-Msystem_reset is deprecated in favor of sys_resetFix numerous registers which were incorrectly included for thumbv6
SHCRS renamed to SHCSR in SCBSupport for ARMv8-M (thumbv8.base and thumbv8.main)
SCB gained methods to set and clear SLEEPONEXIT bit
NVIC gained STIR register and methods to request an interrupt
DCB gained methods to check if debugger is attached
Nothing published for this version
Nothing published for this version
Nothing published for this version
The NVIC.{clear,set}_pending methods have been deprecated in favor of NVIC::{unpend,pend}.
SCB gained methods to set, clear and check the pending state of the PendSV
exception.
SCB gained methods to set, clear and check the pending state of the SysTick
exception.
SCB gained methods to set and get the priority of system handlers like
SVCall and SysTick.
NVIC gained static methods, pend and unpend, to set and clear the
pending state of interrupts.
NVIC.{clear,set}_pending methods have been deprecated in favor of
NVIC::{unpend,pend}.DCB::enable_trace() and DCB::disable_trace()
DCB::enable_trace() and DCB::disable_trace()iprintln! no longer depends on iprint!. cortex_m::iprintln! will work
even if cortex_m::iprint has not been imported.Removed duplicated symbols from binary blobs
Removed duplicated symbols from binary blobs
The check-blobs.sh script
This crate no longer depends on arm-none-eabi-gcc.
arm-none-eabi-gcc.A method to trigger a system reset. See SCB.system_reset.
SCB.system_reset.Made the VTOR register (see peripheral::SCB) available on thumbv6m-none-eabi. This register is
present on Cortex-M0+, but not on Cortex-M0.
Linking with LLD by marking all external assembly functions as .thumb_func. See
https://bugs.llvm.org/show_bug.cgi?id=38435 for details.
Don't assemble basepri*.s and faultmask.s for ARMv6-M. This fix the build when using clang as the assembler.
clang as
the assembler.SCB gained a pair of safe methods to set / clear the DEEPSLEEP bit.
SCB gained a pair of safe methods to set / clear the DEEPSLEEP bit.
asm::delay, delay loops whose execution time doesn't depend on the optimization level.
An opt-in "const-fn" feature that makes Mutex.new constructor into a const fn. This feature requires a nightly toolchain.
"const-fn" feature that makes Mutex.new constructor into a const fn. This feature
requires a nightly toolchain.DebugMonitor and SecureFault variants to the Exception enumeration.
DebugMonitor and SecureFault variants to the Exception enumeration.
An optional "inline-asm" feature
[breaking-change] This crate now requires arm-none-eabi-gcc to be installed and available in
$PATH when built with the "inline-asm" feature disabled (which is disabled by default).
[breaking-change] The register::{apsr,lr,pc} modules are now behind the "inline-asm" feature.
[breaking-change] Some variants of the Exception enumeration are no longer available on
thumbv6m-none-eabi. See API docs for details.
[breaking-change] Several of the variants of the Exception enumeration have been renamed to
match the CMSIS specification.
[breaking-change] fixed typo in shcrs field of scb::RegisterBlock; it was previously named
shpcrs.
[breaking-change] removed several fields from scb::RegisterBlock on ARMv6-M. These registers are
not available on that sub-architecture.
[breaking-change] changed the type of scb::RegisterBlock.shpr from RW<u8> to RW<u32> on
ARMv6-M. These registers are word accessible only on that sub-architecture.
[breaking-change] renamed the mmar field of scb::RegisterBlock to mmfar to match the CMSIS
name.
[breaking-change] removed the iabr field from scb::RegisterBlock on ARMv6-M. This register is
not available on that sub-architecture.
[breaking-change] removed several fields from cpuid::RegisterBlock on ARMv6-M. These registers
are not available on that sub-architecture.
[breaking-change] The Mutex.new constructor is not a const fn by default. To make it a const fn you have to opt into the "const-fn" feature, which was added in v0.5.1, and switch to a
nightly compiler.
exception module has been removed. A replacement for Exception::active
can be found in SCB::vect_active. A modified version exception::Exception can be found in the
peripheral::scb module.The initial value of a singleton! no longer needs to be evaluable in const context; it can now be a value computed at runtime, or even a capture of so
singleton! no longer needs to be evaluable in const context; it can now
be a value computed at runtime, or even a capture of some other local variable.Added a missing Send implementation to all the peripherals.
Send implementation to all the peripherals.peripheral::Peripherals is now re-exported at the root of the crate.
peripheral::Peripherals is now re-exported at the root of the crate.Formatter and Flush Control register (FFCR) accessor to the TPIU register block.
Formatter and Flush Control register (FFCR) accessor to the TPIU register block.
A singleton! macro that creates mutable reference to a statically allocated variable.
A Cargo feature, cm7-r0p1, to work around a silicon erratum that affects writes to BASEPRI on
Cortex-M7 r0p1 devices.
[breaking-change] All peripherals are now exposed as scoped singletons and they need to be taken
into scope to become accessible.
[breaking-change] The signatures of methods exposed by peripheral proxies have changed to better match the new scoped singletons semantics.
All the thin wrappers around assembly instructions now panic when executed on non-ARM devices.
peripheral::{cbp, fpb, fpu, itm, tpiu}, itm) when
compiling for thumb6m-none-eabi.{basepri,basepri_max}::write are now compiler barriers for the same reason that interrupt::{disable,enable} are: they are used to create critical sect
{basepri,basepri_max}::write are now compiler barriers for the same reason
that interrupt::{disable,enable} are: they are used to create critical
sections.[breaking-change] Renamed StackedRergisters to ExceptionFrame to better reflect the ARM documentation.
[breaking-change] Renamed StackedRergisters to ExceptionFrame to better
reflect the ARM documentation.
[breaking-change] Renamed the variants of Exception to better match the
ARM documentation.
[breaking-change] Renamed Exception::current to Exception::active and
changed the signature to return None when no exception is being serviced.
Moved bits non specific to the Cortex-M architecture into the bare-metal
crate with the goal of sharing code between this crate and crates tailored for
other (microcontroller) architectures.
[breaking-change] The ctxt module along with the exception "tokens" in the
exception module. The cortex-m-rt crate v0.3.0 provides a more ergonomic
mechanism to add state to interrupts / exceptions; replace your uses of
Local with that.
[breaking-change] default_handler, DEFAULT_HANDLERS and Handlers from
the exception module as well as Reserved from the root of the crate.
cortex-m-rt v0.3.0 provides a mechanism to override exceptions and the
default exception handler. Change your use of these Handlers and others to
that.
interrupt::{enable,disable} are now compiler barriers. The compiler should
not reorder code around these function calls for memory safety; that is the
case now.Nothing published for this version
An API to maintain the different caches (DCache, ICache) on Cortex M7 devices.
ehprint! macro.Functions for the instructions DMB, ISB and DSB
asm module are now inline(always)A bug in itm::write_all where it would ignore the length of the buffer and serialize contents that come after the buffer.
itm::write_all where it would ignore the length of the buffer and
serialize contents that come after the buffer.An itm::write_aligned function to write 4 byte aligned buffers to an ITM port. This function is faster than itm::write_all for small buffers but requi
itm::write_aligned function to write 4 byte aligned buffers to an ITM
port. This function is faster than itm::write_all for small buffers but
requires the buffer to be aligned.### Added - Dwt.enable_cycle_counter
Dwt.enable_cycle_counter[breaking-change]. MEMORY UNSAFETY. Mutex could be used as a channel to send interrupt tokens from one interrupt to other thus breaking the context Lo
Mutex could be used as a channel to send
interrupt tokens from one interrupt to other thus breaking the context Local
abstraction. See reproduction case below. This has been fixed by making
Mutex Sync only if the protected data is Send.#![feature(const_fn)]
#![feature(used)]
#![no_std]
use core::cell::RefCell;
use cortex_m::ctxt::Local;
use cortex_m::interrupt::Mutex;
use stm32f30x::interrupt::{self, Exti0, Exti1};
fn main() {
// ..
// trigger exti0
// then trigger exti0 again
}
static CHANNEL: Mutex<RefCell<Option<Exti0>>> = Mutex::new(RefCell::new(None));
// Supposedly task *local* data
static LOCAL: Local<i32, Exti0> = Local::new(0);
extern "C" fn exti0(mut ctxt: Exti0) {
static FIRST: Local<bool, Exti0> = Local::new(true);
let first = *FIRST.borrow(&ctxt);
// toggle
if first {
*FIRST.borrow_mut(&mut ctxt) = false;
}
if first {
cortex_m::interrupt::free(
|cs| {
let channel = CHANNEL.borrow(cs);
// BAD: transfer interrupt token to another interrupt
*channel.borrow_mut() = Some(ctxt);
},
);
return;
}
let _local = LOCAL.borrow_mut(&mut ctxt);
// ..
// trigger exti1 here
// ..
// `LOCAL` mutably borrowed up to this point
}
extern "C" fn exti1(_ctxt: Exti1) {
cortex_m::interrupt::free(|cs| {
let channel = CHANNEL.borrow(cs);
let mut channel = channel.borrow_mut();
if let Some(mut other_task) = channel.take() {
// BAD: `exti1` has access to `exti0`'s interrupt token
// so it can now mutably access local while `exti0` is also using it
let _local = LOCAL.borrow_mut(&mut other_task);
}
});
}
#[allow(dead_code)]
#[used]
#[link_section = ".rodata.interrupts"]
static INTERRUPTS: interrupt::Handlers = interrupt::Handlers {
Exti0: exti0,
Exti1: exti1,
..interrupt::DEFAULT_HANDLERS
};
Higher level API for the SysTick and FPU peripherals
interrupt::enable was safe to call
inside an interrupt::free critical section thus breaking the preemption
protection. The interrupt::enable method is now unsafe.[breaking-change]. MEMORY UNSAFETY. interrupt::free leaked the critical section making it possible to access a Mutex when interrupts are enabled (see
interrupt::free leaked the critical
section making it possible to access a Mutex when interrupts are enabled
(see below). This has been fixed by changing the signature of
interrupt::free.static FOO: Mutex<bool> = Mutex::new(false);
fn main() {
let cs = cortex_m::interrupt::free(|cs| cs);
// interrupts are enabled at this point
let foo = FOO.borrow(&cs);
}
[breaking-change]. MEMORY UNSAFETY. Some concurrency models that use "partial" critical sections (cf. BASEPRI) can be broken by changing the priority
NVIC.set_priority and register::basepri::write are now unsafe.[breaking-change]. MEMORY UNSAFETY. The Mutex.borrow_mut method has been removed as it can be used to bypass Rust's borrow checker and get, for exampl
Mutex.borrow_mut method has been
removed as it can be used to bypass Rust's borrow checker and get, for
example, two mutable references to the same data.static FOO: Mutex<bool> = Mutex::new(false);
fn main() {
cortex_m::interrupt::free(|mut cs1| {
cortex_m::interrupt::free(|mut cs2| {
let foo: &mut bool = FOO.borrow_mut(&mut cs1);
let and_foo: &mut bool = FOO.borrow_mut(&mut cs2);
});
});
}
The default exception handler now identifies the exception that's being serviced.
Semihosting functionality in the semihosting module.
Semihosting functionality in the semihosting module.
exception::Handlers struct that represent the section of the vector table
that contains the exception handlers.
A default exception handler
A high level API for the NVIC peripheral.
Context local data.
borrow/borrow_mut methods to Mutex that replace lock.
API and macros to send bytes / (formatted) strings through ITM
[breaking-change] StackFrame has been renamed to StackedRegisters and
moved into the exceptions module.
[breaking-change] Core peripherals can now be modified via a &- reference
and are no longer Sync.
[breaking-change] interrupt::free's closure now includes a critical section
token, CriticalSection.
[breaking-change] the core register API has been revamped for type safety.
The safety of assembly wrappers like wfi and interrupt::free has been
reviewed. In many cases, the functions are no longer unsafe.
[breaking-change] bkpt! has been turned into a function. It no longer
accepts an immediate value.
vector_table and its associated struct, VectorTable. It's not a good
idea to give people a simple way to call the exception handlers.
Mutex's lock method as it's unsound. You could use it to get multiple
&mut - references to the wrapped data.
Nothing published for this version
Nothing published for this version
Exception a enumeration of the kind of exceptions the processor can service. There's also a Exception::current constructor that returns the Exception
Exception a enumeration of the kind of exceptions the processor can service.
There's also a Exception::current constructor that returns the Exception
that's currently being serviced.interrupt::Mutex, a "mutex" based on critical sections.
interrupt::Mutex, a "mutex" based on critical sections.interrupt::free takes can now return a value.asm::nop, a wrapper over the NOP instruction
asm::nop, a wrapper over the NOP instruction### Added - a StackFrame data structure
Read/write Operations on registers (lr, cr, msp, etc.) which were reversed.
Small, non user visible change to make this crate compile further for $HOST (e.g. x86_64) with the goal of making it possible to test, on the HOST, do
Functions to access core peripherals like NVIC, SCB and SysTick.
bkptYour coding agent can read these notes before it upgrades. Set up the MCP server →