Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cortex-m-rt/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Mark `pre_init` as deprecated
- Add `set_msplim` feature to conditionally set the MSPLIM register at device
reset ([#580]).
- Add `skip-data-init` feature to optionally skip copying the `.data` section.

## [v0.7.5]

Expand Down
1 change: 1 addition & 0 deletions cortex-m-rt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ set-vtor = []
set-msplim = []
zero-init-ram = []
paint-stack = []
skip-data-init = []

[package.metadata.docs.rs]
features = ["device"]
38 changes: 38 additions & 0 deletions cortex-m-rt/examples/skip-data-init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//! Example demonstrating the skip-data-init feature
//!
//! This feature is useful when using bootloaders (like RP2040's boot2) that:
//! 1. Copy all data from Flash to RAM
//! 2. Unmap the Flash from memory space
//! 3. Jump to the Reset handler
//!
//! In such scenarios, the default cortex-m-rt data initialization would fail
//! because it tries to copy from Flash which is no longer accessible.
//!
//! To use this feature, enable it in your Cargo.toml:
//! ```toml
//! [dependencies]
//! cortex-m-rt = { version = "0.7", features = ["skip-data-init"] }
//! ```
//!
//! And ensure your bootloader or linker script properly initializes .data before
//! jumping to Reset.
#![no_main]
#![no_std]

use panic_halt as _;

use cortex_m_rt::entry;

static mut COUNTER: u32 = 42;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be put into local scope or replaced by an atomic to avoid unsafe code?


#[entry]
fn main() -> ! {
unsafe {
COUNTER += 1;
}

Copy link

@robamu robamu Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you just print the counter using semihosting printout?

Also, what about panicking if the output is not the expected value?

loop {
cortex_m::asm::nop();
}
}
28 changes: 28 additions & 0 deletions cortex-m-rt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,30 @@
//! where the stack has been used the 'paint' will have been 'scrubbed off' and the memory will
//! have a value other than `STACK_PAINT_VALUE`.
//!
//! ## `skip-data-init`
//!
//! If this feature is enabled, the `.data` section initialization is skipped during startup.
//! By default, cortex-m-rt copies the `.data` section from its load address (LMA) in Flash
//! to its virtual address (VMA) in RAM. However, in some scenarios this copy is unnecessary
//! or undesirable:
//!
//! - When using bootloaders like RP2040's boot2 that copy all data from Flash to RAM and then
//! unmap the Flash, the cortex-m-rt data initialization would fail because Flash is no longer
//! accessible.
//! - When the `.data` section is already placed in RAM at the correct address (LMA equals VMA).
//!
//! When this feature is enabled, it is the user's responsibility to ensure that the `.data`
//! section is properly initialized before the program's main function is called. This can be
//! done by:
//!
//! - Using a bootloader that copies the data before jumping to the Reset handler
//! - Setting `__sidata = ADDR(.data)` in the linker script to make LMA equal to VMA (though this
//! wastes Flash space)
//! - Other custom initialization mechanisms
//!
//! **WARNING:** Using this feature without ensuring proper `.data` initialization will result
//! in undefined behavior if your program uses initialized static variables.
//!
//! # Inspection
//!
//! This section covers how to inspect a binary that builds on top of `cortex-m-rt`.
Expand Down Expand Up @@ -489,6 +513,9 @@
#![deny(missing_docs)]
#![no_std]

#[cfg(all(feature = "skip-data-init", feature = "zero-init-ram"))]
compile_error!("features `skip-data-init` and `zero-init-ram` cannot be enabled at the same time");

extern crate cortex_m_rt_macros as macros;

/// The 32-bit value the stack is painted with before the program runs.
Expand Down Expand Up @@ -603,6 +630,7 @@ cfg_global_asm! {
1:",

// Initialise .data memory. `__sdata`, `__sidata`, and `__edata` come from the linker script.
#[cfg(not(feature = "skip-data-init"))]
"ldr r0, =__sdata
ldr r1, =__edata
ldr r2, =__sidata
Expand Down