Skip to content

cortex-m-rt: Add optional MSPLIM initialization, fix vector table size on armv8m #580

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 18, 2025
Merged
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
3 changes: 3 additions & 0 deletions cortex-m-rt/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

- Add `set_msplim` feature to conditionally set the MSPLIM register at device
reset ([#580]).

## [v0.7.5]

- Fix incorrect dependency on cortex-m-rt-macros in v0.7.4 which led to
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 @@ -45,6 +45,7 @@ required-features = ["device"]
device = []
set-sp = []
set-vtor = []
set-msplim = []
zero-init-ram = []
paint-stack = []

Expand Down
20 changes: 17 additions & 3 deletions cortex-m-rt/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,37 @@ INCLUDE device.x"#
};

println!("cargo:rustc-check-cfg=cfg(armv6m)");
println!("cargo:rustc-check-cfg=cfg(armv7em)");
println!("cargo:rustc-check-cfg=cfg(armv7m)");
println!("cargo:rustc-check-cfg=cfg(armv8m)");
println!("cargo:rustc-check-cfg=cfg(armv8m_base)");
println!("cargo:rustc-check-cfg=cfg(armv8m_main)");
println!("cargo:rustc-check-cfg=cfg(cortex_m)");
println!("cargo:rustc-check-cfg=cfg(has_fpu)");

let max_int_handlers = if target.starts_with("thumbv6m-") {
println!("cargo:rustc-cfg=cortex_m");
println!("cargo:rustc-cfg=armv6m");
32
} else if target.starts_with("thumbv7m-") || target.starts_with("thumbv7em-") {
} else if target.starts_with("thumbv7m-") {
println!("cargo:rustc-cfg=cortex_m");
println!("cargo:rustc-cfg=armv7m");
240
} else if target.starts_with("thumbv8m") {
} else if target.starts_with("thumbv7em-") {
println!("cargo:rustc-cfg=cortex_m");
println!("cargo:rustc-cfg=armv7m");
println!("cargo:rustc-cfg=armv7em");
240
} else if target.starts_with("thumbv8m.base") {
println!("cargo:rustc-cfg=cortex_m");
println!("cargo:rustc-cfg=armv8m");
println!("cargo:rustc-cfg=armv8m_base");
240
} else if target.starts_with("thumbv8m.main") {
println!("cargo:rustc-cfg=cortex_m");
println!("cargo:rustc-cfg=armv8m");
496
println!("cargo:rustc-cfg=armv8m_main");
480
} else {
// Non ARM target. We assume you're just testing the syntax.
// This value seems as good as any.
Expand Down
27 changes: 21 additions & 6 deletions cortex-m-rt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,13 @@
//! required, but some bootloaders do not set VTOR before jumping to application code, leading to
//! your main function executing but interrupt handlers not being used.
//!
//! ## `set-msplim`
//!
//! If this feature is enabled, the main stack pointer limit register (MSPLIM) is initialized in
//! the reset handler to the `_stack_end` value from the linker script. This feature is only
//! available on ARMv8-M Mainline and helps enforce stack limits by defining the lowest valid
//! stack address.
//!
//! ## `zero-init-ram`
//!
//! If this feature is enabled, RAM is initialized with zeros during startup from the `_ram_start`
Expand Down Expand Up @@ -266,7 +273,8 @@
//!
//! - `__INTERRUPTS`. This is the device specific interrupt portion of the vector table; its exact
//! size depends on the target device but if the `"device"` feature has not been enabled it will
//! have a size of 32 vectors (on ARMv6-M), 240 vectors (on ARMv7-M) or 496 vectors (on ARMv8-M).
//! have a size of 32 vectors (on ARMv6-M), 240 vectors (on ARMv7-M, ARMv8-M Baseline) or 480
//! vectors (on ARMv8-M Mainline).
//! This array is located after `__EXCEPTIONS` in the `.vector_table` section.
//!
//! - `__pre_init`. This is a function to be run before RAM is initialized. It defaults to an empty
Expand Down Expand Up @@ -544,6 +552,13 @@ cfg_global_asm! {
ldr r1, =__vector_table
str r1, [r0]",

// If enabled, set the Main Stack Pointer Limit (MSPLIM) to the end of the stack.
// This feature is only available on ARMv8-M Mainline, where it helps enforce stack limits
// by defining the lowest valid stack address.
#[cfg(all(armv8m_main, feature = "set-msplim"))]
"ldr r0, =_stack_end
msr MSPLIM, r0",

// Run user pre-init code which must be executed immediately after startup, before the
// potentially time-consuming memory initialisation takes place.
// Example use cases include disabling default watchdogs or enabling RAM.
Expand Down Expand Up @@ -1245,7 +1260,7 @@ pub static __EXCEPTIONS: [Vector; 14] = [

// If we are not targeting a specific device we bind all the potential device specific interrupts
// to the default handler
#[cfg(all(any(not(feature = "device"), test), not(armv6m), not(armv8m)))]
#[cfg(all(any(not(feature = "device"), test), not(armv6m), not(armv8m_main)))]
#[doc(hidden)]
#[cfg_attr(cortex_m, link_section = ".vector_table.interrupts")]
#[no_mangle]
Expand All @@ -1257,18 +1272,18 @@ pub static __INTERRUPTS: [unsafe extern "C" fn(); 240] = [{
DefaultHandler
}; 240];

// ARMv8-M can have up to 496 device specific interrupts
#[cfg(all(not(feature = "device"), armv8m))]
// ARMv8-M Mainline can have up to 480 device specific interrupts
#[cfg(all(not(feature = "device"), armv8m_main))]
#[doc(hidden)]
#[cfg_attr(cortex_m, link_section = ".vector_table.interrupts")]
#[no_mangle]
pub static __INTERRUPTS: [unsafe extern "C" fn(); 496] = [{
pub static __INTERRUPTS: [unsafe extern "C" fn(); 480] = [{
extern "C" {
fn DefaultHandler();
}

DefaultHandler
}; 496];
}; 480];

// ARMv6-M can only have a maximum of 32 device specific interrupts
#[cfg(all(not(feature = "device"), armv6m))]
Expand Down