Доброго времени суток!
Работаю с платой LPC2478, требуется реализовать вложенные (nested) прерывания.
Нарыл несколько статей на эту тему, но пока ни один метод не запахал.
Тестирую прерывания таким образом:
Код
void TestInterrupts::TestTimers()
{
myPrintf("\nSTART TestTimers()\n");
Timer0VICInit(Timer0ISR);
Timer1VICInit(Timer1ISR);
Timer1StartWithInt(1000);
myPrintf("\nEND TestTimers()\n");
}
void TestInterrupts::Timer0ISR()
{
T0IR = TIR_MR0_INT; // reset interrrupt flags
myPrintf("\nTimer0ISR()\n");
// Dummy write to VIC to signal end of interrupt
VICVectAddr = 0x00000000;
}
void TestInterrupts::Timer1ISR()
{
IENABLE;
T1IR = TIR_MR0_INT; // reset interrrupt flags
myPrintf("\nSTART Timer1ISR()\n");
Timer0StartWithInt(5000);
volatile tU8 dummy = 0;
while(1)
{
dummy = 0;
}
myPrintf("\nEND Timer1ISR()\n");
IDISABLE;
// Dummy write to VIC to signal end of interrupt
VICVectAddr = 0x00000000;
}
Где в качестве IENABLE пробовал разные последовательности ассемблерных команд, вычитанных с разных статей:
Код
// FROM Nesting of interrupts in the LPC2000 (AN10381)
#define IENABLE /* Nested Interrupts Entry */ \
__asm__ ("MRS LR, SPSR"); /* Copy SPSR_irq to LR */ \
__asm__ ("STMFD SP!, {LR}"); /* Save SPSR_irq */ \
__asm__ ("MSR CPSR_c, #0x1F"); /* Enable IRQ (Sys Mode) */ \
__asm__ ("STMFD SP!, {LR}"); /* Save LR */ \
Код
// FROM Real-time processing with the Philips LPC ARM microcontroller; using GCC and the MicroC/OS-II RTOS.
#define IENABLE /* Nested Interrupts Entry */ \
__asm__ ("sub lr, lr, #4"); /* (1) Save IRQ context, including the APCS registers, and r4-6 */ \
__asm__ ("stmfd sp!, {r0-r6, ip, lr}"); \
__asm__ ("mrs r4, spsr"); /* (2) Save the SPSR_irq register */ \
__asm__ ("ldr r5, =0xFFFFFF00"); /* (3) Read the VICVectAddr */ \
__asm__ ("ldr r6, [r5]"); \
__asm__ ("msr cpsr_c, 0x1F"); /* (4) Change to SYS mode and enable IRQ */ \
__asm__ ("stmfd sp!, {lr}"); /* (5) Save the banked SYS mode link register */ \
То есть, на консоли должно появиться
Цитата
START TestTimers()
END TestTimers()
START Timer1ISR()
START Timer0ISR()
А на самом деле последняя строка не выводиться, что говорит о невхождении в обработчик вложенного прерывания Timer0.
Так вот, первый мой вопрос, какая же все таки последовательной команд должна быть в прологе и эпилоге обработчика для LPC2478?
И еще, во втором случае IENABLE полное описание вхождения и вывода их вложенных прерываний выглядит так:
Цитата
nested_irq_isr:
/* (1) Save IRQ context, including the APCS registers, and r4-6 */
sub lr, lr, #4
stmfd sp!, {r0-r6, ip, lr}
/* (2) Save the SPSR_irq register */
mrs r4, spsr
/* (3) Read the VICVectAddr */
ldr r5, VICVECTADDR
ldr r6, [r5]
/* (4) Change to SYS mode and enable IRQ */
msr cpsr_c, #SYS_MODE
/* (5) Save the banked SYS mode link register */
stmfd sp!, {lr}
/* (6) Call the C-coded handler */
mov lr, pc
ldr pc, r6
/* (7) Restore SYS mode link register */
ldmfd sp!, {lr}
36
AR1803 May 10, 2006
/* (8) Change to IRQ mode and disable IRQ */
msr cpsr_c, #IRQ_MODE|IRQ_DISABLE
/* (9) Restore the SPSR */
msr spsr, r4
/* (10) Acknowledge the VIC */
mov r0, #0
str r0, [r5]
/* (11) Restore IRQ context and return from interrupt */
ldmfd sp!, {r0-r6, ip, pc}^
И это описание натолкнуло меня на дополнительный вопрос, а можно ли в GCC переопределять последовательность операций для вызова функций, например путем создания собственных атрибутов для функций. И дальнейшим их использованием в примерно таком виде:
Код
static void Timer0ISR() __attribute__ ((my_nested_interrupt))
Сообщение отредактировал Novichok1 - Mar 1 2010, 05:14