Reply by Markus Weltin November 15, 20062006-11-15
That did it! I guess I started this thread but I'm sure glad for this
discussion. I had no idea about the __atribute__ compiler option. That has
made all the difference.

thank you
thank you
thank you

Markus

An Engineer's Guide to the LPC2100 Series

Reply by elektrknight November 14, 20062006-11-14
Hi,

If you use any gcc based toolkit like GNUARM you need to tell
the compiler that the function is an interrupt handler by using
function attribute. In your code "void Takki (void)" is compiled as a
regular function and does not have code in the epilog to correctly
return from the IRQ, it simply falls through to the "UNDEF_Routine".
Make the change below to turn it into irq handler:

void Takki (void) __attribute__ ((interrupt ("IRQ")));
The only problem is that not every version of the gcc correctly
compiles interrupt IRQ attributed code, you need to check
if your version is OK.

elektrknight
Here is the quote from the GCC documentation

-----------------------------(OO)
interrupt
Use this attribute on the ARM, AVR, C4x, CRX, M32C, M32R/D, MS1,
and Xstormy16 ports to indicate that the specified function is an
interrupt handler. The compiler will generate function entry and exit
sequences suitable for use in an interrupt handler when this attribute
is present.
...
Note, for the ARM, you can specify the kind of interrupt to be
handled by adding an optional parameter to the interrupt attribute
like this:

void f () __attribute__ ((interrupt ("IRQ")));

Permissible values for this parameter are: IRQ, FIQ, SWI, ABORT
and UNDEF.

-----------------------------(##)

--- In l..., "Baldur Gislason" wrote:
>
> I'm having a similiar problem. I'm using an LPC2294 with GNUARM and I
> have a button connected to EINT0. When I push the button the routine
> assigned to EINT0 is executed and then it falls into the undef routine
> which then runs over and over until I push reset.
>
> Here is the snippet from my initialize routine to set up the interrupts.
>
> EXTMODE = 0xf; // Edge trigger, not level trigger.
> PINSEL1 |= 0x1;
> VICProtection = 0;
> // Disable all interrupts but the one used for the ROM monitor
> VICIntEnClr = 0xffffffbf;
> VICDefVectAddr = (unsigned int)&DefDummyInterrupt;
>
> VICIntSelect = 0x0; // No FIQ
> VICVectAddr1 = (unsigned long)Takki;
> VICVectCntl1 = 0x20 | INT_E0;
> VICIntEnable = INT_E0_bit; // EINT0 enabled.
> enableIRQ();
>
> void Takki (void) {
> DumpHex(0xdeadbeef);
> VICVectAddr = 0x0;
> EXTINT = 0x0F; // Acknowledge the interrupt or else we'll run again
> EXTMODE = 0xF;
> enableIRQ(); // re-enable interrupts.
> }
>
> void UNDEF_Routine (void) {
> DumpHex(0xfeccfecc);
> }
>
> DumpHex is just a routine that prints a number to the UART in HEX to
> tell me that a routine has executed.
> enableIRQ is a routine that writes to mpsr.
>
> Baldur
>
Reply by Baldur Gislason November 14, 20062006-11-14
I'm having a similiar problem. I'm using an LPC2294 with GNUARM and I
have a button connected to EINT0. When I push the button the routine
assigned to EINT0 is executed and then it falls into the undef routine
which then runs over and over until I push reset.

Here is the snippet from my initialize routine to set up the interrupts.

EXTMODE = 0xf; // Edge trigger, not level trigger.
PINSEL1 |= 0x1;
VICProtection = 0;
// Disable all interrupts but the one used for the ROM monitor
VICIntEnClr = 0xffffffbf;
VICDefVectAddr = (unsigned int)&DefDummyInterrupt;

VICIntSelect = 0x0; // No FIQ
VICVectAddr1 = (unsigned long)Takki;
VICVectCntl1 = 0x20 | INT_E0;
VICIntEnable = INT_E0_bit; // EINT0 enabled.
enableIRQ();

void Takki (void) {
DumpHex(0xdeadbeef);
VICVectAddr = 0x0;
EXTINT = 0x0F; // Acknowledge the interrupt or else we'll run again
EXTMODE = 0xF;
enableIRQ(); // re-enable interrupts.
}

void UNDEF_Routine (void) {
DumpHex(0xfeccfecc);
}

DumpHex is just a routine that prints a number to the UART in HEX to
tell me that a routine has executed.
enableIRQ is a routine that writes to mpsr.

Baldur
Reply by Andrew Berney November 14, 20062006-11-14
I've not used that part however I imagine it's the same as the rest of the
family whereby, clearing the Uart IRQ is done simply by reading U1IIR, you
can use the information in this register to do further work inside your IRQ
should you so wish. External IRQ's are cleared by use of the EXTINT register
whereby setting the appropriate bits will clear the particular External IRQ.
ie the lowest significance bits are your IRQ sources: bit 0 = EXT IRQ0, bit
1 = EXT IRQ1 etc... write one to the particular bit you want, to clear the
respective Ext IRQ. There are a few other issues surrounding the use of this
however based on how you've set the External IRQ up - ie level or edge
sensitive. Refer to the EXTMODE, EXTPOLAR and EXTINT register definitions to
get a handle on it.

Hope that helps...

Andy

-----Original Message-----
From: l... [mailto:l...]On Behalf Of
kd7vn
Sent: 14 November 2006 07:17
To: l...
Subject: [lpc2000] Not returning from, or getting stuck in interrupts
(maybe)
I'm new to arm and the tools, but have done some PIC in the past, and
I could use some help.

I have a OLIMEX board with a lpc2103, and doing the developement with
the GNU ARM tools.

I have made two interrupt routines. One turns on an LED when I get a
Uart0 interrupt, and the other prints "Philips" to the serial port
when the button gets pushed (extint2).

Both interrupt routines get call as expected. It took a little while
to get the VICVecCtnlx vectors set correctly, but I have a default
Vector address set to a routine that will print "default" to the
serial port.

I have confirmed both routines are called when expected. The trouble
is that they are only called one. I can only push the button once, or
get the led to come one. If either action has occured then the other
will not.

I writting all this in C, so there maybe some things going on that the
assembly level that I'm not sure of, but I have done everthing I can
think of to get this program to work correctly.

I disable interrupts when I first enter my routine. Then do what
routine is supposed to do (i.e. turn on led, or write to the serial
port). Finally I "clear" the interrupt flag, enable interrupts again,
and write a 0x0 address to VICVECADDR.

What is the correct way to clear interrupts. Specifically, the uart
interrupts, and external interrupts.

Thank you,
Markus
p.s. I can post, or email code.
Reply by Tom Walsh November 14, 20062006-11-14
kd7vn wrote:
>
> I'm new to arm and the tools, but have done some PIC in the past, and
> I could use some help.
>
> I have a OLIMEX board with a lpc2103, and doing the developement with
> the GNU ARM tools.
>
> I have made two interrupt routines. One turns on an LED when I get a
> Uart0 interrupt, and the other prints "Philips" to the serial port
> when the button gets pushed (extint2).
>
> Both interrupt routines get call as expected. It took a little while
> to get the VICVecCtnlx vectors set correctly, but I have a default
> Vector address set to a routine that will print "default" to the
> serial port.
>
> I have confirmed both routines are called when expected. The trouble
> is that they are only called one. I can only push the button once, or
> get the led to come one. If either action has occured then the other
> will not.
>
> I writting all this in C, so there maybe some things going on that the
> assembly level that I'm not sure of, but I have done everthing I can
> think of to get this program to work correctly.
>
> I disable interrupts when I first enter my routine. Then do what
> routine is supposed to do (i.e. turn on led, or write to the serial
> port). Finally I "clear" the interrupt flag, enable interrupts again,
> and write a 0x0 address to VICVECADDR.
>
It is not necessary to clear the interrupt flag, the interrupts are
disabled when you enter the ISR. Take that code out and see what happens.
> What is the correct way to clear interrupts. Specifically, the uart
> interrupts, and external interrupts.
>
Some of the hardware needs to have a bit cleared in a register for it to
be able to request another interrupt. The timers are a good example of
this. This is a snippet of a timer0 ISR that I have:

========= begin timer0ISR ===========void timer0ISR(void)
{// maintain system heartbeat timer.
bool changes = False;
// ack the timer's interrupt source.
T0IR = 1;
// service any millisecond delay timer.
if (milliSecondSleepTimer) milliSecondSleepTimer--;
// service front porch precharge of carrier?
// if (Serial5Port.DelayTime) Serial5Port.DelayTime--;
// changes |= serviceGlimmer(&LedRx5, Serial5Port.RxActive, RX5LED);
changes |= serviceGlimmer(&LedALIVE, booleans.BoardActive, ALIVE_LED);
if (changes) booleans.updateLedData = True;
VICVectAddr = 0x00000000; // clear this interrupt from
the VIC
}
============== snip ================
Notice the line with the "T0IR"?

Hope this helps?

TomW

--
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net http://cyberiansoftware.com http://openzipit.org
"Windows? No thanks, I have work to do..."
----------------
Reply by kd7vn November 14, 20062006-11-14
I'm new to arm and the tools, but have done some PIC in the past, and
I could use some help.

I have a OLIMEX board with a lpc2103, and doing the developement with
the GNU ARM tools.

I have made two interrupt routines. One turns on an LED when I get a
Uart0 interrupt, and the other prints "Philips" to the serial port
when the button gets pushed (extint2).

Both interrupt routines get call as expected. It took a little while
to get the VICVecCtnlx vectors set correctly, but I have a default
Vector address set to a routine that will print "default" to the
serial port.

I have confirmed both routines are called when expected. The trouble
is that they are only called one. I can only push the button once, or
get the led to come one. If either action has occured then the other
will not.

I writting all this in C, so there maybe some things going on that the
assembly level that I'm not sure of, but I have done everthing I can
think of to get this program to work correctly.

I disable interrupts when I first enter my routine. Then do what
routine is supposed to do (i.e. turn on led, or write to the serial
port). Finally I "clear" the interrupt flag, enable interrupts again,
and write a 0x0 address to VICVECADDR.

What is the correct way to clear interrupts. Specifically, the uart
interrupts, and external interrupts.

Thank you,
Markus
p.s. I can post, or email code.