自定义CMake构建STM32应用遇Reset_Handler警告,方法是否正确?
问题描述
我尝试用自定义CMake文件构建STM32应用,已完成静态库的编译链接并生成可执行文件,但出现如下警告:
warning: cannot find entry symbol Reset_Handler; defaulting to 0000000008000000
以下是我使用的链接脚本、启动汇编文件及CMake配置,请问当前构建方法是否正确?
链接脚本内容
/* Entry Point */ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ _estack = ORIGIN(RAM_D1) + LENGTH(RAM_D1); /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x200 ; /* required amount of heap */ _Min_Stack_Size = 0x400 ; /* required amount of stack */ /* Specify the memory areas */ MEMORY { ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 320K RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 32K RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 16K } /* Define output sections */ SECTIONS { /* The startup code goes first into FLASH */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); } >FLASH /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ *(.eh_frame) KEEP (*(.init)) KEEP (*(.fini)) . = ALIGN(4); _etext = .; /* define a global symbols at end of code */ } >FLASH /* Constant data goes into FLASH */ .rodata : { . = ALIGN(4); *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ . = ALIGN(4); } >FLASH .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; } >FLASH .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array*)) PROVIDE_HIDDEN (__preinit_array_end = .); } >FLASH .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array*)) PROVIDE_HIDDEN (__init_array_end = .); } >FLASH .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT(.fini_array.*))) KEEP (*(.fini_array*)) PROVIDE_HIDDEN (__fini_array_end = .); } >FLASH /* used by the startup to initialize data */ _sidata = LOADADDR(.data); /* Initialized data sections goes into RAM, load LMA copy after code */ .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ *(.RamFunc) /* .RamFunc sections */ *(.RamFunc*) /* .RamFunc* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end */ } >RAM_D1 AT> FLASH /* Uninitialized data section */ . = ALIGN(4); .bss : { /* This is used by the startup in order to initialize the .bss section */ _sbss = .; /* define a global symbol at bss start */ __bss_start__ = _sbss; *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ __bss_end__ = _ebss; } >RAM_D1 /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : { . = ALIGN(8); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); } >RAM_D1 .lwip_sec (NOLOAD) : { . = ABSOLUTE(0x30000000); *(.RxDecripSection) . = ABSOLUTE(0x30000060); *(.TxDecripSection) . = ABSOLUTE(0x30000200); *(.Rx_PoolSection) } >RAM_D2 /* Remove information from the standard libraries */ /DISCARD/ : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) } .ARM.attributes 0 : { *(.ARM.attributes) } }
启动汇编文件内容
.syntax unified .cpu cortex-m7 .fpu softvfp .thumb .global g_pfnVectors .global Default_Handler /* start address for the initialization values of the .data section. defined in linker script */ .word _sidata /* start address for the .data section. defined in linker script */ .word _sdata /* end address for the .data section. defined in linker script */ .word _edata /* start address for the .bss section. defined in linker script */ .word _sbss /* end address for the .bss section. defined in linker script */ .word _ebss /* stack used for SystemInit_ExtMemCtl; always internal RAM used */ .section .text.Reset_Handler .weak Reset_Handler .type Reset_Handler, %function Reset_Handler: ldr sp, =_estack /* set stack pointer */ /* Call the clock system initialization function.*/ bl SystemInit /* Copy the data segment initializers from flash to SRAM */ ldr r0, =_sdata ldr r1, =_edata ldr r2, =_sidata movs r3, #0 b LoopCopyDataInit CopyDataInit: ldr r4, [r2, r3] str r4, [r0, r3] adds r3, r3, #4 LoopCopyDataInit: adds r4, r0, r3 cmp r4, r1 bcc CopyDataInit /* Zero fill the bss segment. */ ldr r2, =_sbss ldr r4, =_ebss movs r3, #0 b LoopFillZerobss FillZerobss: str r3, [r2] adds r2, r2, #4 LoopFillZerobss: cmp r2, r4 bcc FillZerobss /* Call static constructors */ bl __libc_init_array /* Call the application's entry point.*/ bl main bx lr .size Reset_Handler, .-Reset_Handler ... some code
CMake配置内容
... add_subdirectory(${STLIB_DIR} ${STLIB_DIR}/build) add_executable(${EXECUTABLE} ${CMAKE_SOURCE_DIR}/Core/Src/main.cpp ${CMAKE_SOURCE_DIR}/Core/Src/syscalls.c ${CMAKE_SOURCE_DIR}/Core/Src/stm32h7xx_hal_msp.c ${CMAKE_SOURCE_DIR}/Core/Src/stm32h7xx_it.c ${CMAKE_SOURCE_DIR}/Core/Src/sysmem.c ${CMAKE_SOURCE_DIR}/Core/Src/system_stm32h7xx.c ${CMAKE_SOURCE_DIR}/Core/Startup/startup_stm32h723zgtx.s ) target_link_libraries(${EXECUTABLE} ${STLIB_DIR}/build/libst-lib.a) ... target_link_options(${EXECUTABLE} PUBLIC -T${CMAKE_SOURCE_DIR}/STM32H723ZGTX_FLASH.ld -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -specs=nosys.specs -lc -lm -lnosys -Wl,-Map=${PROJECT_NAME}.map,--cref -Wl,--gc-sections )
问题分析与修复方案
当前构建思路整体正确,但存在几个细节问题导致链接器无法找到Reset_Handler符号:
1. 启动汇编文件中Reset_Handler的弱符号属性
启动汇编里将Reset_Handler标记为.weak,这意味着如果没有其他强符号定义该名称,链接器可能无法将其识别为有效入口。修复方法:将.weak Reset_Handler改为.global Reset_Handler,确保符号为全局强符号:
.section .text.Reset_Handler .global Reset_Handler .type Reset_Handler, %function Reset_Handler:
2. 链接脚本中不必要的库丢弃操作
链接脚本的/DISCARD/段丢弃了libgcc.a,但Cortex-M7架构依赖该库提供的底层指令支持(如Thumb/ARM指令切换、浮点运算辅助等),这可能间接导致符号解析异常。修复方法:注释掉对libgcc.a的丢弃:
/DISCARD/ : { libc.a ( * ) libm.a ( * ) # libgcc.a ( * ) // 保留libgcc.a以支持底层指令 }
3. 确认启动文件的编译与链接顺序
CMake的add_executable已包含启动汇编文件,这是正确的;静态库放在target_link_libraries的末尾也符合链接顺序规则(目标文件在前,依赖库在后)。可通过查看编译日志确认startup_stm32h723zgtx.s是否被正常编译为目标文件并参与链接。
4. 验证链接脚本路径准确性
确保-T${CMAKE_SOURCE_DIR}/STM32H723ZGTX_FLASH.ld指向的链接脚本路径正确,避免因文件缺失导致链接器无法读取ENTRY(Reset_Handler)配置。
总结
调整上述细节后,链接器应该能正确识别Reset_Handler入口符号,消除警告。整体构建流程的方向是正确的,只需修正符号属性、库依赖等细节问题。
内容的提问来源于stack exchange,提问作者dahko37

