代码之家  ›  专栏  ›  技术社区  ›  Alexander Daum

arm-none-eabi-g++无法使用-flto正确处理弱别名

  •  1
  • Alexander Daum  · 技术社区  · 6 年前

    .weak   TIM1_UP_TIM10_IRQHandler
    .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
    

    并在如下对象中引用:

    g_pfnVectors:
      .word _estack
      .word Reset_Handler
      .word NMI_Handler
      .....
      .word TIM1_UP_TIM10_IRQHandler
      .....
    

    g_pfnVectors 是IRQ处理程序函数的地址列表。它们被声明为弱别名,因此如果用户未定义它们,则使用默认处理程序。

    我将处理程序定义为:

    extern "C" {
    void TIM1_UP_TIM10_IRQHandler() {
        if (SU_TIM->SR & TIM_SR_UIF) {
            SU_TIM->SR &= ~TIM_SR_UIF;
            ...
        }
    }
    }
    

    -flto (主要是为了试一下,其实并不需要)。但是在编译时 -flto公司 ,g++忽略了我对处理程序的实现,只使用默认处理程序,我的处理程序根本不在代码中。

    所以我试图通过添加 __attribute__((used)) 函数定义,但它仍然没有被编译。但是如果我给它另一个名字,那么它就包含在二进制文件中了。另外,如果我删除弱别名,只在启动文件中引用处理程序,它也可以工作。

    因此,弱别名在g++链接时间优化中不起作用。也许有人能告诉我错误是什么,我做错了什么。

    我已经看了在生成的.elf文件中使用nm创建的符号,以及 TIM1_UP_TIM10_IRQHandler 作为带有DefaultHandler地址的弱符号导出。但是,当从包含

    1 回复  |  直到 6 年前
        1
  •  1
  •   0___________    6 年前

    我想你应该通知编译器它是中断 __attribute__ ((interrupt ("IRQ"))) ,这通常不需要,因为F4的堆栈默认由硬件对齐到8。

    如果这没有帮助,解决方法是为处理程序分配一个函数指针,这将阻止它丢弃(如果指针本身不会被丢弃-请与调试器检查)。

        2
  •  1
  •   dognotdog    5 年前

    对于那些寻找这一点的人来说,显然在gcc7中有一个与链路时间优化有关的已确认错误( -flto

    https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966

    我刚刚又遇到了这种情况,在gcc8(GCC-arm-none-eabi-8-2019-q3-update release)中,行为仍然是一样的。

    https://github.com/ObKo/stm32-cmake/issues/78 startup_XXX.s 文件,例如更改

        .weak   NMI_Handler
        .thumb_set NMI_Handler,Default_Handler
    

    /*
        .weak   NMI_Handler
        .thumb_set NMI_Handler,Default_Handler
    */
    

    并在源文件中用您自己的实现替换它们:

    void NMI_Handler(void)
    {
        //...
    }
    

    UART1_Handler() 在HAL/LL驱动程序中定义,需要删除相应的 .weak 启动 文件,否则中断将通过陷入默认的无限循环来锁定MCU,而不执行预期的中断处理程序并从中断返回,从而允许其他代码继续执行。