Yahoo Groups archive

Lpc2000

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

Message

Re: [lpc2000] Interrupt function declaration

2006-05-11 by Andy

Robert,
I am running a shared clock network over ethernet, so to reduce task jitter 
on the slave nodes the timer0 interrupt needs to be as close as possible.

Ghetto,
I am currently using the indirect mode parallel bus (WR, RD, CS, INT, 2 addr 
lines and 8 data lines) which is fine but requires a lot more IO Pins than 
the I2C.  Previously I have used the I2C interface which is very easy to 
setup and use, however for my purposes was way too slow.  Wiznet do supply 
sample code which is very helpful and I belive RealOS has some code for it 
too, tho I haven't seen it.

Tom,
Thanks once again.  I think my best bet will be to make the Ext Int 
Fuunction and Timer0 int function as short as possible.  The timings of the 
network should mean that no clashes occur (send out tick message, recieve 
rply message).  I would prefer not to have to mess around with nested 
interrupt where possible.

Cheers,
Andy

----- Original Message ----- 
From: "Tom Walsh" <tom@...>
To: <lpc2000@yahoogroups.com>
Sent: Thursday, May 11, 2006 12:10 AM
Subject: Re: [lpc2000] Interrupt function declaration


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..."
----------------------------------------------------






Yahoo! Groups Links

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.