Yahoo Groups archive

Lpc2000

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

Message

Re: Save/restore IRQ registers in GNU C

2005-10-25 by Guillermo Prandi

Hi, Sten. Thanks for your answer. Since this function was calling 
other functions (and could not possibly know what other registers 
might the other functions alter), I was wondering if this code 
shouldn't have saved the r4-r12 registers. I wasn't aware of APCS (r0-
r3 being scratch registers, as David just explained to me), but I 
deeply suspected there was one.

Guille

--- In lpc2000@yahoogroups.com, "bdmlpc" <list@n...> wrote:
>
> Hello Guille,
> 
> which registers do you expect to save/restore when calling a
> sub-routine? In generell you are only saving registers you need. In
> your IRQ all used registers (r0..r3) are saved and restored.
> CPSR (current program status register) must not be saved if you are
> not using nested interrupts on your IRQ. CPSR is automatically saved
> to SPSR_mode (saved program status register of certain mode) when 
ARM
> switches from user/system/supervisor mode to IRQ mode. IRQ is 
disabled
> when switich to IRQ to disable interrupt nesting. SPSR is shadow
> register. It is restored when you return from IRQ mode to your
> previously used mode. Therfore don't touch CPSR in interrupt 
services
> routines. It is not a x86 architecture! ARM does everything for you.
> 
>   Sten
> 
> --- In lpc2000@yahoogroups.com, "Guillermo Prandi"
> <yahoo.messenger@m...> wrote:
> >
> > Hi, all!
> > 
> > First of all I want to thank everybody in this group. The amount 
and 
> > quality of help I'm receiving from you guys is extraordinary. I 
> > sincerely hope I can contribute helping others in due time.
> > 
> > I am doing some IRQ compilation tests with GCC and the 
__attribute__ 
> > ((interrupt("IRQ")) syntax. Apparently the code doesn't seem to 
> > save/restore all the registers I expected. In particular, it 
doesn't 
> > seem to save spsr. Also, only general registers r1-r4 are saved 
> > before calling an external function. I have the following 
questions:
> > 
> > * Saving spsr is only needed for reentrant IRQs?
> > * Perhaps saving only r1-r4 is a convention, and functions should 
> > always save by themselves any other general registers they may 
use?
> > * Should I worry or this is perfectly normal and *safe*?
> > 
> > Thanks in advance.
> > 
> > Guille
> > 
> > void Uart0Service(void) __attribute__ ((interrupt("IRQ"));
> > 
> > void Uart0Service(void)
> > {
> > 18f0:  e24ee004  sub    lr, lr, #4 ; 0x4
> > 18f4:  e92d500f  stmdb  sp!, {r0, r1, r2, r3, ip, lr}
> > unsigned char temp_id;
> > temp_id = U0IIR;
> >     18f8:  e3a03903   mov  r3, #49152   ; 0xc000
> >     18fc:  e283328e   add  r3, r3, #-536870904  ; 0xe0000008
> >     1900:  e5d32000   ldrb  r2, [r3]
> > switch(temp_id & IDENT_MASK) {
> >     1904:  e202200e   and  r2, r2, #14  ; 0xe
> > case DATA_AVAILABLE:
> > case DATA_TIMEOUT:
> > receive();
> > break;
> > case TRANSMIT_AVAILABLE:
> > transmit();
> > default:
> > break;
> > }
> >     /* case DATA_AVAILABLE */
> >     1908:  e3520004   cmp  r2, #4       ; 0x4
> >     190c:  0a000005   beq  1928 <Uart0Service+0x38>
> > 
> >     /* case DATA_TIMEOUT */
> >     1910:  e352000c   cmp  r2, #12      ; 0xc
> >     1914:  0a000003   beq  1928 <Uart0Service+0x38>
> > 
> >     /* case [not] TRANSMIT_AVAILABLE */
> >     1918:  e3520002   cmp  r2, #2       ; 0x2
> >     191c:  18fd900f   ldmneia  sp!, {r0, r1, r2, r3, ip, pc}^
> > 
> >     1920:  ebfffa69   bl  2cc <transmit>
> >     1924:  e8fd900f   ldmia  sp!, {r0, r1, r2, r3, ip, pc}^
> > 
> >     1928:  ebfffa75   bl  304 <receive>
> >     192c:  e8fd900f   ldmia  sp!, {r0, r1, r2, r3, ip, pc}^
> > }
> > 
> > Shouldn't this code also save spsr? Or perhaps this is only 
needed 
> > for reentrant IRQs?
> > 
> > Guille
> >
>

Attachments

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.