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

Вложенные прерывания ARM7 LPC-2478

Всем привет!

 

У кого-нибудь есть работающий пример вложенных прерываний под LPC-2478? Облазил и форумы, и документацию - везде только общие рекомендации:(

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


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

Ну вложенные прерывания аппаратно не поддерживаются, один из костылей приведен в книги Тревора Мартина.

 

Макросы аля

#define IENABLE __asm { MRS sysreg, SPSR; MSR CPSR_c, #SYS32Mode }
#define IDISABLE __asm { MSR CPSR_c, #(IRQ32Mode|I_Bit); MSR SPSR_cxsf, sysreg }

 

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


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

А что хочется увидеть? Какие волшебные строки?

А указания могут быть только общими:

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

 

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

На вашей совести останется только сброс своего прерывания и отдача команды VIC...

 

 

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


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

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

 

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

 

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

 

#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, который я использую, утверждает, что адреса возврата сохранять не надо - компилятор-де делает это автоматически. Вопрос - почему во внутреннее прерывание не передается управление?

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


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

Вопрос - почему во внутреннее прерывание не передается управление?

Да потому, что при вызове первого прерывания глобально прерывания запрещаются и их нужно ручками разрешать (после IENABLE), а потом запрещать (перед IDISABLE).

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


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

Да потому, что при вызове первого прерывания глобально прерывания запрещаются и их нужно ручками разрешать (после 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;
}

 

Все равно не работает :(

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


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

Все равно не работает :(

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

 

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

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


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

enter:

 

ResetYourInterruptSource();// Источник прерывания должен перестать выставлять прерывание.

VICAddress=0;//Сообщаем ВИК, что он может опять принимать прерывания.

__enable_irq();//Процессор будет на них реагировать.

 

 

 

 

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


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

enter:

 

ResetYourInterruptSource();// Источник прерывания должен перестать выставлять прерывание.

VICAddress=0;//Сообщаем ВИК, что он может опять принимать прерывания.

__enable_irq();//Процессор будет на них реагировать.

Ни в коем случае. Так можно зависнуть в рекурсии :biggrin:

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


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

Если снимаешь источник, то почему?

 

Либо надо знать точно, зачем тебе вложенные прерывания.

Я вот в последнем проекте поставил рекорд. У меня всего одно прерывание вообще. От таймера.

(При этом работает USB host -680K\c, Device mass storage, SD card - 5M\c - две штуки).

 

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

 

 

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


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

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

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

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

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

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

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

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

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

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