Search code examples
interruptavr-gcc

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


I have just tried to add __attribute__ ((weak)) to one of my interrupt handler definitions and I notice the vector jump is not implemented — the interrupt body appears in the compiled binary though.

Example, with "weak" interrupt:

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

Resulting assembly code — no jump:

    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>

Now without the weak attribute:

    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>

            ...

Is this a bug in avr-gcc (I have tried versions 5.3.x and 7.1.0) or have I missed something?


Solution

  • avr-libc implements the ISR vector table using weak symbols. Then your code can define the proper symbol as non-weak to override the default ISR handler __bad_interrupt (cf. crt1/gcrt1.S in the avr-libc source code).

    So only a non-weak ISR symbol will override the weak default handler ISR symbol from avr-libc.

    You might consider having your non-weak symbol ISR call a weak symbol function if you need that overridability and can afford to spend the additional cycles and stack space required for the call.