EmbeddedRelated.com
Forums

Authoring interrupts and disabling/enabling IRQs with gcc

Started by rsturmer March 6, 2009
I've been rifling through examples on the web, and it looks like there are several different methods of both enabling/disabling IRQs as well as actually authoring interrupts with the LPC2000 micros using GCC. (Some people use __attribute___('IRQ'), some people swear against it, etc... )

I just upgraded gcc to 4.3.2 and binutils 2.18, and it seems that anything having to do with my interrupts is now broken.

What is the "correct" way to interact with the interrupt subsystem on these micros, using gcc? Could anyone provide a working source example of how to author, enable and disable IRQs that is known to work well with gcc-4.3.x? I'm pulling my hair out, and I'm afraid it's just something silly. A simple timer LED blink example would be awesome.

Thanks folks!

-R

An Engineer's Guide to the LPC2100 Series

The problem with gcc isn't enable/disable, it's that if you have more
than one firing interrupt source at a time, the attribute(IRQ) stuff
gets confused and you'll get incorrect behavior.

There's a .S routine that nests interrupts by switching stacks, look
for it here and use your irq service routines unadorned.

-Kenny

--
Kenneth R. Crudup Sr. SW Engineer, Scott County Consulting, Los Angeles
O: 3630 S. Sepulveda Blvd. #138, L.A., CA 90034-6809 (888) 454-8181
I will look for that code, (and likely have more questions)

As for enable/disable, then, this is correct? Will this work even if I compile some of my stuff in thumb mode? (will enabling/disabling break due to the inline asm in code potentially called from thumb?

-R

static inline unsigned __get_cpsr(void)

{

unsigned long retval;

asm volatile (" mrs %0, cpsr" : "=r" (retval) : /* no inputs */ );

return retval;

}

static inline void __set_cpsr(unsigned val)

{

asm volatile (" msr cpsr, %0" : /* no outputs */ : "r" (val) );

}

unsigned disableIRQ(void)

{

unsigned _cpsr;

_cpsr = __get_cpsr();

__set_cpsr(_cpsr | IRQ_MASK);

return _cpsr;

}

unsigned restoreIRQ(unsigned oldCPSR)

{

unsigned _cpsr;

_cpsr = __get_cpsr();

__set_cpsr((_cpsr & ~IRQ_MASK) | (oldCPSR & IRQ_MASK));

return _cpsr;

}

unsigned enableIRQ(void)

{

unsigned _cpsr;

_cpsr = __get_cpsr();

__set_cpsr(_cpsr & ~IRQ_MASK);

return _cpsr;

}

--- In l..., Kenneth Crudup wrote:
> The problem with gcc isn't enable/disable, it's that if you have more
> than one firing interrupt source at a time, the attribute(IRQ) stuff
> gets confused and you'll get incorrect behavior.
>
> There's a .S routine that nests interrupts by switching stacks, look
> for it here and use your irq service routines unadorned.
>
> -Kenny
>
> --
> Kenneth R. Crudup Sr. SW Engineer, Scott County Consulting, Los Angeles
> O: 3630 S. Sepulveda Blvd. #138, L.A., CA 90034-6809 (888) 454-8181
>

--- In l..., Kenneth Crudup wrote:
> The problem with gcc isn't enable/disable, it's that if you have more
> than one firing interrupt source at a time, the attribute(IRQ) stuff
> gets confused and you'll get incorrect behavior.
>
> There's a .S routine that nests interrupts by switching stacks, look
> for it here and use your irq service routines unadorned.
>
> -Kenny
>
> --
> Kenneth R. Crudup Sr. SW Engineer, Scott County Consulting, Los Angeles
> O: 3630 S. Sepulveda Blvd. #138, L.A., CA 90034-6809 (888) 454-8181
>

I've tried to search for this code but am having trouble finding it. If someone does find it please post a link.

Thanks!

TC

This is helpful:

http://www.keil.com/support/docs/3353.htm

May you have better luck than I.

My interrupts aren't enabling still! Well, if they are, they aren't firing properly. I had this working before :/

-R

--- In l..., "rsturmer" wrote:
>
> I've been rifling through examples on the web, and it looks like there are several different methods of both enabling/disabling IRQs as well as actually authoring interrupts with the LPC2000 micros using GCC. (Some people use __attribute___('IRQ'), some people swear against it, etc... )
>
> I just upgraded gcc to 4.3.2 and binutils 2.18, and it seems that anything having to do with my interrupts is now broken.
>
> What is the "correct" way to interact with the interrupt subsystem on these micros, using gcc? Could anyone provide a working source example of how to author, enable and disable IRQs that is known to work well with gcc-4.3.x? I'm pulling my hair out, and I'm afraid it's just something silly. A simple timer LED blink example would be awesome.
>
> Thanks folks!
>
> -R
>

> > There's a .S routine that nests interrupts by switching stacks, look
> > for it here and use your irq service routines unadorned.

On Sat, 7 Mar 2009, tcirobot wrote:

> I've tried to search for this code but am having trouble finding it.
> If someone does find it please post a link.

It's not mine (I either got it from here or from the Keil site), but
here it is:

----
.func IRQ_Handler
IRQ_Handler:
stmfd sp!, { lr } /* save return address on IRQ stack */
mrs lr, spsr /* use lr to save spsr_irq */
stmfd sp!, { r4-r5, lr } /* save work regs & spsr on stack */

ldr r4, =VICVECTADDR /* get the ISR address from VIC */
ldr r5, [r4]

msr cpsr_c, #MODE_SVC|F_BIT /* supervisor mode, interrupts ON */

stmfd sp!, { r0-r3, r12, lr } /* save work regs & lr_svc on stack */
mov lr, pc /* set return to common exit of ISR */
mov pc, r5 /* go handle the interrupt */
ldmfd sp!, { r0-r3, r12, lr } /* restore regs & lr_svc */

/* IRQ mode, interrupts OFF */
msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT

str lr, [r4] /* update VICVectAddr */

ldmfd sp!, { r4-r5, lr } /* restore work regs and spsr_irq */
msr spsr_cxsf, lr /* put back spsr_irq */
ldmfd sp!, { lr } /* restore return address */

subs pc, lr, #0x4 /* return, restoring CPSR from SPSR */
.endfunc
----

-Kenny

--
Kenneth R. Crudup Sr. SW Engineer, Scott County Consulting, Los Angeles
O: 3630 S. Sepulveda Blvd. #138, L.A., CA 90034-6809 (888) 454-8181
--- In l..., Kenneth Crudup wrote:
> > > There's a .S routine that nests interrupts by switching stacks, look
> > > for it here and use your irq service routines unadorned.
>
> On Sat, 7 Mar 2009, tcirobot wrote:
>
> > I've tried to search for this code but am having trouble finding it.
> > If someone does find it please post a link.
>
> It's not mine (I either got it from here or from the Keil site), but
> here it is:
>
> ----
> .func IRQ_Handler
> IRQ_Handler:
> stmfd sp!, { lr } /* save return address on IRQ stack */
> mrs lr, spsr /* use lr to save spsr_irq */
> stmfd sp!, { r4-r5, lr } /* save work regs & spsr on stack */
>
> ldr r4, =VICVECTADDR /* get the ISR address from VIC */
> ldr r5, [r4]
>
> msr cpsr_c, #MODE_SVC|F_BIT /* supervisor mode, interrupts ON */
>
> stmfd sp!, { r0-r3, r12, lr } /* save work regs & lr_svc on stack */
> mov lr, pc /* set return to common exit of ISR */
> mov pc, r5 /* go handle the interrupt */
> ldmfd sp!, { r0-r3, r12, lr } /* restore regs & lr_svc */
>
> /* IRQ mode, interrupts OFF */
> msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT
>
> str lr, [r4] /* update VICVectAddr */
>
> ldmfd sp!, { r4-r5, lr } /* restore work regs and spsr_irq */
> msr spsr_cxsf, lr /* put back spsr_irq */
> ldmfd sp!, { lr } /* restore return address */
>
> subs pc, lr, #0x4 /* return, restoring CPSR from SPSR */
> .endfunc
> ----
>
> -Kenny
>
> --
> Kenneth R. Crudup Sr. SW Engineer, Scott County Consulting, Los Angeles
> O: 3630 S. Sepulveda Blvd. #138, L.A., CA 90034-6809 (888) 454-8181
>

Thanks!