Ошибка в startup коде с at91.com для SAM7S128 и MULTI 4.02 Рыл насчёт того, что таймер не работает, нарыл: некорректно обрабатываются вложенные прерывания. Как только я их не разрешаю, так всё работает нормально. Пока что не могу разрешить вложенные прерывания так, чтобы всё правильно работало.
Если действовать немного по-другому (разрешить вложенные прерывания, и для ВСЕХ прерываний установить ОДИНАКОВЫЙ приоритет), тоже всё работает ОК (потому что нет вложенных прерываний).
Может, кто-то сталкивался с похожей проблемой?
Проблема неочевидная и редко когда возникает (только когда низкоуровневое прерывание прервётся высокоуровневым на последних строках стартапного ассемблерного кода обработки прерываний). Зависание приводит к тому, что процессор переходит в режим ABORT и висит на прерываниях Prefetch abort или Data abort.
Дополнительная информация.
Стека IRQ достаточно. Ассемблерный код обработки прерывания сохраняет 3 слова, переводит процессор в режим SVC и разрешает прерывания (одной командой), соответственно, стек обработчика на Си обращается к нормальному стеку (фоновые программы тоже в SVC работают), после завершения обработчика на Си восстанавливается режим работы IRQ и запрещаются прерывания (одной командой), восстанавливаются 3 слова, подтверждаются прерывание в AIC и возвращается управление фоновой программе. Очень похоже, что есть ошибка переключения режимов SVC <-> IRQ, но в коде всё нормально. Это глюк процессора? В application notes и errata такой ошибки не нашёл. Фрагмент кода обработчика прерывания: <pre>
;------------------------------------------------------------------------------
;- Function : IRQ_Handler_Entry
;- Treatments : IRQ Controller Interrupt Handler.
;- Called Functions : AIC_IVR[interrupt]
;------------------------------------------------------------------------------
IRQ_Handler_Entry:
;- Manage Exception Entry
;- Adjust and save LR_irq in IRQ stack
sub lr, lr, #4
stmfd sp!, {lr}
;- Save SPSR need to be saved for nested interrupt
mrs r14, SPSR
stmfd sp!, {r14}
;- Save and r0 in IRQ stack
stmfd sp!, {r0}
;- Write in the IVR to support Protect Mode
;- No effect in Normal Mode
;- De-assert the NIRQ and clear the source in Protect Mode
ldr r14, =AT91C_BASE_AIC
ldr r0 , [r14, #AIC_IVR]
str r14, [r14, #AIC_IVR]
;- Enable Interrupt and Switch in Supervisor Mode
msr CPSR_c, #ARM_MODE_SVC
;- Save scratch/used registers and LR in User Stack
stmfd sp!, { r1-r3, r12, r14}
;- Branch to the routine pointed by the AIC_IVR
mov r14, pc
bx r0
;- Restore scratch/used registers and LR from User Stack
ldmia sp!, { r1-r3, r12, r14}
;- Disable Interrupt and switch back in IRQ mode
msr CPSR_c, #I_BIT | ARM_MODE_IRQ
;- Mark the End of Interrupt on the AIC
ldr r14, =AT91C_BASE_AIC
str r14, [r14, #AIC_EOICR]
;- Restore r0 from IRQ stack
ldmia sp!, {r0}
;- Restore SPSR_irq from IRQ stack
ldmia sp!, {r14}
;- Restore adjusted LR_irq from IRQ stack directly in the PC
ldmia sp!, {pc}^
</pre>
-
- Может быть все-таки переполнение стека. Контроллер считает прерывание обработанным после записи в AIC_EOICR, а на самом деле стек еще не освобожден - Alexandr1(06.06.2006 14:14, )
- Ответ Alexandr1(82 знак., 06.06.2006 13:23, )
- Кстати, в примерах для IAR эта инструкция имеется. - VVB(07.06.2006 09:41, )
- Огромное спасибо!!! Всё заработало. - VVB(06.06.2006 16:20, )