Reply by Peter Dickerson June 17, 20042004-06-17
"Jens Hildebrandt" <jens.hildebrandt@remove_this.etechnik.uni-rostock.de>
wrote in message news:40cd60da@news.uni-rostock.de...
> Hello group, > > I'm curently trying to get familiar with the ARM7 by building some > example-projects for a LPC2106-controller. One such project is the
blinky_irq
> example from Keil which should demonstrate the use of interrupts and of
the
> LPC2xxx vectored interrupt controller. I'm using gcc-3.2.1 with binutils
3.13.1
> and newlib 1.11.0 . So far I had no problems with these tools and I was
able to
> build and succesfully run some small demonstrator programs (without
interrupts)
> on my LPC2106 board. For the blinky_irq example program I use the linker
script
> and startup.s files (with adjustment for the Flash and RAM sizes of the
LPC2106)
> that came with the source code from Keil's download area. Since the
program
> didn't work I stripped it from all unnecessary functionality (main() is > essentially an empty loop now) and simply let the timer ISR toggle a LED
on
> GPIO24. That worked initially, but after some time (~ 3 minutes) the LED
stopped
> toggling. I suspected that somwhere I'm loosing memory such that after
some time
> I'm out of RAM. Hence, I took a look at the disassembled code and saw that
the
> ISR is messing up the IRQ-mode stack pointer, loosing seven words each
time the
> ISR is invoked. > Since the ISR entry and exit codes are automatically generated by the
compiler I
> suspect a bug in gcc. On the other hand, since this would be a very severe > failure other users should have come across it, too. Does anybody of you
know
> that error (i.e. should I change to another gcc version) or am I missing > something (e.g. gcc options)? > Below you'll find the build commands used, the sources of the program and
the
> disassembled ISR code. > > TIA, > Jens
[snip] using arm-elf-gcc 3.3.1 I don't have this problem. Not that the interrupt attribute needs to specify the type of interrupt ("IRQ", "FIQ","SWI" etc). void __attribute__((interrupt("IRQ"))) SYS_10ms_irq_handler(void) { TIMER2->status = 4; // clear timer int VIC->VectAddr = 0; // clear VIC tick_count++; } arm-elf-gcc -S -O -DUVDAS -mcpu=arm7tdmi sys_irq.c SYS_10ms_irq_handler: @ Interrupt Service Routine. @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. stmfd sp!, {r2, r3} @ lr needed for prologue mvn r3, #244736 sub r3, r3, #940 sub r3, r3, #3 mov r2, #4 str r2, [r3, #8] mov r3, #-2147483648 mov r3, r3, asr #19 mov r2, #0 str r2, [r3, #48] ldr r2, .L3 ldr r3, [r2, #0] add r3, r3, #1 str r3, [r2, #0] ldmfd sp!, {r2, r3} subs pc, lr, #4 .L4: .align 2 .L3: .word tick_count this include the correct subs pc,lr,#4 that performs a return from interrupt (swapping back to old stack). regards Peter
Reply by Jens Hildebrandt June 15, 20042004-06-15
Andras Tantos wrote:

> You can download a newer (actually two: 3.3.1 and 3.4.0) GCC from my > webpage. I'm not a GCC expert, but I know they've fixed a serious ARM bugs > in their IRQ handling around 3.3.0. You might be hitting it. > > -- > Regards, > Andras Tantos > <http://andrast.tantos.homedns.org> > > "Jens Hildebrandt" <jens.hildebrandt@remove_this.etechnik.uni-rostock.de> > wrote in message news:40cd60da@news.uni-rostock.de... > >>Hello group, >> >>I'm curently trying to get familiar with the ARM7 by building some >>example-projects for a LPC2106-controller. One such project is the > > blinky_irq > >>example from Keil which should demonstrate the use of interrupts and of > > the > >>LPC2xxx vectored interrupt controller. I'm using gcc-3.2.1 with binutils > > 3.13.1 > >>and newlib 1.11.0 . So far I had no problems with these tools and I was > > able to > >>build and succesfully run some small demonstrator programs (without > > interrupts) > >>on my LPC2106 board. For the blinky_irq example program I use the linker > > script > >>and startup.s files (with adjustment for the Flash and RAM sizes of the > > LPC2106) > >>that came with the source code from Keil's download area. Since the > > program > >>didn't work I stripped it from all unnecessary functionality (main() is >>essentially an empty loop now) and simply let the timer ISR toggle a LED > > on > >>GPIO24. That worked initially, but after some time (~ 3 minutes) the LED > > stopped > >>toggling. I suspected that somwhere I'm loosing memory such that after > > some time > >>I'm out of RAM. Hence, I took a look at the disassembled code and saw that > > the > >>ISR is messing up the IRQ-mode stack pointer, loosing seven words each > > time the > >>ISR is invoked. >>Since the ISR entry and exit codes are automatically generated by the > > compiler I > >>suspect a bug in gcc. On the other hand, since this would be a very severe >>failure other users should have come across it, too. Does anybody of you > > know > >>that error (i.e. should I change to another gcc version) or am I missing >>something (e.g. gcc options)? >>Below you'll find the build commands used, the sources of the program and > > the > >>disassembled ISR code. >> >>TIA, >>Jens >> >>------build commands----------------------------- >>$ make blinky_irq.hex >>arm-elf-as -mcpu=arm7tdmi -gstabs Startup.s -o Startup.o >>Startup.s: Assembler messages: >><couple of warnings about rest of line after ';' being ignored> >>arm-elf-gcc -c -g -I. -mcpu=arm7tdmi Time.c -o Time.o >>arm-elf-gcc -c -g -I. -mcpu=arm7tdmi Blinky.c -o Blinky.o >>arm-elf-gcc -T Flash.ld -nostartfiles -Lgcc -L. -o blinky_irq.elf > > Startup.o > >>Time.o Blinky.o >>arm-elf-objcopy -I elf32-littlearm -O ihex blinky_irq.elf blinky_irq.hex >> >>------sources------------------------------------ >> > > /*************************************************************************** > ***/ > >>/* > > */ > >>/* BLINKY.C: LED Flasher > > */ > >>/* > > */ > > /*************************************************************************** > ***/ > >>#include "LPC210x.h" >>#include "Timer.h" >> >>extern long volatile timeval; /*ISR counter variable*/ >> >>void wait (void) { /* wait function, not used > > actually */ > >> unsigned long i; >> >> i = timeval; >> while ((i + 10) > timeval){ >> }; /* wait 100ms */ >>} >> >>int main (void) { >> >> IODIR = 0xFF000000; /* P1.31..24 defined as > > Outputs */ > >> init_timer(); >> >> while (1) { /* Loop forever */ >> } >>} >> >> > > /*************************************************************************** > ***/ > >>/* > > */ > >>/* TIME.C: Time Functions for 10Hz Clock Tick > > */ > >>/* > > */ > > /*************************************************************************** > ***/ > >>#include "LPC210x.h" >>#include "Timer.h" >> >>long volatile timeval; //counter for wait-routine >> >>void tc0 (void) __attribute__ ((interrupt)); // Generate Interrupt >> >>/* Setup the Timer Counter 0 Interrupt */ >>void init_timer (void) { >> VICVectAddr0 = (unsigned long)tc0; // set interrupt vector > > in 0 > >> VICVectCntl0 = 0x20 | 4; // use it for Timer 0 > > Interrupt > >> VICIntEnable = 0x00000010; // Enable Timer0 > > Interrupt > >> TIMER0_MR0 = 5898239; // 100mSec = >>(0.1*4*14,7456E6)-1 counts >> TIMER0_MCR = 3; // Interrupt and Reset on > > MR0 > >> TIMER0_TCR = 1; // Timer0 Enable >>} >> >> >>/* Timer Counter 0 Interrupt executes each 100ms @ 4x14,7456 MHz CPU Clock > > */ > >>void tc0 (void) { >>/* timeval++;*/ >> if((IOPIN&0x01000000) == 0x00000000){ >> IOSET = 0x01000000; >> }else{ >> IOCLR = 0x01000000; //toggle GPIO24 >> } >> TIMER0_IR = 1; // Clear interrupt flag >> VICVectAddr = 0; // Acknowledge Interrupt >>} >> >>-------------------disassebled ISR (with some > > comments)--------------------- > >>... >>00000278 <tc0>: >>; --ip is stored on stack but not restored at ISR exit (see below)!! >> 278: e52dc004 str ip, [sp, -#4]! >> 27c: e1a0c00d mov ip, sp >> 280: e24ee004 sub lr, lr, #4 ; 0x4 >>; --write-back further decrements sp. This is not corrected on ISR exit!! >>; --btw: why is pc stored on the stack anyway and why is ip with it's new >>; --contents pushed onto the stack, too?? >> 284: e92dd80c stmdb sp!, {r2, r3, fp, ip, lr, pc} >> 288: e24cb004 sub fp, ip, #4 ; 0x4 >> 28c: e3a0320e mov r3, #-536870912 ; 0xe0000000 >> 290: e283390a add r3, r3, #163840 ; 0x28000 >> 294: e5933000 ldr r3, [r3] >> 298: e2033401 and r3, r3, #16777216 ; 0x1000000 >> 29c: e3530000 cmp r3, #0 ; 0x0 >> 2a0: 1a000004 bne 2b8 <tc0+0x40> >> 2a4: e3a0324e mov r3, #-536870908 ; 0xe0000004 >> 2a8: e283390a add r3, r3, #163840 ; 0x28000 >> 2ac: e3a02401 mov r2, #16777216 ; 0x1000000 >> 2b0: e5832000 str r2, [r3] >> 2b4: ea000003 b 2c8 <tc0+0x50> >> 2b8: e3a032ce mov r3, #-536870900 ; 0xe000000c >> 2bc: e283390a add r3, r3, #163840 ; 0x28000 >> 2c0: e3a02401 mov r2, #16777216 ; 0x1000000 >> 2c4: e5832000 str r2, [r3] >> 2c8: e3a0320e mov r3, #-536870912 ; 0xe0000000 >> 2cc: e2833901 add r3, r3, #16384 ; 0x4000 >> 2d0: e3a02001 mov r2, #1 ; 0x1 >> 2d4: e5832000 str r2, [r3] >> 2d8: e3e03d3f mvn r3, #4032 ; 0xfc0 >> 2dc: e243300f sub r3, r3, #15 ; 0xf >> 2e0: e3a02000 mov r2, #0 ; 0x0 >> 2e4: e5832000 str r2, [r3] >>; --registers are restored, pc is loaded with (lr-4) and cpsr is restored >>; --so this causes a return to the user code. But ip is not restored to > > it's > >>; --initial value but to the value that was assigned to ip after it was > > saved > >>; --on the stack. And, sp is not restored to it's initial value!! >> 2e8: e95b980c ldmdb fp, {r2, r3, fp, ip, pc}^ ; >> >> >> > > > > >
Hi Andras, I already suspected such a bug but wanted to make sure that a new gcc version would solve my problem before downloading and installing the new tools. BTW: the link to your page gets me a "403: Forbidden" error. Anyway, thanks for the reply, Jens
Reply by Andras Tantos June 14, 20042004-06-14
You can download a newer (actually two: 3.3.1 and 3.4.0) GCC from my
webpage. I know they've fixed a serious ARM bugs in their IRQ handling
around 3.3.0. You might be hitting it.

--
Regards,
Andras Tantos
<http://andrast.tantos.homedns.org>

"Jens Hildebrandt" <jens.hildebrandt@remove_this.etechnik.uni-rostock.de>
wrote in message news:40cd60da@news.uni-rostock.de...
> Hello group, > > I'm curently trying to get familiar with the ARM7 by building some > example-projects for a LPC2106-controller. One such project is the
blinky_irq
> example from Keil which should demonstrate the use of interrupts and of
the
> LPC2xxx vectored interrupt controller. I'm using gcc-3.2.1 with binutils
3.13.1
> and newlib 1.11.0 . So far I had no problems with these tools and I was
able to
> build and succesfully run some small demonstrator programs (without
interrupts)
> on my LPC2106 board. For the blinky_irq example program I use the linker
script
> and startup.s files (with adjustment for the Flash and RAM sizes of the
LPC2106)
> that came with the source code from Keil's download area. Since the
program
> didn't work I stripped it from all unnecessary functionality (main() is > essentially an empty loop now) and simply let the timer ISR toggle a LED
on
> GPIO24. That worked initially, but after some time (~ 3 minutes) the LED
stopped
> toggling. I suspected that somwhere I'm loosing memory such that after
some time
> I'm out of RAM. Hence, I took a look at the disassembled code and saw that
the
> ISR is messing up the IRQ-mode stack pointer, loosing seven words each
time the
> ISR is invoked. > Since the ISR entry and exit codes are automatically generated by the
compiler I
> suspect a bug in gcc. On the other hand, since this would be a very severe > failure other users should have come across it, too. Does anybody of you
know
> that error (i.e. should I change to another gcc version) or am I missing > something (e.g. gcc options)? > Below you'll find the build commands used, the sources of the program and
the
> disassembled ISR code. > > TIA, > Jens >
Reply by Andras Tantos June 14, 20042004-06-14
You can download a newer (actually two: 3.3.1 and 3.4.0) GCC from my
webpage. I'm not a GCC expert, but I know they've fixed a serious ARM bugs
in their IRQ handling around 3.3.0. You might be hitting it.

--
Regards,
Andras Tantos
<http://andrast.tantos.homedns.org>

"Jens Hildebrandt" <jens.hildebrandt@remove_this.etechnik.uni-rostock.de>
wrote in message news:40cd60da@news.uni-rostock.de...
> Hello group, > > I'm curently trying to get familiar with the ARM7 by building some > example-projects for a LPC2106-controller. One such project is the
blinky_irq
> example from Keil which should demonstrate the use of interrupts and of
the
> LPC2xxx vectored interrupt controller. I'm using gcc-3.2.1 with binutils
3.13.1
> and newlib 1.11.0 . So far I had no problems with these tools and I was
able to
> build and succesfully run some small demonstrator programs (without
interrupts)
> on my LPC2106 board. For the blinky_irq example program I use the linker
script
> and startup.s files (with adjustment for the Flash and RAM sizes of the
LPC2106)
> that came with the source code from Keil's download area. Since the
program
> didn't work I stripped it from all unnecessary functionality (main() is > essentially an empty loop now) and simply let the timer ISR toggle a LED
on
> GPIO24. That worked initially, but after some time (~ 3 minutes) the LED
stopped
> toggling. I suspected that somwhere I'm loosing memory such that after
some time
> I'm out of RAM. Hence, I took a look at the disassembled code and saw that
the
> ISR is messing up the IRQ-mode stack pointer, loosing seven words each
time the
> ISR is invoked. > Since the ISR entry and exit codes are automatically generated by the
compiler I
> suspect a bug in gcc. On the other hand, since this would be a very severe > failure other users should have come across it, too. Does anybody of you
know
> that error (i.e. should I change to another gcc version) or am I missing > something (e.g. gcc options)? > Below you'll find the build commands used, the sources of the program and
the
> disassembled ISR code. > > TIA, > Jens > > ------build commands----------------------------- > $ make blinky_irq.hex > arm-elf-as -mcpu=arm7tdmi -gstabs Startup.s -o Startup.o > Startup.s: Assembler messages: > <couple of warnings about rest of line after ';' being ignored> > arm-elf-gcc -c -g -I. -mcpu=arm7tdmi Time.c -o Time.o > arm-elf-gcc -c -g -I. -mcpu=arm7tdmi Blinky.c -o Blinky.o > arm-elf-gcc -T Flash.ld -nostartfiles -Lgcc -L. -o blinky_irq.elf
Startup.o
> Time.o Blinky.o > arm-elf-objcopy -I elf32-littlearm -O ihex blinky_irq.elf blinky_irq.hex > > ------sources------------------------------------ >
/*************************************************************************** ***/
> /*
*/
> /* BLINKY.C: LED Flasher
*/
> /*
*/
>
/*************************************************************************** ***/
> > #include "LPC210x.h" > #include "Timer.h" > > extern long volatile timeval; /*ISR counter variable*/ > > void wait (void) { /* wait function, not used
actually */
> unsigned long i; > > i = timeval; > while ((i + 10) > timeval){ > }; /* wait 100ms */ > } > > int main (void) { > > IODIR = 0xFF000000; /* P1.31..24 defined as
Outputs */
> > init_timer(); > > while (1) { /* Loop forever */ > } > } > >
/*************************************************************************** ***/
> /*
*/
> /* TIME.C: Time Functions for 10Hz Clock Tick
*/
> /*
*/
>
/*************************************************************************** ***/
> > #include "LPC210x.h" > #include "Timer.h" > > long volatile timeval; //counter for wait-routine > > void tc0 (void) __attribute__ ((interrupt)); // Generate Interrupt > > /* Setup the Timer Counter 0 Interrupt */ > void init_timer (void) { > VICVectAddr0 = (unsigned long)tc0; // set interrupt vector
in 0
> VICVectCntl0 = 0x20 | 4; // use it for Timer 0
Interrupt
> VICIntEnable = 0x00000010; // Enable Timer0
Interrupt
> > TIMER0_MR0 = 5898239; // 100mSec = > (0.1*4*14,7456E6)-1 counts > TIMER0_MCR = 3; // Interrupt and Reset on
MR0
> TIMER0_TCR = 1; // Timer0 Enable > } > > > /* Timer Counter 0 Interrupt executes each 100ms @ 4x14,7456 MHz CPU Clock
*/
> void tc0 (void) { > /* timeval++;*/ > if((IOPIN&0x01000000) == 0x00000000){ > IOSET = 0x01000000; > }else{ > IOCLR = 0x01000000; //toggle GPIO24 > } > TIMER0_IR = 1; // Clear interrupt flag > VICVectAddr = 0; // Acknowledge Interrupt > } > > -------------------disassebled ISR (with some
comments)---------------------
> ... > 00000278 <tc0>: > ; --ip is stored on stack but not restored at ISR exit (see below)!! > 278: e52dc004 str ip, [sp, -#4]! > 27c: e1a0c00d mov ip, sp > 280: e24ee004 sub lr, lr, #4 ; 0x4 > ; --write-back further decrements sp. This is not corrected on ISR exit!! > ; --btw: why is pc stored on the stack anyway and why is ip with it's new > ; --contents pushed onto the stack, too?? > 284: e92dd80c stmdb sp!, {r2, r3, fp, ip, lr, pc} > 288: e24cb004 sub fp, ip, #4 ; 0x4 > 28c: e3a0320e mov r3, #-536870912 ; 0xe0000000 > 290: e283390a add r3, r3, #163840 ; 0x28000 > 294: e5933000 ldr r3, [r3] > 298: e2033401 and r3, r3, #16777216 ; 0x1000000 > 29c: e3530000 cmp r3, #0 ; 0x0 > 2a0: 1a000004 bne 2b8 <tc0+0x40> > 2a4: e3a0324e mov r3, #-536870908 ; 0xe0000004 > 2a8: e283390a add r3, r3, #163840 ; 0x28000 > 2ac: e3a02401 mov r2, #16777216 ; 0x1000000 > 2b0: e5832000 str r2, [r3] > 2b4: ea000003 b 2c8 <tc0+0x50> > 2b8: e3a032ce mov r3, #-536870900 ; 0xe000000c > 2bc: e283390a add r3, r3, #163840 ; 0x28000 > 2c0: e3a02401 mov r2, #16777216 ; 0x1000000 > 2c4: e5832000 str r2, [r3] > 2c8: e3a0320e mov r3, #-536870912 ; 0xe0000000 > 2cc: e2833901 add r3, r3, #16384 ; 0x4000 > 2d0: e3a02001 mov r2, #1 ; 0x1 > 2d4: e5832000 str r2, [r3] > 2d8: e3e03d3f mvn r3, #4032 ; 0xfc0 > 2dc: e243300f sub r3, r3, #15 ; 0xf > 2e0: e3a02000 mov r2, #0 ; 0x0 > 2e4: e5832000 str r2, [r3] > ; --registers are restored, pc is loaded with (lr-4) and cpsr is restored > ; --so this causes a return to the user code. But ip is not restored to
it's
> ; --initial value but to the value that was assigned to ip after it was
saved
> ; --on the stack. And, sp is not restored to it's initial value!! > 2e8: e95b980c ldmdb fp, {r2, r3, fp, ip, pc}^ ; > > >
Reply by Jens Hildebrandt June 14, 20042004-06-14
Hello group,

I'm curently trying to get familiar with the ARM7 by building some 
example-projects for a LPC2106-controller. One such project is the blinky_irq 
example from Keil which should demonstrate the use of interrupts and of the 
LPC2xxx vectored interrupt controller. I'm using gcc-3.2.1 with binutils 3.13.1 
and newlib 1.11.0 . So far I had no problems with these tools and I was able to 
build and succesfully run some small demonstrator programs (without interrupts) 
on my LPC2106 board. For the blinky_irq example program I use the linker script 
and startup.s files (with adjustment for the Flash and RAM sizes of the LPC2106) 
that came with the source code from Keil's download area. Since the program 
didn't work I stripped it from all unnecessary functionality (main() is 
essentially an empty loop now) and simply let the timer ISR toggle a LED on 
GPIO24. That worked initially, but after some time (~ 3 minutes) the LED stopped 
toggling. I suspected that somwhere I'm loosing memory such that after some time 
I'm out of RAM. Hence, I took a look at the disassembled code and saw that the 
ISR is messing up the IRQ-mode stack pointer, loosing seven words each time the 
ISR is invoked.
Since the ISR entry and exit codes are automatically generated by the compiler I 
suspect a bug in gcc. On the other hand, since this would be a very severe 
failure other users should have come across it, too. Does anybody of you know 
that error (i.e. should I change to another gcc version) or am I missing 
something (e.g. gcc options)?
Below you'll find the build commands used, the sources of the program and the 
disassembled ISR code.

TIA,
Jens

------build commands-----------------------------
$ make blinky_irq.hex
arm-elf-as -mcpu=arm7tdmi -gstabs Startup.s -o Startup.o
Startup.s: Assembler messages:
<couple of warnings about rest of line after ';' being ignored>
arm-elf-gcc -c -g -I. -mcpu=arm7tdmi Time.c -o Time.o
arm-elf-gcc -c -g -I. -mcpu=arm7tdmi Blinky.c -o Blinky.o
arm-elf-gcc -T Flash.ld -nostartfiles -Lgcc -L. -o blinky_irq.elf Startup.o 
Time.o Blinky.o
arm-elf-objcopy -I elf32-littlearm -O ihex blinky_irq.elf blinky_irq.hex

------sources------------------------------------
/******************************************************************************/
/*                                                                            */
/*  BLINKY.C:  LED Flasher                                                    */
/*                                                                            */
/******************************************************************************/

#include "LPC210x.h"
#include "Timer.h"

extern long volatile timeval;		 /*ISR counter variable*/

void wait (void)  {                      /* wait function, not used actually */
   unsigned long i;

   i = timeval;
   while ((i + 10) > timeval){
   };              /* wait 100ms */
}

int main (void) {

   IODIR = 0xFF000000;                        /* P1.31..24 defined as Outputs */

   init_timer();

   while (1)  {                                  /* Loop forever */
   }
}

/******************************************************************************/
/*                                                                            */
/*  TIME.C:  Time Functions for 10Hz Clock Tick                               */
/*                                                                            */
/******************************************************************************/

#include "LPC210x.h"
#include "Timer.h"

long volatile timeval;				//counter for wait-routine

void tc0 (void) __attribute__ ((interrupt));    // Generate Interrupt

/* Setup the Timer Counter 0 Interrupt */
void init_timer (void) {
     VICVectAddr0 = (unsigned long)tc0;          // set interrupt vector in 0
     VICVectCntl0 = 0x20 | 4;                    // use it for Timer 0 Interrupt
     VICIntEnable = 0x00000010;                  // Enable Timer0 Interrupt

     TIMER0_MR0 = 5898239;                        // 100mSec = 
(0.1*4*14,7456E6)-1 counts
     TIMER0_MCR = 3;                             // Interrupt and Reset on MR0
     TIMER0_TCR = 1;                             // Timer0 Enable
}


/* Timer Counter 0 Interrupt executes each 100ms @ 4x14,7456 MHz CPU Clock */
void tc0 (void) {
/*    timeval++;*/
     if((IOPIN&0x01000000) == 0x00000000){    	
      IOSET = 0x01000000;
     }else{
      IOCLR = 0x01000000;			//toggle GPIO24
     }
     TIMER0_IR = 1;                              // Clear interrupt flag
     VICVectAddr = 0;                            // Acknowledge Interrupt
}

-------------------disassebled ISR (with some comments)---------------------
...
00000278 <tc0>:
; --ip is stored on stack but not restored at ISR exit (see below)!!
  278:	e52dc004 	str	ip, [sp, -#4]!
  27c:	e1a0c00d 	mov	ip, sp
  280:	e24ee004 	sub	lr, lr, #4	; 0x4
; --write-back further decrements sp. This is not corrected on ISR exit!!
; --btw: why is pc stored on the stack anyway and why is ip with it's new
; --contents pushed onto the stack, too??
  284:	e92dd80c 	stmdb	sp!, {r2, r3, fp, ip, lr, pc}
  288:	e24cb004 	sub	fp, ip, #4	; 0x4	
  28c:	e3a0320e 	mov	r3, #-536870912	; 0xe0000000
  290:	e283390a 	add	r3, r3, #163840	; 0x28000
  294:	e5933000 	ldr	r3, [r3]
  298:	e2033401 	and	r3, r3, #16777216	; 0x1000000
  29c:	e3530000 	cmp	r3, #0	; 0x0
  2a0:	1a000004 	bne	2b8 <tc0+0x40>
  2a4:	e3a0324e 	mov	r3, #-536870908	; 0xe0000004
  2a8:	e283390a 	add	r3, r3, #163840	; 0x28000
  2ac:	e3a02401 	mov	r2, #16777216	; 0x1000000
  2b0:	e5832000 	str	r2, [r3]
  2b4:	ea000003 	b	2c8 <tc0+0x50>
  2b8:	e3a032ce 	mov	r3, #-536870900	; 0xe000000c
  2bc:	e283390a 	add	r3, r3, #163840	; 0x28000
  2c0:	e3a02401 	mov	r2, #16777216	; 0x1000000
  2c4:	e5832000 	str	r2, [r3]
  2c8:	e3a0320e 	mov	r3, #-536870912	; 0xe0000000
  2cc:	e2833901 	add	r3, r3, #16384	; 0x4000
  2d0:	e3a02001 	mov	r2, #1	; 0x1
  2d4:	e5832000 	str	r2, [r3]
  2d8:	e3e03d3f 	mvn	r3, #4032	; 0xfc0
  2dc:	e243300f 	sub	r3, r3, #15	; 0xf
  2e0:	e3a02000 	mov	r2, #0	; 0x0
  2e4:	e5832000 	str	r2, [r3]
; --registers are restored, pc is loaded with (lr-4) and cpsr is restored
; --so this causes a return to the user code. But ip is not restored to it's
; --initial value but to the value that was assigned to ip after it was saved
; --on the stack. And, sp is not restored to it's initial value!!
  2e8:	e95b980c 	ldmdb	fp, {r2, r3, fp, ip, pc}^ ;