diff options
author | 2020-12-02 15:19:30 +0000 | |
---|---|---|
committer | 2020-12-02 15:19:30 +0000 | |
commit | 038396e6f944fb8697e2d4ecbd88cfca9d16b90e (patch) | |
tree | 7eb1e4514b8159b7e1657626dc27a45131b227b9 /asm/inline.rs | |
parent | d34b1ce3eda92777ba9bafe2fca96e1985ec6d72 (diff) | |
parent | 64842461ba4caa384487ae52cbe15a4f3834b4b4 (diff) | |
download | cortex-m-038396e6f944fb8697e2d4ecbd88cfca9d16b90e.tar.gz cortex-m-038396e6f944fb8697e2d4ecbd88cfca9d16b90e.tar.zst cortex-m-038396e6f944fb8697e2d4ecbd88cfca9d16b90e.zip |
Merge #299
299: Expose __syscall and add new bootstrap method r=jonas-schievink a=adamgreig
We added `__syscall` in the new inline asm, but did not expose it in the crate API, and the cortex-m-semihosting crate can't use it directly because the pre-built binaries would contain duplicate symbols (#271). This PR renames it to `__sh_syscall` (since we could imagine other different syscalls; this one is explicitly semihosting with the `bkpt 0xAB`) and exposes it in `cortex_m::asm::sh_syscall`.
This PR also adds the new methods discussed in #297 to permit sound bootstrapping, either from an MSP and RV or a vector table address.
Co-authored-by: Adam Greig <adam@adamgreig.com>
Diffstat (limited to 'asm/inline.rs')
-rw-r--r-- | asm/inline.rs | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/asm/inline.rs b/asm/inline.rs index f6a3ebb..f2014f8 100644 --- a/asm/inline.rs +++ b/asm/inline.rs @@ -177,11 +177,31 @@ 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 } +/// Set CONTROL.SPSEL to 0, write `msp` to MSP, branch to `rv`. +#[inline(always)] +pub unsafe fn __bootstrap(msp: u32, rv: u32) -> ! { + asm!( + "mrs {tmp}, CONTROL", + "bics {tmp}, {spsel}", + "msr CONTROL, {tmp}", + "isb", + "msr MSP, {msp}", + "bx {rv}", + // `out(reg) _` is not permitted in a `noreturn` asm! call, + // so instead use `in(reg) 0` and don't restore it afterwards. + tmp = in(reg) 0, + spsel = in(reg) 2, + msp = in(reg) msp, + rv = in(reg) rv, + options(noreturn), + ); +} + // v7m *AND* v8m.main, but *NOT* v8m.base #[cfg(any(armv7m, armv8m_main))] pub use self::v7m::*; |