ISR-support in ARM

Richard Slaughter rslaughter@anatel.com
Wed Oct 3 10:20:00 GMT 2001


Kai,

The current release of 3.0.2 and snapshot I used was recognizing the
interrupt keyword and generating ISR code.   I "assumed" it was correct.
I'm using the atmel AT91FR40807 processor and with the debugger I was
getting
interrupts and returning correctly.

I didn't anaylsis the interrupt handler as closely as I should have
and missed the r12 register usage.

I don't understand how you concluded that the GCC ISR works
for the atmel AT91.  It seems to me that r12 is overwritten.

Richard Slaughter

----- Original Message -----
From: "Kai Ruottu" <kai.ruottu@luukku.com>
To: "Richard Slaughter" <rslaughter@anatel.com>
Cc: <crossgcc@sourceware.cygnus.com>; <ananda.motte@philips.com>
Sent: Monday, November 12, 2001 4:33 AM
Subject: ISR-support in ARM


> Hi,
> here were some discussion about this subject earlier, but some issues were
> left unclear, at least to me....
>
> Richard Slaughter wrote:
> >
> >  Hi Amanda,
> >  I'm trying to do the same thing with the interrupt key words.  Only I'm
> >  using the ARM7TDMI core.
> >  If I'm understanding things correctly version 3.0.X has provisions for
this
> >  keyword for the ARM.
> >  I could not get any earlier version of the GCC to recognize the keyword
but
> >  was able to get the 3.0.2 snapshot to work.   I'm trying to use it with
C++
> >  and the compiler is recognizing the keyword and adding code for the
interrupt.
> >  The code added is only using the default stack and not the dedicated
interrupt
> >  stack.
> >  example:  foo() __attribute__((interrupt("IRQ")))
>
>  Hmmmm...
>
>  A quick check with the gcc-3.0.2-implementation gave an impression about
at
> least one 'bug' being there :
>
> --------------------------
clip -------------------------------------------
> @ Generated by gcc 3.0.2 for ARM/elf
> .file "isr_demo.c"
> .text
> .align 2
> .global handle_intr
> .type handle_intr,function
> handle_intr:
> @ Interrupt Service Routine.
> @ args = 0, pretend = 0, frame = 0
> @ frame_needed = 0, current_function_anonymous_args = 0
> @ link register save eliminated.  <--- 'lr' not used as 'scratch' ?
> stmfd sp!, {r0, r1, r2, r3}
> ldr r1, .L3
> ldr r3, [r1, #0]
> add r3, r3, #1
> str r3, [r1, #0]
> ldr r0, .L3+4
> cmp r3, #400
> ldreqb r3, [r0, #0]
> moveq r2, #0
> eoreq r3, r3, #1
> streq r2, [r1, #0]
> ldr ip, .L3+8 <------ Oops, the r12 ('ip') is allocated !!!!
> streqb r3, [r0, #0]
> ldrb r3, [ip, #0]
> and r3, r3, #254
> strb r3, [ip, #0]
> ldmfd sp!, {r0, r1, r2, r3}
> subs pc, lr, #4
> .L4:
> .align 2
> .L3:
> .word count
> .word 16777174
> .word 16777063
> .Lfe1:
> .size handle_intr,.Lfe1-handle_intr
> --------------------------
clip -------------------------------------------
>
>  When this was the 1st ISR-test I tried with gcc-3.0.2, and there was this
> error in the basic principle: "All the registers used inside the ISR must
> be saved in the prologue and restored in the epilogue", this wasn't very
> promising...
>
>  However fixing this 'bug' in gcc-3.0.2 isn't hard, after my own
implementation
> for the earlier GCCs, and then doing some work to handle the r11 - r15
(the 'fp',
> 'ip', 'lr' and 'pc' - the r13 is the 'sp') inside a ISR, some kind of
'fix' was
> done in 15 minutes...
>
>  But should this 'bug' be fixed?  Perhaps not because the 'ip' case, but
also
> the 'lr' handling fails in gcc-3.0.2. The 'lr'/'r14' is one of those
'scratch'
> registers and may be allocated too... Another test with more processing in
the
> ISR revealed that this really happens and the return address in 'lr' is
written
> over...
>
>  Ok, the words "was able to get the 3.0.2 snapshot to work" clash with my
> experiences presented here... What I cannot find is what kind of prologue
and
> epilogue wrappers done in assembly should be done for this. I understand
that
> the ARM-architecture is not so well defined in this respect. For instance
the
> Atmel AT91 has a special interrupt controller, 'AIC', which helps the
following
> to happen:
>
> ----------------------
clip ---------------------------------------------------
> ;- An interrupt occurs :
> ;- The core set the I bit and switch in IRQ Mode. The Program counter is
stored
> ;- in the Link Register before being loaded with the IRQ vector
0x00000018.
> ;- The Current Program Status Register is stored in the SPSR_irq register.
> ;- The core execute the instruction stored in the vector ( ldr pc,
[pc,#-&F20] )
> ;- and load the PC with the value read in the Interrupt Vector Register of
the
> ;- Advanced Interrupt Controller.
> ;- Read of the Interrupt Vector Register automatically clears the
interrupt
> ;- if this one is programmed edge triggered, and push in hardware stack
the
> ;- level of priority of the interrupt.
> ;- The value read in IVR is stored in the PC. This branch here.
> ----------------------
clip ---------------------------------------------------
>
>  So 'stand-alone' ISR-functions can be generated by GCC at least for this
ARM-
> CPU variation, if wanted, but what about all the others?
>
>  If there is a support for ISRs now in GCC, there should somewhere an
explanation
> how one uses the support, what kind of 'wrappers' one needs around the
gcc-3.x-
> generated code and so on... Has anyone found anything about this?
>
>  Meanwhile my opinion is that the 'ip', 'lr' and 'fp' should be saved in
the
> GCC-generated prologue, if the ISR uses them or if the ISR calls a
'normal'
> function which perhaps uses them but doesn't save them... A clip from the
> 'gcc/config/arm/arm.h' tells about the current register usage:
>
> --------------------------
clip -------------------------------------------
> /* Standard register usage.  */
>
> /* Register allocation in ARM Procedure Call Standard (as used on RISCiX):
>    (S - saved over call).
>
>         r0         *    argument word/integer result
>         r1-r3           argument word
>
>         r4-r8        S  register variable
>         r9           S  (rfp) register variable (real frame pointer)
>
>         r10        F S  (sl) stack limit (used by -mapcs-stack-check)
>         r11        F S  (fp) argument pointer
>         r12             (ip) temp workspace
>         r13        F S  (sp) lower end of current stack frame
>         r14             (lr) link address/workspace
>         r15        F    (pc) program counter
>
>         f0              floating point result
>         f1-f3           floating point scratch
>
>         f4-f7        S  floating point variable
> --------------------------
clip -------------------------------------------
>
>  Not leaving the 'ip' and 'fp'-saving to some unspecified wrappers, but
> doing this in the ISR-prologue, and the restoring in the ISR-epilogue,
> would be more 'normal', I don't understand what is the idea behind the
> current implementation...
>
> Cheers, Kai


------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sourceware.cygnus.com



More information about the crossgcc mailing list