Yahoo Groups archive

Lpc2000

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

Message

RE: [lpc2000] Save/restore IRQ registers in GNU C

2005-10-25 by David Hawkins

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

Hi Guille,

Let me help explain with the following (but incomplete) startup code:

    .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}^


Ok, above I define two external interrupt handlers written as
C-functions *** without the __interrupt__ attribute ***

The FIQ handler lives at the FIQ vector address, while the IRQ
handler is loaded into the PC, jumping it to irq_isr, which\
in turn saves context and jumps to the irq_handler function.

The ONLY registers you need to save there are the APCS
(ARM Procedure Calling Standard) 'scratch' registers.
Those registers are; r0-r3, and ip. The lr you save cause
you're calling a function.

All that the GNU compiler does is exactly that, and then
it optimizes, i.e., if it doesn't use r0-r3, it'll remove
them from the generated code.

The SPSR register only needs saving when nesting IRQ interrupts.
If an FIQ interrupt occurs while processing an IRQ interrupt,
its ok, as the FIQ mode has its own SPSR.

Cheers
Dave

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.