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

Weak function definitions for interrupt vector in a static library are preferred over strong ones

简介

我为 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
)

问题

我已经在 Nordic nRF5 SDK 之上创建了一个自定义 C 硬故障处理程序。它适用于以前的构建系统(makefile 构建系统)。必须注意的是,以前的构建系统不会像新的 CMake 系统那样创建静态库。它只是 link 无条件地提供所有内容。

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

在nRF5 SDK库中,目标nrf5_sdk(静态库)中包含一个启动文件(modules/nrfx/mdk/gcc_startup_nrf52840.S)。本题相关代码:

__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/libraries/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)
    );
}

c 文件中的代码应该在出现硬故障时由 MCU 调用,但它不会。

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

我尝试过的东西

编辑

我的 link 标记:

-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 关键字。在这种情况下,关键字会按预期工作。请注意,链接到另一个对象库的对象库无法正常工作。并且底层对象库也必须包含在 top-most(non-object 库)目标中。