ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
28 ноября
60255
VVB (06.06.2006 11:48, просмотров: 1853)
Ошибка в 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>