gcc и прерывания Я много раз сталкивался с тем, что при включении какого-либо даже не относящегося к делу irq, начинают происходить совершенно невероятные вещи: либо глюки, либо падение в исключение. Особенно это проявляется при включенной оптимизации.
Как я потом выяснил, покопавшись в интернете, GCC для ARM'а имеет непофиксанный BUG по части генерации пролога/эпилога функций обработчиков IRQ ( __attribute__ (( interrupt )) ), а именно В НЕКОТОРЫХ СЛУЧАЯХ неправильно заносятся/извлекаются регистры в стек.
Решение проблемы мне видится так:
файл irq.h:
#ifndef __irq_h_
#define __irq_h_
#define INTERRUPT_PROC __attribute__(( naked ))
#define INTERRUPT_PROC_BEGIN \
{ asm( " stmdb sp!, {r0-r11, ip, lr} " ); \
asm( " mov r12, sp " ); \
asm( " sub r11, r12, #4 " ); }
#define INTERRUPT_PROC_END \
{ asm( " ldmia sp!, {r0-r11, ip, lr} " ); \
asm( " subs pc, lr, #4 " ); }
#endif
А обработчик оформляется так:
void INTERRUPT_PROC timer0_irq()
{
INTERRUPT_PROC_BEGIN
...
INTERRUPT_PROC_END
}
Недостаток, конечно, приходится загонять в стек все регистры, а не только те, что используются в обработчике (примерно 40 тактов на все).
После того, как я перешел на такие обработчики, все проблемы с прерываниями исчезли.
Может кто сталкивался с подобным поведением GCC и может посоветовать лучшее решение?
И еще, никто не знает как правильно работать с r11, r12?