首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >arm-none eabi-g++无法正确处理-flto的弱别名

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

Stack Overflow用户
提问于 2018-08-21 18:09:07
回答 3查看 741关注 0票数 3

我正在使用SystemWorkbench 4 stm32对STM32F413微控制器进行编程。在程序集启动文件中将中断向量定义为弱别名,如下所示:

代码语言:javascript
复制
.weak   TIM1_UP_TIM10_IRQHandler
.thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler

并在如下所示的对象中引用:

代码语言:javascript
复制
g_pfnVectors:
  .word _estack
  .word Reset_Handler
  .word NMI_Handler
  .....
  .word TIM1_UP_TIM10_IRQHandler
  .....

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

我像这样定义了处理程序:

代码语言:javascript
复制
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++包含该函数,但它仍然没有编译。但是,如果我给它另一个名称,那么它就包含在二进制文件中。另外,如果我删除了弱别名,并且在启动文件中只有一个对处理程序的引用,它也可以工作。

因此,不知何故,弱别名不适用于g++链接时间优化。也许有人可以告诉我错误是什么,以及我在这里做错了什么。

编辑:

我已经查看了在生成的.elf文件中使用nm创建的符号,并且TIM1_UP_TIM10_IRQHandler被导出为具有DefaultHandler地址的弱符号。但是,当仅从包含TIM1_UP_TIM10_IRQHandler函数的编译单元查看.o文件时,它将作为文本部分(T)中的符号导出。因此,链接器出于某种原因选择保留弱符号,即使有同名的强符号也是如此。

EN

回答 3

Stack Overflow用户

发布于 2018-08-21 18:39:15

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

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

最后一种方法-使用向量表定义更改.s文件

票数 1
EN

Stack Overflow用户

发布于 2019-08-08 22:16:16

对于那些正在寻找这一点的人来说,显然在GCC 7中有一个与链接时间优化(-flto)相关的已确认的错误:

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

我刚刚遇到了这一点,再次,在GCC 8(gcc-arm-none eabi-8-2019-q3-update release)中,行为仍然是相同的。

同样适用于我(来自https://github.com/ObKo/stm32-cmake/issues/78)的解决方法是删除或注释startup_XXX.s文件末尾的弱定义,例如,更改

代码语言:javascript
复制
    .weak   NMI_Handler
    .thumb_set NMI_Handler,Default_Handler

代码语言:javascript
复制
/*
    .weak   NMI_Handler
    .thumb_set NMI_Handler,Default_Handler
*/

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

代码语言:javascript
复制
void NMI_Handler(void)
{
    //...
}

所有被调用的弱处理程序都需要删除,因此,例如,如果您在HAL/LL驱动程序中定义了UART1_Handler(),则需要从startup_XXX.s文件中删除相应的.weak条目,否则中断将通过陷入默认的无限循环来锁定MCU,而不执行预期的中断处理程序并从中断返回,从而允许其他代码继续执行。

票数 1
EN

Stack Overflow用户

发布于 2020-11-29 19:56:42

此错误仍然存在于gcc-arm-none-eabi-9-2020-q3-update中,但仅适用于C处理程序。奇怪的是,用C++编写的处理程序(并使用extern "C"链接声明)不再受此错误的影响。

作为另一种解决方法,我发现将IRQ处理程序放在单独的.c文件中并构建那些(并且只构建那些)不带LTO的startup.s处理程序是可行的,而不是处理IRQ文件。

适用于那些使用CubeIDE并使用CubeMX生成IRQ/HAL处理程序的人(也称为。“设备配置工具”),所有自动生成的处理程序都在Core\Src\stm32XXXX_it.c中,您只需编辑此文件的属性并从编译选项中删除LTO即可。

这不是最优的,但它很适合自动生成的IRQ/HAL处理程序:只有第一个调用(从IRQ处理程序到HAL处理程序)是未优化的,但HAL代码本身是正确优化的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51946333

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档