Как определить процедуру обработки прерываний для 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
Другие вопросы по тегам