0

介绍

  • 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
)

问题

我在 Nordic nRF5 SDK 之上创建了一个自定义 C 硬故障处理程序。它适用于以前的构建系统(makefile 构建系统)。必须注意的是,以前的构建系统不会创建静态库,新的 CMake 系统也是如此。它只是无条件地链接一切。

在理想情况下,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

HardFault_Handler此外,在 ac 文件中有一个强定义,应该优先于这个弱定义。文件(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)
    );
}

在硬故障的情况下,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
4

1 回答 1

0

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

于 2022-01-21T09:56:08.440 回答