EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Crossworks & irq handlers in C

Started by Markus Zingg February 7, 2008
Hi all,

I'm new to the Crossworks IDE/Envireonment and also to ARM7. I need to
declare an IRQ handler function and I'm having troubles to do so.

I looked up the GCC docs (I'm also also new to GCC...) and found the
__attribute__ instruction to do so. However, the following
code does not seem to be accepted by the compiler.

void Handler( void ) __attribute__ ((interrupt ("IRQ") ));
{
.....

Which from what I understand should be the way to do it. However, the
copiler complains with "expected identifier or '(' before '{' token"
which tells me something is wrong with this kind of declaration.

So, how does one propperly define an IRQ handler with Crossworks, GCC
and an ARM7?

The next question I have is that the code sniped I try to use uses the
macros IENABLE/IDISABLE whoes purpose is to handle nested interrupts.
They are declared like this:

#define IENABLE __asm { MRS sysreg, SPSR; MSR CPSR_c, #SYS32Mode }
#define IDISABLE __asm { MSR CPSR_c, #(IRQ32Mode|I_Bit); MSR SPSR_cxsf,
sysreg }

However this seems to follow the syntax requierements of a different
compiler (don't know, KEIL or IAR or whatever). So, how do I code the
identical functionality with GCC?

TIA

Markus

An Engineer's Guide to the LPC2100 Series

The 'interrupt' attribute must be placed only in function declaration, not
in his body.
In Crossworks you may use libarm_enable_irq( ) functions.

Marcelo
----- Original Message -----
From: "Markus Zingg"
To:
Sent: Thursday, February 07, 2008 12:59 PM
Subject: [lpc2000] Crossworks & irq handlers in C
> Hi all,
>
> I'm new to the Crossworks IDE/Envireonment and also to ARM7. I need to
> declare an IRQ handler function and I'm having troubles to do so.
>
> I looked up the GCC docs (I'm also also new to GCC...) and found the
> __attribute__ instruction to do so. However, the following
> code does not seem to be accepted by the compiler.
>
> void Handler( void ) __attribute__ ((interrupt ("IRQ") ));
> {
> .....
>
> Which from what I understand should be the way to do it. However, the
> copiler complains with "expected identifier or '(' before '{' token"
> which tells me something is wrong with this kind of declaration.
>
> So, how does one propperly define an IRQ handler with Crossworks, GCC
> and an ARM7?
>
> The next question I have is that the code sniped I try to use uses the
> macros IENABLE/IDISABLE whoes purpose is to handle nested interrupts.
> They are declared like this:
>
> #define IENABLE __asm { MRS sysreg, SPSR; MSR CPSR_c, #SYS32Mode }
> #define IDISABLE __asm { MSR CPSR_c, #(IRQ32Mode|I_Bit); MSR SPSR_cxsf,
> sysreg }
>
> However this seems to follow the syntax requierements of a different
> compiler (don't know, KEIL or IAR or whatever). So, how do I code the
> identical functionality with GCC?
>
> TIA
>
> Markus
>
Markus,

> I'm new to the Crossworks IDE/Envireonment and also to ARM7. I need to
> declare an IRQ handler function and I'm having troubles to do so.
>
> I looked up the GCC docs (I'm also also new to GCC...) and found the
> __attribute__ instruction to do so. However, the following
> code does not seem to be accepted by the compiler.
>
> void Handler( void ) __attribute__ ((interrupt ("IRQ") ));
> {

You need:

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

void Handle(void)
{
// do my stuff
}

> So, how does one propperly define an IRQ handler with Crossworks, GCC
> and an ARM7?

Let the train take the strain! Use ctl_set_isr(). Even though "CTL" stands
for CrossWorks Tasking Library at present, TASKING is separate from
INTERRUPT HANDLING. I hate to make this point, but some customers don't
grasp it. Using ctl_set_isr you don't even need to think about all that
attribute crap and can write ISRs in Thumb if you want.

> The next question I have is that the code sniped I try to use uses the
> macros IENABLE/IDISABLE whoes purpose is to handle nested interrupts.
> They are declared like this:

#include

void monitor(void)
{
ctl_global_interrupts_disable();
// Do critical stuff
ctl_global_interrupts_enable();
}

You can wrap this to be state-aware too so it preserves the interrupt state
(but it's beyond your question).

> #define IENABLE __asm { MRS sysreg, SPSR; MSR CPSR_c, #SYS32Mode }
> #define IDISABLE __asm { MSR CPSR_c, #(IRQ32Mode|I_Bit); MSR SPSR_cxsf,
> sysreg }

Eek! Don't do that. Let me poke you with a cattle prod to convince you...

> However this seems to follow the syntax requierements of a different
> compiler (don't know, KEIL or IAR or whatever). So, how do I code the
> identical functionality with GCC?

Use the library... It's what we wrote it for.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors
Paul,

Many thanks for your explanation. The IRQ handler declearing stuff is
now clear to me - again, thank you.

The code snippet is from NXP example code (emac.c from the LPC2378
examples). However, you confused me a bit on the IENABLE / IDISABLE
thing. The NXP code ENABLES the interupts at the entry of the IRQ
serviceing routine and disables them on exit with what I think the
intention to allow the interupt service routine to be interupted again
(can't tell at the moment if this would also hold true for the same
interrupt or only for higher priority but datasheet shoud tell :-) ). I
thus asumed IRQs are disabled by default, and returning from the IRQ
service routine (poping status from the stack) would revert everything
to the state it was in bevore? Could you elaborate a bit on this? Ok,
that's surely something I will have to look up in the users manual/
datasheet, but I of course don't object if someone can quickly confirm
or deny.

The reason I would like to avoid the tasking library is that I need to
keep the code as much independant of proprietary stuff as possible. I DO
of course generally apreciate the fact that the tasking library exists,
but for this project must "avoid" it.

Markus

Paul Curtis schrieb:
>
> Markus,
>
> > I'm new to the Crossworks IDE/Envireonment and also to ARM7. I need to
> > declare an IRQ handler function and I'm having troubles to do so.
> >
> > I looked up the GCC docs (I'm also also new to GCC...) and found the
> > __attribute__ instruction to do so. However, the following
> > code does not seem to be accepted by the compiler.
> >
> > void Handler( void ) __attribute__ ((interrupt ("IRQ") ));
> > {
>
> You need:
>
> void Handler(void) __attribute__((interrupt("IRQ")));
>
> void Handle(void)
> {
> // do my stuff
> }
>
> > So, how does one propperly define an IRQ handler with Crossworks, GCC
> > and an ARM7?
>
> Let the train take the strain! Use ctl_set_isr(). Even though "CTL" stands
> for CrossWorks Tasking Library at present, TASKING is separate from
> INTERRUPT HANDLING. I hate to make this point, but some customers don't
> grasp it. Using ctl_set_isr you don't even need to think about all that
> attribute crap and can write ISRs in Thumb if you want.
>
> > The next question I have is that the code sniped I try to use uses the
> > macros IENABLE/IDISABLE whoes purpose is to handle nested interrupts.
> > They are declared like this:
>
> #include void monitor(void)
> {
> ctl_global_interrupts_disable();
> // Do critical stuff
> ctl_global_interrupts_enable();
> }
>
> You can wrap this to be state-aware too so it preserves the interrupt
> state
> (but it's beyond your question).
>
> > #define IENABLE __asm { MRS sysreg, SPSR; MSR CPSR_c, #SYS32Mode }
> > #define IDISABLE __asm { MSR CPSR_c, #(IRQ32Mode|I_Bit); MSR SPSR_cxsf,
> > sysreg }
>
> Eek! Don't do that. Let me poke you with a cattle prod to convince you...
>
> > However this seems to follow the syntax requierements of a different
> > compiler (don't know, KEIL or IAR or whatever). So, how do I code the
> > identical functionality with GCC?
>
> Use the library... It's what we wrote it for.
>
> --
> Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
>
> CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors
>
>
Markus Zingg Wrote
>The reason I would like to avoid the tasking library is that I need to
>keep the code as much independant of proprietary stuff as possible. I DO
>of course generally apreciate the fact that the tasking library exists,
>but for this project must "avoid" it.

So write your own stubs, it's not difficult. There is an example in the
newlib-lpc library that you are free to steal. It only supports ARM (no
thumb) unlike Crossworks but that could be added if necessary.

BTW kudos to Rowely for doing it "right".

Robert
--------------------------------
mail2web.com What can On Demand Business Solutions do for you?
http://link.mail2web.com/Business/SharePoint



Hi,

> The code snippet is from NXP example code (emac.c from the LPC2378
> examples). However, you confused me a bit on the IENABLE / IDISABLE
> thing. The NXP code ENABLES the interupts at the entry of the IRQ
> serviceing routine and disables them on exit with what I think the
> intention to allow the interupt service routine to be interupted again
> (can't tell at the moment if this would also hold true for the same
> interrupt or only for higher priority but datasheet shoud tell :-) ).

Ok, take a look at:

ctl_global_interrupts_re_enable_from_isr

and

ctl_global_interrupts_un_re_enable_from_isr

These are wordy, yes, and not too well named I guess. (Michael takes
responsibility here.)

> The reason I would like to avoid the tasking library is that I need to
> keep the code as much independant of proprietary stuff as possible.

IOW you need to write all this yourself--ok, well done, nice initiative, but
I thought reinventing the wheel went out with the ark. Or should have done.

> I DO
> of course generally apreciate the fact that the tasking library exists,
> but for this project must "avoid" it.

You don't need to use it, but hey, there are plenty of other libraries for
RTOS functionality around.

-- Paul.
Paul,

Thanks for your answer. I looked up the documentation of the calls and
as a result, I figure that if I restrict myself to this very few calls,
I think a port to a different envireonement would probably mean fewer
work than now implementing the needed code. Besides, chances that this
really happens seem extremly small to me. I just have to asure (as parts
of requierements not made by myself) that a port is feasable within
certain limits.

Markus

Paul Curtis schrieb:
>
> Hi,
>
> > The code snippet is from NXP example code (emac.c from the LPC2378
> > examples). However, you confused me a bit on the IENABLE / IDISABLE
> > thing. The NXP code ENABLES the interupts at the entry of the IRQ
> > serviceing routine and disables them on exit with what I think the
> > intention to allow the interupt service routine to be interupted again
> > (can't tell at the moment if this would also hold true for the same
> > interrupt or only for higher priority but datasheet shoud tell :-) ).
>
> Ok, take a look at:
>
> ctl_global_interrupts_re_enable_from_isr
>
> and
>
> ctl_global_interrupts_un_re_enable_from_isr
>
> These are wordy, yes, and not too well named I guess. (Michael takes
> responsibility here.)
>
> > The reason I would like to avoid the tasking library is that I need to
> > keep the code as much independant of proprietary stuff as possible.
>
> IOW you need to write all this yourself--ok, well done, nice
> initiative, but
> I thought reinventing the wheel went out with the ark. Or should have
> done.
>
> > I DO
> > of course generally apreciate the fact that the tasking library exists,
> > but for this project must "avoid" it.
>
> You don't need to use it, but hey, there are plenty of other libraries for
> RTOS functionality around.
>
> -- Paul.
>
>
Markus Zingg Wrote
>Thanks for your answer. I looked up the documentation of the calls and
>as a result, I figure that if I restrict myself to this very few calls,
>I think a port to a different envireonement would probably mean fewer
>work than now implementing the needed code. Besides, chances that this
>really happens seem extremly small to me. I just have to asure (as parts
>of requierements not made by myself) that a port is feasable within
>certain limits.

Put a shell around them ie

void myisrsetup ( ...)
{
...
clt....
...
}

Filling in the dots is left as an exercise for the reader ;)

Then a port consists of rewriting myisrsetup rather than duplicating the
ctl function. Syntactic sugar but it can give real benefits on porting and
if you always use in a way that combines several ctl... functions you can
give yourself another level of abstraction. If nothing else it looks like
a porting layer and that may be what you need to convince others that it
can in fact be ported.

Of course it's only truly portable if it has been ported.

Robert

--------------------------------
mail2web.com Enhanced email for the mobile individual based on Microsoft
Exchange - http://link.mail2web.com/Personal/EnhancedEmail




The 2024 Embedded Online Conference