реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Вложенные прерывания ARM7 LPC-2478
lecko
сообщение Sep 12 2011, 07:15
Сообщение #1





Группа: Участник
Сообщений: 10
Регистрация: 22-08-11
Пользователь №: 66 820



Всем привет!

У кого-нибудь есть работающий пример вложенных прерываний под LPC-2478? Облазил и форумы, и документацию - везде только общие рекомендацииsad.gif
Go to the top of the page
 
+Quote Post
Lotor
сообщение Sep 12 2011, 07:26
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866



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

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



--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Sep 12 2011, 07:36
Сообщение #3


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



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

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



--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
lecko
сообщение Sep 12 2011, 10:23
Сообщение #4





Группа: Участник
Сообщений: 10
Регистрация: 22-08-11
Пользователь №: 66 820



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

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

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

Код
#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, который я использую, утверждает, что адреса возврата сохранять не надо - компилятор-де делает это автоматически. Вопрос - почему во внутреннее прерывание не передается управление?
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Sep 12 2011, 11:11
Сообщение #5


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(lecko @ Sep 12 2011, 15:23) *
Вопрос - почему во внутреннее прерывание не передается управление?

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


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
lecko
сообщение Sep 12 2011, 11:50
Сообщение #6





Группа: Участник
Сообщений: 10
Регистрация: 22-08-11
Пользователь №: 66 820



Цитата(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
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Sep 12 2011, 12:25
Сообщение #7


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



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

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

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


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Sep 13 2011, 03:58
Сообщение #8


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



enter:

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





--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Sep 13 2011, 09:13
Сообщение #9


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



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

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

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


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Sep 14 2011, 07:49
Сообщение #10


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



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

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

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



--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 12:17
Рейтинг@Mail.ru


Страница сгенерированна за 0.01439 секунд с 7
ELECTRONIX ©2004-2016