Skip to content

Commit 69b56a2

Browse files
committed
feature-gate pre-init
1 parent ceda84d commit 69b56a2

File tree

8 files changed

+46
-13
lines changed

8 files changed

+46
-13
lines changed

riscv-rt/CHANGELOG.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1717
The benefits of leaving this optional are backwards compatibility and
1818
allowing users to define less typical linker scripts that do not rely on a
1919
`device.x` or `memory.x` file.
20+
- New `pre-init` feature to run a `__pre_init` function before RAM initialization.
2021

2122
### Changed
2223

@@ -34,10 +35,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
3435
- Replace weak definition of `_start_trap` with `PROVIDE(_start_trap = _default_start_trap)`.
3536
- Replace weak definition of `_setup_interrupts` with `PROVIDE(_setup_interrupts = _default_setup_interrupts)`.
3637
- Now, `_default_start_trap` is 4-byte aligned instead of target width-aligned.
38+
- Remove `__pre_init` function from default `riscv_rt`. Now, if users want a `__pre_init` function,
39+
they must enable the `pre-init` feature.
40+
- Deprecate `riscv_rt::pre_init` attribute macro. It is not sound to run Rust code before initializing the RAM.
41+
Instead, we recommend defining the `__pre_init` function with `core::arch::global_asm!`.
3742

3843
### Fixed
3944

40-
- New `clippy` fixes
45+
- `clippy` fixes
4146

4247
## [v0.14.0] - 2025-02-18
4348

riscv-rt/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ links = "riscv-rt" # Prevent multiple versions of riscv-rt being linked
1414

1515
[package.metadata.docs.rs]
1616
default-target = "riscv64imac-unknown-none-elf"
17+
features = ["pre-init"]
1718
targets = [
1819
"riscv32i-unknown-none-elf", "riscv32imc-unknown-none-elf", "riscv32imac-unknown-none-elf",
1920
"riscv64imac-unknown-none-elf", "riscv64gc-unknown-none-elf",
@@ -31,6 +32,7 @@ riscv-rt-macros = { path = "macros", version = "0.4.0" }
3132
panic-halt = "1.0.0"
3233

3334
[features]
35+
pre-init = []
3436
s-mode = ["riscv-rt-macros/s-mode"]
3537
single-hart = []
3638
v-trap = ["riscv-rt-macros/v-trap"]

riscv-rt/macros/src/lib.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,15 @@ fn is_correct_type(ty: &Type, name: &str) -> bool {
174174
}
175175

176176
/// Attribute to mark which function will be called at the beginning of the reset handler.
177+
/// You must enable the `pre_init` feature in the `riscv-rt` crate to use this macro.
177178
///
178-
/// **IMPORTANT**: This attribute can appear at most *once* in the dependency graph. Also, if you
179+
/// # IMPORTANT
180+
///
181+
/// This attribute is **deprecated**, as it is not safe to run Rust code **before** the static
182+
/// variables are initialized. The recommended way to run code before the static variables
183+
/// are initialized is to use the `global_asm!` macro to define the `__pre_init` function.
184+
///
185+
/// This attribute can appear at most *once* in the dependency graph. Also, if you
179186
/// are using Rust 1.30 the attribute must be used on a reachable item (i.e. there must be no
180187
/// private modules between the item and the root of the crate); if the item is in the root of the
181188
/// crate you'll be fine. This reachability restriction doesn't apply to Rust 1.31 and newer
@@ -197,6 +204,7 @@ fn is_correct_type(ty: &Type, name: &str) -> bool {
197204
///
198205
/// # fn main() {}
199206
/// ```
207+
#[deprecated(note = "Use global_asm! to define the __pre_init function instead")]
200208
#[proc_macro_attribute]
201209
pub fn pre_init(args: TokenStream, input: TokenStream) -> TokenStream {
202210
let f = parse_macro_input!(input as ItemFn);

riscv-rt/src/asm.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,11 @@ cfg_global_asm!(
141141
142142
beqz a0, 4f",
143143
);
144-
// IF CURRENT HART IS THE BOOT HART CALL __pre_init AND INITIALIZE RAM
144+
// IF CURRENT HART IS THE BOOT HART CALL __pre_init (IF ENABLED) AND INITIALIZE RAM
145145
cfg_global_asm!(
146-
"call __pre_init
147-
// Copy .data from flash to RAM
146+
#[cfg(feature = "pre-init")]
147+
"call __pre_init",
148+
"// Copy .data from flash to RAM
148149
la t0, __sdata
149150
la a0, __edata
150151
la t1, __sidata
@@ -221,11 +222,6 @@ cfg_global_asm!(
221222
);
222223

223224
cfg_global_asm!(
224-
// Default implementation of `__pre_init` does nothing.
225-
// Users can override this function with the [`#[pre_init]`] macro.
226-
".weak __pre_init
227-
__pre_init:
228-
ret",
229225
#[cfg(not(feature = "single-hart"))]
230226
// Default implementation of `_mp_hook` wakes hart 0 and busy-loops all the other harts.
231227
// Users can override this function by defining their own `_mp_hook`.

riscv-rt/src/interrupts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Interrupt handling for targets that comply with the RISC-V interrupt handling standard.
22
//!
33
//! In direct mode (i.e., `v-trap` feature disabled), interrupt dispatching is performed by the
4-
//! [`_dispatch_core_interrupt`] function. This function is called by the [crate::start_trap_rust]
4+
//! `_dispatch_core_interrupt` function. This function is called by the [crate::start_trap_rust]
55
//! whenever an interrupt is triggered. This approach relies on the [`__CORE_INTERRUPTS`] array,
66
//! which sorts all the interrupt handlers depending on their corresponding interrupt source code.
77
//!

riscv-rt/src/lib.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
//! - Before main initialization of the `.bss` and `.data` sections.
2424
//!
2525
//! - [`#[entry]`][attr-entry] to declare the entry point of the program
26-
//! - [`#[pre_init]`][attr-pre-init]to run code *before* `static` variables are initialized
2726
//! - [`#[exception]`][attr-exception] to override an exception handler.
2827
//! - [`#[core_interrupt]`][attr-core-interrupt] to override a core interrupt handler.
2928
//! - [`#[external_interrupt]`][attr-external-interrupt] to override an external interrupt handler.
@@ -476,6 +475,20 @@
476475
//!
477476
//! # Cargo Features
478477
//!
478+
//! ## `pre-init`
479+
//!
480+
//! The pre-init feature (`pre-init`) can be activated via [Cargo features](https://doc.rust-lang.org/cargo/reference/features.html).
481+
//! When enabled, the runtime will execute the `__pre_init` function to be run **before RAM is initialized**.
482+
//! If the feature is enabled, the `__pre_init` function must be defined in the user code (i.e., no default implementation is
483+
//! provided by this crate). If the feature is disabled, the `__pre_init` function is not required.
484+
//!
485+
//! As `__pre_init` runs before RAM is initialised, it is not sound to use a Rust function for `__pre_init`, and
486+
//! instead it should typically be written in assembly using `global_asm` or an external assembly file.
487+
//!
488+
//! Alternatively, you can use the [`#[pre_init]`][attr-pre-init] attribute to define a pre-init function with Rust.
489+
//! Note that using this macro is discouraged, as it may lead to undefined behavior.
490+
//! We left this option for backwards compatibility, but it is subject to removal in the future.
491+
//!
479492
//! ## `single-hart`
480493
//!
481494
//! The single hart feature (`single-hart) can be activated via [Cargo features](https://doc.rust-lang.org/cargo/reference/features.html).
@@ -570,7 +583,10 @@ use riscv::register::scause as xcause;
570583
use riscv::register::mcause as xcause;
571584

572585
pub use riscv_pac::*;
573-
pub use riscv_rt_macros::{core_interrupt, entry, exception, external_interrupt, pre_init};
586+
pub use riscv_rt_macros::{core_interrupt, entry, exception, external_interrupt};
587+
588+
#[cfg(feature = "pre-init")]
589+
pub use riscv_rt_macros::pre_init;
574590

575591
/// We export this static with an informative name so that if an application attempts to link
576592
/// two copies of riscv-rt together, linking will fail. We also declare a links key in

tests-build/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ riscv = { path = "../riscv", version = "0.13.0" }
99
riscv-rt = { path = "../riscv-rt", version = "0.14.0" }
1010

1111
[features]
12+
pre-init = ["riscv-rt/pre-init"]
1213
single-hart = ["riscv-rt/single-hart"]
1314
v-trap = ["riscv-rt/v-trap"]
1415
device = ["riscv-rt/device"]

tests-build/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,8 @@ pub enum Exception {
4141
LoadPageFault = 13,
4242
StorePageFault = 15,
4343
}
44+
45+
#[cfg(feature = "pre-init")]
46+
#[allow(deprecated)]
47+
#[cfg_attr(feature = "pre-init", riscv_rt::pre_init)]
48+
unsafe fn pre_init() {}

0 commit comments

Comments
 (0)