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; }
What did you expect to happen?
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 } }