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
>Message
Re: Save/restore IRQ registers in GNU C
2005-10-25 by bdmlpc
Attachments
- No local attachments were found for this message.