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 bdmlpc

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.