I am trying to use EINT3 on LPC2148 in Logomatic2.
When EINT3 is triggered, it runs the ISR but it doesn’t come back to main in the end.
I have defined a Nonvectored interrupt, and it is performed, after this interrupt is done, it goes back to main, to where it came from. But If I don’t define nonvectored interrupt, It resets the Microcontroller.
When using vectored interrupts your handler needs to read the interrupt from the VICVectAddr (0xffffff030) and then call the interrupt routine.
How this is done depends on the general interrupt handler code and possibly compiler - the last time I tried using GCC it didn’t work due to a bug and so an interrupt dispatcher was needed (a general interrupt handler which loads the address and jumps there - the interrupt routine itself is then not declared as interrupt but as normal sub-routine since the dispatcher performs the IRQ part.
If using a compiler that can do this it does something like this:
; Reset entry point
MODULE ?RESET
COMMON INTVEC:CODE:NOROOT(2)
PUBLIC __program_start
EXTERN ?cstartup
CODE32 ; Always ARM mode after reset
ORG 0x00 ; reset starts at address 0
__program_start
ldr pc,[pc,#24] ; Branch to program start
org 0x04
ldr pc,[pc,#24] ; Branch to undef_handler
org 0x08
ldr pc,[pc,#24] ; Branch to swi_handler
org 0x0c
ldr pc,[pc,#24] ; Branch to prefetch_handler
org 0x10
ldr pc,[pc,#24] ; Branch to data_handler
org 0x18
LDR PC, [PC, #-0x0FF0] ; Vector from VicVectAddr
org 0x1c
ldr pc,[pc,#24] ; Branch to fiq_handler
In this case the line
LDR PC, [PC, #-0x0FF0] ; Vector from VicVectAddr
does a direct branch to the interrupt routine (which is also a real interrupt routine and so much be declared correctly).
As mentioned before - I am not sure that this works with GCC since it doesn’t correctly handle the method.
stevech:
I use the mode where you store the address of the ISR in the interrupt number and let the hardware do the vectoring.
Hi thanks for the answer, but may I ask How exactly you do it?
durin this time I tried to use Keil, but I cannot, because I need to use SDMemory and also the Sparkfun bootlaoder so Keil doesnät build FW.SFE and nither has a good examples like bubblelogger and logomatic example that I can easyly chang for my own application. But for now I definitely need to use external interrupts there.
Also dear mjbcswitzerland, I really donät think I can change the Startup.S is seems to be so complicated.
I find it easier to have a common vector and dispatch, but use the VIC to store a pointer to device context for the device. (Including func ptr/vtable entry to the device interrupt handler.) This means you load up the VIC with addresses of device structures but set the vector itself not to read from the VIC but jump to a fixed handler. I also do this because I like to save thread state and update the VIC enable bits to implement IPLs. The common handler in my case also saves thread state. Kinda repetitive to make every device interrupt handler have to do that, although it would probably save 5 instructions or so. (But running out of internal NOR flash that’s negligible. And there’s always FIQ for even better latency.)
In my soft-IPL model each device context structure (class Device) contains two 32-bit values that are loaded into two VIC registers by the common handler, and the device interrupt handler then reenables interrupts if it wants to. A Device::SetIPL() method computes the values to use for each device - basically a mask with only the devices enabled that have higher IPLs. When the device interrupt handler is invoked the CPU is at that soft IPL. I try to do as much as possible out of interrupt using elevated priority threads, especially things like ethernet drivers and protocol processing. All the ethernet drive does for instance is to signal a condition on the Device that wakes a thread that then performs mac/ip processing. So it’s pretty cheap, reasonable latency, and fully preemptible; when the ethernet interrupt handler the protocol thread is the one reloaded on return, if nothing of higher priority is already running. Schedulers IMO are better than IPLs and VIC masking, and it’s more SMP friendly. (Although using a shared controller.) I like to resort to interrupt masking and priorities only when either a scheduler can’t really do something, or as low-level glue (cross the t’s and dot the i’s kinda thing).