Created
April 25, 2025 09:25
-
-
Save folkertdev/6a5ebe1272b38472310cec3964b6ae44 to your computer and use it in GitHub Desktop.
cfg macro example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[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" | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment