diff options
author | 2020-12-02 01:17:53 +0000 | |
---|---|---|
committer | 2020-12-02 01:17:53 +0000 | |
commit | 4a1c82fe37e05223951595648a74792cdc3c2179 (patch) | |
tree | 50e8e4faeeeaa462a360bfa074f94b1e4b4851d8 | |
parent | 5910cbeac5882670e6a1fd906e21ebcbcced2f83 (diff) | |
download | cortex-m-4a1c82fe37e05223951595648a74792cdc3c2179.tar.gz cortex-m-4a1c82fe37e05223951595648a74792cdc3c2179.tar.zst cortex-m-4a1c82fe37e05223951595648a74792cdc3c2179.zip |
Expose __syscall and add new bootstrap method
-rw-r--r-- | CHANGELOG.md | 5 | ||||
-rw-r--r-- | asm/inline.rs | 16 | ||||
-rw-r--r-- | asm/lib.rs | 3 | ||||
-rw-r--r-- | src/asm.rs | 41 |
4 files changed, 63 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 142a63f..065d620 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added + +- New assembly methods `asm::sh_syscall`, `asm::bootstrap`, and + `asm::bootload`. + ## [v0.7.0] - 2020-11-09 ### Added diff --git a/asm/inline.rs b/asm/inline.rs index f6a3ebb..bba5e6e 100644 --- a/asm/inline.rs +++ b/asm/inline.rs @@ -177,11 +177,25 @@ pub unsafe fn __wfi() { /// Semihosting syscall. #[inline(always)] -pub unsafe fn __syscall(mut nr: u32, arg: u32) -> u32 { +pub unsafe fn __sh_syscall(mut nr: u32, arg: u32) -> u32 { asm!("bkpt #0xab", inout("r0") nr, in("r1") arg); nr } +/// Bootstrap: ensure we are using the main stack, then write `msp` to MSP and jump to `rv`. +#[inline(always)] +pub unsafe fn __bootstrap(msp: u32, rv: u32) { + asm!( + "msr CONTROL, {}", + "isb", + "msr MSP, {}", + "bx {}", + in(reg) 0, + in(reg) msp, + in(reg) rv, + ); +} + // v7m *AND* v8m.main, but *NOT* v8m.base #[cfg(any(armv7m, armv8m_main))] pub use self::v7m::*; @@ -72,7 +72,8 @@ shims! { fn __udf(); fn __wfe(); fn __wfi(); - fn __syscall(nr: u32, arg: u32) -> u32; + fn __sh_syscall(nr: u32, arg: u32) -> u32; + fn __bootstrap(msp: u32, rv: u32); } // v7m *AND* v8m.main, but *NOT* v8m.base @@ -164,3 +164,44 @@ pub fn ttat(addr: *mut u32) -> u32 { pub unsafe fn bx_ns(addr: u32) { call_asm!(__bxns(addr: u32)); } + +/// Semihosing syscall. +/// +/// This method is used by cortex-m-semihosting to provide semihosting syscalls. +#[inline] +pub unsafe fn sh_syscall(nr: u32, arg: u32) -> u32 { + call_asm!(__sh_syscall(nr: u32, arg: u32) -> u32) +} + +/// Bootstrap. +/// +/// Sets the active stack to the main stack, updates the main stack pointer to `msp`, +/// then jumps execution to the address in `rv`. +/// Writes `msp` to the MSP special register, then jumps to the address in `rv`. +#[inline] +pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! { + let msp = msp as u32; + let rv = rv as u32; + call_asm!(__bootstrap(msp: u32, rv: u32)); + core::hint::unreachable_unchecked(); +} + +/// Bootload. +/// +/// Reads the initial stack pointer value and reset vector from +/// the provided vector table address, sets the active stack to +/// the main stack, sets the main stack pointer to the new initial +/// stack pointer view, then jumps to the reset vector. +/// +/// # Safety +/// +/// The provided `vector_table` must point to a valid vector +/// table, with a valid stack pointer as the first word and +/// a valid reset vector (in thumb mode, with the least significant +/// bit cleared) as the second word. +#[inline] +pub unsafe fn bootload(vector_table: *const u32) -> ! { + let msp = core::ptr::read_volatile(vector_table); + let rv = core::ptr::read_volatile(vector_table.offset(1)); + bootstrap(msp as *const u32, rv as *const u32); +} |