Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Обработка прерываний под FreeRTOS
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > FreeRTOS
Igor_F
Помогите, пожалуйста, разобраться.

Работаем с процессором AT91SAM7X256, компилятор IAR.
Есть два обработчика IRQ. Первый из них:


//////////////////////////////////////////
IRQ_Handler_Entry:

;-------------------------
;- Manage Exception Entry
;-------------------------
;- Adjust and save LR_irq in IRQ stack
sub lr, lr, #4
stmfd sp!, {lr}

;- Save r0 and SPSR (need to be saved for nested interrupt)
mrs r14, SPSR
stmfd sp!, {r0,r14}

;- 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

;----------------------------------------------
;- Manage Exception Exit
;----------------------------------------------
;- 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 SPSR_irq and r0 from IRQ stack
ldmia sp!, {r0,r14}
msr SPSR_cxsf, r14

;- Restore adjusted LR_irq from IRQ stack directly in the PC
ldmia sp!, {pc}^
///////////////////////////////////////////


И второй, который вызывается по следующей команде:

LDR PC, [PC, #-0xF20] ; Jump directly to the address given by the AIC

Вот этот обработчик:

vPortPreemptiveTick:
portSAVE_CONTEXT ; Save the context of the current task.

LDR R0, =vTaskIncrementTick ; Increment the tick count - this may wake a task.
mov lr, pc
BX R0
LDR R0, =vTaskSwitchContext ; Select the next task to execute.
mov lr, pc
BX R0

LDR R14, =AT91C_BASE_PITC ; Clear the PIT interrupt
LDR R0, [R14, #PITC_PIVR ]

LDR R14, =AT91C_BASE_AIC ; Mark the End of Interrupt on the AIC
STR R14, [R14, #AIC_EOICR]

portRESTORE_CONTEXT ; Restore the context of the selected task.


При этом первый из них нормально обрабатывает прерывания USART-а, но при переключении между задачами программа вылетает в исключение Data Abort.

При использовании второго обработчика переключение между задачами происходит корректно, но другие прерывания (USART, таймеры) не работают (тоже происходит исключение Data Abort).

Подскажите, как можно объединить два эти обработчика.

И, если не трудно, оставьте ссылку на data sheet с описанием ассемблера AT91SAM7X256.
xelax
sad.gif

Во FreeRTOS сохранение контекста реализованно в самой оси.

А по сему первый и второй обработчики неверены.

Вот так обработчики прерывания стартуют. То есть видно, что адрес IRQ обработчика берётся напрямую из регистра AIC, без каких-либо самостоятельных сохранений контекста
Код
b     _start                        /* reset - _start            */
    ldr   pc, _undf                        /* undefined - _undf        */
    ldr   pc, _swi                        /* SWI - _swi                */
    ldr   pc, _pabt                        /* program abort - _pabt    */
    ldr   pc, _dabt                        /* data abort - _dabt        */
    nop                                    /* reserved                    */
    ldr   pc, [pc,#-0xF20]                /* IRQ - read the AIC        */
    ldr   pc, _fiq                        /* FIQ - _fiq                */


А все твои обработчики, адреса которых ты записываешь в AIC должны иметь следующий вид.

Вот пример прерывания от EMAC из примеров с сайта FreeRTOS
Код
void  vEMACISR_Wrapper( void )
{
    /* Save the context of the interrupted task. */
    portSAVE_CONTEXT();

    /* Call the handler to do the work.  This must be a separate
    function to ensure the stack frame is set up correctly. */
    vEMACISR_Handler();

    /* Restore the context of whichever task will execute next. */
    portRESTORE_CONTEXT();
}


То есть сначала сохраняется контекст, затем выполняется твой обработчик, затем контекст восстанавливается.

Когда реализуешь всё таким образом, должно заработать.

З.Ы.

ВАЖНО!!! Все функции обработчика должны быть без пролога и эпилога. Т.е. объявлены следующим образом.
Код
/* The interrupt entry point is naked so we can control the context saving. */
void vEMACISR_Wrapper( void ) __attribute__((naked));
zltigo
Цитата(xelax @ Feb 11 2008, 15:50) *
То есть сначала сохраняется контекст, затем выполняется твой обработчик, затем контекст восстанавливается.

Если не вызывать переключение контекста непосредственно по выходу из обработчика прерывания, то и сохранять весь контекст "по-FreeRTOS-овски" совершенно никчему. Писать совершенно обычные обработчики прерываний можно. У меня, например, крайне редко обработчики прерывания имеют переключение контекста - устраивает вызов планировщика из прерывания и отложенное до окончания текущей задачи/системного тика преключение контекста.
xelax
Цитата(zltigo @ Feb 11 2008, 17:52) *
Если не вызывать переключение контекста непосредственно по выходу из обработчика прерывания, то и сохранять весь контекст "по-FreeRTOS-овски" совершенно никчему. Писать совершенно обычные обработчики прерываний можно. У меня, например, крайне редко обработчики прерывания имеют переключение контекста - устраивает вызов планировщика из прерывания и отложенное до окончания текущей задачи/системного тика преключение контекста.


Можно и своё, но это уже когда в родном FreeRTOS-овском разберёшься. smile.gif А по началу лучше следовать советам(примерам) разработчика оси, хуже точно не будет.
Chudik
А можно линк на страничку, где описывается работа с прерываниями? Чего-то при чтении сайта не нашёл.
Или пример оформления обработчика прерывания... blush.gif
xelax
Цитата(Chudik @ Feb 23 2008, 20:14) *
А можно линк на страничку, где описывается работа с прерываниями? Чего-то при чтении сайта не нашёл.
Или пример оформления обработчика прерывания... blush.gif


Я из примеров всё беру... Да и в FAQ аффтар на example ссылается.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.