Gradient 0 Posted December 10, 2021 · Report post Модифицирую чужой старенький проект для LPC2138. Портировал код под IAR. Все хорошо даже, частично работает, кроме отсутствия прерываний. Прерывание по событию взводится, в отладчике флаги видно. Но перехода на обработчик нет. Сделал вектор как в старом примере от IAR: #pragma vector=0x18 __irq void IRQ_ISR_Handler(void) { void (*interrupt_function)(); unsigned int vector; //Get interrupt vector. vector = VICVectAddr; interrupt_function = (void(*)())vector; // Call vectored interrupt function. (*interrupt_function)(); } Но линкер не размещает вектор по указанному адресу. в map файле он лежит по адресу: 0x00005b20 IRQ_ISR_Handler() 0x00005b20 0x28 Code Gb Подскажите, что сделал не правильно или забыл? Quote Ответить с цитированием Share this post Link to post Share on other sites
jcxz 0 Posted December 10, 2021 · Report post 43 минуты назад, Gradient сказал: Но линкер не размещает вектор по указанному адресу. А какой адрес Вы считаете "правильным" и почему компилятор должен IRQ_ISR_Handler() туда поместить? Цитата в map файле он лежит по адресу: 0x00005b20 IRQ_ISR_Handler() 0x00005b20 0x28 Code Gb Не вижу ничего криминального. Вы понимаете как устроена система прерываний в ARM7? PS: Советую всё-таки найти таблицу векторов прерываний и проверить её. И проверить, что интересующий источник прерываний переключен в режим "IRQ". Quote Ответить с цитированием Share this post Link to post Share on other sites
Gradient 0 Posted December 10, 2021 (edited) · Report post Никогда не работал с ARM7, понимаю смутно. Цитата Для векторизованных и невекторизованных прерываний следующая инструкция должна быть размещена по адресу 0x18: LDR pc, [pc,#-0xFF0] Согласно доке, по адресу 0x18 должна лежать инструкция: ldr pc,[pc,#24] ;IRQ_Handler Посмотрел код Disasm, там Abort_Handler. В стартап файле такое: __vector: ; All default exception handlers (except reset) are ; defined as weak symbol definitions. ; If a handler is defined by the application it will take precedence. ldr PC,Reset_Addr ; To allow remap, a relative branch is required ! ldr PC,Undefined_Addr ; Undefined instructions ldr PC,SWI_Addr ; Software interrupt (SWI/SVC) ldr PC,Prefetch_Addr ; Prefetch abort ldr PC,Abort_Addr ; Data abort __vector_0x14: dcd 0 ; RESERVED ldr PC,IRQ_Addr ; IRQ ldr PC,FIQ_Addr ; FIQ DATA Reset_Addr: DCD __iar_program_start Undefined_Addr: DCD Undefined_Handler SWI_Addr: DCD SWI_Handler Prefetch_Addr: DCD Prefetch_Handler Abort_Addr: DCD Abort_Handler IRQ_Addr: DCD IRQ_Handler FIQ_Addr: DCD FIQ_Handler __vector_end: Вроде правильный стартап... Edited December 10, 2021 by Gradient Quote Ответить с цитированием Share this post Link to post Share on other sites
jcxz 0 Posted December 10, 2021 · Report post 32 минуты назад, Gradient сказал: Согласно доке, по адресу 0x18 должна лежать инструкция: ldr pc,[pc,#24] ;IRQ_Handler Не обязательно, но обычно. Цитата Теперь разбирайтесь почему у вас все Handler-ы заменились на Abort_Handler. Видимо IRQ_Handler() неправильно объявлен или не объявлен вовсе в этом asm-файле где таблица векторов. Quote Ответить с цитированием Share this post Link to post Share on other sites
Gradient 0 Posted December 10, 2021 · Report post Сообразил. Нельзя называть обработчики произвольными именами. А только как прописано в стартап файле. Т.е : IRQ_Addr: DCD IRQ_Handler FIQ_Addr: DCD FIQ_Handler Исправил, адреса прилинковались правильно. Но прерывания все равно не работают. Quote Ответить с цитированием Share this post Link to post Share on other sites
jcxz 0 Posted December 10, 2021 · Report post 1 минуту назад, Gradient сказал: Но прерывания все равно не работают. 50 минут назад, jcxz сказал: И проверить, что интересующий источник прерываний переключен в режим "IRQ". Quote Ответить с цитированием Share this post Link to post Share on other sites
Gradient 0 Posted December 10, 2021 (edited) · Report post // All interrupts are routed to IRQ (not FIQ) VICIntSelect = 0; Вроде переключено. Прерываний нет... Вероятно не правильно переключаю. Подскажите как сделать. Edited December 10, 2021 by Gradient Quote Ответить с цитированием Share this post Link to post Share on other sites
jcxz 0 Posted December 10, 2021 · Report post 31 минуту назад, Gradient сказал: Подскажите как сделать. Я уже давным-давно последний раз работал с этими LPC. Плохо помню. Контроллер прерываний (VIC) проинициализировали? Разрешили в нём соответствующий вектор? Прописали в него адреса ISR-ов? У меня было так: В самом начале main(): IntDisAll(); Потом далее инит самого VIC: void VIC_Init() { static void (__arm * const isrs[])(void) = { //vector addresses VIC_DummyWDT, VIC_DummySW, VIC_DummyDEBUGRX, VIC_DummyDEBUGTX, VIC_DummyTIMER0, VIC_DummyTIMER1, VIC_DummyUART0, VIC_DummyUART1, VIC_DummyPWM01, VIC_DummyI2C0, VIC_DummySPI, VIC_DummySSP1, VIC_DummyPLL, VIC_DummyRTC, VIC_DummyEINT0, VIC_DummyEINT1, VIC_DummyEINT2, VIC_DummyEINT3, VIC_DummyAD0, VIC_DummyI2C1, VIC_DummyBOD, VIC_DummyETHERNET, VIC_DummyUSB, VIC_DummyCAN01, VIC_DummyMMC, VIC_DummyGP_DMA, VIC_DummyTIMER2, VIC_DummyTIMER3, VIC_DummyUART2, VIC_DummyUART3, VIC_DummyI2C2, VIC_DummyI2S}; VICADDRESS = 0; //Acknowlege any pending VIC interrupt VICPROTECTION = 0; //Allow VIC register access in User of Priviledged modes int i = ncell(isrs) - 1; do { (&VICVECTADDR0)[i] = (u32)isrs[i]; (&VICVECTPRIORITY0)[i] = 15; } while (--i >= 0); } А потом далее, для каждой периферии, которой нужны прерывания (например I2C), инит вектора: IniVICvector(VIC_I2C0, ISRi2c0); Скрытый текст //DISABLE ALL INTERRUPTS void IntDisAll() { VICINTENCLEAR = ~0; } void IntDis(int vic) { VICINTENCLEAR = 1 << vic; } void IntEna(int vic) { VICINTENABLE = 1 << vic; } //установка обработчика IRQ isr на заданный вектор vic void IniVICvector(int vic, u32 (* isr)()) { //соответствие приоритетов прерываний векторам static const u8 vic2prio[] = { 14, //Watchdog 14, //Software interrupts 14, //Embedded ICE, DbgCommRx 14, //Embedded ICE, DbgCommTx 14, //Timer 0 (Match 0-3 Capture 0-3) 14, //Timer 1 (Match 0-3 Capture 0-3) 14, //UART 0 (RLS, THRE, RDA, CTI) 14, //UART 1 (RLS, THRE, RDA, CTI, MSI) 14, //PWM 01 (Match 0-6 Capture 0-3) 14, //I2C 0 (SI) 14, //SPI 0, SSP 0 15, //SSP 1 14, //PLL lock (PLOCK) 14, //RTC (RTCCIF, RTCALF) 14, //External interrupt 0 (EINT0) 14, //External interrupt 1 (EINT1) 14, //External interrupt 2 (EINT2) 14, //External interrupt 3 (EINT3) 14, //A/D converter 0 14, //I2C 1 14, //Brown out detect 14, //Ethernet 14, //USB Low and High priority 14, //CAN0,1 Tx, Rx 14, //SD/MMC 14, //DMA channel 0, DMA channel 1 14, //Timer 2 (Match 0-3 Capture 0-3) 14, //Timer 3 (Match 0-3 Capture 0-3) 14, //UART 2 (RLS, THRE, RDA, CTI) 13, //UART 3 (RLS, THRE, RDA, CTI, MSI) 14, //I2C 0 (SI) 14}; //I2S Rx, Tx VICINTSELECT &= ~(1 << vic); (&VICVECTPRIORITY0)[vic] = vic2prio[vic]; (&VICVECTADDR0)[vic] = (u32)isr; IntEna(vic); } Quote Ответить с цитированием Share this post Link to post Share on other sites
Gradient 0 Posted December 10, 2021 (edited) · Report post В общем - достало конкретно! Помог метод перебора, такой синтаксис: //#pragma vector = 0x18 extern "C" __irq __arm void IRQ_Handler(void){...} //#pragma vector = 0x1c extern "C" __fiq __arm void FIQ_Handler(void){...} Еслим прагму оставить - работать перестает. И надо обязательно свой стартап файл, со стандартным тоже не работает. startup_lpc21.zip Edited December 10, 2021 by Gradient Quote Ответить с цитированием Share this post Link to post Share on other sites