aboutsummaryrefslogtreecommitdiff
path: root/cortex-m-rt/asm.S
diff options
context:
space:
mode:
authorGravatar Adam Greig <adam@adamgreig.com> 2021-01-21 02:39:12 +0000
committerGravatar Jonas Schievink <jonasschievink@gmail.com> 2021-01-21 13:18:26 +0100
commit4426f26ab0aed70ae2cc433f55ee48f62d7eb46b (patch)
tree57a88f00c50b1f9d22c368c22ef828b8bd1b7d26 /cortex-m-rt/asm.S
parent0e82907ca384d10a7fb1f2b8cc70fdb58c0b2fcf (diff)
downloadcortex-m-4426f26ab0aed70ae2cc433f55ee48f62d7eb46b.tar.gz
cortex-m-4426f26ab0aed70ae2cc433f55ee48f62d7eb46b.tar.zst
cortex-m-4426f26ab0aed70ae2cc433f55ee48f62d7eb46b.zip
Update Reset-in-asm.
* Use arm-none-eabi-gcc to assemble, allowing use of preprocessor to conditionally enable the FPU for eabihf targets. * Remove has_fpu configuration from build.rs. * Remove FpuTrampoline as no longer required. * Remove the Rust Reset method entirely, since the asm Reset can now enable FPU and jump to user main.
Diffstat (limited to 'cortex-m-rt/asm.S')
-rw-r--r--cortex-m-rt/asm.S105
1 files changed, 105 insertions, 0 deletions
diff --git a/cortex-m-rt/asm.S b/cortex-m-rt/asm.S
new file mode 100644
index 0000000..6254129
--- /dev/null
+++ b/cortex-m-rt/asm.S
@@ -0,0 +1,105 @@
+ .cfi_sections .debug_frame
+
+ # Notes for function attributes:
+ # .type and .thumb_func are _both_ required, otherwise the Thumb mode bit
+ # will not be set and an invalid vector table is generated.
+ # LLD requires that section flags are set explicitly.
+
+ .section .HardFaultTrampoline, "ax"
+ .global HardFaultTrampoline
+ .type HardFaultTrampoline,%function
+ .thumb_func
+ .cfi_startproc
+ # HardFault exceptions are bounced through this trampoline which grabs the
+ # stack pointer at the time of the exception and passes it to the user's
+ # HardFault handler in r0.
+HardFaultTrampoline:
+ # Depending on the stack mode in EXC_RETURN, fetch stack pointer from
+ # PSP or MSP.
+ mov r0, lr
+ mov r1, #4
+ tst r0, r1
+ bne 0f
+ mrs r0, MSP
+ b HardFault
+0:
+ mrs r0, PSP
+ b HardFault
+ .cfi_endproc
+ .size HardFaultTrampoline, . - HardFaultTrampoline
+
+ .section .Reset, "ax"
+ .global Reset
+ .type Reset,%function
+ .thumb_func
+ .cfi_startproc
+ # Main entry point after reset. This jumps to the user __pre_init function,
+ # which cannot be called from Rust code without invoking UB, then
+ # initialises RAM. If the target has an FPU, it is enabled. Finally, jumps
+ # to the user main function.
+Reset:
+ # ARMv6-M does not initialise LR, but many tools expect it to be 0xFFFF_FFFF
+ # when reaching the first call frame, so we set it at startup.
+ # ARMv7-M and above initialise LR to 0xFFFF_FFFF at reset.
+ ldr r4,=0xffffffff
+ mov lr,r4
+
+ # Run user pre-init code, which must be executed immediately after startup,
+ # before the potentially time-consuming memory initialisation takes place.
+ # Example use cases include disabling default watchdogs or enabling RAM.
+ bl __pre_init
+
+ # Restore LR after calling __pre_init (r4 is preserved by subroutines).
+ mov lr,r4
+
+ # Initialise .bss memory. `__sbss` and `__ebss` come from the linker script.
+ ldr r0,=__sbss
+ ldr r1,=__ebss
+ mov r2,#0
+0:
+ cmp r1, r0
+ beq 1f
+ stm r0!, {r2}
+ b 0b
+1:
+
+ # Initialise .data memory. `__sdata`, `__sidata`, and `__edata` come from the
+ # linker script. Copy from r2 into r0 until r0 reaches r1.
+ ldr r0,=__sdata
+ ldr r1,=__edata
+ ldr r2,=__sidata
+2:
+ cmp r1, r0
+ beq 3f
+ # load 1 word from r2 to r3, inc r2
+ ldm r2!, {r3}
+ # store 1 word from r3 to r0, inc r0
+ stm r0!, {r3}
+ b 2b
+3:
+
+#ifdef HAS_FPU
+ # Conditionally enable the FPU.
+ # Address of SCB.CPACR.
+ ldr r0, =0xE000ED88
+ # Enable access to CP10 and CP11 from both privileged and unprivileged mode.
+ ldr r1, =(0b1111 << 20)
+ # RMW.
+ ldr r2, [r0]
+ orr r2, r2, r1
+ str r2, [r0]
+ # Barrier is required on some processors.
+ dsb
+ isb
+#endif
+
+4:
+ # Jump to user main function. We use bl for the extended range, but the
+ # user main function may not return.
+ bl main
+
+ # Trap on return.
+ udf
+
+ .cfi_endproc
+ .size Reset, . - Reset