diff --git a/riscv-rt/CHANGELOG.md b/riscv-rt/CHANGELOG.md index 3ce8123c..d816a0f3 100644 --- a/riscv-rt/CHANGELOG.md +++ b/riscv-rt/CHANGELOG.md @@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). linker will place this new section in `REGION_BSS`. - Additional feature `no-xie-xip` to work on chips without the XIE and XIP CSRs (e.g. ESP32-C2, ESP32-C3) - Additional feature `defmt` which will implement `defmt::Format` on certain types - +- Additional feature `pre-default-start-trap` to execute custom code before `_default_start_trap` ### Changed - `main` function no longer needs to be close to `_start`. A linker script may copy diff --git a/riscv-rt/Cargo.toml b/riscv-rt/Cargo.toml index b6a3f83d..28c57bf9 100644 --- a/riscv-rt/Cargo.toml +++ b/riscv-rt/Cargo.toml @@ -46,3 +46,4 @@ no-xie-xip = [] device = [] memory = [] defmt = ["dep:defmt"] +pre-default-start-trap = ["riscv-rt-macros/pre-default-start-trap"] diff --git a/riscv-rt/macros/Cargo.toml b/riscv-rt/macros/Cargo.toml index 29be4502..837cfcaf 100644 --- a/riscv-rt/macros/Cargo.toml +++ b/riscv-rt/macros/Cargo.toml @@ -25,3 +25,4 @@ syn = { version = "2.0", features = ["extra-traits", "full"] } s-mode = [] v-trap = [] u-boot = [] +pre-default-start-trap = [] diff --git a/riscv-rt/macros/src/lib.rs b/riscv-rt/macros/src/lib.rs index d174a9bb..9c0ca2b2 100644 --- a/riscv-rt/macros/src/lib.rs +++ b/riscv-rt/macros/src/lib.rs @@ -606,6 +606,16 @@ pub fn default_start_trap(_input: TokenStream) -> TokenStream { #[cfg(not(feature = "s-mode"))] let ret = "mret"; + let pre_default_start_trap = if cfg!(feature = "pre-default-start-trap") { + r#" + j _pre_default_start_trap +.global _pre_default_start_trap_ret +_pre_default_start_trap_ret: + "# + } else { + "" + }; + format!( r#" core::arch::global_asm!( @@ -613,6 +623,7 @@ core::arch::global_asm!( .balign 4 /* Alignment required for xtvec */ .global _default_start_trap _default_start_trap: + {pre_default_start_trap} addi sp, sp, - {trap_size} * {width} {store} add a0, sp, zero diff --git a/riscv-rt/src/lib.rs b/riscv-rt/src/lib.rs index f15f2aa4..4c3b79b5 100644 --- a/riscv-rt/src/lib.rs +++ b/riscv-rt/src/lib.rs @@ -598,6 +598,38 @@ //! because when booting from elf, U-boot passes `argc` and `argv`. This feature also implies `single-hart`. //! The only way to get boot-hart is through fdt, so other harts initialization is up to you. //! +//! ## `pre-default-start-trap` +//! +//! This provides a mechanism to execute custom code prior to `_default_start_trap`. +//! +//! To use it, the user must define a symbol named `_pre_default_start_trap`, which the system will jump to. +//! After executing the custom code, control should return by jumping to `_pre_default_start_trap_ret`. +//! +//! It's recommended to place the code in the `.trap.start` section to make sure it's reachable from `_default_start_trap`. +//! +//! It is expected that the custom code does not clobber any registers. +//! +//! Please note that your code won't be run for interrupts in vectored mode. +//! +//! ### Example +//! +//! ```rust,no_run +//! core::arch::global_asm!( +//! r#" +//! .section .trap.start, "ax" +//! .extern _pre_default_start_trap_ret +//! .global _pre_default_start_trap +//! +//! _pre_default_start_trap: +//! +//! // your code goes here remember to not clobber any registers, +//! // use mscratch to retain a single register if needed +//! +//! // jump back to continue with _default_start_trap +//! j _pre_default_start_trap_ret +//! "# +//! ); +//! ``` //! [attr-entry]: attr.entry.html //! [attr-exception]: attr.exception.html //! [attr-external-interrupt]: attr.external_interrupt.html