2

使用 GCC 编译时,ISR 是通过使用interrupt带有向量编号的属性来定义的,该属性在msp430fr*.hTI 分发的 GCC 工具链附带的标头中定义:

__attribute__ ((interrupt(TIMER2_A1_VECTOR)))
void TIMER2_A1_ISR (void) { ... }

但是,当使用 LLVM/Clang 编译并使用 GCC 组装和链接时

clang -emit-llvm -c -MD --target=msp430 -D__MSP430FR5969__ -nobuiltininc -nostdinc++ -isysroot /none -O1 -g -std=c99 -pedantic -Wall -I /opt/ti/msp430-gcc/lib/gcc/msp430-elf/4.9.1/include -I /opt/ti/msp430-gcc/msp430-elf/include -I /opt/ti/msp430-gcc/include -I ../src  -DBOARD_MSP_TS430  ../../src/main.c -o main.bc

以上导致编译时错误:

../../src/main.c:80:17: error: 'interrupt' attribute parameter 38 is out of bounds
__attribute__ ((interrupt(TIMER2_A1_VECTOR)))
            ^         ~~~~~~~~~~~~~~~~
4

1 回答 1

4

来自 clang 的错误是由于对中断向量数的硬编码限制为偶数且低于 30 in handleMSP430InterruptAttrin tools/clang/lib/Sema/SemaDeclAttr.cpp

但是,即使忽略这一点,来自 TI 的带有 GCC 的链接器脚本也与 Clang 不兼容,因为与 GCC 不同,Clang 不会为向量生成节,它只会生成符号(别名),例如__isr_6for interrupt(12)。TI GCC 发行版中提供的链接描述文件对部分进行操作,如下所示:

 VECT38           : ORIGIN = 0xFFDA, LENGTH = 0x0002
 ...
 __interrupt_vector_38  : {
     KEEP (*(__interrupt_vector_38))
     KEEP (*(__interrupt_vector_timer2_a1))
 } > VECT38

我们为向量定义了一个符号,并将其放在链接描述文件所需的名称中。我们仍然想要这个interrupt属性,因为它用正确的调用约定等标记了 ISR 函数。数字可以是 dummy,0,重复使用是可以的,Clang 为它生成的别名添加后缀。(在这个解决方案中,Clang 定义的每个别名符号的 2 个字节被浪费了。)

#ifdef __clang__
__attribute__ ((interrupt(0)))
#else
__attribute__ ((interrupt(TIMER2_A1_VECTOR)))
#endif
void TIMER2_A1_ISR (void)
{  ... }  
#ifdef __clang__
__attribute__ ((section("__interrupt_vector_timer2_a1"),aligned(2)))
void (*__vector_timer2_a1)(void) = TIMER2_A1_ISR;
#endif
于 2015-10-21T17:57:35.670 回答