【问题标题】:Definitions of interrupt handlers are optimized out, so the null handler is called中断处理程序的定义被优化了,所以调用了空处理程序
【发布时间】:2020-09-09 19:35:55
【问题描述】:

我的应用程序被分成几个静态库,最后链接在一起。

其中一个库是 PORT 库,其中包含中断处理程序的源代码。如果我的 isr.cpp 的源代码如下所示,实际上 sys_tick_handler 定义已被优化出来,每当 sys_tick 中断发生时,都会调用 null_handler。我创建了一个简单的解决方法来解决这个问题,方法是在 isr.h 中声明某种虚拟函数,然后在 isr.cpp 文件中定义它。然后我需要在我的 main.js 中调用这个虚拟函数。这很有帮助,因为毕竟 sys_tick 中断正在从 isr.cpp 调用处理程序。但我并不为此感到自豪,正如我所说的那样,它只是一种解决方法 - 所以我想知道如何在不进行此类黑客攻击的情况下修复它。

这里是isr.cpp的代码

extern "C" {
void sys_tick_handler(void)
{

}
}

解决方法 isr.h

void func();

解决方法 isr.cpp

void func() {} 
extern "C" {
void sys_tick_handler(void)
{

}
}

【问题讨论】:

  • 它是如何被优化出来的?如果向量表中有一个条目,链接器不会删除它。项目/代码中的任何地方都没有引用标签 sys_tick_handler 吗?或者它的引用位置也被删除,因为它没有被使用?
  • 开始,它在哪里被删除?什么工具,什么步骤?
  • 极不可能。链接器不会随意删除函数。
  • sys_tick_handler的地址如何与中断关联?
  • 如果您怀疑编译器正在“优化”一些需要运行的代码,并且不应该...查看 volatile 限定符。 “出于优化的目的,通过 volatile 限定类型的左值表达式进行的每次访问(读取或写入操作、成员函数调用等)都被视为可见的副作用。”如果您在缺少的代码中增加一个计数器,将计数器标记为 volatile 应该会阻止优化。

标签: c++ microcontroller stm32


【解决方案1】:

假设您在代码中的某处定义了向量表,则中断处理程序名称必须与这些名称匹配。

例如,如果您使用 STM 启动代码,您的 sys tick 处理程序将必须被称为 SysTick_Handler。只需检查你的启动代码,看看你有什么。

g_pfnVectors:
  .word  _estack
  .word  Reset_Handler

  .word  NMI_Handler
  .word  HardFault_Handler
  .word  MemManage_Handler
  .word  BusFault_Handler
  .word  UsageFault_Handler
  .word  0
  .word  0
  .word  0
  .word  0
  .word  SVC_Handler
  .word  DebugMon_Handler
  .word  0
  .word  PendSV_Handler
  .word  SysTick_Handler

  /* External Interrupts */
  .word     WWDG_IRQHandler                   /* Window WatchDog              */                                        
  .word     PVD_IRQHandler                    /* PVD through EXTI Line detection */                        
  .word     TAMP_STAMP_IRQHandler             /* Tamper and TimeStamps through the EXTI line */            
  .word     RTC_WKUP_IRQHandler               /* RTC Wakeup through the EXTI line */                      
  .word     FLASH_IRQHandler                  /* FLASH                        */                                          

  /* ... */

如果您定义了许多没有主体的处理程序(如您的),或者处理程序将相同,编译器将只留下一个定义来优化重复代码。

【讨论】:

  • 我的处理程序没有空的身体 - 这只是为了向您展示问题。真正的问题是我的 sys_tick 处理程序被定义为 #pragma weak sys_tick_handler = null_handler,所以如果没有对定义了适当 sys_tick_handler 的翻译单元中定义的任何函数的任何引用,则 sys_tick_handler 函数的地址保持不变。我找到了实现我需要的简单解决方案。我已将名为 ISR_TAG 的 uint8_t 变量添加到定义 sys_tick_handler 的翻译单元,并将 -u ISR_TAG 选项传递给链接器配置。
  • 现在,每当 sys_tick isr 发生时,我的库中的 sys_tick_handler 就会被称为 null_handler。
猜你喜欢
  • 1970-01-01
  • 2012-09-17
  • 2013-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-21
  • 1970-01-01
相关资源
最近更新 更多