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?
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.