Перейти к содержанию
    

Обработка прерываний под FreeRTOS

Помогите, пожалуйста, разобраться.

 

Работаем с процессором 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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

:(

 

Во 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));

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Если не вызывать переключение контекста непосредственно по выходу из обработчика прерывания, то и сохранять весь контекст "по-FreeRTOS-овски" совершенно никчему. Писать совершенно обычные обработчики прерываний можно. У меня, например, крайне редко обработчики прерывания имеют переключение контекста - устраивает вызов планировщика из прерывания и отложенное до окончания текущей задачи/системного тика преключение контекста.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если не вызывать переключение контекста непосредственно по выходу из обработчика прерывания, то и сохранять весь контекст "по-FreeRTOS-овски" совершенно никчему. Писать совершенно обычные обработчики прерываний можно. У меня, например, крайне редко обработчики прерывания имеют переключение контекста - устраивает вызов планировщика из прерывания и отложенное до окончания текущей задачи/системного тика преключение контекста.

 

Можно и своё, но это уже когда в родном FreeRTOS-овском разберёшься. :) А по началу лучше следовать советам(примерам) разработчика оси, хуже точно не будет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А можно линк на страничку, где описывается работа с прерываниями? Чего-то при чтении сайта не нашёл.

Или пример оформления обработчика прерывания... :blush:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А можно линк на страничку, где описывается работа с прерываниями? Чего-то при чтении сайта не нашёл.

Или пример оформления обработчика прерывания... :blush:

 

Я из примеров всё беру... Да и в FAQ аффтар на example ссылается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...