Jump to content

    
Gradient

lpc2138, не работают прерывания

Recommended Posts

Модифицирую чужой старенький проект для 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

 

Подскажите, что сделал не правильно или забыл?

 

Share this post


Link to post
Share on other sites
43 минуты назад, Gradient сказал:

Но линкер не размещает вектор по указанному адресу.

А какой адрес Вы считаете "правильным" и почему компилятор должен IRQ_ISR_Handler() туда поместить?

Цитата

в map файле он лежит по адресу: 0x00005b20

IRQ_ISR_Handler()       0x00005b20    0x28  Code  Gb

Не вижу ничего криминального.  :unknw:

Вы понимаете как устроена система прерываний в ARM7?

 

PS: Советую всё-таки найти таблицу векторов прерываний и проверить её. И проверить, что интересующий источник прерываний переключен в режим "IRQ".

Share this post


Link to post
Share on other sites

Никогда не работал с 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:

Вроде правильный стартап...

 

iar-addr.png

Edited by Gradient

Share this post


Link to post
Share on other sites
32 минуты назад, Gradient сказал:

Согласно доке, по адресу 0x18 должна лежать инструкция: ldr pc,[pc,#24] ;IRQ_Handler

Не обязательно, но обычно.

Цитата

iar-addr.png

Теперь разбирайтесь почему у вас все Handler-ы заменились на Abort_Handler.  :unknw:

Видимо IRQ_Handler() неправильно объявлен или не объявлен вовсе в этом asm-файле где таблица векторов.

Share this post


Link to post
Share on other sites

Сообразил. Нельзя называть обработчики произвольными именами.

А только как прописано в стартап файле. Т.е :

 

IRQ_Addr:       DCD   IRQ_Handler
FIQ_Addr:       DCD   FIQ_Handler

 

Исправил, адреса прилинковались правильно.

Но прерывания все равно не работают.

Share this post


Link to post
Share on other sites
1 минуту назад, Gradient сказал:

Но прерывания все равно не работают.

50 минут назад, jcxz сказал:

И проверить, что интересующий источник прерываний переключен в режим "IRQ".

 

Share this post


Link to post
Share on other sites

// All interrupts are routed to IRQ (not FIQ)  
VICIntSelect = 0;

Вроде переключено.

Прерываний нет... Вероятно не правильно переключаю.

Подскажите как сделать.

 

iar-cpsr.png

Edited by Gradient

Share this post


Link to post
Share on other sites
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);
}

 

 

 

 

 

Share this post


Link to post
Share on other sites

В общем - достало конкретно!

Помог метод перебора, такой синтаксис:

//#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 by Gradient

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.