为什么 AVR 中断向量不能是 '__attribute__((weak))'?

Why can't AVR interrupt vectors be '__attribute__((weak))'?

我刚刚尝试将 __attribute__ ((weak)) 添加到我的中断处理程序定义之一,但我注意到未实现向量跳转 — 尽管中断主体出现在已编译的二进制文件中。

示例,带有 "weak" 中断:

ISR(TIMER1_COMPA_vect, __attribute__ ((weak)))
{
    // some compiled code
    ...
}

生成的汇编代码——没有跳转:

    00000000 <__vectors>:
       0:   48 c0           rjmp    .+144           ; 0x92 <__ctors_end>
       4:   92 c0           rjmp    .+292           ; 0x12a <__bad_interrupt>
       8:   90 c0           rjmp    .+288           ; 0x12a <__bad_interrupt>
       c:   8e c0           rjmp    .+284           ; 0x12a <__bad_interrupt>
      10:   8c c0           rjmp    .+280           ; 0x12a <__bad_interrupt>
      14:   8a c0           rjmp    .+276           ; 0x12a <__bad_interrupt>
      18:   88 c0           rjmp    .+272           ; 0x12a <__bad_interrupt>
      1c:   86 c0           rjmp    .+268           ; 0x12a <__bad_interrupt>
      20:   84 c0           rjmp    .+264           ; 0x12a <__bad_interrupt>
      24:   82 c0           rjmp    .+260           ; 0x12a <__bad_interrupt>
      28:   80 c0           rjmp    .+256           ; 0x12a <__bad_interrupt>
      2c:   7e c0           rjmp    .+252           ; 0x12a <__bad_interrupt>
      30:   7c c0           rjmp    .+248           ; 0x12a <__bad_interrupt>
      34:   7a c0           rjmp    .+244           ; 0x12a <__bad_interrupt>
      38:   78 c0           rjmp    .+240           ; 0x12a <__bad_interrupt>
      3c:   76 c0           rjmp    .+236           ; 0x12a <__bad_interrupt>
      40:   74 c0           rjmp    .+232           ; 0x12a <__bad_interrupt>
      44:   72 c0           rjmp    .+228           ; 0x12a <__bad_interrupt>
      48:   70 c0           rjmp    .+224           ; 0x12a <__bad_interrupt>
      4c:   6e c0           rjmp    .+220           ; 0x12a <__bad_interrupt>
      50:   6c c0           rjmp    .+216           ; 0x12a <__bad_interrupt>
      54:   6a c0           rjmp    .+212           ; 0x12a <__bad_interrupt>
      58:   68 c0           rjmp    .+208           ; 0x12a <__bad_interrupt>
      5c:   66 c0           rjmp    .+204           ; 0x12a <__bad_interrupt>
      60:   64 c0           rjmp    .+200           ; 0x12a <__bad_interrupt>
      64:   62 c0           rjmp    .+196           ; 0x12a <__bad_interrupt>
      68:   60 c0           rjmp    .+192           ; 0x12a <__bad_interrupt>
      6c:   5e c0           rjmp    .+188           ; 0x12a <__bad_interrupt>

现在没有 weak 属性:

    00000000 <__vectors>:
       0:   48 c0           rjmp    .+144           ; 0x92 <__ctors_end>
       4:   92 c0           rjmp    .+292           ; 0x12a <__bad_interrupt>
       8:   90 c0           rjmp    .+288           ; 0x12a <__bad_interrupt>
       c:   8e c0           rjmp    .+284           ; 0x12a <__bad_interrupt>
      10:   8c c0           rjmp    .+280           ; 0x12a <__bad_interrupt>
      14:   8a c0           rjmp    .+276           ; 0x12a <__bad_interrupt>
      18:   88 c0           rjmp    .+272           ; 0x12a <__bad_interrupt>
      1c:   29 c0           rjmp    .+82            ; 0x70 <__vector_7>
      20:   84 c0           rjmp    .+264           ; 0x12a <__bad_interrupt>
      24:   82 c0           rjmp    .+260           ; 0x12a <__bad_interrupt>
      28:   80 c0           rjmp    .+256           ; 0x12a <__bad_interrupt>
      2c:   7e c0           rjmp    .+252           ; 0x12a <__bad_interrupt>

            ...

这是 avr-gcc 中的一个错误吗(我试过版本 5.3.x7.1.0) 还是我错过了什么?

avr-libc 使用弱符号实现 ISR 向量 table,以便您的代码可以将适当的符号定义为非弱符号以覆盖默认的 ISR 处理程序 __bad_interrupt(参见 crt1/gcrt1.Savr-libc 代码中)。

因此只有非弱 ISR 会覆盖来自 avr-libc 的弱 ISR。

如果需要可覆盖性,您可能希望让非弱 ISR 调用弱函数。