【问题标题】:Why does the compiler not optimize away interrupt code?为什么编译器不优化掉中断代码?
【发布时间】:2014-08-29 21:59:02
【问题描述】:

我最近遇到了一个问题,一个变量只在中断处理程序中被修改。变量本身未声明为 volatile,因此在更高级别的优化中编译器会破坏代码。但是,编译器足够聪明,可以编译中断代码,因为中断仍然会触发。

所以这是我的问题:

  1. 如果编译器足够聪明,可以编译中断代码,为什么它还不够聪明,无法意识到中断内部的变量发生了变化?

  2. 在更高级别的优化中,未被调用的函数会得到优化。由于没有代码调用中断处理程序,因此应该对其进行优化。是什么导致编译器编译中断代码?

【问题讨论】:

  • 发布您的代码以及可能的相关反汇编
  • 您使用的是什么编译器(是GCC 的最新版本)?什么是优化标志?目标平台和处理器是什么?你为什么不使用volatile(在你的情况下你真的应该)?
  • 可能是因为在加载带有地址的向量中断控制器时引用了它?如果引用了处理程序的地址,则编译器将假定它可能被调用。

标签: c optimization interrupt-handling cortex-m3


【解决方案1】:
  1. 语言执行模型说普通(非易失)变量不能被“外力”改变。 IE。如果您的代码流没有显式更改变量,那么从该代码流的角度来看,变量不可能更改。 (除了 C11 为多线程执行定义的内容)。您必须手动“指定”可由中断处理程序更改的变量。

    这是实现 C 代码高效优化的主要因素之一。如果不对 C 程序的性能产生显着的负面影响,就无法消除它。

  2. 首先,编译器通常不会优化带有外部链接的函数。您的中断处理程序是否使用外部链接声明?

    其次,优化或保留函数的决定并不是真正基于函数是否被调用。它基于相应的符号是否以任何方式在您的程序中被引用。未引用的符号被删除,而引用的符号被保留。除了调用函数符号之外,还有其他方法可以引用函数符号。例如,获取函数的地址也算作对函数符号的引用。在程序中的任何地方获取地址的函数永远不会被优化掉。

    您的中断向量条目在程序启动时以某种方式初始化,这通常涉及获取处理函数的地址。这已经足以保护此功能不被优化。

【讨论】:

  • 我使用的是 stm32 处理器,制造商的支持库已经掩盖了许多中断链接细节。我知道我需要在我的代码中的某处写TIM4_IRQHandler,并且链接器将此处理程序放置在向量部分的正确位置。编译器保留该函数,因为链接器将TIM4_IRQHandler 的地址放在向量部分中。这就是我认为正在发生的事情。
  • @thndrwrks:如果您的实现提供了一些隐含的“幕后”功能,以确保您的TIM4_IRQHandler 被放置在中断向量中的正确位置,那么很可能同样的功能也采取了所有必要的步骤来防止TIM4_IRQHandler被优化掉。
  • 确实是这样。获取 VIC 的处理程序地址意味着编译器假定它可以被调用。
猜你喜欢
  • 2015-09-15
  • 1970-01-01
  • 2019-02-18
  • 2014-10-16
  • 2013-07-18
  • 1970-01-01
  • 1970-01-01
  • 2021-02-01
  • 2015-05-13
相关资源
最近更新 更多