Существуют ли какие-то хитрости при одновременной работе IRQ и FIQ в LPC21x? Есть два таймера. Т0 просто отсчитывает миллисекундные интервалы. Т1 должен формировать с помощью компараторов (MATCH) довольно сложную последовательность синхроимпульсов, но в примере он просто крутится и дергает ногу. Если прерывания от обоих таймеров заведены на IRQ, то все нормально работает. Если прерывания от Т1 заводятся на FIQ, а прерывание от Т0 запрещено (других прерываний вообще нет), то тоже все работает. А вот если разрешить и IRQ и FIQ, то программа работает долю секунды и «улетает». Если отладчик остановить, то РС оказывается в районе 0х00000004 - 0х00000010. Работаю в ИАР 4.41. Проект размещается в RAM. Стартап из какого-то ИАРовского примера без доработок, инициализация стека FIQ там вроде есть. Код инициализации VIC и обработчиков также взят из примеров. от куски программы:
///////////////////////////////////// void InerruptInit(void) { VICIntEnClear = 0xFFFFFFFF; VICProtection = 0; VICVectAddr = 0; VICProtection = 0; //VICIntSelect &= (1<<VIC_TIMER1); // так работает VICIntSelect |= (1<<VIC_TIMER1); // так нет VICVectAddr0 = (unsigned int)&TIMER1_ISR; VICVectCntl0 = 0x20 | VIC_TIMER1; VICIntEnable |= (1<<VIC_TIMER1); VICIntSelect &= ~(1<<VIC_TIMER0); VICVectAddr2 = (unsigned int)&TIMER0_ISR; VICVectCntl2 = 0x20 | VIC_TIMER0; VICIntEnable |= (1<<VIC_TIMER0); }
/////////////////////////////////////
#pragma vector=0x18 __irq __arm void IRQ_ISR_Handler (void) { void (*interrupt_function)(); unsigned int vector; vector = VICVectAddr; interrupt_function = (void(*)())vector; (*interrupt_function)(); VICVectAddr = 0;
}
//////////////////////////////////// #pragma vector=0x1c __fiq __arm void FIQ_ISR_Handler (void) { TIMER1_ISR(); }
/////////////////////////////////// void TIMER0_ISR() { T0IR = 0x0f; IO0PIN ^= (1<<20); Delay (100); }
//////////////////////////////////
void TIMER1_ISR() { T1IR = 0x0f; IO0PIN ^= (1<<21); }
//////////////////////////////////
void main() {
CLOCK_Init(); MEM_Init(); InerruptInit(); IOPinInit();
T0TCR = 0; T0IR=0xFF; T0MR0=SysTimerCnt; T0MCR_bit.MR0INT=1; T0MCR_bit.MR0RES=1;
T1TCR = 0; T1IR=0xFF; T1MR0=3000; T1MCR_bit.MR0INT=1; T1MCR_bit.MR0RES=1;
__enable_interrupt(); // Global interrupt enable
T0TCR = 1; T1TCR = 1;
while(TRUE) { IO0PIN ^= (1<<19); Delay (100); } }
|