Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вложенные прерывания ARM7 LPC-2478
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
lecko
Всем привет!

У кого-нибудь есть работающий пример вложенных прерываний под LPC-2478? Облазил и форумы, и документацию - везде только общие рекомендацииsad.gif
Lotor
Ну вложенные прерывания аппаратно не поддерживаются, один из костылей приведен в книги Тревора Мартина.

Макросы аля
Код
#define IENABLE __asm { MRS sysreg, SPSR; MSR CPSR_c, #SYS32Mode }
#define IDISABLE __asm { MSR CPSR_c, #(IRQ32Mode|I_Bit); MSR SPSR_cxsf, sysreg }

DpInRock
А что хочется увидеть? Какие волшебные строки?
А указания могут быть только общими:
Внутри обработчика надо сохранить адрес возврата где-нибудь, разрешить прерывания, сбросить собственный источник прерывания и дать команду VIC, что собственное прерывание завершено. После чего начинать выполнять код прерывания.

Реализация всего этого в большей части возлагается на компилятор. К примеру, в IAR, достаточно указать атрибут __nested и обработчик будет оформлен соответсвующим образом.
На вашей совести останется только сброс своего прерывания и отдача команды VIC...

lecko
Спасибо за ответ!

В соответствии с общими указаниями сделано следующее:

Так выглядит код внешнего прерывания:

Код
#define IENABLE __asm { MRS sysreg, SPSR; MSR CPSR_c, #SYS32Mode }
#define IDISABLE __asm { MSR CPSR_c, #(IRQ32Mode|I_Bit); MSR SPSR_cxsf, sysreg }
...
void UARTHandler (void) __irq    
{
    IENABLE;
    ...
    //тут происходит вызов функции, инициирующей срабатывание вложенного прерывания
    ...
    IDISABLE;
    VICVectAddr = 0;
}


В коде внутреннего прерывания никаких специальных действий не происходит. Оба прерывания зарегистрированы с высшим приоритетом. Документация по компилятору RealView, который я использую, утверждает, что адреса возврата сохранять не надо - компилятор-де делает это автоматически. Вопрос - почему во внутреннее прерывание не передается управление?
GetSmart
Цитата(lecko @ Sep 12 2011, 15:23) *
Вопрос - почему во внутреннее прерывание не передается управление?

Да потому, что при вызове первого прерывания глобально прерывания запрещаются и их нужно ручками разрешать (после IENABLE), а потом запрещать (перед IDISABLE).
lecko
Цитата(GetSmart @ Sep 12 2011, 15:11) *
Да потому, что при вызове первого прерывания глобально прерывания запрещаются и их нужно ручками разрешать (после IENABLE), а потом запрещать (перед IDISABLE).


Сделал. Вторая версия кода:
Код
#define IENABLE __asm { MRS sysreg, SPSR; MSR CPSR_c, #SYS32Mode }
#define IDISABLE __asm { MSR CPSR_c, #(IRQ32Mode|I_Bit); MSR SPSR_cxsf, sysreg }
...
DWORD install_irq( DWORD IntNumber, void *HandlerAddr, DWORD Priority )
{
    DWORD *vect_addr;
    DWORD *vect_cntl;
      
    VICIntEnClr = 1 << IntNumber;
    if ( IntNumber >= VIC_SIZE )
    {
        return ( FALSE );
    }
    else
    {
        vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4);
        vect_cntl = (DWORD *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + IntNumber*4);
        *vect_addr = (DWORD)HandlerAddr;
        *vect_cntl = Priority;
        VICIntEnable = 1 << IntNumber;
        return( TRUE );
    }
}
...
void UARTHandler (void) __irq    
{
    IENABLE;
    install_irq(MCI_INT, (void*)MCI_IRQHandler, HIGHEST_PRIORITY);//включаем прерывание
    ...
    //тут происходит вызов функции, инициирующей срабатывание вложенного прерывания
    ...
    VICIntEnClr = 1 << IntNumber;//отключаем прерывание
    IDISABLE;
    VICVectAddr = 0;
}


Все равно не работает sad.gif
GetSmart
Цитата(lecko @ Sep 12 2011, 16:50) *
Все равно не работает sad.gif

Читаем ещё раз моё сообщение.

Во-первых оба прерывания в VIC должны быть уже разрешены и настроены. Во-вторых глобальное разрешение прерываний (которое должно быть сразу после IENABLE) в IAR-е пишется как __enable_interrupt(). В РеалВью не знаю как. Но суть команды в сбросе флага I (иногда вместе с F) во флагах ядра ARM7.
DpInRock
enter:

ResetYourInterruptSource();// Источник прерывания должен перестать выставлять прерывание.
VICAddress=0;//Сообщаем ВИК, что он может опять принимать прерывания.
__enable_irq();//Процессор будет на них реагировать.



GetSmart
Цитата(DpInRock @ Sep 13 2011, 08:58) *
enter:

ResetYourInterruptSource();// Источник прерывания должен перестать выставлять прерывание.
VICAddress=0;//Сообщаем ВИК, что он может опять принимать прерывания.
__enable_irq();//Процессор будет на них реагировать.

Ни в коем случае. Так можно зависнуть в рекурсии biggrin.gif
DpInRock
Если снимаешь источник, то почему?

Либо надо знать точно, зачем тебе вложенные прерывания.
Я вот в последнем проекте поставил рекорд. У меня всего одно прерывание вообще. От таймера.
(При этом работает USB host -680K\c, Device mass storage, SD card - 5M\c - две штуки).

Т.е вложенные прерывания нужны для очень и очень конкретных целей. Ты должен точно знать что делаешь и зачем.

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