Никак не получается нормально запустить FIQ.
плата на AT91RM9200, ось uCOS 2.84 с портом ARM 1.81, компилер IAR 4.41
Кусочки стартапа, которые я и не менял, вроде работают штатно:
Код
org 0x00
__program_start
b ?start
b ?OS_CPU_ARM_ExceptUndefInstrHndlr
b ?OS_CPU_ARM_ExceptSwiHndlr
b ?OS_CPU_ARM_ExceptPrefetchAbortHndlr
b ?OS_CPU_ARM_ExceptDataAbortHndlr
b ?OS_CPU_ARM_ExceptAddrAbortHndlr
b ?OS_CPU_ARM_ExceptIrqHndlr
b ?OS_CPU_ARM_ExceptFiqHndlr
?OS_CPU_ARM_ExceptResetHndlr
b OS_CPU_ARM_ExceptResetHndlr
?OS_CPU_ARM_ExceptUndefInstrHndlr
b OS_CPU_ARM_ExceptUndefInstrHndlr
?OS_CPU_ARM_ExceptSwiHndlr
b OS_CPU_ARM_ExceptSwiHndlr
?OS_CPU_ARM_ExceptPrefetchAbortHndlr
b OS_CPU_ARM_ExceptPrefetchAbortHndlr
?OS_CPU_ARM_ExceptDataAbortHndlr
b OS_CPU_ARM_ExceptDataAbortHndlr
?OS_CPU_ARM_ExceptAddrAbortHndlr
b OS_CPU_ARM_ExceptAddrAbortHndlr
?OS_CPU_ARM_ExceptIrqHndlr
b OS_CPU_ARM_ExceptIrqHndlr
?OS_CPU_ARM_ExceptFiqHndlr
b OS_CPU_ARM_ExceptFiqHndlr
в файле os_cpu_a.asm:
Код
;*******************************************************************************
*************************
; INTERRUPT REQUEST EXCEPTION HANDLER
;*******************************************************************************
*************************
OS_CPU_ARM_ExceptIrqHndlr
SUB LR, LR, #4 ; LR offset to return from this exception: -4
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
;*******************************************************************************
*************************
; FAST INTERRUPT REQUEST EXCEPTION HANDLER
;*******************************************************************************
*************************
OS_CPU_ARM_ExceptFiqHndlr
SUB LR, LR, #4 ; LR offset to return from this exception: -4
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
;*******************************************************************************
*************************
; GLOBAL EXCEPTION HANDLER
;*******************************************************************************
*************************
OS_CPU_ARM_ExceptHndlr
MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR)
; DETERMINE IF WE INTERRUPTED A TASK OR ANOTHER LOWER PRIORITY EXCEPTION
; SPSR.Mode = FIQ, IRQ, SVC, ABT, UND : Other exception
; SPSR.Mode = SYS : Task
; SPSR.Mode = USR : *unsupported state*
AND R2, R1, #OS_CPU_ARM_MODE_MASK
CMP R2, #OS_CPU_ARM_MODE_SYS
BNE OS_CPU_ARM_ExceptHndlr_BreakExcept
и далее по тексту.
В результате попадаем уже в C-ную функцию - обработчик:
Код
void OS_CPU_ExceptHndlr (CPU_DATA except_id) {
BSP_FNCT_PTR pfnct;
CPU_INT32U *sp;
if (except_id == OS_CPU_ARM_EXCEPT_FIQ) {
pfnct = (BSP_FNCT_PTR)*AT91C_AIC_FVR; // Read the interrupt vector from the AIC.
*AT91C_AIC_FVR=0; // Protected mode
if (pfnct != (BSP_FNCT_PTR)0) { // Make sure we don't have a NULL pointer.
(*pfnct)(); // Execute the ISR for the interrupting device.
}
}
else {
if (except_id == OS_CPU_ARM_EXCEPT_IRQ) {
pfnct = (BSP_FNCT_PTR)*AT91C_AIC_IVR; // Read the interrupt vector from the AIC.
*AT91C_AIC_IVR=0;
if (pfnct != (BSP_FNCT_PTR)0) { // Make sure we don't have a NULL pointer.
(*pfnct)(); // Execute the ISR for the interrupting device.
}
} else {
... тут вырезан вывод в dbgu инфы об исключении ...
// Infinite loop on other exceptions.
// Should be replaced by other behavior (reboot, etc.)
while (DEF_TRUE) {
;
}
}
}
}
Эту функцию пришлось переделать, т.к. она не читала AIC_FVR для FIQ, а было написано чтение AIC_IVR в любом варианте, что для FIQ не работало. Сейчас вызывается обработчик, который мы записали в AIC_SVR[0], сам этот обработчик вот такой:
Код
void FIQ_Handler (void) {
FIQ_counter++;
}
В EOICR не записываю ничего, т.к. FIQ настроен на фронт и автоматичекси сбрасывается при чтении AIC_FVR. Хотя и писать пробовал тоже, результат одинаков.
В принципе, все работает ... но недолго. Запускаю прогу, беру проводочек и начинаю FIQ вход им коротить на землю. В результате на один 'коротыш' выскакивает от нескольких, до сотни прерываний из за дребезга. И может насчитать несколько тысяч но, в какой-то прекрасный момент, процессор проваливается в data abort. После долгих колупаний удалось выяснить, что в функции OS_SchedNew переменная OSPrioHighRdy получает значение 56 (десятичное). С какого перепугу я так и не понял, а такой задачи у меня нет, т.е. TCB у неё нулевой. При попытке сшедулится на эту задачу операционка воспринимает начало памяти с 0 адреса как TCB, грузит в R13 вместо адреса стека команду перехода и, в результате попытки чтения из стека, из адреса 0xEA...... происходит data abort.
Если FIQ не тыкать - всё работает долго и стабильно. Может кто сталкивался с подобной проблемой? Или есть работающий пример с FIQ под uCOS и IAR? Ну или хоть какой, где FIQ и IRQ работают в параллель? А то уже блин и идей нет, как это можно отыскать