#[unsafe(naked)] extern "C" fn Reset() { core::arch::naked_asm!( // debug info ".cfi_sections .debug_frame", ".cfi_startproc", // If enabled, initialise the SP. This is normally initialised by the CPU itself or by a // bootloader, but some debuggers fail to set it when resetting the target, leading to // stack corruptions. #[cfg(feature = "set-sp")] concat!("ldr r0, =_stack_start", "msr msp, r0",), // If enabled, initialise VTOR to the start of the vector table. This is normally initialised // by a bootloader when the non-reset value is required, but some bootloaders do not set it, // leading to frustrating issues where everything seems to work but interrupts are never // handled. The VTOR register is optional on ARMv6-M, but when not present is RAZ,WI and // therefore safe to write to. #[cfg(feature = "set-vtor")] concat!( "ldr r0, =0xe000ed08", "ldr r1, =__vector_table", "str r1, [r0]", ), // If enabled, set the Main Stack Pointer Limit (MSPLIM) to the end of the stack. // This feature is only available on ARMv8-M Mainline, where it helps enforce stack limits // by defining the lowest valid stack address. #[cfg(all(armv8m_main, feature = "set-msplim"))] concat!("ldr r0, =_stack_end", "msr MSPLIM, r0",), // 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", // If enabled, initialize RAM with zeros. This is not usually required, but might be necessary // to properly initialize checksum-based memory integrity measures on safety-critical hardware. // // Otherwise, initialise .bss memory. `__sbss` and `__ebss` come from the linker script. cfg_match! { feature = "zero-init-ram" => { concat!( "ldr r0, =_ram_start", "ldr r1, =_ram_end", ) } _ => { concat!( "ldr r0, =__sbss", "ldr r1, =__ebss", ) } }, // zero out r0..r1 "movs r2, #0", "0:", "cmp r1, r0", "beq 1f", "stm r0!, {{r2}}", "b 0b", "1:", // If enabled, paint stack/heap RAM with 0xcccccccc. // `_stack_end` and `_stack_start` come from the linker script. #[cfg(feature = "paint-stack")] concat!( "ldr r0, =_stack_end", "ldr r1, =_stack_start", "ldr r2, =0xcccccccc", // This must match STACK_PAINT_VALUE "0:", "cmp r1, r0", "beq 1f", "stm r0!, {{r2}}", "b 0b", "1:", ), // Initialise .data memory. `__sdata`, `__sidata`, and `__edata` come from the linker script. "ldr r0, =__sdata", "ldr r1, =__edata", "ldr r2, =__sidata", "0:", "cmp r1, r0", "beq 1f", "ldm r2!, {{r3}}", "stm r0!, {{r3}}", "b 0b", "1:", // Potentially enable an FPU. // SCB.CPACR is 0xE000_ED88. // We enable access to CP10 and CP11 from priviliged and unprivileged mode. #[cfg(has_fpu)] concat!( "ldr r0, =0xE000ED88", "ldr r1, =(0b1111 << 20)", "ldr r2, [r0]", "orr r2, r2, r1", "str r2, [r0]", "dsb", "isb", ), // Jump to user main function. // `bl` is used for the extended range, but the user main function should not return, // so trap on any unexpected return. "bl main", "udf #0", ".cfi_endproc" ) }