Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Message

Re: [lpc2000] Interrupt function declaration

2006-05-10 by Tom Walsh

Andy wrote:

>Thanks Tom,
>
>I'm still quite new to embedded systems generally so please bear with me.
>I'm running a task scheduler based on a 1ms tick using Timer0, so need one 
>interrupt for this.  In addition I require an interrupt from EINT3 due to an 
>external ethernet chip which requires attention when a message is recieved.
>The timer0 int is time critical and must happen on time, the external 
>interrupt can wait a bit if need be.  Currently I have the follow setup, do 
>you think this would be ok?
>
>  
>
Well, in that case, you want to run nested interrupts.  I don't use that 
mode, perhaps some others can comment on implementing nesting?

 From what I understand, you have to use some assembly language stubs 
to: save out some registers onto stack, ACK the current interrupt being 
serviced to allow others to pre-empt your current routine if needed, and 
then call your actual code for the current interrupt service.  Return 
from the call, restore the registers and simply return.


>VICVectAddr0 = (tDWord)Sch_Tick_Function;
>VICVectCntl0 = 0x20 | 4;
>VICIntEnable |= (1 << 4);
>
>VICVectAddr1 = (tDWord)W3100A_Int_Service;
>VICVectCntl1 = 0x20 | 17;
>VICIntEnable |= (1 << 17);
>
>  
>
What that will do is to allow preference for the Sch_Tick_Function over 
the W3100A_Int_Service should they be asserted simultaneously.  It does 
not allow the timer interrrupt to interrupt the execution of the W3100A 
service, if the timer fires during the ISR for the W3100A, it will be 
heldoff until you write to the VicVectAddr (VICVectAddr = 0;).  From the 
LPC2106 manual:

"Following the completion of the desired interrupt service routine, 
clearing of the interrupt flag on the peripheral level will propagate to 
corresponding bits in VIC registers (VICRawIntr, VICFIQStatus and 
VICIRQStatus). Also, before the next interrupt can be serviced, it is 
necessary that write is performed into the VICVectAddr register before 
the return from interrupt is executed. Thiswrite will clear the 
respective interrupt flag in the internal interrupt priority hardware."

Nesting handled differently.  As I mentioned, I do not have a need to 
nest.  Essentailly you have to simultaneously turn on the Interrupt an 
switch your context to Supv mode (this would be done by setting value in 
the CPSR register).  By switching to Supv Mode, you use the Supv stack 
for your ISR.  When a higher level interrupt pre-empts an on-going ISR, 
it would get the IRQ context stack, leaving your stack frame intact.

Then that higher level service switches to the Supv context.  So, your 
first job in the Supv context is to save registers(!) as you may have 
pre-empted  a lower ISR task.

I am not sure of the return process...

>and using the __attribute__((interrupt)); extention for the task 
>declarations.
>  
>
That attribute tells gcc that any register it uses in the service must 
be preserved.  gcc is two pass, maybe three pass, compiler, it will 
build the code, then when it is time to emit the opcodes, it will 
produce a prolog / epilog to save / restore registers used.

>The program sits in a while(1) loop until either of the interrupts occur.
>Also, so whats the __irq; extention for?
>  
>

Don't know, gcc-4.01 considers "__irq" in place of "__attribute__ 
((interrupt))" as a syntax error.  I would suspect that you are using a 
modified gcc compiler, or some other compiler?  Actually, I see no 
effect when using ((interrupt)), ((interrupt("IRQ"))), or 
((interrupt("FIQ"))) upon the code generated.  IIRC, I think that I read 
somewhere that those attributes are ignored?


TomW

-- 
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------------------------------------------

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.