Yahoo Groups archive

Lpc2000

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

Thread

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-06 by Marko Panger

Hi Sten,

I was experiencing the same GCC bug as you encountered. It came out only 
with optimization enabled.

I've searched around I and discovered that there seems to be some 
patches out there but all of them are not 100% confirmed as working 
patches. I read about the patches on bugzilla. After that I decided that 
is better for me not to apply unconfirmed patches and I simply tricked 
GCC by calling the "ISR_Body()" function from my ISR. 

Like you I was also surprised that this bug has not been still fixed.

Regards,
marko


Sten wrote:

>Tom Walsh wrote:
>  
>
>>Sten wrote:
>>
>>
>>    
>>
>>>Tom Walsh wrote:
>>>
>>>
>>>
>>>      
>>>
>>>>Sten wrote:
>>>>
>>>>
>>>>  
>>>>
>>>>
>>>>        
>>>>
>>>>>Hello Tom,
>>>>>
>>>>>some days ago I discovered a GCC bug on interrupt service routines for functions with
>>>>>__attribute__((interrupt("IRQ"))). At GCC-Bugzilla I found that this bug has still been reported in
>>>>>2005 under bug report #16634 in which you are involved in. Do you know why this bug is still
>>>>>"UNCONFIRMED"?!?
>>>>>
>>>>>The bug still persists in:
>>>>>arm-elf-gcc (GCC) 4.0.1
>>>>>arm-elf-gcc (GCC) 4.1.0
>>>>>
>>>>>Do you (or somebody else) have a gcc-patch to solve this problem? I took a look to the gcc sources
>>>>>by myself but the problem occurs in conjunction with optimization under conditions, where LR
>>>>>register is used for subroutine branches, and this could a little bit more tricky to solve it than
>>>>>just hacking the ARM section of GCC!
>>>>>
>>>>>Can somebody confirm this bug in the binary-tool-chain from www.gnuarm.com or on other GCC-based
>>>>>cross compiler versions? It seems gnuarm don't have any special patches against this problem, too.
>>>>>(See test-case below!)
>>>>>
>>>>>
>>>>>    
>>>>>
>>>>>          
>>>>>
>>>>I am not sure what your question is. Why do you feel you have to 
>>>>intentionally suppress the apcs stack frame?
>>>>
>>>>  
>>>>
>>>>        
>>>>
>>>With -mapcs-frame the code produced looks good but due to the APCS a lot of overhead at entry and
>>>exit of my functions is generated. Without that option (or with -mno-apcs-frame) gcc generates wrong
>>>entry/exit code but the code footprint is more slim.
>>>In my opinion an arm-elf-gcc should produce correct code for ARM cores in any case.
>>>
>>>GCC manual says for ARM option -mapcs-frame:
>>>"Generate a stack frame that is compliant with the ARM Procedure Call Standard for all functions,
>>>even if this is not strictly necessary for correct execution of the code."
>>>
>>>My question was if you know something about the detailed status of bug report #16634? I'm wondering
>>>why it is still UNCONFIRMED since 2005.
>>>
>>>
>>>
>>>      
>>>
>>No, I don't.  AFAIK, the apcs frame is used for backtracing code.  So 
>>far, the Insight debugger has been fine for backtracing with the options 
>>I specify for compiles:
>>
>>arm-elf-gcc -c -O0 -mthumb  -mcpu=arm7tdmi -march=armv4t 
>>-DTOPLEVEL=/home/tom/MuxPad3Devel/EvntCPU/../ -I. -gstabs -DROM_RUN 
>>-I/home/tom/MuxPad3Devel/EvntCPU/../include 
>>-I/home/tom/MuxPad3Devel/EvntCPU/../libs/include -Wall 
>>-Wstrict-prototypes -Wcast-align -Wcast-qual -Wimplicit 
>>-Wmissing-declarations -Wmissing-prototypes -Wnested-externs 
>>-Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow 
>>-Wstrict-prototypes -Wunused -Wa,-adhlns=main2138.lst  -std=gnu99 
>>-nostdlib -nodefaultlibs 
>>-L/home/tom/devtools/armThumb-4.0.2/arm-elf/lib/thumb/interwork/ 
>>-L/home/tom/devtools/armThumb-4.0.2/lib/gcc/arm-elf/4.0.2/interwork/ -MD 
>>-MP -MF .dep/main2138.o.d -DLPC2138 
>>-I/home/tom/MuxPad3Devel/EvntCPU//include  -DLPC2138 main2138.c -o 
>>main2138.o
>>
>>I am not optimizing as yet for two reasons:
>>
>>1. I have adequate codespace, yet.
>>2. It is a nightmare to debug optimized code!
>>
>>    
>>
>
>Ok, that's the reason! I explored that it happens only in conjunction with optimization options. It
>seems that gcc is mixing up optimized code with non-optimized.
>
>Sometimes gcc results in very neat optimized code like this:
>irq:
>	sub	lr, lr, #4
>	stmdb	sp!, {r1,r2,lr}
>	...
>	ldmia	sp!, {r1,r2,pc}		@ loading pc with lr-4 directly from stack
>
>or in the default code recommended in ARM manual:
>
>irq:
>	stmdb	sp!, {r1,r2,lr}
>	...
>	ldmia	sp!, {r1,r2,lr}
>	subs	pc, lr, #4
>
>The erronous output when optimizing looks like a mixture of both:
>
>irq:
>	sub	lr, lr, #4
>	stmdb	sp!, {r1,r2,lr}
>	...
>	ldmia	sp!, {r1,r2,lr}
>	subs	sp, lr, #4
>
>Has nobody else recognized this?!?
>
>Regards.
>   Sten
>
>  
>



[Non-text portions of this message have been removed]

{To TomW} GCC-Bug in IRQs

2006-03-25 by Sten

Hello Tom,

some days ago I discovered a GCC bug on interrupt service routines for functions with
__attribute__((interrupt("IRQ"))). At GCC-Bugzilla I found that this bug has still been reported in
2005 under bug report #16634 in which you are involved in. Do you know why this bug is still
"UNCONFIRMED"?!?

The bug still persists in:
arm-elf-gcc (GCC) 4.0.1
arm-elf-gcc (GCC) 4.1.0

Do you (or somebody else) have a gcc-patch to solve this problem? I took a look to the gcc sources
by myself but the problem occurs in conjunction with optimization under conditions, where LR
register is used for subroutine branches, and this could a little bit more tricky to solve it than
just hacking the ARM section of GCC!

Can somebody confirm this bug in the binary-tool-chain from www.gnuarm.com or on other GCC-based
cross compiler versions? It seems gnuarm don't have any special patches against this problem, too.
(See test-case below!)

At the moment I'm using a dirty workaround by generating correct entry and exit code "manually" in a
naked function.

Thanks,
     Sten

-----------------------------------------------------------------------------------------
Test-case:

#include <stdio.h>
#include <stdlib.h>

void irqFunc2a(void) __attribute__((interrupt("IRQ")));
void dummy(void);

void irqFunc2a(void) {
        dummy();
}
void dummy(void) {
        int test;

        test = *((volatile char*) 0xffff);
        test += 10;
        *((volatile char*) 0xffff) = test;
}

Compile these functions with:
$ arm-elf-gcc -mcpu=arm7tdmi-s -mthumb-interwork -fomit-frame-pointer -c test.c
OR
$ arm-elf-gcc -mcpu=arm7tdmi-s -mthumb-interwork -O2 -c test.c

and have a look at operations on LR register at entry and exit code of irqFunc2a() with:
$ arm-elf-objdump -DS test.o

-- 
/************************************************
 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/

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

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Tom Walsh

Sten wrote:

>Hello Tom,
>
>some days ago I discovered a GCC bug on interrupt service routines for functions with
>__attribute__((interrupt("IRQ"))). At GCC-Bugzilla I found that this bug has still been reported in
>2005 under bug report #16634 in which you are involved in. Do you know why this bug is still
>"UNCONFIRMED"?!?
>
>The bug still persists in:
>arm-elf-gcc (GCC) 4.0.1
>arm-elf-gcc (GCC) 4.1.0
>
>Do you (or somebody else) have a gcc-patch to solve this problem? I took a look to the gcc sources
>by myself but the problem occurs in conjunction with optimization under conditions, where LR
>register is used for subroutine branches, and this could a little bit more tricky to solve it than
>just hacking the ARM section of GCC!
>
>Can somebody confirm this bug in the binary-tool-chain from www.gnuarm.com or on other GCC-based
>cross compiler versions? It seems gnuarm don't have any special patches against this problem, too.
>(See test-case below!)
>  
>
I am not sure what your question is. Why do you feel you have to 
intentionally suppress the apcs stack frame?


Regards,

TomW

-- 
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------------------------------------------

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Sten

Tom Walsh wrote:
> Sten wrote:
> 
> 
>>Hello Tom,
>>
>>some days ago I discovered a GCC bug on interrupt service routines for functions with
>>__attribute__((interrupt("IRQ"))). At GCC-Bugzilla I found that this bug has still been reported in
>>2005 under bug report #16634 in which you are involved in. Do you know why this bug is still
>>"UNCONFIRMED"?!?
>>
>>The bug still persists in:
>>arm-elf-gcc (GCC) 4.0.1
>>arm-elf-gcc (GCC) 4.1.0
>>
>>Do you (or somebody else) have a gcc-patch to solve this problem? I took a look to the gcc sources
>>by myself but the problem occurs in conjunction with optimization under conditions, where LR
>>register is used for subroutine branches, and this could a little bit more tricky to solve it than
>>just hacking the ARM section of GCC!
>>
>>Can somebody confirm this bug in the binary-tool-chain from www.gnuarm.com or on other GCC-based
>>cross compiler versions? It seems gnuarm don't have any special patches against this problem, too.
>>(See test-case below!)
>> 
>>
> 
> I am not sure what your question is. Why do you feel you have to 
> intentionally suppress the apcs stack frame?
> 

With -mapcs-frame the code produced looks good but due to the APCS a lot of overhead at entry and
exit of my functions is generated. Without that option (or with -mno-apcs-frame) gcc generates wrong
entry/exit code but the code footprint is more slim.
In my opinion an arm-elf-gcc should produce correct code for ARM cores in any case.

GCC manual says for ARM option -mapcs-frame:
"Generate a stack frame that is compliant with the ARM Procedure Call Standard for all functions,
even if this is not strictly necessary for correct execution of the code."

My question was if you know something about the detailed status of bug report #16634? I'm wondering
why it is still UNCONFIRMED since 2005.

Maybe there is somebody out there, who knows something about a patch to fix this problem in GCC
directly.

Regards,
  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/

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

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Tom Walsh

Sten wrote:

>Tom Walsh wrote:
>  
>
>>Sten wrote:
>>
>>
>>    
>>
>>>Hello Tom,
>>>
>>>some days ago I discovered a GCC bug on interrupt service routines for functions with
>>>__attribute__((interrupt("IRQ"))). At GCC-Bugzilla I found that this bug has still been reported in
>>>2005 under bug report #16634 in which you are involved in. Do you know why this bug is still
>>>"UNCONFIRMED"?!?
>>>
>>>The bug still persists in:
>>>arm-elf-gcc (GCC) 4.0.1
>>>arm-elf-gcc (GCC) 4.1.0
>>>
>>>Do you (or somebody else) have a gcc-patch to solve this problem? I took a look to the gcc sources
>>>by myself but the problem occurs in conjunction with optimization under conditions, where LR
>>>register is used for subroutine branches, and this could a little bit more tricky to solve it than
>>>just hacking the ARM section of GCC!
>>>
>>>Can somebody confirm this bug in the binary-tool-chain from www.gnuarm.com or on other GCC-based
>>>cross compiler versions? It seems gnuarm don't have any special patches against this problem, too.
>>>(See test-case below!)
>>>
>>>
>>>      
>>>
>>I am not sure what your question is. Why do you feel you have to 
>>intentionally suppress the apcs stack frame?
>>
>>    
>>
>
>With -mapcs-frame the code produced looks good but due to the APCS a lot of overhead at entry and
>exit of my functions is generated. Without that option (or with -mno-apcs-frame) gcc generates wrong
>entry/exit code but the code footprint is more slim.
>In my opinion an arm-elf-gcc should produce correct code for ARM cores in any case.
>
>  
>
I don't use:

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

I declare as:

void someISR (void) __attribute__((interrupt));

Entry / exit code is fine.



TomW



>GCC manual says for ARM option -mapcs-frame:
>"Generate a stack frame that is compliant with the ARM Procedure Call Standard for all functions,
>even if this is not strictly necessary for correct execution of the code."
>
>My question was if you know something about the detailed status of bug report #16634? I'm wondering
>why it is still UNCONFIRMED since 2005.
>
>Maybe there is somebody out there, who knows something about a patch to fix this problem in GCC
>directly.
>
>Regards,
>  Sten
>
>  
>


-- 
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------------------------------------------

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Tom Walsh

Sten wrote:

>Tom Walsh wrote:
>  
>
>>Sten wrote:
>>
>>
>>    
>>
>>>Hello Tom,
>>>
>>>some days ago I discovered a GCC bug on interrupt service routines for functions with
>>>__attribute__((interrupt("IRQ"))). At GCC-Bugzilla I found that this bug has still been reported in
>>>2005 under bug report #16634 in which you are involved in. Do you know why this bug is still
>>>"UNCONFIRMED"?!?
>>>
>>>The bug still persists in:
>>>arm-elf-gcc (GCC) 4.0.1
>>>arm-elf-gcc (GCC) 4.1.0
>>>
>>>Do you (or somebody else) have a gcc-patch to solve this problem? I took a look to the gcc sources
>>>by myself but the problem occurs in conjunction with optimization under conditions, where LR
>>>register is used for subroutine branches, and this could a little bit more tricky to solve it than
>>>just hacking the ARM section of GCC!
>>>
>>>Can somebody confirm this bug in the binary-tool-chain from www.gnuarm.com or on other GCC-based
>>>cross compiler versions? It seems gnuarm don't have any special patches against this problem, too.
>>>(See test-case below!)
>>>
>>>
>>>      
>>>
>>I am not sure what your question is. Why do you feel you have to 
>>intentionally suppress the apcs stack frame?
>>
>>    
>>
>
>With -mapcs-frame the code produced looks good but due to the APCS a lot of overhead at entry and
>exit of my functions is generated. Without that option (or with -mno-apcs-frame) gcc generates wrong
>entry/exit code but the code footprint is more slim.
>In my opinion an arm-elf-gcc should produce correct code for ARM cores in any case.
>
>GCC manual says for ARM option -mapcs-frame:
>"Generate a stack frame that is compliant with the ARM Procedure Call Standard for all functions,
>even if this is not strictly necessary for correct execution of the code."
>
>My question was if you know something about the detailed status of bug report #16634? I'm wondering
>why it is still UNCONFIRMED since 2005.
>
>  
>
No, I don't.  AFAIK, the apcs frame is used for backtracing code.  So 
far, the Insight debugger has been fine for backtracing with the options 
I specify for compiles:

arm-elf-gcc -c -O0 -mthumb  -mcpu=arm7tdmi -march=armv4t 
-DTOPLEVEL=/home/tom/MuxPad3Devel/EvntCPU/../ -I. -gstabs -DROM_RUN 
-I/home/tom/MuxPad3Devel/EvntCPU/../include 
-I/home/tom/MuxPad3Devel/EvntCPU/../libs/include -Wall 
-Wstrict-prototypes -Wcast-align -Wcast-qual -Wimplicit 
-Wmissing-declarations -Wmissing-prototypes -Wnested-externs 
-Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow 
-Wstrict-prototypes -Wunused -Wa,-adhlns=main2138.lst  -std=gnu99 
-nostdlib -nodefaultlibs 
-L/home/tom/devtools/armThumb-4.0.2/arm-elf/lib/thumb/interwork/ 
-L/home/tom/devtools/armThumb-4.0.2/lib/gcc/arm-elf/4.0.2/interwork/ -MD 
-MP -MF .dep/main2138.o.d -DLPC2138 
-I/home/tom/MuxPad3Devel/EvntCPU//include  -DLPC2138 main2138.c -o 
main2138.o

I am not optimizing as yet for two reasons:

1. I have adequate codespace, yet.
2. It is a nightmare to debug optimized code!

Regards,

TomW



-- 
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------------------------------------------

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Sten

Tom Walsh wrote:
> Sten wrote:
> 
> 
>>Tom Walsh wrote:
>> 
>>
>>
>>>Sten wrote:
>>>
>>>
>>>   
>>>
>>>
>>>>Hello Tom,
>>>>
>>>>some days ago I discovered a GCC bug on interrupt service routines for functions with
>>>>__attribute__((interrupt("IRQ"))). At GCC-Bugzilla I found that this bug has still been reported in
>>>>2005 under bug report #16634 in which you are involved in. Do you know why this bug is still
>>>>"UNCONFIRMED"?!?
>>>>
>>>>The bug still persists in:
>>>>arm-elf-gcc (GCC) 4.0.1
>>>>arm-elf-gcc (GCC) 4.1.0
>>>>
>>>>Do you (or somebody else) have a gcc-patch to solve this problem? I took a look to the gcc sources
>>>>by myself but the problem occurs in conjunction with optimization under conditions, where LR
>>>>register is used for subroutine branches, and this could a little bit more tricky to solve it than
>>>>just hacking the ARM section of GCC!
>>>>
>>>>Can somebody confirm this bug in the binary-tool-chain from www.gnuarm.com or on other GCC-based
>>>>cross compiler versions? It seems gnuarm don't have any special patches against this problem, too.
>>>>(See test-case below!)
>>>>
>>>>
>>>>     
>>>>
>>>
>>>I am not sure what your question is. Why do you feel you have to 
>>>intentionally suppress the apcs stack frame?
>>>
>>>   
>>>
>>
>>With -mapcs-frame the code produced looks good but due to the APCS a lot of overhead at entry and
>>exit of my functions is generated. Without that option (or with -mno-apcs-frame) gcc generates wrong
>>entry/exit code but the code footprint is more slim.
>>In my opinion an arm-elf-gcc should produce correct code for ARM cores in any case.
>>
>> 
>>
> 
> I don't use:
> 
> void someISR (void) __attribute__((interrupt("IRQ")));
> 
> I declare as:
> 
> void someISR (void) __attribute__((interrupt));
> 
> Entry / exit code is fine.
> 
> 
> 
> TomW
> 

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?

Regards.
  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/

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

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Robert Adsett

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

" '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/

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Sten

Tom Walsh wrote:
> Sten wrote:
> 
> 
>>Tom Walsh wrote:
>> 
>>
>>
>>>Sten wrote:
>>>
>>>
>>>   
>>>
>>>
>>>>Hello Tom,
>>>>
>>>>some days ago I discovered a GCC bug on interrupt service routines for functions with
>>>>__attribute__((interrupt("IRQ"))). At GCC-Bugzilla I found that this bug has still been reported in
>>>>2005 under bug report #16634 in which you are involved in. Do you know why this bug is still
>>>>"UNCONFIRMED"?!?
>>>>
>>>>The bug still persists in:
>>>>arm-elf-gcc (GCC) 4.0.1
>>>>arm-elf-gcc (GCC) 4.1.0
>>>>
>>>>Do you (or somebody else) have a gcc-patch to solve this problem? I took a look to the gcc sources
>>>>by myself but the problem occurs in conjunction with optimization under conditions, where LR
>>>>register is used for subroutine branches, and this could a little bit more tricky to solve it than
>>>>just hacking the ARM section of GCC!
>>>>
>>>>Can somebody confirm this bug in the binary-tool-chain from www.gnuarm.com or on other GCC-based
>>>>cross compiler versions? It seems gnuarm don't have any special patches against this problem, too.
>>>>(See test-case below!)
>>>>
>>>>
>>>>     
>>>>
>>>
>>>I am not sure what your question is. Why do you feel you have to 
>>>intentionally suppress the apcs stack frame?
>>>
>>>   
>>>
>>
>>With -mapcs-frame the code produced looks good but due to the APCS a lot of overhead at entry and
>>exit of my functions is generated. Without that option (or with -mno-apcs-frame) gcc generates wrong
>>entry/exit code but the code footprint is more slim.
>>In my opinion an arm-elf-gcc should produce correct code for ARM cores in any case.
>>
>>GCC manual says for ARM option -mapcs-frame:
>>"Generate a stack frame that is compliant with the ARM Procedure Call Standard for all functions,
>>even if this is not strictly necessary for correct execution of the code."
>>
>>My question was if you know something about the detailed status of bug report #16634? I'm wondering
>>why it is still UNCONFIRMED since 2005.
>>
>> 
>>
> 
> No, I don't.  AFAIK, the apcs frame is used for backtracing code.  So 
> far, the Insight debugger has been fine for backtracing with the options 
> I specify for compiles:
> 
> arm-elf-gcc -c -O0 -mthumb  -mcpu=arm7tdmi -march=armv4t 
> -DTOPLEVEL=/home/tom/MuxPad3Devel/EvntCPU/../ -I. -gstabs -DROM_RUN 
> -I/home/tom/MuxPad3Devel/EvntCPU/../include 
> -I/home/tom/MuxPad3Devel/EvntCPU/../libs/include -Wall 
> -Wstrict-prototypes -Wcast-align -Wcast-qual -Wimplicit 
> -Wmissing-declarations -Wmissing-prototypes -Wnested-externs 
> -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow 
> -Wstrict-prototypes -Wunused -Wa,-adhlns=main2138.lst  -std=gnu99 
> -nostdlib -nodefaultlibs 
> -L/home/tom/devtools/armThumb-4.0.2/arm-elf/lib/thumb/interwork/ 
> -L/home/tom/devtools/armThumb-4.0.2/lib/gcc/arm-elf/4.0.2/interwork/ -MD 
> -MP -MF .dep/main2138.o.d -DLPC2138 
> -I/home/tom/MuxPad3Devel/EvntCPU//include  -DLPC2138 main2138.c -o 
> main2138.o
> 
> I am not optimizing as yet for two reasons:
> 
> 1. I have adequate codespace, yet.
> 2. It is a nightmare to debug optimized code!
> 

Ok, that's the reason! I explored that it happens only in conjunction with optimization options. It
seems that gcc is mixing up optimized code with non-optimized.

Sometimes gcc results in very neat optimized code like this:
irq:
	sub	lr, lr, #4
	stmdb	sp!, {r1,r2,lr}
	...
	ldmia	sp!, {r1,r2,pc}		@ loading pc with lr-4 directly from stack

or in the default code recommended in ARM manual:

irq:
	stmdb	sp!, {r1,r2,lr}
	...
	ldmia	sp!, {r1,r2,lr}
	subs	pc, lr, #4

The erronous output when optimizing looks like a mixture of both:

irq:
	sub	lr, lr, #4
	stmdb	sp!, {r1,r2,lr}
	...
	ldmia	sp!, {r1,r2,lr}
	subs	sp, lr, #4

Has nobody else recognized this?!?

Regards.
   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/

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

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Sten

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.

  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/

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

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Robert Adsett

At 08:17 PM 3/25/2006 +0100, Sten wrote:
>Robert Adsett wrote:
> > 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.
>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.


If you write a stub that problem disappears. The procedure call standard 
ensures that the proper registers are saved when you call out of the stub. 
You only have to save something like 6 registers for IRQ, the called 
routine preserves any of the others it uses..

Also are you sure you actually really care about the extra saves?  Beware 
of premature optimization.  Didn't Knuth call it the root of all evil? 
:)  If your response time is sufficient and your are not overloading the 
CPU forget about the wasted cycles, you are spending time doing something 
that simply does not matter.

I do a stub not for efficiency but because experience has taught me to 
never trust any compiler to produce correct interrupt code.  Correct does 
sometimes mean efficient but it can also mean the more obvious things.

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/

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Sten

Robert Adsett wrote:
> At 08:17 PM 3/25/2006 +0100, Sten wrote:
> 
>>Robert Adsett wrote:
>>
>>>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.
>>
>>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.
> 
> 
> 
> If you write a stub that problem disappears. The procedure call standard 
> ensures that the proper registers are saved when you call out of the stub. 
> You only have to save something like 6 registers for IRQ, the called 
> routine preserves any of the others it uses..
> 
> Also are you sure you actually really care about the extra saves?  Beware 
> of premature optimization.  Didn't Knuth call it the root of all evil? 
> :)  If your response time is sufficient and your are not overloading the 
> CPU forget about the wasted cycles, you are spending time doing something 
> that simply does not matter.
> 
> I do a stub not for efficiency but because experience has taught me to 
> never trust any compiler to produce correct interrupt code.  Correct does 
> sometimes mean efficient but it can also mean the more obvious things.
> 
> Robert

Ok, what exactly did you mean by a "stub"? You write a piece of assembler code for a particular IRQ
and then branch to your (normal) C service function, don't you?
I'm thinking of writing a generic IRQ handler instead of a direct branch to VIC-vector register from
vector table, I'm using at the moment. This IRQ handler (in clean assembler) could have correct
entry and exit code and is branching to the service function from VIC-vector. The overhead would be
very less. In this case I can also add some extra code to serve spurious interrupts in any way I
like. (STOP! I DONT WANT TO START A NEW ENDLESS THREAD HERE!)

  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/

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

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Sten

Marko Panger wrote:
> Hi Sten,
> 
> I was experiencing the same GCC bug as you encountered. It came out only 
> with optimization enabled.
> 
> I've searched around I and discovered that there seems to be some 
> patches out there but all of them are not 100% confirmed as working 
> patches. I read about the patches on bugzilla. After that I decided that 
> is better for me not to apply unconfirmed patches and I simply tricked 
> GCC by calling the "ISR_Body()" function from my ISR. 
> 
> Like you I was also surprised that this bug has not been still fixed.
> 
> Regards,
> marko
> 
> 
> Sten wrote:
> 
> 
>>Tom Walsh wrote:
>> 
>>
>>
>>>Sten wrote:
>>>
>>>
>>>   
>>>
>>>
>>>>Tom Walsh wrote:
>>>>
>>>>
>>>>
>>>>     
>>>>
>>>>
>>>>>Sten wrote:
>>>>>
>>>>>
>>>>> 
>>>>>
>>>>>
>>>>>       
>>>>>
>>>>>
>>>>>>Hello Tom,
>>>>>>
>>>>>>some days ago I discovered a GCC bug on interrupt service routines for functions with
>>>>>>__attribute__((interrupt("IRQ"))). At GCC-Bugzilla I found that this bug has still been reported in
>>>>>>2005 under bug report #16634 in which you are involved in. Do you know why this bug is still
>>>>>>"UNCONFIRMED"?!?
>>>>>>
>>>>>>The bug still persists in:
>>>>>>arm-elf-gcc (GCC) 4.0.1
>>>>>>arm-elf-gcc (GCC) 4.1.0
>>>>>>
>>>>>>Do you (or somebody else) have a gcc-patch to solve this problem? I took a look to the gcc sources
>>>>>>by myself but the problem occurs in conjunction with optimization under conditions, where LR
>>>>>>register is used for subroutine branches, and this could a little bit more tricky to solve it than
>>>>>>just hacking the ARM section of GCC!
>>>>>>
>>>>>>Can somebody confirm this bug in the binary-tool-chain from www.gnuarm.com or on other GCC-based
>>>>>>cross compiler versions? It seems gnuarm don't have any special patches against this problem, too.
>>>>>>(See test-case below!)
>>>>>>
>>>>>>
>>>>>>   
>>>>>>
>>>>>>         
>>>>>>
>>>>>
>>>>>I am not sure what your question is. Why do you feel you have to 
>>>>>intentionally suppress the apcs stack frame?
>>>>>
>>>>> 
>>>>>
>>>>>       
>>>>>
>>>>
>>>>With -mapcs-frame the code produced looks good but due to the APCS a lot of overhead at entry and
>>>>exit of my functions is generated. Without that option (or with -mno-apcs-frame) gcc generates wrong
>>>>entry/exit code but the code footprint is more slim.
>>>>In my opinion an arm-elf-gcc should produce correct code for ARM cores in any case.
>>>>
>>>>GCC manual says for ARM option -mapcs-frame:
>>>>"Generate a stack frame that is compliant with the ARM Procedure Call Standard for all functions,
>>>>even if this is not strictly necessary for correct execution of the code."
>>>>
>>>>My question was if you know something about the detailed status of bug report #16634? I'm wondering
>>>>why it is still UNCONFIRMED since 2005.
>>>>
>>>>
>>>>
>>>>     
>>>>
>>>
>>>No, I don't.  AFAIK, the apcs frame is used for backtracing code.  So 
>>>far, the Insight debugger has been fine for backtracing with the options 
>>>I specify for compiles:
>>>
>>>arm-elf-gcc -c -O0 -mthumb  -mcpu=arm7tdmi -march=armv4t 
>>>-DTOPLEVEL=/home/tom/MuxPad3Devel/EvntCPU/../ -I. -gstabs -DROM_RUN 
>>>-I/home/tom/MuxPad3Devel/EvntCPU/../include 
>>>-I/home/tom/MuxPad3Devel/EvntCPU/../libs/include -Wall 
>>>-Wstrict-prototypes -Wcast-align -Wcast-qual -Wimplicit 
>>>-Wmissing-declarations -Wmissing-prototypes -Wnested-externs 
>>>-Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow 
>>>-Wstrict-prototypes -Wunused -Wa,-adhlns=main2138.lst  -std=gnu99 
>>>-nostdlib -nodefaultlibs 
>>>-L/home/tom/devtools/armThumb-4.0.2/arm-elf/lib/thumb/interwork/ 
>>>-L/home/tom/devtools/armThumb-4.0.2/lib/gcc/arm-elf/4.0.2/interwork/ -MD 
>>>-MP -MF .dep/main2138.o.d -DLPC2138 
>>>-I/home/tom/MuxPad3Devel/EvntCPU//include  -DLPC2138 main2138.c -o 
>>>main2138.o
>>>
>>>I am not optimizing as yet for two reasons:
>>>
>>>1. I have adequate codespace, yet.
>>>2. It is a nightmare to debug optimized code!
>>>
>>>   
>>>
>>
>>Ok, that's the reason! I explored that it happens only in conjunction with optimization options. It
>>seems that gcc is mixing up optimized code with non-optimized.
>>
>>Sometimes gcc results in very neat optimized code like this:
>>irq:
>>	sub	lr, lr, #4
>>	stmdb	sp!, {r1,r2,lr}
>>	...
>>	ldmia	sp!, {r1,r2,pc}		@ loading pc with lr-4 directly from stack
>>
>>or in the default code recommended in ARM manual:
>>
>>irq:
>>	stmdb	sp!, {r1,r2,lr}
>>	...
>>	ldmia	sp!, {r1,r2,lr}
>>	subs	pc, lr, #4
>>
>>The erronous output when optimizing looks like a mixture of both:
>>
>>irq:
>>	sub	lr, lr, #4
>>	stmdb	sp!, {r1,r2,lr}
>>	...
>>	ldmia	sp!, {r1,r2,lr}
>>	subs	sp, lr, #4
>>
>>Has nobody else recognized this?!?
>>
>>Regards.
>>  Sten
>>
>> 
>>

Hello Marko,

do you still know where you to find these patches? I would take a look into, because I started to
search the gcc sources for the root of this problem. Maybe there is a simple patch which do not
touch sensible code in gcc. To fix something in the ARM section of GCC would be more easy, but the
fact that this occurs along with optimization makes it very tricky!

  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/

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

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by David Hawkins

> I'm thinking of writing a generic IRQ handler instead of a 
> direct branch to VIC-vector register from vector table, 

You mean something like this ....

irq_isr:
     /* Save IRQ context, including the APCS registers, and r4-6 */
     sub   lr, lr, #4
     stmfd sp!, {r0-r6, ip, lr}

     /* Save the SPSR_irq register */
     mrs r4, spsr

     /* Read the VICVectAddr */
     ldr r5, VICVECTADDR
     ldr r6, [r5]

     /* Change to SYS mode and enable IRQ */
     msr cpsr_c, #SYS_MODE

     /* Debug:
      * Comment out the change to system mode with IRQs enabled
      * and uncomment the following to leave IRQs disabled. IRQs
      * are then handled non-nested (with more overhead than normal)
      */
/*    msr cpsr_c, #SYS_MODE|IRQ_DISABLE*/

     /* Save the banked SYS mode link register */
     stmfd sp!, {lr}

     /* Call the C-coded handler */
     mov lr, pc
     mov pc, r6

     /* Restore SYS mode link register */
     ldmfd sp!, {lr}

     /* Change to IRQ mode and disable IRQ */
     msr cpsr_c, #IRQ_MODE|IRQ_DISABLE

     /* Restore the SPSR */
     msr spsr, r4

     /* Acknowledge the VIC */
     mov r0, #0
     str r0, [r5]

     /* Restore IRQ context and return from interrupt */
     ldmfd sp!, {r0-r6, ip, pc}^

VICVECTADDR:     .word   0xFFFFF030

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Robert Adsett

At 09:33 PM 3/25/2006 +0100, Sten wrote:
>Robert Adsett wrote:
> > At 08:17 PM 3/25/2006 +0100, Sten wrote:
> >
> >>Robert Adsett wrote:
> >>
> >>>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.
> >>
> >>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.
> >
> >
> >
> > If you write a stub that problem disappears. The procedure call standard
> > ensures that the proper registers are saved when you call out of the stub.
> > You only have to save something like 6 registers for IRQ, the called
> > routine preserves any of the others it uses..
> >
> > Also are you sure you actually really care about the extra saves?  Beware
> > of premature optimization.  Didn't Knuth call it the root of all evil?
> > :)  If your response time is sufficient and your are not overloading the
> > CPU forget about the wasted cycles, you are spending time doing something
> > that simply does not matter.
> >
> > I do a stub not for efficiency but because experience has taught me to
> > never trust any compiler to produce correct interrupt code.  Correct does
> > sometimes mean efficient but it can also mean the more obvious things.
> >
> > Robert
>
>Ok, what exactly did you mean by a "stub"? You write a piece of assembler 
>code for a particular IRQ
>and then branch to your (normal) C service function, don't you?

As a matter of fact, yes.  That would be a stub.

>I'm thinking of writing a generic IRQ handler instead of a direct branch 
>to VIC-vector register from
>vector table, I'm using at the moment. This IRQ handler (in clean 
>assembler) could have correct
>entry and exit code and is branching to the service function from 
>VIC-vector. The overhead would be
>very less.

That would also be a stub.  I don't see any reason off hand not to do it 
that way although I also don't see that it will change the overhead at all.

branch to irq source specific stub
save registers
call service function

versus

branch to stub
save registers
call irq source specific function

Since you cannot take advantage of the 'wrap-around indexing' into the VIC 
table it might even be a little more overhead in the second case.  I doubt 
it matters in most cases and I can see some real clarity advantages to 
doing it that way.  Hmmmm....

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/

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Sten

Robert Adsett wrote:
> At 09:33 PM 3/25/2006 +0100, Sten wrote:
> 
>>Robert Adsett wrote:
>>
>>>At 08:17 PM 3/25/2006 +0100, Sten wrote:
>>>
>>>
>>>>Robert Adsett wrote:
>>>>
>>>>
>>>>>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.
>>>>
>>>>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.
>>>
>>>
>>>
>>>If you write a stub that problem disappears. The procedure call standard
>>>ensures that the proper registers are saved when you call out of the stub.
>>>You only have to save something like 6 registers for IRQ, the called
>>>routine preserves any of the others it uses..
>>>
>>>Also are you sure you actually really care about the extra saves?  Beware
>>>of premature optimization.  Didn't Knuth call it the root of all evil?
>>>:)  If your response time is sufficient and your are not overloading the
>>>CPU forget about the wasted cycles, you are spending time doing something
>>>that simply does not matter.
>>>
>>>I do a stub not for efficiency but because experience has taught me to
>>>never trust any compiler to produce correct interrupt code.  Correct does
>>>sometimes mean efficient but it can also mean the more obvious things.
>>>
>>>Robert
>>
>>Ok, what exactly did you mean by a "stub"? You write a piece of assembler 
>>code for a particular IRQ
>>and then branch to your (normal) C service function, don't you?
> 
> 
> As a matter of fact, yes.  That would be a stub.
> 
> 
>>I'm thinking of writing a generic IRQ handler instead of a direct branch 
>>to VIC-vector register from
>>vector table, I'm using at the moment. This IRQ handler (in clean 
>>assembler) could have correct
>>entry and exit code and is branching to the service function from 
>>VIC-vector. The overhead would be
>>very less.
> 
> 
> That would also be a stub.  I don't see any reason off hand not to do it 
> that way although I also don't see that it will change the overhead at all.
> 
> branch to irq source specific stub
> save registers
> call service function
> 
> versus
> 
> branch to stub
> save registers
> call irq source specific function
> 
> Since you cannot take advantage of the 'wrap-around indexing' into the VIC 
> table it might even be a little more overhead in the second case.  I doubt 
> it matters in most cases and I can see some real clarity advantages to 
> doing it that way.  Hmmmm....
> 
> Robert
> 

You're right, the overhead is exceptable. And it needs less clocks than my current work-around. I
think, I will write a stub tomorrow! ;-)

  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/

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

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Sten

David Hawkins wrote:
>>I'm thinking of writing a generic IRQ handler instead of a 
>>direct branch to VIC-vector register from vector table, 
> 
> 
> You mean something like this ....
> 
> irq_isr:
>      /* Save IRQ context, including the APCS registers, and r4-6 */
>      sub   lr, lr, #4
>      stmfd sp!, {r0-r6, ip, lr}
> 
>      /* Save the SPSR_irq register */
>      mrs r4, spsr
> 
>      /* Read the VICVectAddr */
>      ldr r5, VICVECTADDR
>      ldr r6, [r5]
> 
>      /* Change to SYS mode and enable IRQ */
>      msr cpsr_c, #SYS_MODE
> 
>      /* Debug:
>       * Comment out the change to system mode with IRQs enabled
>       * and uncomment the following to leave IRQs disabled. IRQs
>       * are then handled non-nested (with more overhead than normal)
>       */
> /*    msr cpsr_c, #SYS_MODE|IRQ_DISABLE*/
> 
>      /* Save the banked SYS mode link register */
>      stmfd sp!, {lr}
> 
>      /* Call the C-coded handler */
>      mov lr, pc
>      mov pc, r6
> 
>      /* Restore SYS mode link register */
>      ldmfd sp!, {lr}
> 
>      /* Change to IRQ mode and disable IRQ */
>      msr cpsr_c, #IRQ_MODE|IRQ_DISABLE
> 
>      /* Restore the SPSR */
>      msr spsr, r4
> 
>      /* Acknowledge the VIC */
>      mov r0, #0
>      str r0, [r5]
> 
>      /* Restore IRQ context and return from interrupt */
>      ldmfd sp!, {r0-r6, ip, pc}^
> 
> VICVECTADDR:     .word   0xFFFFF030
> 

YES, something like that! ;-) But without nesting and change of cpu-mode.

  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/

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

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by David Hawkins

> YES, something like that! ;-) But without nesting and change of cpu-mode.

Then perhaps this :)

irq_isr:
     sub   lr, lr, #4
     stmfd sp!, {r0-r3, ip, lr}
     bl irq_handler
     ldmfd sp!, {r0-r3, ip, pc}^


/* VICVectAddr dispatch loop */
void irq_handler(void)
{
	/* Process IRQ interrupts */
	irq_handler_t handler;
	while (VICIRQStatus) {
		/* Get the address of the highest priority handler */
		handler = (irq_handler_t)VICVectAddr;

		/* Execute the handler */
		(*handler)();

		/* Acknowledge the VIC */
		VICVectAddr = 0;
	}
}

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Sten

David Hawkins wrote:
>>YES, something like that! ;-) But without nesting and change of cpu-mode.
> 
> 
> Then perhaps this :)
> 
> irq_isr:
>      sub   lr, lr, #4
>      stmfd sp!, {r0-r3, ip, lr}
>      bl irq_handler
>      ldmfd sp!, {r0-r3, ip, pc}^
> 
> 
> /* VICVectAddr dispatch loop */
> void irq_handler(void)
> {
> 	/* Process IRQ interrupts */
> 	irq_handler_t handler;
> 	while (VICIRQStatus) {
> 		/* Get the address of the highest priority handler */
> 		handler = (irq_handler_t)VICVectAddr;
> 
> 		/* Execute the handler */
> 		(*handler)();
> 
> 		/* Acknowledge the VIC */
> 		VICVectAddr = 0;
> 	}
> }
> 

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!

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/

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

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-25 by Robert Adsett

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

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/

Re: {To TomW} GCC-Bug in IRQs

2006-03-26 by roger_lynx

--- In lpc2000@yahoogroups.com, 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=60 MHz
LA's sampling rate; f=200 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
Show quoted textHide quoted text
> 
>   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/
> 
> ************************************************/
>

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-26 by Sten

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/

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

Re: {To TomW} GCC-Bug in IRQs

2006-03-26 by frankcallaghan9

--- In lpc2000@yahoogroups.com, "roger_lynx" <roger_lynx@...> wrote:
>
> --- In lpc2000@yahoogroups.com, 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=60 MHz
> LA's sampling rate; f=200 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,

Re: [lpc2000] Interrupt Prologue/Epilogue Was: {To TomW} GCC-Bug in IRQs

2006-03-26 by Robert Adsett

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/

Re: [lpc2000] Re: {To TomW} GCC-Bug in IRQs

2006-03-27 by Sten

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/

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

Re: [lpc2000] Re: {To TomW} GCC-Bug in IRQs

2006-03-27 by Richard Duits

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:
Show quoted textHide quoted text
> 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
>

Re: {To TomW} GCC-Bug in IRQs

2006-03-27 by roger_lynx

--- In lpc2000@yahoogroups.com, Richard Duits <yahoo@...> wrote:
>
> 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.
> 
>

Yes, I think you're correct. Since pc is included in the register_list
it is a LDM(3)-type, to copy SPSR of the current mode (SPSR_irq) to
CPSR, "^" is needed. 
ARM ARM pg. A4-34.

Roger
 
> 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()                                        
      \
Show quoted textHide quoted text
> >         __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
> >
>

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-27 by clemens fischer

> David Hawkins:

> irq_isr:
>      sub   lr, lr, #4
>      stmfd sp!, {r0-r3, ip, lr}
>      bl irq_handler
>      ldmfd sp!, {r0-r3, ip, pc}^
> 
> 
> /* VICVectAddr dispatch loop */
> void irq_handler(void)

wouldn't this handler need the "naked" attribute when using the stub
above? would you please write out the declaration in full?

> {
> 	/* Process IRQ interrupts */
> 	irq_handler_t handler;
> 	while (VICIRQStatus) {
> 		/* Get the address of the highest priority handler */
> 		handler = (irq_handler_t)VICVectAddr;
> 
> 		/* Execute the handler */
> 		(*handler)();
> 
> 		/* Acknowledge the VIC */
> 		VICVectAddr = 0;
> 	}
> }

  clemens

Re: [lpc2000] {To TomW} GCC-Bug in IRQs

2006-03-27 by David Hawkins

Hi Clemens,

> wouldn't this handler need the "naked" attribute when using the stub
> above? would you please write out the declaration in full?

With the assembler coded stub in place, the functions loaded
into the VIC are standard C functions. The code requires no
attributes anywhere. Maximum portability.

Given that the functions called by the VIC are standard,
they adhere to the ACPS, and so the assembler stub just
handles the caller save registers and expects the compiler
to do-the-right-thing for the rest.

The example code below demonstrates this ...

Cheers
Dave


/* ex10_main.c
  *
  * Software generated EINT[0:3] example (non-nested IRQs)
  */
#include "led.h"

/* ----------------------------------------------------------------
  * LPC2138 registers
  * ----------------------------------------------------------------
  */
#define VICIRQStatus    (*((volatile unsigned long *) 0xFFFFF000))
#define VICIntSelect    (*((volatile unsigned long *) 0xFFFFF00C))
#define VICIntEnable    (*((volatile unsigned long *) 0xFFFFF010))
#define VICSoftInt      (*((volatile unsigned long *) 0xFFFFF018))
#define VICSoftIntClear (*((volatile unsigned long *) 0xFFFFF01C))
#define VICVectAddr     (*((volatile unsigned long *) 0xFFFFF030))
#define VICDefVectAddr  (*((volatile unsigned long *) 0xFFFFF034))
#define VICVectAddr0    (*((volatile unsigned long *) 0xFFFFF100))
#define VICVectAddr1    (*((volatile unsigned long *) 0xFFFFF104))
#define VICVectAddr2    (*((volatile unsigned long *) 0xFFFFF108))
#define VICVectAddr3    (*((volatile unsigned long *) 0xFFFFF10C))
#define VICVectCntl0    (*((volatile unsigned long *) 0xFFFFF200))
#define VICVectCntl1    (*((volatile unsigned long *) 0xFFFFF204))
#define VICVectCntl2    (*((volatile unsigned long *) 0xFFFFF208))
#define VICVectCntl3    (*((volatile unsigned long *) 0xFFFFF20C))

/* ----------------------------------------------------------------
  * Function declarations and globals
  * ----------------------------------------------------------------
  */
void irq_init();
void fiq_handler(void);
typedef void(*irq_handler_t)(void);

void irq_handler(void);
void eint0_handler(void);
void eint1_handler(void);
void eint2_handler(void);
void eint3_handler(void);

/* IRQ register bit locations */
#define EINT0 (1 << 14)
#define EINT1 (2 << 14)
#define EINT2 (4 << 14)
#define EINT3 (8 << 14)

/* ----------------------------------------------------------------
  * Function definitions
  * ----------------------------------------------------------------
  */

/* Setup the IRQ interrupts */
void irq_init(void)
{
   /* Setup the VIC to have EINT[0:3] generate IRQs */
   VICIntSelect   = 0;                           /* Select IRQ      */
   VICVectAddr0   = (unsigned long)eint0_handler;/* Vector 0        */
   VICVectAddr1   = (unsigned long)eint1_handler;/* Vector 1        */
   VICVectAddr2   = (unsigned long)eint2_handler;/* Vector 2        */
   VICVectAddr3   = (unsigned long)eint3_handler;/* Vector 3        */
   VICVectCntl0   = 0x20 | 14;                   /* EINT0 Interrupt */
   VICVectCntl1   = 0x20 | 15;                   /* EINT1 Interrupt */
   VICVectCntl2   = 0x20 | 16;                   /* EINT2 Interrupt */
   VICVectCntl3   = 0x20 | 17;                   /* EINT3 Interrupt */
   VICIntEnable   = (0xF << 14);                 /* Enable          */

}

/* VICVectAddr dispatch loop */
void irq_handler(void)
{
	/* Process IRQ interrupts */
	irq_handler_t handler;
	while (VICIRQStatus) {
		/* Get the address of the highest priority handler */
		handler = (irq_handler_t)VICVectAddr;

		/* Execute the handler */
		(*handler)();

		/* Acknowledge the VIC */
		VICVectAddr = 0;
	}
}

void eint0_handler(void)
{
	/* Clear interrupt source */
	VICSoftIntClear = EINT0;

	/* Processing EINT0 complete */
	led_clr(1);
}

void eint1_handler(void)
{
	/* Clear interrupt source */
	VICSoftIntClear = EINT1;

	/* Process EINT1 */

	/* Trigger EINT0 */
	led_set(1);
	VICSoftInt = EINT0;

	/* Processing EINT1 complete */
	led_clr(2);
}

void eint2_handler(void)
{
	/* Clear interrupt source */
	VICSoftIntClear = EINT2;

	/* Process EINT2 */

	/* Trigger EINT1 */
	led_set(2);
	VICSoftInt = EINT1;

	/* Processing EINT2 complete */
	led_clr(4);
}

void eint3_handler(void)
{
	/* Clear interrupt source */
	VICSoftIntClear = EINT3;

	/* Process EINT3 */

	/* Trigger EINT2 */
	led_set(4);
	VICSoftInt = EINT2;

	/* Processing EINT3 complete */
	led_clr(8);
}

/* Empty handler (since the startup code references it) */
void fiq_handler(void)
{
	return;
}

/* ----------------------------------------------------------------
  * Application
  * ----------------------------------------------------------------
  */
int main (void)
{
	led_init();
	/* Start low */
	led(0);
	irq_init();
	while(1) {
		/* Trigger EINT3 */
		led_set(8);
		VICSoftInt = EINT3;
	}
	return 0;
}


/* ex10a_start.s */

     .global main
     .global _start
	
     /* Symbols defined by the linker script */
     .global _etext
     .global _data
     .global _edata
     .global _bss
     .global _ebss

     /* External functions */
     .global fiq_handler
     .global irq_handler

     .text
     .arm

/* ----------------------------------------------------------------
  * Exception vectors
  * ----------------------------------------------------------------
  */
_start:
     b reset  /* reset */
     b loop   /* undefined instruction */
     b loop   /* software interrupt */
     b loop   /* prefetch abort */
     b loop   /* data abort */
     nop      /* reserved for the bootloader checksum */
     ldr pc, irq_addr

     /* FIQ ISR */
fiq_isr:
     sub   lr, lr, #4
     stmfd sp!, {r0-r3, ip, lr}
     bl fiq_handler
     ldmfd sp!, {r0-r3, ip, pc}^

irq_addr: .word irq_isr
irq_isr:
     sub   lr, lr, #4
     stmfd sp!, {r0-r3, ip, lr}
     bl irq_handler
     ldmfd sp!, {r0-r3, ip, pc}^

/* ----------------------------------------------------------------
  * LPC21xx PLL setup
  * ----------------------------------------------------------------
  */
reset:
     /* Use r0 for indirect addressing */
     ldr	r0, PLLBASE

     /* PLLCFG = PLLCFG_VALUE */
     mov	r3, #PLLCFG_VALUE
     str r3, [r0, #PLLCFG_OFFSET]

     /* PLLCON = PLLCON_PLLE */
     mov	r3, #PLLCON_PLLE
     str r3, [r0, #PLLCON_OFFSET]

     /* PLLFEED = PLLFEED1, PLLFEED2 */
     mov	r1, #PLLFEED1
     mov	r2, #PLLFEED2
     str r1, [r0, #PLLFEED_OFFSET]
     str r2, [r0, #PLLFEED_OFFSET]

     /* 	while ((PLLSTAT & PLLSTAT_PLOCK) == 0); */
pll_loop:
     ldr r3, [r0, #PLLSTAT_OFFSET]
     tst	r3, #PLLSTAT_PLOCK
     beq	pll_loop

     /* PLLCON = PLLCON_PLLC|PLLCON_PLLE */
     mov	r3, #PLLCON_PLLC|PLLCON_PLLE
     str r3, [r0, #PLLCON_OFFSET]

     /* PLLFEED = PLLFEED1, PLLFEED2 */
     str r1, [r0, #PLLFEED_OFFSET]
     str r2, [r0, #PLLFEED_OFFSET]

/* ----------------------------------------------------------------
  * LPC21xx MAM setup
  * ----------------------------------------------------------------
  */
mam_init:
     /* Use r0 for indirect addressing */
     ldr	r0, MAMBASE

     /* MAMCR = MAMCR_VALUE */
     mov	r1, #MAMCR_VALUE
     str r1, [r0, #MAMCR_OFFSET]

     /* MAMTIM = MAMTIM_VALUE */
     mov	r1, #MAMTIM_VALUE
     str r1, [r0, #MAMTIM_OFFSET]

/* ----------------------------------------------------------------
  * LPC21xx stacks setup
  * ----------------------------------------------------------------
  */
stacks_init:
     ldr r0, STACK_START

     /* FIQ mode stack */
     msr CPSR_c, #FIQ_MODE|IRQ_DISABLE|FIQ_DISABLE
     mov sp, r0
     sub r0, r0, #FIQ_STACK_SIZE

     /* IRQ mode stack */
     msr CPSR_c, #IRQ_MODE|IRQ_DISABLE|FIQ_DISABLE
     mov sp, r0
     sub r0, r0, #IRQ_STACK_SIZE

     /* Supervisor mode stack */
     msr CPSR_c, #SVC_MODE|IRQ_DISABLE|FIQ_DISABLE
     mov sp, r0
     sub r0, r0, #SVC_STACK_SIZE

     /* Undefined mode stack */
     msr CPSR_c, #UND_MODE|IRQ_DISABLE|FIQ_DISABLE
     mov sp, r0
     sub r0, r0, #UND_STACK_SIZE

     /* Abort mode stack */
     msr CPSR_c, #ABT_MODE|IRQ_DISABLE|FIQ_DISABLE
     mov sp, r0
     sub r0, r0, #ABT_STACK_SIZE

     /* System mode stack */
/*    msr CPSR_c, #SYS_MODE|IRQ_DISABLE|FIQ_DISABLE*/
     msr CPSR_c, #SYS_MODE
     mov sp, r0

     /* Leave the processor in system mode */

/* ----------------------------------------------------------------
  * C runtime setup
  * ----------------------------------------------------------------
  */
runtime_init:
     /* Copy .data */
     ldr r0, data_source
     ldr r1, data_start
     ldr r2, data_end
copy_data:
     cmp   r1, r2
     ldrne r3, [r0], #4
     strne r3, [r1], #4
     bne   copy_data
	
     /* Clear .bss */
     ldr r0, =0
     ldr r1, bss_start
     ldr r2, bss_end
clear_bss:
     cmp   r1, r2
     strne r0, [r1], #4
     bne   clear_bss

     /* Jump to main */
     bl  main

/* Catch return from main */
loop:   b   loop

/* ----------------------------------------------------------------
  * 32-bit constants (and storage)
  * ----------------------------------------------------------------
  *
  * These 32-bit constants are used in ldr statements.
  */

/* LPC SRAM starts at 0x40000000, and there is 32Kb = 8000h */
STACK_START:	.word   0x40008000
PLLBASE:        .word   0xE01FC080
MAMBASE:        .word   0xE01FC000

/* Linker symbols */
data_source:    .word   _etext
data_start:     .word   _data
data_end:       .word   _edata
bss_start:      .word   _bss
bss_end:        .word   _ebss

/* ----------------------------------------------------------------
  * 8-bit constants
  * ----------------------------------------------------------------
  *
  * These 8-bit constants are used as immediate values and offsets.
  */

/* PLL configuration */
     .equ PLLCON_OFFSET,   0x0
     .equ PLLCFG_OFFSET,   0x4
     .equ PLLSTAT_OFFSET,  0x8
     .equ PLLFEED_OFFSET,  0xC

     .equ PLLCON_PLLE,    (1 << 0)
     .equ PLLCON_PLLC,    (1 << 1)
     .equ PLLSTAT_PLOCK,  (1 << 10)
     .equ PLLFEED1,        0xAA
     .equ PLLFEED2,        0x55

     .equ PLLCFG_VALUE,    0x24

/* MAM configuration */
     .equ MAMCR_OFFSET,   0x0
     .equ MAMTIM_OFFSET,  0x4

     .equ MAMCR_VALUE,    0x2  /* fully enabled */
     .equ MAMTIM_VALUE,   0x4  /* fetch cycles  */

/* Stack configuration */
     /* Processor modes (see pA2-11 ARM-ARM) */
     .equ FIQ_MODE,       0x11
     .equ IRQ_MODE,       0x12
     .equ SVC_MODE,       0x13  /* reset mode */
     .equ ABT_MODE,       0x17
     .equ UND_MODE,       0x1B
     .equ SYS_MODE,       0x1F

     /* Stack sizes */
     .equ FIQ_STACK_SIZE, 0x00000080    /*  32x32-bit words */
     .equ IRQ_STACK_SIZE, 0x00000080
     .equ SVC_STACK_SIZE, 0x00000080
     .equ ABT_STACK_SIZE, 0x00000010    /*   4x32-bit words */
     .equ UND_STACK_SIZE, 0x00000010
     .equ SYS_STACK_SIZE, 0x00000400    /* 256x32-bit words */

     /* CPSR interrupt disable bits */
     .equ IRQ_DISABLE,    (1 << 7)
     .equ FIQ_DISABLE,    (1 << 6)

     .end

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.