This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Can't get interrupt to work

Hi, I am sorry if there is already a thread open with this problem, I just couldn't find it.

I have a problem which should be easy to solve for you guys. I am trying to get a simple interrupt service routine to run, when i press the INT0 button on a MCB2300 Board (LPC2368). I didn't chance the startup.s code at all. When I press the button, nothing happens. Please help me.

#include <LPC23xx.h>

int main(void) {

PINSEL10 = 0;
FIO2DIR  = 0x000000FF;
FIO2MASK = 0x00000000;
FIO2CLR = 0xFF;
FIO2SET =  0x55;

VICIntSelect = 0x00008000;
VICIntEnable = 0x00008000;


while(1){

}
return 0;
}


int i;

void __irq FIQ_Handler (void)  {
        FIO2DIR  = 0x000000FF;
        FIO2MASK = 0x00000000;
        //Here goes the interrupt
        for ( i = 0; i <10000; i++) {
                FIO2CLR = 0xFF;
                FIO2SET =       0xAA;
        }
        FIO2CLR = 0xFF;
        VICVectAddr = 0x00000000;
}

  • I wanted the LEDs to change their pattern from 0x55 to 0xAA.

  • and what did you actually see?

  • All it does till now is: it turns on LEDs 0, 2, 4, 6. And when I press the button, nothing happens but it should switch on LEDs 1, 3, 5, 7 or something similar, or just something... anything! :(

  • Are the Fast Interrupts enabled within the Core?

  • Hi and thanks again. I know I am new to this and this all is pretty annoying to you.

    I changed my code a bit. I tried to use the vectored interrupts, but still it won't work. Maybe I do not understand the layout of the MCB2300 Board correctly. I looked up the interrupts in the NXP manual on page 90 FF, than I made sure the button INT0 is connected to EINT0 as interrupt source. Still nothing happens.
    I do not know, if the FIQs are activated in the core, mainly cause I don't know how to do that. But as far as I understand this is not necessary if I use vectored IRQs? I changed from FIQ to IRQ anyhow, do I have to activate them somewhere else?

    Here is my code as follows:

    int a;
    
    extern __irq void interrupt1(void);
    int main(void) {
    
    PINSEL10 = 0;
    FIO2DIR  = 0x000000FF;
    FIO2MASK = 0x00000000;
    
    
    /***
    *       Make sure interrupt 14 (EINT0) is used as IRQ
    ***/
    VICIntSelect = 0x00000000;      //(0 = IRQ / 1 = FIQ)
    
    /***
    *       aktivate interrupt 14 (EINT0)
    ***/
    VICIntEnable = 0x00004000;
    
    /***
    *       setup vector address register 14 to point to irq method
    ***/
    VICVectAddr14 = (unsigned long)interrupt1;
    
    while(1){
    
            //loop around and let the LEDs blink
            FIO2CLR = 0xFF;
            for(a=0; a<5000; a++)
                    FIO2SET =  0x55;
                    FIO2CLR = 0xFF;
            for(a=0; a<5000; a++)
                    FIO2SET = 0xAA;
    }
    
    return 0;
    }
    

    and in another file the interrupt method itself:

    int i;
    
    void interrupt1 (void) __irq {
            FIO2DIR  = 0x000000FF;
            FIO2MASK = 0x00000000;
            for ( i = 0; i <10000; i++) {
                    FIO2CLR = 0xFF;
                    FIO2SET = 0x0F;
            }
            FIO2CLR = 0xFF;
            VICVectAddr = 0x00000000;
    }
    

    thats all I have done till now, I may have forgotten a lot, because I don't know better.
    Thanks for your help!

  • I haven't an code playing with EINT0, but with EINT2. Note that I have declared a number of constants to make the code more readable:

    enum {
        EINT2           = 0x04,
        EINT2_EDGE      = 0x04,
        EXTMODE2        = 0x04,
        INT_EINT0       = 14,
        INT_EINT1       = 15,
        INT_EINT2       = 16,
        INT_EINT3       = 17,
    };
    
    unsigned eint2_irq_count;       ///< Total # of EINT2 interrupts.
    
    void eint2_irq(void) __irq {
        EXTINT = EINT2;             // Clear interrupt.
        eint2_irq_count++;
        VICVectAddr = 0;            // Acknowledge Interrupt
    }
    
    void init_eint2(void) {
        // Enable EINT2 on P2.12
        PINSEL4 = (PINSEL4 % ~0x3000000) | 0x1000000;
    
        // Falling edge.
        EXTMODE |= EINT2_EDGE;      // 0x04 - Edge-triggged.
        EXTPOLAR &= ~EXTMODE2;      // 0x04 - Falling edge.
        EXTINT = EINT2;             // Enable interrupt.
    
        VICVectAddr16 = (unsigned long)eint2_irq;
        VICVectCntl16 = PRIO_EINT2;         // Wrong symbol name in Keil header - is VICVectPriority16
        VICIntEnable = 1 << INT_EINT2;      // Enable EINT2 Interrupt
    }
    


    But you really have to do something about that uggly interrupt handler of yours.
    1) Why do you think your interrupt handler have to change in/out direction for the LED pins - shouldn't main() have done that earlier?
    2) Why do you think it's ok for a lowly little interrupt handler to control input/output direction for 32 processor pins when all you want is to make sure that 8 of the pins are outputs?
    3) Are you sure the interrupt handler should modify the mask bits for 32 GPIO pins just to be able to write to 8 LEDs?
    4) No busy-loops in an interrupt - you want them short. Use a timer or something else to restore original state of LEDs x ms after the interrupt handler changed the state. But do not stay in the interrupt handler like that.
    5) Do you really want a global variable with the ugly name "i"? A temporary variable used for a local loop should really not get itself upgraded to a global variable to be seen by all of the program. That is just namespace pollution. Besides - the interrupt handler has its own stack allowing it to have local variables.
    6) Your main() function has some very creative indenting - including a line that looks like it's part of a for loop, while it isn't.

  • Hi, I tried to change the code but it didn't work. So I looked around a bit and tried to find a solution but all I found didn't work.

    I now use code I found on the internet and changed a bit but still, nothing.

    I know my code wasn't exactly what one would call beautiful, it was just for testing, nothing to keep for later.

    So can anyone tell me whats wrong here?

    #include <stdio.h>
    #include <LPC23xx.H>
    
    
    void initialize_leds (void)
    {
      FIO2DIR  = 0x000000FF;            // Define P2.0 through P2.7 as Outputs
      FIO2MASK = 0x00000000;
    }
    
    void set_led(unsigned int value)
    {
      FIO2CLR = 0xFF;
      FIO2SET = (value & 0xFF);
    }
    
    volatile int led_state = 0;
    
    void isr_handler_eint0(void) __irq // for external interrupt 0
    {
            VICIntEnClr = (1 << 14); // Disable EINT0 in the VIC
    
            //this causes the leds to light up in sequence
            led_state = ( led_state << 1 ) | 1;
    
            //if all leds are lit up, turn them all off
            if( led_state > 0xFF)
                    led_state = 0;
    
            set_led(led_state);
    
            //EXTPOLAR = 1; // next interrupt on rising edge
    
            EXTINT = 0x01; // Clear the peripheral interrupt flag
            VICIntEnable = (1 << 14); // Enable EINT0 in the VIC
            VICVectAddr = 0; // Acknowledge Interrupt
    }
    
    
    void initialize_eint0 (void)
    {
            // P2.10 as EINT0 interrupt    (push button on MCB2300)
            PINSEL4 |= 0x01 << 20;
            // EINT0 is (falling) edge-sensitive
            EXTMODE = 0x01;
            // assign our ISR handler function to this VIC address
            VICVectAddr14 = (unsigned) isr_handler_eint0;
            // Interrupt on the falling edge (should default to 0)
            EXTPOLAR = 0x00;
    
            // Clear the peripheral interrupt flag
            EXTINT = 0x01;
            // Enable EINT0
            VICIntEnable = (1 << 14);
    }
    
    
    
    __inline void enable_IRQ(void)
    {
    int tmp;
        __asm
        {
            MRS tmp, CPSR
            BIC tmp, tmp, #0x80
            MSR CPSR_c, tmp
        }
    }
    
    __inline void enable_FIQ(void)
    {
    int tmp;
        __asm
        {
            MRS tmp, CPSR
            BIC tmp, tmp, #0x40
            MSR CPSR_c, tmp
        }
    }
    
    int main (void)
    {
            enable_IRQ();
            enable_FIQ();
    
            PINSEL10 = 0;                   // Disable ETM interface
    
            initialize_leds();              // Init LEDS
    
            initialize_eint0();             // Init EINT0
    
            while (1)
            {
                    // ... do nothing
            }
    
    }