Skip to content

Commit 43fdade

Browse files
bors[bot]japaric
andauthored
Merge #293
293: [ARMv6-M] initialize the LR register r=therealprof a=japaric NOTE: same as PR #292 the ARMv6-M Architecture Reference Manual (ARM DDI 0419D) indicates in section B1.5.5 "Reset behavior" that the LR (Link Register) starts in an unknown state when the Reset handler is taken and that its "Value must be initialised by software" So this PR does that: it initializes the LR register to 0xFFFF_FFFF (-1) first thing in the Reset handler (only for v6). The manual doesn't say which value to use so I decided to use the value used by the ARMv7-M (v7 sets LR to 0xFFFF_FFFF before invoking the Reset handler; see its Architecture Manual for details). The values of LR (these are pushed onto the stack in function preludes) are used to unwind the stack (e.g. GDB's `backtrace` or a future `cortex_m_panic_unwind` handler). Having the initial stack frame use a known value on all Cortex-M variants makes it easier to implement `panic_unwind` and avoids virtual unwinders like GDB `backtrace` trying to unwind beyond the `Reset` handler Note that this implementation uses a trampoline that runs before `Reset` to set LR on v6. This is required because the prelude of the `Reset` routine will push LR onto the stack; we want that LR value to be -1. Calling `register::lr::write` from `Reset` would perform the write after LR has been pushed onto the stack and that's too late Co-authored-by: Jorge Aparicio <[email protected]>
2 parents d53d096 + 965a6d2 commit 43fdade

10 files changed

+29
-0
lines changed

cortex-m-rt/asm.s

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,17 @@ FpuTrampoline:
4040
# Hand execution over to `main`.
4141
bl main
4242
# Note: `main` must not return. `bl` is used only because it has a wider range than `b`.
43+
44+
# ARMv6-M leaves LR in an unknown state on Reset
45+
# this trampoline sets LR before it's pushed onto the stack by Reset
46+
.section .PreResetTrampoline, "ax"
47+
.global PreResetTrampoline
48+
# .type and .thumb_func are both required; otherwise its Thumb bit does not
49+
# get set and an invalid vector table is generated
50+
.type PreResetTrampoline,%function
51+
.thumb_func
52+
PreResetTrampoline:
53+
# set LR to the initial value used by the ARMv7-M (0xFFFF_FFFF)
54+
ldr r0,=0xffffffff
55+
mov lr,r0
56+
b Reset

cortex-m-rt/bin/thumbv6m-none-eabi.a

272 Bytes
Binary file not shown.

cortex-m-rt/bin/thumbv7em-none-eabi.a

236 Bytes
Binary file not shown.
236 Bytes
Binary file not shown.

cortex-m-rt/bin/thumbv7m-none-eabi.a

236 Bytes
Binary file not shown.
272 Bytes
Binary file not shown.
236 Bytes
Binary file not shown.
236 Bytes
Binary file not shown.

cortex-m-rt/link.x.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ SECTIONS
8585
/* ### .text */
8686
.text _stext :
8787
{
88+
/* place these 2 close to each other or the `b` instruction will fail to link */
89+
*(.PreResetTrampoline);
90+
*(.Reset);
91+
8892
*(.text .text.*);
8993
*(.HardFaultTrampoline);
9094
*(.HardFault.*);

cortex-m-rt/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,9 +923,17 @@ pub fn heap_start() -> *mut u32 {
923923
#[doc(hidden)]
924924
#[link_section = ".vector_table.reset_vector"]
925925
#[no_mangle]
926+
#[cfg(not(armv6m))]
926927
pub static __RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset;
927928

928929
#[doc(hidden)]
930+
#[link_section = ".vector_table.reset_vector"]
931+
#[no_mangle]
932+
#[cfg(armv6m)]
933+
pub static __RESET_VECTOR: unsafe extern "C" fn() -> ! = PreResetTrampoline;
934+
935+
#[doc(hidden)]
936+
#[link_section = ".Reset"]
929937
#[no_mangle]
930938
pub unsafe extern "C" fn Reset() -> ! {
931939
extern "C" {
@@ -1030,6 +1038,9 @@ pub enum Exception {
10301038
pub use self::Exception as exception;
10311039

10321040
extern "C" {
1041+
#[cfg(armv6m)]
1042+
fn PreResetTrampoline() -> !;
1043+
10331044
fn NonMaskableInt();
10341045

10351046
fn HardFaultTrampoline();

0 commit comments

Comments
 (0)