When compiling with GCC, an ISR is defined by marking it with an interrupt
attribute with a vector number defined in msp430fr*.h
header that ships with GCC toolchain distributed by TI:
__attribute__ ((interrupt(TIMER2_A1_VECTOR)))
void TIMER2_A1_ISR (void) { ... }
However, when compiling with LLVM/Clang and assembling and linking with 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
the above causes a compile-time error:
../../src/main.c:80:17: error: 'interrupt' attribute parameter 38 is out of bounds
__attribute__ ((interrupt(TIMER2_A1_VECTOR)))
^ ~~~~~~~~~~~~~~~~
The error from clang is due to the hardcoded restriction on the interrupt vector number to be even and below 30 in
handleMSP430InterruptAttr
intools/clang/lib/Sema/SemaDeclAttr.cpp
.But, even ignoring this, the linker script with GCC from TI is not compatible with Clang, because Clang, unlike GCC, does not generate sections for the vectors, it only generates symbols (aliases), like
__isr_6
forinterrupt(12)
. The linker script shipped in the TI GCC distribution operates on sections, like so:We define a symbol for the vector and put it in its own section named as the linker script wants it. We still want the
interrupt
attribute, because it marks the ISR function with the right calling convention, etc. The number can be dummy, 0, re-using is ok, Clang suffixes the aliases it generates. (In this solution, the 2 bytes per alias symbol defined by Clang are wasted.)