aboutsummaryrefslogtreecommitdiff
path: root/cortex-m-rt/asm.S
diff options
context:
space:
mode:
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