lecko 0 12 сентября, 2011 Опубликовано 12 сентября, 2011 · Жалоба Всем привет! У кого-нибудь есть работающий пример вложенных прерываний под LPC-2478? Облазил и форумы, и документацию - везде только общие рекомендации:( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lotor 0 12 сентября, 2011 Опубликовано 12 сентября, 2011 · Жалоба Ну вложенные прерывания аппаратно не поддерживаются, один из костылей приведен в книги Тревора Мартина. Макросы аля #define IENABLE __asm { MRS sysreg, SPSR; MSR CPSR_c, #SYS32Mode } #define IDISABLE __asm { MSR CPSR_c, #(IRQ32Mode|I_Bit); MSR SPSR_cxsf, sysreg } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 12 сентября, 2011 Опубликовано 12 сентября, 2011 · Жалоба А что хочется увидеть? Какие волшебные строки? А указания могут быть только общими: Внутри обработчика надо сохранить адрес возврата где-нибудь, разрешить прерывания, сбросить собственный источник прерывания и дать команду VIC, что собственное прерывание завершено. После чего начинать выполнять код прерывания. Реализация всего этого в большей части возлагается на компилятор. К примеру, в IAR, достаточно указать атрибут __nested и обработчик будет оформлен соответсвующим образом. На вашей совести останется только сброс своего прерывания и отдача команды VIC... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lecko 0 12 сентября, 2011 Опубликовано 12 сентября, 2011 · Жалоба Спасибо за ответ! В соответствии с общими указаниями сделано следующее: Так выглядит код внешнего прерывания: #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 0 12 сентября, 2011 Опубликовано 12 сентября, 2011 · Жалоба Вопрос - почему во внутреннее прерывание не передается управление? Да потому, что при вызове первого прерывания глобально прерывания запрещаются и их нужно ручками разрешать (после IENABLE), а потом запрещать (перед IDISABLE). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lecko 0 12 сентября, 2011 Опубликовано 12 сентября, 2011 · Жалоба Да потому, что при вызове первого прерывания глобально прерывания запрещаются и их нужно ручками разрешать (после 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; } Все равно не работает :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 12 сентября, 2011 Опубликовано 12 сентября, 2011 · Жалоба Все равно не работает :( Читаем ещё раз моё сообщение. Во-первых оба прерывания в VIC должны быть уже разрешены и настроены. Во-вторых глобальное разрешение прерываний (которое должно быть сразу после IENABLE) в IAR-е пишется как __enable_interrupt(). В РеалВью не знаю как. Но суть команды в сбросе флага I (иногда вместе с F) во флагах ядра ARM7. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 13 сентября, 2011 Опубликовано 13 сентября, 2011 · Жалоба enter: ResetYourInterruptSource();// Источник прерывания должен перестать выставлять прерывание. VICAddress=0;//Сообщаем ВИК, что он может опять принимать прерывания. __enable_irq();//Процессор будет на них реагировать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 13 сентября, 2011 Опубликовано 13 сентября, 2011 · Жалоба enter: ResetYourInterruptSource();// Источник прерывания должен перестать выставлять прерывание. VICAddress=0;//Сообщаем ВИК, что он может опять принимать прерывания. __enable_irq();//Процессор будет на них реагировать. Ни в коем случае. Так можно зависнуть в рекурсии Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 14 сентября, 2011 Опубликовано 14 сентября, 2011 · Жалоба Если снимаешь источник, то почему? Либо надо знать точно, зачем тебе вложенные прерывания. Я вот в последнем проекте поставил рекорд. У меня всего одно прерывание вообще. От таймера. (При этом работает USB host -680K\c, Device mass storage, SD card - 5M\c - две штуки). Т.е вложенные прерывания нужны для очень и очень конкретных целей. Ты должен точно знать что делаешь и зачем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться