我正在用SystemWorkbench 4 stm32编程STM32F413微控制器。在程序集启动文件中,将中断向量定义为弱别名,如下所示:
.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 ++包含该函数,但仍未编译。但是,如果我给它起另一个名字,则它包含在二进制文件中。另外,如果我删除了弱别名,并且在启动文件中仅引用了处理程序,它也可以工作。
因此,弱别名在g ++链接时间优化中不起作用。也许有人可以告诉我错误是什么,我在做什么错。
编辑:
我查看了在最终的.elf文件中使用nm创建哪些符号,并且将TIM1_UP_TIM10_IRQHandler
导出为带有DefaultHandler地址的弱符号。但是,仅从包含TIM1_UP_TIM10_IRQHandler
函数的编译单元查看.o文件时,该文件将作为符号导出到文本部分(T)中。因此,链接器出于某种原因会选择保留弱符号,即使存在同名的强符号也是如此。
答案 0 :(得分:1)
对于那些正在寻找这些的人,GCC 7中显然还有一个与链接时优化(-flto
)相关的错误:
https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966
我再次遇到了这个问题,在GCC 8(gcc-arm-none-eabi-8-2019-q3-update版本)中,行为仍然相同。
(对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)
{
//...
}
需要删除所有被调用的弱处理程序,因此,例如,如果在HAL / LL驱动程序中定义了UART1_Handler()
,则需要从{{ 1}}文件,否则该中断将陷入默认的无限循环中,从而导致MCU锁定,而无需执行预期的中断处理程序并从中断返回,从而允许其他代码恢复执行。
答案 1 :(得分:0)
我认为您应该通知编译器它中断 takePhoto(flag) {
return new Promise((resolve, reject) => {
var sourceType: any;
if (flag == "PHOTOLIBRARY") {
sourceType = this.camera.PictureSourceType.PHOTOLIBRARY;
} else {
sourceType = this.camera.PictureSourceType.CAMERA;
}
const options: CameraOptions = {
quality: 50,
sourceType: sourceType,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
targetWidth: 450,
targetHeight: 450,
saveToPhotoAlbum: false,
correctOrientation: true,
cameraDirection: this.camera.Direction.FRONT
};
this.camera.getPicture(options).then(
imageData => {
resolve(imageData);
})
})
,这通常是不需要的,因为F4的堆栈默认被硬件对齐为8。
如果不起作用,则解决方法是为处理程序分配一个函数指针,这将防止其被丢弃(如果指针本身不会被丢弃,请与调试器联系)。
不得已-用向量表定义更改.s文件
答案 2 :(得分:0)
gcc-arm-none-eabi-9-2020-q3-update
中仍然存在此错误,但仅适用于C处理程序。足够奇怪的是,用C ++编写的处理程序(并通过extern "C"
链接声明)不再受此bug的影响。
作为另一种解决方法,我发现并没有把startup.s
文件弄乱,而是将IRQ处理程序放在单独的.c
文件中,并在没有LTO的情况下构建了(并且只有那些)。
对于那些使用CubeIDE并通过CubeMX(也称为“设备配置工具”)生成IRQ / HAL处理程序的人,所有自动生成的处理程序都位于Core\Src\stm32XXXX_it.c
中,您只需编辑此文件的属性并删除编译选项中的LTO。
这是次优的,但它与自动生成的IRQ / HAL处理程序非常吻合:仅第一个调用(从IRQ处理程序到HAL处理程序)未优化,但是HAL代码本身已正确优化。