Как определить процедуру обработки прерываний для MSP430 с LLVM/Clang+GCC?
При компиляции с GCC ISR определяется путем пометки его interrupt
атрибут с векторным номером, определенным в msp430fr*.h
заголовок, который поставляется с GCC toolchain, распространяемым TI:
__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)))
^ ~~~~~~~~~~~~~~~~
1 ответ
Ошибка от clang обусловлена жестко заданным ограничением числа векторов прерываний, которое должно быть четным и ниже 30 в handleMSP430InterruptAttr
в tools/clang/lib/Sema/SemaDeclAttr.cpp
,
Но, даже игнорируя это, скрипт компоновщика с GCC от TI не совместим с Clang, потому что Clang, в отличие от GCC, не генерирует секции для векторов, он только генерирует символы (псевдонимы), как __isr_6
за interrupt(12)
, Сценарий компоновщика, поставляемый в дистрибутиве TI GCC, работает по следующим разделам:
VECT38 : ORIGIN = 0xFFDA, LENGTH = 0x0002
...
__interrupt_vector_38 : {
KEEP (*(__interrupt_vector_38))
KEEP (*(__interrupt_vector_timer2_a1))
} > VECT38
Мы определяем символ для вектора и помещаем его в отдельный раздел, названный так, как этого требует скрипт компоновщика. Мы все еще хотим interrupt
атрибут, потому что он помечает функцию ISR с правильным соглашением о вызовах и т. д. Число может быть фиктивным, 0, повторное использование в порядке, суффикс Clang генерирует псевдонимы, которые он генерирует. (В этом решении 2 байта на символ псевдонима, определенные Clang, теряются.)
#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