静态库中中断向量的弱函数定义优先于强函数定义



简介

  • arm none eabi gcc版本10.3-2021.10 20210824
  • 设备:北欧nRF52840/nRF52832/nRF52833
  • 受影响的库:Nordic NRF5 SDK 17.1.0-自定义构建系统(CMake(

我为Nordic NRF5 SDK编写了CMake构建系统(本机仅支持makefile(。构建系统有一个可执行文件(应用程序(和多个底层静态库。依赖关系如下:

application
...
- NordicAl (abstraction layer)
- nrf5_sdk
...
//root/CMakeLists.txt
add_executable(application)
...
add_subdirectory(lib/NordicAl)
...
target_link_libraries(application PRIVATE 
nordic_al
...)
....
//root/lib/NordicAl/CMakeLists.txt
add_library(nordic_al)
...
add_subdirectory(lib/nrf5_sdk)
target_link_libraries(nordic_al PRIVATE 
nrf5_sdk
...)
...
//root/lib/NordicAl/lib/nrf5_sdk/CMakeLists.txt
add_library(nrf5_sdk)
...
target_sources(nrf5_sdk PRIVATE
...
${NRF5_SDK_ROOT}/modules/nrfx/mdk/gcc_startup_${PLATFORM_MCU_FAMILY}.S
${NRF5_SDK_ROOT}/components/libraries/hardfault/nrf52/handler/hardfault_handler_gcc.c
)

问题

我在NordicnRF5SDK之上创建了一个自定义的C硬故障处理程序。它与以前的生成系统(makefile生成系统(配合使用。必须注意的是,以前的构建系统不会像新的CMake系统那样创建静态库。它只是无条件地将一切联系在一起。

在完美的世界中,SDK的用户(即i(应该定义一个回调(HardFault_c_handler(,在发生硬故障时,它将由中断向量调用。

在nRF5 SDK库中,启动文件(modules/nrfx/mdk/gcc_startup_nrf52840.S(包含在目标nRF5_SDK(静态库(中。此问题的相关代码:

__isr_vector:
.long   __StackTop                  /* Top of Stack */
.long   Reset_Handler
.long   NMI_Handler
.long   HardFault_Handler
...
.weak   HardFault_Handler
.type   HardFault_Handler, %function
HardFault_Handler:
b       .
.size   HardFault_Handler, . - HardFault_Handler

此外,在c文件中有一个HardFault_Handler的强定义,应该优先于这个弱定义。文件(components/librarys/hardfault/nrf52/handler/hardfault_handler_gcc.c(包含:

extern void HardFault_c_handler(uint32_t *);
void HardFault_Handler(void) __attribute__(( naked ));
void HardFault_Handler(void)
{
__ASM volatile(
...
"   .ltorg                                  n"
: : "X"(HardFault_c_handler)
);
}

在发生硬故障的情况下,MCU应该调用c文件中的代码,但它没有。

我的问题是为什么?如何使它更喜欢强大的功能?我现在的想法,尽管我不确定。因为这个回调,即HardFault_Handler,在主应用程序中没有被引用(或者在到达启动文件之前(,链接器不需要解析它。只有当它在启动文件中看到这个符号时,它才会查找它,并且因为这是一个静态库,它只查找第一次出现的符号。

我尝试过的东西

  • 删除静态库,这修复了问题
  • HardFault_Handler的弱定义分离成单独的汇编文件,这使得链接器将函数从第一个出现的文件链接起来,使用-Wl,-trace-symbol=HardFault_Handler我看到链接器只查找第一个出现而不停止(弱和强无关(
  • 将c文件放在源中的启动文件之前,不会更改结果

编辑

我的链接器标志:

-mcpu=cortex-m4
-mfloat-abi=hard
-mfpu=fpv4-sp-d16
-mthumb 
-mabi=aapcs 
-ffreestanding 
-fno-common 
-finline-small-functions 
-findirect-inlining 
-fstack-protector-strong
-ffunction-sections 
-fdata-sections 
-Wl,--gc-sections 
--specs=nano.specs

我发现,当我使用CMake时,我可以使用add_library()函数提供OBJECT关键字。在这种情况下,关键字按预期工作。请注意,链接到另一个对象库的对象库无法正常工作。底层对象库也必须包含在最顶层(非对象库(的目标中。

最新更新