EmbeddedRelated.com
Forums
Memfault Beyond the Launch

{To TomW} GCC-Bug in IRQs

Started by Sten March 25, 2006
--- In l..., Sten wrote:
>
> Robert Adsett wrote:
> > At 07:49 PM 3/25/2006 +0100, Sten wrote:
> >
> >>I've tried this. But entry/exit is still not correct.
> >>Here's the result:
> >>
> >>void uart_irqHandler0(void) __attribute__((interrupt));
> >>
> >>00000204 :
> >> 204: e24ee004 sub lr, lr, #4 ; 0x4
> >> 208: e92d500f stmdb sp!, {r0, r1, r2, r3, ip, lr}
> >> 20c: e3a0120e mov r1, #-536870912 ; 0xe0000000
> >> 210: e2811903 add r1, r1, #49152 ; 0xc000
> >> 214: e3a00000 mov r0, #0 ; 0x0
> >> 218: ebfffffe bl d0
> >> 21c: e8bd500f ldmia sp!, {r0, r1, r2, r3, ip, lr}
> >> 220: e25ef004 subs pc, lr, #4 ; 0x4
> >>
> >>Question:
> >>Which gcc version do you use? Which command line parameters do use?
> >>How do you differentiate between IRQ and FIQ (only r0..r7 need to be
> >>saved) if use
> >>__attribute__((interrupt)) only?
> >
> >
> >
> > Rather than go through all this hand-wringing why not just write an
> > assembly stub? You'd know it was correct and you'd be done
already. At
> > most it would cost you an extra call from the stub to your C
> > function. Heck if it was small enough it might make sense to do
the whole
> > thing in asm. For that matter you could steal one of my stubs.
> >
> > Robert
> > Thanks Robert.
> At the moment I declare my IRQ functions as "naked" and write my own
prologue/epilogue with inline
> assembler. But it is less efficient because I don't know which
registers are really used, so I have
> to save all non-banked registers (r0..12 for IRQ and r0..r7 for FIQ)
which is a wast of performance.
Yes. IRQ "undressed" and inline assembly for prologue/epilogue.

I was curious about the performance hit myself, but rather
than doing it academic-like way (in days), I measured it (in 10 minutes).
The test is lousy,since the execution of logic analyzer markers skews
the measurement, but comparing:
1. stmia sp, {r0-r11} // 12 regs took 435 ns
2. stmia sp, {r0-r3} // 4 regs took 305 ns
3. stmia sp, {r0} // 1 reg took 255 ns
on LPC 2148, pclk=clck` MHz
LA's sampling rate; f 0 MHz.
we get some idea; with systematic error factored in,
it doesn't make such a big difference to save 12 or 4 regs.
Roger

>
> Sten
>
> --
> /************************************************
> Do you need a tiny and efficient real time
> operating system (RTOS) with a preemtive
> multitasking for LPC2000 or AT91SAM7?
>
> http://nanortos.net-attack.de/
>
> Or some open-source tools and code for LPC2000?
>
> http://www.net-attack.de/
>
> ************************************************/
>

Yahoo! Groups Links

An Engineer's Guide to the LPC2100 Series

--- In lpc2000@lpc2..., Sten <list@...> wrote:
>
> Robert Adsett wrote:
> > At 07:49 PM 3/25/2006 +0100, Sten wrote:
> >
> >>I've tried this. But entry/exit is still not correct.
> >>Here's the result:
> >>
> >>void uart_irqHandler0(void) __attribute__((interrupt));
> >>
> >>00000204 <uart_irqHandler0>:
> >> 204: e24ee004 sub lr, lr, #4 ; 0x4
> >> 208: e92d500f stmdb sp!, {r0, r1, r2, r3, ip, lr}
> >> 20c: e3a0120e mov r1, #-536870912 ; 0xe0000000
> >> 210: e2811903 add r1, r1, #49152 ; 0xc000
> >> 214: e3a00000 mov r0, #0 ; 0x0
> >> 218: ebfffffe bl d0 <uart_irqHandler_common>
> >> 21c: e8bd500f ldmia sp!, {r0, r1, r2, r3, ip, lr}
> >> 220: e25ef004 subs pc, lr, #4 ; 0x4
> >>
> >>Question:
> >>Which gcc version do you use? Which command line parameters do use?
> >>How do you differentiate between IRQ and FIQ (only r0..r7 need to be
> >>saved) if use
> >>__attribute__((interrupt)) only?
> >
> >
> >
> > Rather than go through all this hand-wringing why not just write an
> > assembly stub? You'd know it was correct and you'd be done
already. At
> > most it would cost you an extra call from the stub to your C
> > function. Heck if it was small enough it might make sense to do
the whole
> > thing in asm. For that matter you could steal one of my stubs.
> >
> > Robert
> >
>
> Thanks Robert.
> At the moment I declare my IRQ functions as "naked" and write my own
prologue/epilogue with inline
> assembler. But it is less efficient because I don't know which
registers are really used, so I have
> to save all non-banked registers (r0..12 for IRQ and r0..r7 for FIQ)
which is a wast of performance.
Yes. IRQ "undressed" and inline assembly for prologue/epilogue.

I was curious about the performance hit myself, but rather
than doing it academic-like way (in days), I measured it (in 10 minutes).
The test is lousy,since the execution of logic analyzer markers skews
the measurement, but comparing:
1. stmia sp, {r0-r11} // 12 regs took 435 ns
2. stmia sp, {r0-r3} // 4 regs took 305 ns
3. stmia sp, {r0} // 1 reg took 255 ns
on LPC 2148, pclk=clck` MHz
LA's sampling rate; f 0 MHz.
we get some idea; with systematic error factored in,
it doesn't make such a big difference to save 12 or 4 regs.
Roger

>
> Sten
>
> --
> /************************************************
> Do you need a tiny and efficient real time
> operating system (RTOS) with a preemtive
> multitasking for LPC2000 or AT91SAM7?
>
> http://nanortos.net-attack.de/
>
> Or some open-source tools and code for LPC2000?
>
> http://www.net-attack.de/
>
> ************************************************/
>
Robert Adsett wrote:
> At 12:04 AM 3/26/2006 +0100, Sten wrote:
>
>>Wonderful! ;-)
>>But why to save r0..r3 and ip in your irq_isr?!? Only lr will be changed
>>by bl and registers used by
>>irq_handler() should be saved in its function prologue by irq_handler()
>>itself!
> According to the APCS "A (called)subroutine must preserve the contents of
> the registers r4-r8, r10, r11 and SP ".
>
> R0-R3 are temporary/parameter registers and must be saved by the caller if
> needed R12 is the intra-procedure call scratch register so similar
> restrictions apply to it, R14 is the link register so make sure you've
> saved it properly or you won't be able to return.
>
> That leaves R9 the platform specific register, which I believe gcc treats
> the same as r4-r8 (I can't lay my hands on my reference for that at the
> moment).
>
Ok, this makes sense...

Sten

--
/************************************************
Do you need a tiny and efficient real time
operating system (RTOS) with a preemtive
multitasking for LPC2000 or AT91SAM7?

http://nanortos.net-attack.de/

Or some open-source tools and code for LPC2000?

http://www.net-attack.de/

************************************************/

Yahoo! Groups Links
Robert Adsett wrote:
> At 12:04 AM 3/26/2006 +0100, Sten wrote:
>
>>Wonderful! ;-)
>>But why to save r0..r3 and ip in your irq_isr?!? Only lr will be changed
>>by bl and registers used by
>>irq_handler() should be saved in its function prologue by irq_handler()
>>itself!
>
>
> According to the APCS "A (called)subroutine must preserve the contents of
> the registers r4-r8, r10, r11 and SP ".
>
> R0-R3 are temporary/parameter registers and must be saved by the caller if
> needed R12 is the intra-procedure call scratch register so similar
> restrictions apply to it, R14 is the link register so make sure you've
> saved it properly or you won't be able to return.
>
> That leaves R9 the platform specific register, which I believe gcc treats
> the same as r4-r8 (I can't lay my hands on my reference for that at the
> moment).
>
Ok, this makes sense...

Sten

--
/************************************************
Do you need a tiny and efficient real time
operating system (RTOS) with a preemtive
multitasking for LPC2000 or AT91SAM7?

http://nanortos.net-attack.de/

Or some open-source tools and code for LPC2000?

http://www.net-attack.de/

************************************************/

--- In l..., "roger_lynx" wrote:
>
> --- In l..., Sten wrote:
> >
> > Robert Adsett wrote:
> > > At 07:49 PM 3/25/2006 +0100, Sten wrote:
> > >
> > >>I've tried this. But entry/exit is still not correct.
> > >>Here's the result:
> > >>
> > >>void uart_irqHandler0(void) __attribute__((interrupt));
> > >>
> > >>00000204 :
> > >> 204: e24ee004 sub lr, lr, #4 ; 0x4
> > >> 208: e92d500f stmdb sp!, {r0, r1, r2, r3, ip, lr}
> > >> 20c: e3a0120e mov r1, #-536870912 ; 0xe0000000
> > >> 210: e2811903 add r1, r1, #49152 ; 0xc000
> > >> 214: e3a00000 mov r0, #0 ; 0x0
> > >> 218: ebfffffe bl d0
> > >> 21c: e8bd500f ldmia sp!, {r0, r1, r2, r3, ip, lr}
> > >> 220: e25ef004 subs pc, lr, #4 ; 0x4
> > >>
> > >>Question:
> > >>Which gcc version do you use? Which command line parameters do use?
> > >>How do you differentiate between IRQ and FIQ (only r0..r7 need
to be
> > >>saved) if use
> > >>__attribute__((interrupt)) only?
> > >
> > >
> > >
> > > Rather than go through all this hand-wringing why not just write an
> > > assembly stub? You'd know it was correct and you'd be done
> already. At
> > > most it would cost you an extra call from the stub to your C
> > > function. Heck if it was small enough it might make sense to do
> the whole
> > > thing in asm. For that matter you could steal one of my stubs.
> > >
> > > Robert
> > >
> >
> > Thanks Robert.
> > At the moment I declare my IRQ functions as "naked" and write my own
> prologue/epilogue with inline
> > assembler. But it is less efficient because I don't know which
> registers are really used, so I have
> > to save all non-banked registers (r0..12 for IRQ and r0..r7 for FIQ)
> which is a wast of performance.
> Yes. IRQ "undressed" and inline assembly for prologue/epilogue.
>
> I was curious about the performance hit myself, but rather
> than doing it academic-like way (in days), I measured it (in 10
minutes).
> The test is lousy,since the execution of logic analyzer markers skews
> the measurement, but comparing:
> 1. stmia sp, {r0-r11} // 12 regs took 435 ns
> 2. stmia sp, {r0-r3} // 4 regs took 305 ns
> 3. stmia sp, {r0} // 1 reg took 255 ns
> on LPC 2148, pclk=clck` MHz
> LA's sampling rate; f 0 MHz.
> we get some idea; with systematic error factored in,
> it doesn't make such a big difference to save 12 or 4 regs.
> Roger
>
> >
> > Sten
> >
> > --
> > /************************************************
> > Do you need a tiny and efficient real time
> > operating system (RTOS) with a preemtive
> > multitasking for LPC2000 or AT91SAM7?
> >
> > http://nanortos.net-attack.de/
> >
> > Or some open-source tools and code for LPC2000?
> >
> > http://www.net-attack.de/
> >
> > ************************************************/
>
Hi Guys,
I've just hit this problem in my UART handler, I'm new to the ARM
and haven't used it's asm yet! could one of you ASM gurus
please post the required inline entry/exit code for us dummys
thanks,

Yahoo! Groups Links
At 10:42 PM 3/26/2006 +0000, frankcallaghan9 wrote:
>Hi Guys,
>I've just hit this problem in my UART handler, I'm new to the ARM
>and haven't used it's asm yet! could one of you ASM gurus
>please post the required inline entry/exit code for us dummys
>thanks,

My experience with inline matches that of compiler interrupt keywords. It
makes far more sense just to do it in assembly.

Take a look at the interrupt example in newlib-lpc.
http://www.aeolusdevelopment.com/Articles/download.html They can be easily
separated from the rest so using the epilogues and prologues from there
doesn't commit you to the rest of the library.

Robert

" 'Freedom' has no meaning of itself. There are always restrictions, be
they legal, genetic, or physical. If you don't believe me, try to chew a
radio signal. " -- Kelvin Throop, III
http://www.aeolusdevelopment.com/

Yahoo! Groups Links
--- In lpc2000@lpc2..., "roger_lynx" <roger_lynx@...>
wrote:
>
> --- In lpc2000@lpc2..., Sten <list@> wrote:
> >
> > Robert Adsett wrote:
> > > At 07:49 PM 3/25/2006 +0100, Sten wrote:
> > >
> > >>I've tried this. But entry/exit is still not correct.
> > >>Here's the result:
> > >>
> > >>void uart_irqHandler0(void) __attribute__((interrupt));
> > >>
> > >>00000204 <uart_irqHandler0>:
> > >> 204: e24ee004 sub lr, lr, #4 ; 0x4
> > >> 208: e92d500f stmdb sp!, {r0, r1, r2, r3, ip, lr}
> > >> 20c: e3a0120e mov r1, #-536870912 ; 0xe0000000
> > >> 210: e2811903 add r1, r1, #49152 ; 0xc000
> > >> 214: e3a00000 mov r0, #0 ; 0x0
> > >> 218: ebfffffe bl d0 <uart_irqHandler_common>
> > >> 21c: e8bd500f ldmia sp!, {r0, r1, r2, r3, ip, lr}
> > >> 220: e25ef004 subs pc, lr, #4 ; 0x4
> > >>
> > >>Question:
> > >>Which gcc version do you use? Which command line parameters do use?
> > >>How do you differentiate between IRQ and FIQ (only r0..r7 need
to be
> > >>saved) if use
> > >>__attribute__((interrupt)) only?
> > >
> > >
> > >
> > > Rather than go through all this hand-wringing why not just write an
> > > assembly stub? You'd know it was correct and you'd be done
> already. At
> > > most it would cost you an extra call from the stub to your C
> > > function. Heck if it was small enough it might make sense to do
> the whole
> > > thing in asm. For that matter you could steal one of my stubs.
> > >
> > > Robert
> > >
> >
> > Thanks Robert.
> > At the moment I declare my IRQ functions as "naked" and write my own
> prologue/epilogue with inline
> > assembler. But it is less efficient because I don't know which
> registers are really used, so I have
> > to save all non-banked registers (r0..12 for IRQ and r0..r7 for FIQ)
> which is a wast of performance.
>
>
> Yes. IRQ "undressed" and inline assembly for prologue/epilogue.
>
> I was curious about the performance hit myself, but rather
> than doing it academic-like way (in days), I measured it (in 10
minutes).
> The test is lousy,since the execution of logic analyzer markers skews
> the measurement, but comparing:
>
>
> 1. stmia sp, {r0-r11} // 12 regs took 435 ns
> 2. stmia sp, {r0-r3} // 4 regs took 305 ns
> 3. stmia sp, {r0} // 1 reg took 255 ns
>
>
> on LPC 2148, pclk=clck` MHz
> LA's sampling rate; f 0 MHz.
>
>
> we get some idea; with systematic error factored in,
> it doesn't make such a big difference to save 12 or 4 regs.
>
>
> Roger
>
> >
> > Sten
> >
> > --
> > /************************************************
> > Do you need a tiny and efficient real time
> > operating system (RTOS) with a preemtive
> > multitasking for LPC2000 or AT91SAM7?
> >
> > http://nanortos.net-attack.de/
> >
> > Or some open-source tools and code for LPC2000?
> >
> > http://www.net-attack.de/
> >
> > ************************************************/
> >
>

Hi Guys,
I've just hit this problem in my UART handler, I'm new to the ARM
and haven't used it's asm yet! could one of you ASM gurus
please post the required inline entry/exit code for us dummys
thanks,
At 10:42 PM 3/26/2006 +0000, frankcallaghan9 wrote:
>Hi Guys,
>I've just hit this problem in my UART handler, I'm new to the ARM
>and haven't used it's asm yet! could one of you ASM gurus
>please post the required inline entry/exit code for us dummys
>thanks,

My experience with inline matches that of compiler interrupt keywords. It
makes far more sense just to do it in assembly.

Take a look at the interrupt example in newlib-lpc.
http://www.aeolusdevelopment.com/Articles/download.html They can be easily
separated from the rest so using the epilogues and prologues from there
doesn't commit you to the rest of the library.

Robert

" 'Freedom' has no meaning of itself. There are always restrictions, be
they legal, genetic, or physical. If you don't believe me, try to chew a
radio signal. " -- Kelvin Throop, III
http://www.aeolusdevelopment.com/
frankcallaghan9 wrote:
>
> Hi Guys,
> I've just hit this problem in my UART handler, I'm new to the ARM
> and haven't used it's asm yet! could one of you ASM gurus
> please post the required inline entry/exit code for us dummys
> thanks,

Hello Frank,

if you want to use "manually" written prologue/epilogue instead of a stub try this:

#define VIC_GCCFIX_IRQ_PROLOGUE() \
__asm__ __volatile__( " sub lr, lr, #4 \n" \
" stmdb sp!, {r0-r12,lr} \n");
#define VIC_GCCFIX_IRQ_EPILOGUE() \
__asm__ __volatile__( " ldmia sp!, {r0-r12,pc} \n");

void myIRQ(void) __attribute__((interrupt("IRQ"), naked));

void myIRQ(void) {
VIC_GCCFIX_IRQ_PROLOGUE();
/* ... */
VIC_GCCFIX_IRQ_EPILOGUE();
}

Sten

--
/************************************************
Do you need a tiny and efficient real time
operating system (RTOS) with a preemtive
multitasking for LPC2000 or AT91SAM7?

http://nanortos.net-attack.de/

Or some open-source tools and code for LPC2000?

http://www.net-attack.de/

************************************************/

Yahoo! Groups Links
I think VIC_GCCFIX_IRQ_EPILOGUE should be:

#define VIC_GCCFIX_IRQ_EPILOGUE() \
__asm__ __volatile__( " ldmia sp!, {r0-r12,pc}^
\n");
The "^" tells the arm to copy SPSR to CPSR.

Richard.
Sten wrote:
> frankcallaghan9 wrote:
> >
> > Hi Guys,
> > I've just hit this problem in my UART handler, I'm new to the ARM
> > and haven't used it's asm yet! could one of you ASM gurus
> > please post the required inline entry/exit code for us dummys
> > thanks,
>
> Hello Frank,
>
> if you want to use "manually" written prologue/epilogue instead of a
> stub try this:
>
> #define
> VIC_GCCFIX_IRQ_PROLOGUE() \
> __asm__ __volatile__( " sub lr, lr,
> #4 \n" \
> " stmdb sp!,
> {r0-r12,lr} \n");
> #define VIC_GCCFIX_IRQ_EPILOGUE() \
> __asm__ __volatile__( " ldmia sp!,
> {r0-r12,pc} \n");
>
> void myIRQ(void) __attribute__((interrupt("IRQ"), naked));
>
> void myIRQ(void) {
> VIC_GCCFIX_IRQ_PROLOGUE();
> /* ... */
> VIC_GCCFIX_IRQ_EPILOGUE();
> }
>
> Sten
>

Yahoo! Groups Links

Memfault Beyond the Launch