为什么 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.x 和 7.1.0) 还是我错过了什么?
avr-libc
使用弱符号实现 ISR 向量 table,以便您的代码可以将适当的符号定义为非弱符号以覆盖默认的 ISR 处理程序 __bad_interrupt
(参见 crt1/gcrt1.S
在 avr-libc
代码中)。
因此只有非弱 ISR 会覆盖来自 avr-libc
的弱 ISR。
如果需要可覆盖性,您可能希望让非弱 ISR 调用弱函数。
我刚刚尝试将 __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.x 和 7.1.0) 还是我错过了什么?
avr-libc
使用弱符号实现 ISR 向量 table,以便您的代码可以将适当的符号定义为非弱符号以覆盖默认的 ISR 处理程序 __bad_interrupt
(参见 crt1/gcrt1.S
在 avr-libc
代码中)。
因此只有非弱 ISR 会覆盖来自 avr-libc
的弱 ISR。
如果需要可覆盖性,您可能希望让非弱 ISR 调用弱函数。