|
Вложенные прерывания, GCC и ARM7 |
|
|
|
Mar 1 2010, 05:08
|
Участник

Группа: Участник
Сообщений: 73
Регистрация: 8-07-09
Пользователь №: 51 032

|
Доброго времени суток! Работаю с платой 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
|
|
|
|
|
 |
Ответов
|
Mar 4 2010, 05:44
|
Участник

Группа: Участник
Сообщений: 73
Регистрация: 8-07-09
Пользователь №: 51 032

|
Хорошо, частично разобрался, для вызовов всех прерываний использую Код HandlerIRQ_ISR_NESTED: /* (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, =0xFFFFFF00 ldr r6, [r5] /* (4) Change to SYS mode and enable IRQ */ msr cpsr_c, #0x1F /* (5) Save the banked SYS mode link register */ stmfd sp!, {lr} /* (6) Call the C-coded handler */ mov lr, pc ldr pc, [r5] /* (7) Restore SYS mode link register */ ldmfd sp!, {lr} /* (8) Change to IRQ mode and disable IRQ */ msr cpsr_c, #Mode_IRQ|I_Bit /* (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}^ И что происходит, в обработчике внешнего прерывания в цикле просматриваю флаги прерываний, и вижу, что да, второе прерывание срабатывает, но его обработчик не запуститься до тех пор, пока мы не запишем что-либо в VicVectAddr, что сделает возможными и прерывания меньшего приоритета Цитата Writing to the VICVECTADDR Register indicates to the interrupt priority hardware that the current interrupt is serviced, enabling lower priority or the same priority interrupts to be removed, and for the interrupts to become active to go active И тем более запись в VicVectAddr советуют делать в самом конце обработчика прерывания, а без этой записи ядру не идет сообщение о прерывании. Может есть другой способ разрешить VIC инициализировать прерывания, без записи в VicVectAddr? И еще, если использовать директивы компилятора, указывающими на то что данная функция является обработчиком прерывания, то компилятор сам сохраняет изменяемые регистры, а тут мы это делаем ручками и для всех обработчиков, поэтому возникает вопрос, а достаточно ли сохранение первых семи регистров(stmfd sp!, {r0-r6, ip, lr})? И еще, небольшое наблюдение- приведенный выше подход проявляет более лучшую устойчивость, чем этот: Цитата #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 */ \
// Macro for disabling interrupts, switching back to IRQ and relevant stack operations #define IDISABLE /* Nested Interrupts Exit */ \ __asm__ ("LDMFD SP!, {LR}"); /* Restore LR */ \ __asm__ ("MSR CPSR_c, #0x92"); /* Disable IRQ (IRQ Mode) */ \ __asm__ ("LDMFD SP!, {LR}"); /* Restore SPSR_irq to LR */ \ __asm__ ("MSR SPSR_cxsf, LR"); /* Copy LR to SPSR_irq */ \ Так, если в обработчике первого прерывания происходит второе прерывания, а в вызванном обработчике второго прерывания происходит первое, то после выхода из обработчика программа глючит.
Сообщение отредактировал Novichok1 - Mar 4 2010, 06:25
|
|
|
|
Сообщений в этой теме
Novichok1 Вложенные прерывания, GCC и ARM7 Mar 1 2010, 05:08 sergeeff Про прерывания а форуме для ARM столько уже понапи... Mar 1 2010, 06:57 Novichok1 Цитата1. Заставить VIC вызывать по прерыванию С++ ... Mar 1 2010, 08:07 Novichok1 Может и правда, дело в стартапе, выложу его на вся... Mar 1 2010, 09:12 Novichok1 И благодаря такому подходу исчезли глюки, которые ... Mar 4 2010, 07:06 GetSmart театр одного актёра Mar 4 2010, 23:26 aaarrr Цитата(GetSmart @ Mar 5 2010, 02:26) теат... Mar 4 2010, 23:57 Novichok1 Цитата(aaarrr @ Mar 5 2010, 02:57) Перед ... Mar 5 2010, 04:59  aaarrr Цитата(Novichok1 @ Mar 5 2010, 07:59) Бол... Mar 5 2010, 10:04   GetSmart Цитата(aaarrr @ Mar 5 2010, 15:04) Вложен... Mar 5 2010, 12:14    Novichok1 Цитата(GetSmart @ Mar 5 2010, 15:14) Это ... Mar 5 2010, 12:43     GetSmart Цитата(Novichok1 @ Mar 5 2010, 17:43) То ... Mar 5 2010, 12:54      Novichok1 Цитата(GetSmart @ Mar 5 2010, 15:54) То б... Mar 5 2010, 13:12   Novichok1 Цитата(aaarrr @ Mar 5 2010, 13:04) Вложен... Mar 5 2010, 12:23 GetSmart Цитата(Novichok1)Вот и складывается впечатление, ч... Mar 5 2010, 06:44 Novichok1 Ну точнее, там используется два источника прерыван... Mar 5 2010, 07:22 GetSmart Если после команды ldmfd в эпилоге второго ничего ... Mar 5 2010, 07:43 Novichok1 Цитата(GetSmart @ Mar 5 2010, 10:43) Если... Mar 5 2010, 07:47 GetSmart ЦитатаВсе-таки кажется странным, что некорректный ... Mar 5 2010, 12:35 Novichok1 Цитата(GetSmart @ Mar 5 2010, 15:35) Со с... Mar 5 2010, 12:55 aaarrr Цитата(Novichok1 @ Mar 5 2010, 15:23) А н... Mar 5 2010, 12:41 GetSmart Это не свой атрибут, а стандартный. Используется т... Mar 5 2010, 13:03 GetSmart Цитата(Novichok1)Спасибо, а не в курсе,
Не, не в к... Mar 5 2010, 14:03 GetSmart Novichok1, хотел ещё спросить, зачем было делать о... Mar 11 2010, 12:21 Novichok1 А разве к статическим членам нет доступа? Ведь обр... Mar 11 2010, 15:07 GetSmart Я бы всё таки выделил прерывания из класса. ИМХО э... Mar 11 2010, 16:35 Novichok1 Цитата(GetSmart @ Mar 11 2010, 20:35) Зна... Mar 11 2010, 18:22 GetSmart Вообще, излишняя универсальность, которая не понад... Mar 11 2010, 19:02 Novichok1 Цитата(GetSmart @ Mar 11 2010, 22:02) А ч... Mar 12 2010, 04:49 GetSmart Цитата(Novichok1)Но в любом случае, мне не совсем ... Mar 12 2010, 05:50 Aurochs Цитата(GetSmart @ Mar 12 2010, 07:50) Так... Mar 13 2010, 18:30
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|