ARM IAR, LPC200 relocation question

gasilvis wrote on Wednesday, April 22, 2009:

I am unable to relocate the demo project from a start location of 0x0 to 0x4000. I move up the intvec and the start of ROM by 0x4000 and sometimes it runs, sometimes it ends up wandering somewhere down around 0x21F0. If I back those changes out and locate at 0x0, it runs fine.

Are there any location dependencies buried in the headers or macros or the IAR setup that would cause this behavior?

Thanks
George

gasilvis wrote on Wednesday, April 22, 2009:

To explain further: The jump that takes it out of its own memory space comes at the end of the portRESTORE_CONTEXT macro.

Why does this appear to work sometimes?

George

davedoors wrote on Thursday, April 23, 2009:

The ARM7 will expect the interrupt vector table to be at zero. Are you remapping it somehow?

gasilvis wrote on Thursday, April 23, 2009:

The IAR has a .ICF file that tells the linker where the intvec table is to be put, remapping it. In this case it is in front of my rom region, 0x4000. The IDE will start the debug from there or in the normal target a bootloader running from 0x00 will jump to 0x4000 when its ready to start. I don’t believe this is the problem area.

The last step of the portRESTORE_CONTEXT :
   ; And return - correcting the offset in the LR to obtain the
   ; correct address.
   SUBS  PC, LR, #4

is where it disappears. And it doesn’t happen everytime which makes it spooky.

Thanks
George

rtel wrote on Thursday, April 23, 2009:

…but the CPU will still use address 0 for the vector table, won’t it?  Unless there is something else mapped to address zero (this is how its done in SAM7, you have a copy of the vector table elsewhere then map the elsewhere address to address zero because the CPU allays looks at address zero.  I forget how the LPC does it).

If its the first call to portRESTORE_CONTEXT() then most likely the CPU is in the wrong mode.  You must have the CPU in Supervisor mode when vTaskStartScheduler() is called.  Step through the macro to see what it tries to do and what mode its in.

Regards.

rtel wrote on Thursday, April 23, 2009:

Just had a quick look at the LPC2368 manual - are you setting the MEMMAP register to tell the CPU where the vector table is?

Regards.

gasilvis wrote on Thursday, April 23, 2009:

MEMMAP is not being used. This if the first call of the portRESTORE_CONTEXT(). And right at the end, when it is executing the SUBS PC, LR, #4  statement the mode is Supervisor (0x13).

The debugger doesn’t single step at this point so I have to hit pause to see where we land: Its in the lower rom region and the mode is ABT…

Spurious interrupt maybe?

The only mods to the Demo code:
   - processor is LPC2148. The appropriate changes have been made in the IDE, 2 tweaks of the code.
   - I’ve added code to get to my LED’s which requires I2C activated. But at the point of this fault none of this is even initialized, let alone run.

George

gasilvis wrote on Tuesday, April 28, 2009:

Of course MEMMAP needs to be used if the code is being relocated! Doh.

So I reserved the space and added the code:
   memcpy((void*)0x40000000, (void*)(0x00004000), 0x60);
   MEMMAP= 0x02; // look for interrupts in ram

Still no joy. The code spends all of its time in the Prefetch_handler. I hooked up counters in all the un-used interrupts. eg:
  __irq __arm void Prefetch_Handler(void)
     {   Prefetch_cnt++;  }

After a few seconds the Prefetch interrupt has been hit 9 million times. And the Data_Handler also 200 times.

George

gasilvis wrote on Tuesday, April 28, 2009:

break through!! ( At least it works now)

If you are going to relocate the intvec, then the intvec needs to be relocatable.
in cstart.s:
        ldr   pc,[pc,#+24]              ;; Reset
        ldr   pc,[pc,#+24]              ;; Undefined instructions
;        b vPortYieldProcessor                                           <<<<<<<<<<<<<< don’t do this, its won’t relocate
                                                                                                                or the b will not have the range when it
                                                                                                        is placed in RAM
        ldr   pc,[pc,#+24]              ;; Software interrupt (SWI/SVC)      <<<<<<<<<<< count on the indirection
        ldr   pc,[pc,#+24]              ;; Prefetch abort
        ldr   pc,[pc,#+24]              ;; Data abort
__vector_0x14
        DC32  0                         ;; RESERVED
        ldr   pc, [PC, #-0xFF0]         ;; IRQ
        ldr   pc,[pc,#+24]              ;; FIQ

        DC32  __iar_program_start       ;; Reset
        DC32  undef_handler             ;; Undefined instructions
        DC32  swi_handler               ;; Software interrupt (SWI/SVC)   <<<<<<<<<<<, to here
        DC32  prefetch_handler          ;; Prefetch abort
        DC32  data_handler              ;; Data abort
        DC32  0                         ;; RESERVED
        DC32  0                           ;; IRQ
        DC32  fiq_handler               ;; FIQ

swi_handler
    b         vPortYieldProcessor                                                <<<<<<<<<<<<<<<,   and to here
undef_handler
    b         Undef_Handler
prefetch_handler
    b         Prefetch_Handler
data_handler
    b         Data_Handler
fiq_handler
    b         fiq_handler

Thanks for your patience
George

ps if this still is wrong, warn me!