Reply by David Hawkins March 27, 20062006-03-27
Hi Clemens,

> wouldn't this handler need the "naked" attribute when using the stub
> above? would you please write out the declaration in full?

With the assembler coded stub in place, the functions loaded
into the VIC are standard C functions. The code requires no
attributes anywhere. Maximum portability.

Given that the functions called by the VIC are standard,
they adhere to the ACPS, and so the assembler stub just
handles the caller save registers and expects the compiler
to do-the-right-thing for the rest.

The example code below demonstrates this ...

Cheers
Dave
/* ex10_main.c
*
* Software generated EINT[0:3] example (non-nested IRQs)
*/
#include "led.h"

/* ----------------------------
* LPC2138 registers
* ----------------------------
*/
#define VICIRQStatus (*((volatile unsigned long *) 0xFFFFF000))
#define VICIntSelect (*((volatile unsigned long *) 0xFFFFF00C))
#define VICIntEnable (*((volatile unsigned long *) 0xFFFFF010))
#define VICSoftInt (*((volatile unsigned long *) 0xFFFFF018))
#define VICSoftIntClear (*((volatile unsigned long *) 0xFFFFF01C))
#define VICVectAddr (*((volatile unsigned long *) 0xFFFFF030))
#define VICDefVectAddr (*((volatile unsigned long *) 0xFFFFF034))
#define VICVectAddr0 (*((volatile unsigned long *) 0xFFFFF100))
#define VICVectAddr1 (*((volatile unsigned long *) 0xFFFFF104))
#define VICVectAddr2 (*((volatile unsigned long *) 0xFFFFF108))
#define VICVectAddr3 (*((volatile unsigned long *) 0xFFFFF10C))
#define VICVectCntl0 (*((volatile unsigned long *) 0xFFFFF200))
#define VICVectCntl1 (*((volatile unsigned long *) 0xFFFFF204))
#define VICVectCntl2 (*((volatile unsigned long *) 0xFFFFF208))
#define VICVectCntl3 (*((volatile unsigned long *) 0xFFFFF20C))

/* ----------------------------
* Function declarations and globals
* ----------------------------
*/
void irq_init();
void fiq_handler(void);
typedef void(*irq_handler_t)(void);

void irq_handler(void);
void eint0_handler(void);
void eint1_handler(void);
void eint2_handler(void);
void eint3_handler(void);

/* IRQ register bit locations */
#define EINT0 (1 << 14)
#define EINT1 (2 << 14)
#define EINT2 (4 << 14)
#define EINT3 (8 << 14)

/* ----------------------------
* Function definitions
* ----------------------------
*/

/* Setup the IRQ interrupts */
void irq_init(void)
{
/* Setup the VIC to have EINT[0:3] generate IRQs */
VICIntSelect = 0; /* Select IRQ */
VICVectAddr0 = (unsigned long)eint0_handler;/* Vector 0 */
VICVectAddr1 = (unsigned long)eint1_handler;/* Vector 1 */
VICVectAddr2 = (unsigned long)eint2_handler;/* Vector 2 */
VICVectAddr3 = (unsigned long)eint3_handler;/* Vector 3 */
VICVectCntl0 = 0x20 | 14; /* EINT0 Interrupt */
VICVectCntl1 = 0x20 | 15; /* EINT1 Interrupt */
VICVectCntl2 = 0x20 | 16; /* EINT2 Interrupt */
VICVectCntl3 = 0x20 | 17; /* EINT3 Interrupt */
VICIntEnable = (0xF << 14); /* Enable */

}

/* VICVectAddr dispatch loop */
void irq_handler(void)
{
/* Process IRQ interrupts */
irq_handler_t handler;
while (VICIRQStatus) {
/* Get the address of the highest priority handler */
handler = (irq_handler_t)VICVectAddr;

/* Execute the handler */
(*handler)();

/* Acknowledge the VIC */
VICVectAddr = 0;
}
}

void eint0_handler(void)
{
/* Clear interrupt source */
VICSoftIntClear = EINT0;

/* Processing EINT0 complete */
led_clr(1);
}

void eint1_handler(void)
{
/* Clear interrupt source */
VICSoftIntClear = EINT1;

/* Process EINT1 */

/* Trigger EINT0 */
led_set(1);
VICSoftInt = EINT0;

/* Processing EINT1 complete */
led_clr(2);
}

void eint2_handler(void)
{
/* Clear interrupt source */
VICSoftIntClear = EINT2;

/* Process EINT2 */

/* Trigger EINT1 */
led_set(2);
VICSoftInt = EINT1;

/* Processing EINT2 complete */
led_clr(4);
}

void eint3_handler(void)
{
/* Clear interrupt source */
VICSoftIntClear = EINT3;

/* Process EINT3 */

/* Trigger EINT2 */
led_set(4);
VICSoftInt = EINT2;

/* Processing EINT3 complete */
led_clr(8);
}

/* Empty handler (since the startup code references it) */
void fiq_handler(void)
{
return;
}

/* ----------------------------
* Application
* ----------------------------
*/
int main (void)
{
led_init();
/* Start low */
led(0);
irq_init();
while(1) {
/* Trigger EINT3 */
led_set(8);
VICSoftInt = EINT3;
}
return 0;
}
/* ex10a_start.s */

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

/* ----------------------------
* LPC21xx PLL setup
* ----------------------------
*/
reset:
/* Use r0 for indirect addressing */
ldr r0, PLLBASE

/* PLLCFG = PLLCFG_VALUE */
mov r3, #PLLCFG_VALUE
str r3, [r0, #PLLCFG_OFFSET]

/* PLLCON = PLLCON_PLLE */
mov r3, #PLLCON_PLLE
str r3, [r0, #PLLCON_OFFSET]

/* PLLFEED = PLLFEED1, PLLFEED2 */
mov r1, #PLLFEED1
mov r2, #PLLFEED2
str r1, [r0, #PLLFEED_OFFSET]
str r2, [r0, #PLLFEED_OFFSET]

/* while ((PLLSTAT & PLLSTAT_PLOCK) == 0); */
pll_loop:
ldr r3, [r0, #PLLSTAT_OFFSET]
tst r3, #PLLSTAT_PLOCK
beq pll_loop

/* PLLCON = PLLCON_PLLC|PLLCON_PLLE */
mov r3, #PLLCON_PLLC|PLLCON_PLLE
str r3, [r0, #PLLCON_OFFSET]

/* PLLFEED = PLLFEED1, PLLFEED2 */
str r1, [r0, #PLLFEED_OFFSET]
str r2, [r0, #PLLFEED_OFFSET]

/* ----------------------------
* LPC21xx MAM setup
* ----------------------------
*/
mam_init:
/* Use r0 for indirect addressing */
ldr r0, MAMBASE

/* MAMCR = MAMCR_VALUE */
mov r1, #MAMCR_VALUE
str r1, [r0, #MAMCR_OFFSET]

/* MAMTIM = MAMTIM_VALUE */
mov r1, #MAMTIM_VALUE
str r1, [r0, #MAMTIM_OFFSET]

/* ----------------------------
* LPC21xx stacks setup
* ----------------------------
*/
stacks_init:
ldr r0, STACK_START

/* FIQ mode stack */
msr CPSR_c, #FIQ_MODE|IRQ_DISABLE|FIQ_DISABLE
mov sp, r0
sub r0, r0, #FIQ_STACK_SIZE

/* IRQ mode stack */
msr CPSR_c, #IRQ_MODE|IRQ_DISABLE|FIQ_DISABLE
mov sp, r0
sub r0, r0, #IRQ_STACK_SIZE

/* Supervisor mode stack */
msr CPSR_c, #SVC_MODE|IRQ_DISABLE|FIQ_DISABLE
mov sp, r0
sub r0, r0, #SVC_STACK_SIZE

/* Undefined mode stack */
msr CPSR_c, #UND_MODE|IRQ_DISABLE|FIQ_DISABLE
mov sp, r0
sub r0, r0, #UND_STACK_SIZE

/* Abort mode stack */
msr CPSR_c, #ABT_MODE|IRQ_DISABLE|FIQ_DISABLE
mov sp, r0
sub r0, r0, #ABT_STACK_SIZE

/* System mode stack */
/* msr CPSR_c, #SYS_MODE|IRQ_DISABLE|FIQ_DISABLE*/
msr CPSR_c, #SYS_MODE
mov sp, r0

/* Leave the processor in system mode */

/* ----------------------------
* C runtime setup
* ----------------------------
*/
runtime_init:
/* Copy .data */
ldr r0, data_source
ldr r1, data_start
ldr r2, data_end
copy_data:
cmp r1, r2
ldrne r3, [r0], #4
strne r3, [r1], #4
bne copy_data

/* Clear .bss */
ldr r0, =0
ldr r1, bss_start
ldr r2, bss_end
clear_bss:
cmp r1, r2
strne r0, [r1], #4
bne clear_bss

/* Jump to main */
bl main

/* Catch return from main */
loop: b loop

/* ----------------------------
* 32-bit constants (and storage)
* ----------------------------
*
* These 32-bit constants are used in ldr statements.
*/

/* LPC SRAM starts at 0x40000000, and there is 32Kb = 8000h */
STACK_START: .word 0x40008000
PLLBASE: .word 0xE01FC080
MAMBASE: .word 0xE01FC000

/* Linker symbols */
data_source: .word _etext
data_start: .word _data
data_end: .word _edata
bss_start: .word _bss
bss_end: .word _ebss

/* ----------------------------
* 8-bit constants
* ----------------------------
*
* These 8-bit constants are used as immediate values and offsets.
*/

/* PLL configuration */
.equ PLLCON_OFFSET, 0x0
.equ PLLCFG_OFFSET, 0x4
.equ PLLSTAT_OFFSET, 0x8
.equ PLLFEED_OFFSET, 0xC

.equ PLLCON_PLLE, (1 << 0)
.equ PLLCON_PLLC, (1 << 1)
.equ PLLSTAT_PLOCK, (1 << 10)
.equ PLLFEED1, 0xAA
.equ PLLFEED2, 0x55

.equ PLLCFG_VALUE, 0x24

/* MAM configuration */
.equ MAMCR_OFFSET, 0x0
.equ MAMTIM_OFFSET, 0x4

.equ MAMCR_VALUE, 0x2 /* fully enabled */
.equ MAMTIM_VALUE, 0x4 /* fetch cycles */

/* Stack configuration */
/* Processor modes (see pA2-11 ARM-ARM) */
.equ FIQ_MODE, 0x11
.equ IRQ_MODE, 0x12
.equ SVC_MODE, 0x13 /* reset mode */
.equ ABT_MODE, 0x17
.equ UND_MODE, 0x1B
.equ SYS_MODE, 0x1F

/* Stack sizes */
.equ FIQ_STACK_SIZE, 0x00000080 /* 32x32-bit words */
.equ IRQ_STACK_SIZE, 0x00000080
.equ SVC_STACK_SIZE, 0x00000080
.equ ABT_STACK_SIZE, 0x00000010 /* 4x32-bit words */
.equ UND_STACK_SIZE, 0x00000010
.equ SYS_STACK_SIZE, 0x00000400 /* 256x32-bit words */

/* CPSR interrupt disable bits */
.equ IRQ_DISABLE, (1 << 7)
.equ FIQ_DISABLE, (1 << 6)

.end

Yahoo! Groups Links

An Engineer's Guide to the LPC2100 Series

Reply by clemens fischer March 27, 20062006-03-27
> David Hawkins:

> irq_isr:
> sub lr, lr, #4
> stmfd sp!, {r0-r3, ip, lr}
> bl irq_handler
> ldmfd sp!, {r0-r3, ip, pc}^
> /* VICVectAddr dispatch loop */
> void irq_handler(void)

wouldn't this handler need the "naked" attribute when using the stub
above? would you please write out the declaration in full?

> {
> /* Process IRQ interrupts */
> irq_handler_t handler;
> while (VICIRQStatus) {
> /* Get the address of the highest priority handler */
> handler = (irq_handler_t)VICVectAddr;
>
> /* Execute the handler */
> (*handler)();
>
> /* Acknowledge the VIC */
> VICVectAddr = 0;
> }
> }

clemens

Yahoo! Groups Links
Reply by roger_lynx March 27, 20062006-03-27
--- In l..., Richard Duits wrote:
>
> I think VIC_GCCFIX_IRQ_EPILOGUE should be:
>
> #define VIC_GCCFIX_IRQ_EPILOGUE() \
> __asm__ __volatile__( " ldmia sp!, {r0-r12,pc}^
> \n");
> The "^" tells the arm to copy SPSR to CPSR.
>
> Richard.

Yes, I think you're correct. Since pc is included in the register_list
it is a LDM(3)-type, to copy SPSR of the current mode (SPSR_irq) to
CPSR, "^" is needed.
ARM ARM pg. A4-34.

Roger

> Sten wrote:
> > frankcallaghan9 wrote:
> > >
> > > Hi Guys,
> > > I've just hit this problem in my UART handler, I'm new to the ARM
> > > and haven't used it's asm yet! could one of you ASM gurus
> > > please post the required inline entry/exit code for us dummys
> > > thanks,
> >
> > Hello Frank,
> >
> > if you want to use "manually" written prologue/epilogue instead of a
> > stub try this:
> >
> > #define
> > VIC_GCCFIX_IRQ_PROLOGUE()
\
> > __asm__ __volatile__( " sub lr, lr,
> > #4 \n" \
> > " stmdb sp!,
> > {r0-r12,lr} \n");
> > #define VIC_GCCFIX_IRQ_EPILOGUE() \
> > __asm__ __volatile__( " ldmia sp!,
> > {r0-r12,pc} \n");
> >
> > void myIRQ(void) __attribute__((interrupt("IRQ"), naked));
> >
> > void myIRQ(void) {
> > VIC_GCCFIX_IRQ_PROLOGUE();
> > /* ... */
> > VIC_GCCFIX_IRQ_EPILOGUE();
> > }
> >
> > Sten
>

Yahoo! Groups Links
Reply by Richard Duits March 27, 20062006-03-27
I think VIC_GCCFIX_IRQ_EPILOGUE should be:

#define VIC_GCCFIX_IRQ_EPILOGUE() \
__asm__ __volatile__( " ldmia sp!, {r0-r12,pc}^
\n");
The "^" tells the arm to copy SPSR to CPSR.

Richard.
Sten wrote:
> frankcallaghan9 wrote:
> >
> > Hi Guys,
> > I've just hit this problem in my UART handler, I'm new to the ARM
> > and haven't used it's asm yet! could one of you ASM gurus
> > please post the required inline entry/exit code for us dummys
> > thanks,
>
> Hello Frank,
>
> if you want to use "manually" written prologue/epilogue instead of a
> stub try this:
>
> #define
> VIC_GCCFIX_IRQ_PROLOGUE() \
> __asm__ __volatile__( " sub lr, lr,
> #4 \n" \
> " stmdb sp!,
> {r0-r12,lr} \n");
> #define VIC_GCCFIX_IRQ_EPILOGUE() \
> __asm__ __volatile__( " ldmia sp!,
> {r0-r12,pc} \n");
>
> void myIRQ(void) __attribute__((interrupt("IRQ"), naked));
>
> void myIRQ(void) {
> VIC_GCCFIX_IRQ_PROLOGUE();
> /* ... */
> VIC_GCCFIX_IRQ_EPILOGUE();
> }
>
> Sten
>

Yahoo! Groups Links
Reply by Sten March 27, 20062006-03-27
frankcallaghan9 wrote:
>
> Hi Guys,
> I've just hit this problem in my UART handler, I'm new to the ARM
> and haven't used it's asm yet! could one of you ASM gurus
> please post the required inline entry/exit code for us dummys
> thanks,

Hello Frank,

if you want to use "manually" written prologue/epilogue instead of a stub try this:

#define VIC_GCCFIX_IRQ_PROLOGUE() \
__asm__ __volatile__( " sub lr, lr, #4 \n" \
" stmdb sp!, {r0-r12,lr} \n");
#define VIC_GCCFIX_IRQ_EPILOGUE() \
__asm__ __volatile__( " ldmia sp!, {r0-r12,pc} \n");

void myIRQ(void) __attribute__((interrupt("IRQ"), naked));

void myIRQ(void) {
VIC_GCCFIX_IRQ_PROLOGUE();
/* ... */
VIC_GCCFIX_IRQ_EPILOGUE();
}

Sten

--
/************************************************
Do you need a tiny and efficient real time
operating system (RTOS) with a preemtive
multitasking for LPC2000 or AT91SAM7?

http://nanortos.net-attack.de/

Or some open-source tools and code for LPC2000?

http://www.net-attack.de/

************************************************/

Yahoo! Groups Links
Reply by Robert Adsett March 26, 20062006-03-26
At 10:42 PM 3/26/2006 +0000, frankcallaghan9 wrote:
>Hi Guys,
>I've just hit this problem in my UART handler, I'm new to the ARM
>and haven't used it's asm yet! could one of you ASM gurus
>please post the required inline entry/exit code for us dummys
>thanks,

My experience with inline matches that of compiler interrupt keywords. It
makes far more sense just to do it in assembly.

Take a look at the interrupt example in newlib-lpc.
http://www.aeolusdevelopment.com/Articles/download.html They can be easily
separated from the rest so using the epilogues and prologues from there
doesn't commit you to the rest of the library.

Robert

" 'Freedom' has no meaning of itself. There are always restrictions, be
they legal, genetic, or physical. If you don't believe me, try to chew a
radio signal. " -- Kelvin Throop, III
http://www.aeolusdevelopment.com/
Reply by frankcallaghan9 March 26, 20062006-03-26
--- In lpc2000@lpc2..., "roger_lynx" <roger_lynx@...>
wrote:
>
> --- In lpc2000@lpc2..., Sten <list@> wrote:
> >
> > Robert Adsett wrote:
> > > At 07:49 PM 3/25/2006 +0100, Sten wrote:
> > >
> > >>I've tried this. But entry/exit is still not correct.
> > >>Here's the result:
> > >>
> > >>void uart_irqHandler0(void) __attribute__((interrupt));
> > >>
> > >>00000204 <uart_irqHandler0>:
> > >> 204: e24ee004 sub lr, lr, #4 ; 0x4
> > >> 208: e92d500f stmdb sp!, {r0, r1, r2, r3, ip, lr}
> > >> 20c: e3a0120e mov r1, #-536870912 ; 0xe0000000
> > >> 210: e2811903 add r1, r1, #49152 ; 0xc000
> > >> 214: e3a00000 mov r0, #0 ; 0x0
> > >> 218: ebfffffe bl d0 <uart_irqHandler_common>
> > >> 21c: e8bd500f ldmia sp!, {r0, r1, r2, r3, ip, lr}
> > >> 220: e25ef004 subs pc, lr, #4 ; 0x4
> > >>
> > >>Question:
> > >>Which gcc version do you use? Which command line parameters do use?
> > >>How do you differentiate between IRQ and FIQ (only r0..r7 need
to be
> > >>saved) if use
> > >>__attribute__((interrupt)) only?
> > >
> > >
> > >
> > > Rather than go through all this hand-wringing why not just write an
> > > assembly stub? You'd know it was correct and you'd be done
> already. At
> > > most it would cost you an extra call from the stub to your C
> > > function. Heck if it was small enough it might make sense to do
> the whole
> > > thing in asm. For that matter you could steal one of my stubs.
> > >
> > > Robert
> > >
> >
> > Thanks Robert.
> > At the moment I declare my IRQ functions as "naked" and write my own
> prologue/epilogue with inline
> > assembler. But it is less efficient because I don't know which
> registers are really used, so I have
> > to save all non-banked registers (r0..12 for IRQ and r0..r7 for FIQ)
> which is a wast of performance.
>
>
> Yes. IRQ "undressed" and inline assembly for prologue/epilogue.
>
> I was curious about the performance hit myself, but rather
> than doing it academic-like way (in days), I measured it (in 10
minutes).
> The test is lousy,since the execution of logic analyzer markers skews
> the measurement, but comparing:
>
>
> 1. stmia sp, {r0-r11} // 12 regs took 435 ns
> 2. stmia sp, {r0-r3} // 4 regs took 305 ns
> 3. stmia sp, {r0} // 1 reg took 255 ns
>
>
> on LPC 2148, pclk=clck` MHz
> LA's sampling rate; f 0 MHz.
>
>
> we get some idea; with systematic error factored in,
> it doesn't make such a big difference to save 12 or 4 regs.
>
>
> Roger
>
> >
> > Sten
> >
> > --
> > /************************************************
> > Do you need a tiny and efficient real time
> > operating system (RTOS) with a preemtive
> > multitasking for LPC2000 or AT91SAM7?
> >
> > http://nanortos.net-attack.de/
> >
> > Or some open-source tools and code for LPC2000?
> >
> > http://www.net-attack.de/
> >
> > ************************************************/
> >
>

Hi Guys,
I've just hit this problem in my UART handler, I'm new to the ARM
and haven't used it's asm yet! could one of you ASM gurus
please post the required inline entry/exit code for us dummys
thanks,
Reply by Robert Adsett March 26, 20062006-03-26
At 10:42 PM 3/26/2006 +0000, frankcallaghan9 wrote:
>Hi Guys,
>I've just hit this problem in my UART handler, I'm new to the ARM
>and haven't used it's asm yet! could one of you ASM gurus
>please post the required inline entry/exit code for us dummys
>thanks,

My experience with inline matches that of compiler interrupt keywords. It
makes far more sense just to do it in assembly.

Take a look at the interrupt example in newlib-lpc.
http://www.aeolusdevelopment.com/Articles/download.html They can be easily
separated from the rest so using the epilogues and prologues from there
doesn't commit you to the rest of the library.

Robert

" 'Freedom' has no meaning of itself. There are always restrictions, be
they legal, genetic, or physical. If you don't believe me, try to chew a
radio signal. " -- Kelvin Throop, III
http://www.aeolusdevelopment.com/

Yahoo! Groups Links
Reply by frankcallaghan9 March 26, 20062006-03-26
--- In l..., "roger_lynx" wrote:
>
> --- In l..., Sten wrote:
> >
> > Robert Adsett wrote:
> > > At 07:49 PM 3/25/2006 +0100, Sten wrote:
> > >
> > >>I've tried this. But entry/exit is still not correct.
> > >>Here's the result:
> > >>
> > >>void uart_irqHandler0(void) __attribute__((interrupt));
> > >>
> > >>00000204 :
> > >> 204: e24ee004 sub lr, lr, #4 ; 0x4
> > >> 208: e92d500f stmdb sp!, {r0, r1, r2, r3, ip, lr}
> > >> 20c: e3a0120e mov r1, #-536870912 ; 0xe0000000
> > >> 210: e2811903 add r1, r1, #49152 ; 0xc000
> > >> 214: e3a00000 mov r0, #0 ; 0x0
> > >> 218: ebfffffe bl d0
> > >> 21c: e8bd500f ldmia sp!, {r0, r1, r2, r3, ip, lr}
> > >> 220: e25ef004 subs pc, lr, #4 ; 0x4
> > >>
> > >>Question:
> > >>Which gcc version do you use? Which command line parameters do use?
> > >>How do you differentiate between IRQ and FIQ (only r0..r7 need
to be
> > >>saved) if use
> > >>__attribute__((interrupt)) only?
> > >
> > >
> > >
> > > Rather than go through all this hand-wringing why not just write an
> > > assembly stub? You'd know it was correct and you'd be done
> already. At
> > > most it would cost you an extra call from the stub to your C
> > > function. Heck if it was small enough it might make sense to do
> the whole
> > > thing in asm. For that matter you could steal one of my stubs.
> > >
> > > Robert
> > >
> >
> > Thanks Robert.
> > At the moment I declare my IRQ functions as "naked" and write my own
> prologue/epilogue with inline
> > assembler. But it is less efficient because I don't know which
> registers are really used, so I have
> > to save all non-banked registers (r0..12 for IRQ and r0..r7 for FIQ)
> which is a wast of performance.
> Yes. IRQ "undressed" and inline assembly for prologue/epilogue.
>
> I was curious about the performance hit myself, but rather
> than doing it academic-like way (in days), I measured it (in 10
minutes).
> The test is lousy,since the execution of logic analyzer markers skews
> the measurement, but comparing:
> 1. stmia sp, {r0-r11} // 12 regs took 435 ns
> 2. stmia sp, {r0-r3} // 4 regs took 305 ns
> 3. stmia sp, {r0} // 1 reg took 255 ns
> on LPC 2148, pclk=clck` MHz
> LA's sampling rate; f 0 MHz.
> we get some idea; with systematic error factored in,
> it doesn't make such a big difference to save 12 or 4 regs.
> Roger
>
> >
> > Sten
> >
> > --
> > /************************************************
> > Do you need a tiny and efficient real time
> > operating system (RTOS) with a preemtive
> > multitasking for LPC2000 or AT91SAM7?
> >
> > http://nanortos.net-attack.de/
> >
> > Or some open-source tools and code for LPC2000?
> >
> > http://www.net-attack.de/
> >
> > ************************************************/
>
Hi Guys,
I've just hit this problem in my UART handler, I'm new to the ARM
and haven't used it's asm yet! could one of you ASM gurus
please post the required inline entry/exit code for us dummys
thanks,

Yahoo! Groups Links
Reply by Sten March 26, 20062006-03-26
Robert Adsett wrote:
> At 12:04 AM 3/26/2006 +0100, Sten wrote:
>
>>Wonderful! ;-)
>>But why to save r0..r3 and ip in your irq_isr?!? Only lr will be changed
>>by bl and registers used by
>>irq_handler() should be saved in its function prologue by irq_handler()
>>itself!
>
>
> According to the APCS "A (called)subroutine must preserve the contents of
> the registers r4-r8, r10, r11 and SP ".
>
> R0-R3 are temporary/parameter registers and must be saved by the caller if
> needed R12 is the intra-procedure call scratch register so similar
> restrictions apply to it, R14 is the link register so make sure you've
> saved it properly or you won't be able to return.
>
> That leaves R9 the platform specific register, which I believe gcc treats
> the same as r4-r8 (I can't lay my hands on my reference for that at the
> moment).
>
Ok, this makes sense...

Sten

--
/************************************************
Do you need a tiny and efficient real time
operating system (RTOS) with a preemtive
multitasking for LPC2000 or AT91SAM7?

http://nanortos.net-attack.de/

Or some open-source tools and code for LPC2000?

http://www.net-attack.de/

************************************************/