Hi After some research I was able to make the external interrupt to work with the LPC2129 under Crossworks 1.5. However, when asserted the external signal (low-edge) the code jumps to my ISR, but instead of exiting it enters again, and after this time the code starts at the init of the main function, and after some instructions it stops working. I've followed the procedure to acknoledge the interrupt, and I have no idea why this is working like that. I guess it's not hard to use the interrupts, but I've spent some days trying this thing to work properly. Besides I added an irq_handler() function because if not the code enters into a infinite loop. Any idea?? Am I missing something?? This is the code, and if more info is need please ask. Thanks =) //====================================================================== ====== #include <stdio.h> #include <targets/lpc21xx.h> static void isrEINT3(void) _attribute_ ((interrupt ("IRQ"))); //static void irq_handler(void) _attribute_ ((interrupt ("IRQ"))); void ledInit(void){ IO1DIR = 0; IO1DIR |= (3 << 22); IO1SET = (3 << 22); } #define led1On IO1CLR=(1<<22) #define led1Off IO1SET=(1<<22) #define led2On IO1CLR=(1<<23) #define led2Off IO1SET=(1<<23) void delay(unsigned d){ asm volatile("subs r0, r0, #0x00000001"); asm volatile("bne -1"); } void isrEINT3(void){ EXTINT = 8; /* Clear the interrupt */ VICVectAddr = 0; /* Update VIC priorities */ } void vicInit(void){ VICIntSelect=0; /* all vectored IRQ */ VICIntEnable=(1<<17); /* enable eint3 */ VICVectCntl1=(1<<5)|(17); /* enable eint3 */ VICVectAddr1=(unsigned long)isrEINT3; /* eint isr address */ } void eintInit(void){ EXTINT=0xff; /* clear any pending interrupt */ EXTMODE=(1<<3); /* edge-sensitive */ EXTPOLAR=0; /* low-active */ } /* ATTENTION HERE IS WHERE THE CORRECT ISR IS ADDRESSED, HOWEVER WHEN THE ISR RETURNS IT STUCKS AT THE <MARKED> INTRUCTION AND ENTERS AGAIN TO THE ISR */ void irq_handler(void){ // <-- Added to handle the IRQ void (*interrupt_function)(); unsigned int vector; vector = VICVectAddr; // Get interrupt vector. interrupt_function = (void(*)())vector; (*interrupt_function)(); // <<< MARKED >>> VICVectAddr = 0; // Clear interrupt in VIC. } void boardInit(void){ IO1DIR = 0; IO1DIR |= (3 << 22); /* leds on board*/ IO1SET = (3 << 22); PINSEL1 |= (0x0F << 6); eintInit(); /* initializes eint3 */ vicInit(); // <----- Initilize the VIC __ARMLIB_enableIRQ(); } int main(void){ boardInit(); led1On; /* board is alive */ for(;;); return 0; } //====================================================================== ======
Hi again I guess I found how to make this thing to work. The code is the same except that I changed the attributes to these //static void isrEINT3(void) _attribute_ ((interrupt ("IRQ"))); static void irq_handler(void) _attribute_ ((interrupt ("IRQ"))); My board now is counting external pulses. According what I'm seeing I can say that the only function that must be marked with the attribute "IRQ" is the IRQ handler function, whereas the other isr's should be treated as normal functions. Is this thought right??
Javier Rod wrote: > Hi again > > I guess I found how to make this thing to work. The code is the same > except that I changed the attributes to these > > //static void isrEINT3(void) _attribute_ ((interrupt ("IRQ"))); > static void irq_handler(void) _attribute_ ((interrupt ("IRQ"))); > > My board now is counting external pulses. According what I'm seeing I > can say that the only function that must be marked with the attribute > "IRQ" is the IRQ handler function, whereas the other isr's should be > treated as normal functions. > > Is this thought right?? Depends on you exceptions-settings. I expect you will find something like this in your startup-code/vectors-settings: [...] LDR PC, IRQ_Addr [...] IRQ_Addr: .word irq_handler [...] So on an IRQ exception your c-function irq_handler() gets called. The c-function is a "wrapper" which reads the address of the service-routine (isrEINT3()) from the VIC and calls it though a C-function-pointer. The function called by the core must be "prepared" for IRQ which can be done for example with the attribute like here. Functions called from inside the wrapper are usual C-Functions. I guess you have been confused by the different approaches how a IRQ-hander can be called. Other examples for LPC load the PC directly from the VIC with something like LDR PC, [PC, #xxxxxx] at the IRQ address. In this case isrEINT3 would be called directly and preparation would be needed (i.e. attribute).
> > Depends on you exceptions-settings. I expect you will find something > like this in your startup-code/vectors-settings: > > [...] > LDR PC, IRQ_Addr > [...] > IRQ_Addr: .word irq_handler > [...] > > So on an IRQ exception your c-function irq_handler() gets called. The > c-function is a "wrapper" which reads the address of the service-routine > (isrEINT3()) from the VIC and calls it though a C-function-pointer. The > function called by the core must be "prepared" for IRQ which can be done > for example with the attribute like here. Functions called from inside > the wrapper are usual C-Functions. > > I guess you have been confused by the different approaches how a > IRQ-hander can be called. Other examples for LPC load the PC directly > from the VIC with something like LDR PC, [PC, #xxxxxx] at the IRQ > address. In this case isrEINT3 would be called directly and preparation > would be needed (i.e. attribute). Hi!! Yes I'm very confused with the several aproaches to make the interrupts to work. I understood how to set up the interrupts, but there is a lack of information about what's next (irq_handler is not documented). I read some examples, and all were different among them, besides the compiler that will be used adds more complexity to this thing. After my code worked, I realized that the only function that must have the attributes is the one that will redirect the interrupt sources. There are examples where all the interrupt sources that are used have the atrributes, but I don't still have a clue why. Now I have the EINT3 and CAP1.2 peripherals working as interrupts in the way I found. If you may tell me where I can find some information about the attributes for the interrupts (something for idiots), you're welcome. Thanks !! =)
First you nee to understand that the ARM core only has two interrupt sources. Most ARM based microcontrollers have a interrupt controller. This external to the ARM core. The interrupt controller implementation varies amongst vendors and the compiler has no knowledge of this whatsoever. Furthermore interrupt handling is not defined in the C or C++ languages, so any provision for this by the compiler is proprietary. Personally in my projects I have never used this compiler extension, but rather hook a default handler in the start-up code, the handler then deals with teh interrupt controller, identifies the source, and calls an interrupt handler as a normal function through a pointer hooked in at runtime. My projects use an RTOS so this mechanism is a necessary part of the BSP. I imagine that something like freeRTOS for example will allow such mecanisms. Any way my point is that it is a good idea to take responsibility for interrupt handling rather than expect teh compiler to support it. The code will be more portable as a consequence. This free PDF book: http://www.hitex.co.uk/arm/lpc2000book/ may help. Its examples use the Keil compiler, but the discussion of the architectural aspects should still be useful to you. (and it is free!) Perhaps of more direct use is http://www.quantum-leaps.com/resources/papers.htm##GNU-ARM. It is GNU specific and parts 8 and 9 deal with interrupt handling. The files include links to many other resources. Unfortunately the first publication is LPC2xxx specific, but not GNU specific, while the second is is GNU specific but not LPC2xxx specific. In fact it uses an Atmel device for the examples. In both cases much of the principles apply regardless and the ARM core specifics are identical. You will have to be aware of the differences between the parts if not the compilers, so you should also have the LPC2xxx user manual to hand as well. Clifford
Hi Clifford!! I'm newbie at ARM architecture, so while I'm developing my application I'm learning this MCU, although I'm experienced 8 bit developer. Can you send my your irq_handler (just an example) in order to integrate it into my code?? Yours seems to be cleaner and more independant than I'm using. Thanks!! =)
Javier Rod wrote: > I'm learning this MCU, although I'm experienced 8 bit developer. Can you > send my your irq_handler (just an example) in order to integrate it into > my code?? Yours seems to be cleaner and more independent than I'm using. Unfortunately it is not strictly my code but rather that of my employer (even if I did write it). It also includes code that is the copyright of the RTOS vendor, so unfortunately not. Moreover it is for an ARM9 (Samsung S3C2410X) so may differ from what you need. I think the Quantum Leap code implements more or less teh architecture I suggested. You simply need to be aware of teh interrupt controller differences between the Atmel AM91 and the NXP LCP21xx. Clifford
Clifford Slocombe wrote: > Javier Rod wrote: >> I'm learning this MCU, although I'm experienced 8 bit developer. Can you >> send my your irq_handler (just an example) in order to integrate it into >> my code?? Yours seems to be cleaner and more independent than I'm using. > > Unfortunately it is not strictly my code but rather that of my > employer (even if I did write it). It also includes code that is the > copyright of the RTOS vendor, so unfortunately not. Moreover it is for > an ARM9 (Samsung S3C2410X) so may differ from what you need. I think the > Quantum Leap code implements more or less teh architecture I suggested. > You simply need to be aware of teh interrupt controller differences > between the Atmel AM91 and the NXP LCP21xx. The function __IRQ_Wrapper in file startup.S in the zip-package available from http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/lpc2k_bundle_port/index.html should demonstrate an implementation of the approach described by Clifford for LPC21xx.
Martin Thomas wrote: > Clifford Slocombe wrote: >> Javier Rod wrote: >>> I'm learning this MCU, although I'm experienced 8 bit developer. Can you >>> send my your irq_handler (just an example) in order to integrate it into >>> my code?? Yours seems to be cleaner and more independent than I'm using. >> >> Unfortunately it is not strictly my code but rather that of my >> employer (even if I did write it). It also includes code that is the >> copyright of the RTOS vendor, so unfortunately not. Moreover it is for >> an ARM9 (Samsung S3C2410X) so may differ from what you need. I think the >> Quantum Leap code implements more or less teh architecture I suggested. >> You simply need to be aware of teh interrupt controller differences >> between the Atmel AM91 and the NXP LCP21xx. > > The function __IRQ_Wrapper in file startup.S in the zip-package > available from > http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/lpc2k_bundle_port/index.html > should demonstrate an implementation of the approach described by > Clifford for LPC21xx. Thanks!! My system is now working in the way I explained before, however I'll take a look in order to do the things right (as the pros do). Let me ask you something related. When I reset the MCU through the RST pin it doesn't run (it does nothing). I need to cycle the power in order the MCU to work. Is this related with the reset interrupt??
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.