All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
critical-section-single-core
feature added in v0.7.6.critical-section-single-core
feature which provides an implementation for the critical-section
crate for single-core systems, based on disabling all interrupts. (#448)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.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)Delay
struct now offers direct delay_us()
and delay_ms()
methods without having to go through the embedded-hal traits (#344).asm::delay()
with an argument of 0 or 1 would underflow, leading to a very long delay.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.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_pending
NVIC::disable
NVIC::enable
NVIC::set_pending
SCB::system_reset
basepri
, basepri_max
, and faultmask
registers from thumbv8m.baseperipheral::itm
reexport.thumbv8m.base
targets.aligned
dependency.UDF
intrinsicasm::delay
not updating status clobber flagsllvm_asm!
to support inline assembly on new nightliesis_fifo_ready
improved to support armv8CONTROL
register via register::control::write
DWT::unlock()
for a safe way to unlock the DWTBASPRI
, BASEPRI_MAX
, FAULTMASK
) on thumbv8.base
Debug
, PartialEq
and Eq
for more typesdelay
function is fixed for Cortex-M0 MCUssystem_reset
as system_reset2
links = "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_reset
SHCRS
renamed to SHCSR
in SCB
Support 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
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()
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
The check-blobs.sh script
arm-none-eabi-gcc
.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.
clang
as the assembler.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.
"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.
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.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.Send
implementation to all the peripherals.peripheral::Peripherals
is now re-exported at the root of the crate.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 take
n 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 sections.[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.ehprint!
macro.asm
module are now inline(always)
itm::write_all
where it would ignore the length of the buffer and serialize contents that come after the buffer.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.Dwt.enable_cycle_counter
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 };
interrupt::enable
was safe to call inside an interrupt::free
critical section thus breaking the preemption protection. The interrupt::enable
method is now unsafe
.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); }
NVIC.set_priority
and register::basepri::write
are now unsafe
.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); }); }); }
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.
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::free
takes can now return a value.asm::nop
, a wrapper over the NOP instructionbkpt