diff options
author | 2020-12-02 15:19:30 +0000 | |
---|---|---|
committer | 2020-12-02 15:19:30 +0000 | |
commit | 038396e6f944fb8697e2d4ecbd88cfca9d16b90e (patch) | |
tree | 7eb1e4514b8159b7e1657626dc27a45131b227b9 | |
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>
-rw-r--r-- | CHANGELOG.md | 5 | ||||
-rw-r--r-- | asm/inline.rs | 22 | ||||
-rw-r--r-- | asm/lib.rs | 5 | ||||
-rw-r--r-- | bin/thumbv6m-none-eabi-lto.a | bin | 15124 -> 15860 bytes | |||
-rw-r--r-- | bin/thumbv6m-none-eabi.a | bin | 17944 -> 18580 bytes | |||
-rw-r--r-- | bin/thumbv7em-none-eabi-lto.a | bin | 19372 -> 20004 bytes | |||
-rw-r--r-- | bin/thumbv7em-none-eabi.a | bin | 22340 -> 23008 bytes | |||
-rw-r--r-- | bin/thumbv7em-none-eabihf-lto.a | bin | 20356 -> 20868 bytes | |||
-rw-r--r-- | bin/thumbv7em-none-eabihf.a | bin | 23424 -> 24096 bytes | |||
-rw-r--r-- | bin/thumbv7m-none-eabi-lto.a | bin | 18120 -> 18796 bytes | |||
-rw-r--r-- | bin/thumbv7m-none-eabi.a | bin | 21172 -> 21840 bytes | |||
-rw-r--r-- | bin/thumbv8m.base-none-eabi-lto.a | bin | 18384 -> 19136 bytes | |||
-rw-r--r-- | bin/thumbv8m.base-none-eabi.a | bin | 21640 -> 22280 bytes | |||
-rw-r--r-- | bin/thumbv8m.main-none-eabi-lto.a | bin | 23044 -> 23504 bytes | |||
-rw-r--r-- | bin/thumbv8m.main-none-eabi.a | bin | 26992 -> 27664 bytes | |||
-rw-r--r-- | bin/thumbv8m.main-none-eabihf-lto.a | bin | 24028 -> 24388 bytes | |||
-rw-r--r-- | bin/thumbv8m.main-none-eabihf.a | bin | 28040 -> 28712 bytes | |||
-rw-r--r-- | src/asm.rs | 45 |
18 files changed, 74 insertions, 3 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 142a63f..e6d8ef7 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::semihosting_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..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::*; @@ -69,10 +69,11 @@ shims! { fn __psp_r() -> u32; fn __psp_w(val: u32); fn __sev(); - fn __udf(); + 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 diff --git a/bin/thumbv6m-none-eabi-lto.a b/bin/thumbv6m-none-eabi-lto.a Binary files differindex 74cee4d..f3858a0 100644 --- a/bin/thumbv6m-none-eabi-lto.a +++ b/bin/thumbv6m-none-eabi-lto.a diff --git a/bin/thumbv6m-none-eabi.a b/bin/thumbv6m-none-eabi.a Binary files differindex d53c97a..571396b 100644 --- a/bin/thumbv6m-none-eabi.a +++ b/bin/thumbv6m-none-eabi.a diff --git a/bin/thumbv7em-none-eabi-lto.a b/bin/thumbv7em-none-eabi-lto.a Binary files differindex 919e00b..51e02c6 100644 --- a/bin/thumbv7em-none-eabi-lto.a +++ b/bin/thumbv7em-none-eabi-lto.a diff --git a/bin/thumbv7em-none-eabi.a b/bin/thumbv7em-none-eabi.a Binary files differindex b8ba53c..d6ccf53 100644 --- a/bin/thumbv7em-none-eabi.a +++ b/bin/thumbv7em-none-eabi.a diff --git a/bin/thumbv7em-none-eabihf-lto.a b/bin/thumbv7em-none-eabihf-lto.a Binary files differindex 68dd787..cc52e63 100644 --- a/bin/thumbv7em-none-eabihf-lto.a +++ b/bin/thumbv7em-none-eabihf-lto.a diff --git a/bin/thumbv7em-none-eabihf.a b/bin/thumbv7em-none-eabihf.a Binary files differindex 7d7349f..aea284d 100644 --- a/bin/thumbv7em-none-eabihf.a +++ b/bin/thumbv7em-none-eabihf.a diff --git a/bin/thumbv7m-none-eabi-lto.a b/bin/thumbv7m-none-eabi-lto.a Binary files differindex a65077c..85720da 100644 --- a/bin/thumbv7m-none-eabi-lto.a +++ b/bin/thumbv7m-none-eabi-lto.a diff --git a/bin/thumbv7m-none-eabi.a b/bin/thumbv7m-none-eabi.a Binary files differindex 59f5da2..d9cf989 100644 --- a/bin/thumbv7m-none-eabi.a +++ b/bin/thumbv7m-none-eabi.a diff --git a/bin/thumbv8m.base-none-eabi-lto.a b/bin/thumbv8m.base-none-eabi-lto.a Binary files differindex b683c22..37e74a9 100644 --- a/bin/thumbv8m.base-none-eabi-lto.a +++ b/bin/thumbv8m.base-none-eabi-lto.a diff --git a/bin/thumbv8m.base-none-eabi.a b/bin/thumbv8m.base-none-eabi.a Binary files differindex 87560a3..0660245 100644 --- a/bin/thumbv8m.base-none-eabi.a +++ b/bin/thumbv8m.base-none-eabi.a diff --git a/bin/thumbv8m.main-none-eabi-lto.a b/bin/thumbv8m.main-none-eabi-lto.a Binary files differindex b4fd6fc..4312c64 100644 --- a/bin/thumbv8m.main-none-eabi-lto.a +++ b/bin/thumbv8m.main-none-eabi-lto.a diff --git a/bin/thumbv8m.main-none-eabi.a b/bin/thumbv8m.main-none-eabi.a Binary files differindex 5ea8f33..59affcc 100644 --- a/bin/thumbv8m.main-none-eabi.a +++ b/bin/thumbv8m.main-none-eabi.a diff --git a/bin/thumbv8m.main-none-eabihf-lto.a b/bin/thumbv8m.main-none-eabihf-lto.a Binary files differindex 87fdb8a..62fcad3 100644 --- a/bin/thumbv8m.main-none-eabihf-lto.a +++ b/bin/thumbv8m.main-none-eabihf-lto.a diff --git a/bin/thumbv8m.main-none-eabihf.a b/bin/thumbv8m.main-none-eabihf.a Binary files differindex 29d6381..f7795d1 100644 --- a/bin/thumbv8m.main-none-eabihf.a +++ b/bin/thumbv8m.main-none-eabihf.a @@ -164,3 +164,48 @@ pub fn ttat(addr: *mut u32) -> u32 { pub unsafe fn bx_ns(addr: u32) { call_asm!(__bxns(addr: u32)); } + +/// Semihosting syscall. +/// +/// This method is used by cortex-m-semihosting to provide semihosting syscalls. +#[inline] +pub unsafe fn semihosting_syscall(nr: u32, arg: u32) -> u32 { + call_asm!(__sh_syscall(nr: u32, arg: u32) -> u32) +} + +/// Bootstrap. +/// +/// Clears CONTROL.SPSEL (setting the main stack to be the active stack), +/// updates the main stack pointer to the address in `msp`, then jumps +/// to the address in `rv`. +/// +/// # Safety +/// +/// `msp` and `rv` must point to valid stack memory and executable code, +/// respectively. +#[inline] +pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! { + // Ensure thumb mode is set. + let rv = (rv as u32) | 1; + let msp = msp as u32; + call_asm!(__bootstrap(msp: u32, rv: u32) -> !); +} + +/// 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, 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 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); +} |