crashes upon swi handler, vPortYieldProcessor

cynergizer wrote on Thursday, January 27, 2011:

I have a user app that runs splendidly when I place the app at the start of flash. However, when I instead locate my user app at location 0x00007000 in flash, my user app’s swi handler is no longer found. I have a custom bootloader at the start of flash that always runs upon reboot, then jumps to my user app. The bootloader runs fine, and jumps to my user app no problem. My user app starts running fine, including successfully executing various vectored IRQs, but then crashes when it doesn’t find the swi handler, vPortYieldProcessor. My map file shows that my swi handler, vPortYieldProcessor is at location 0x0000be70. This seems reasonable. My map file also shows my vectors to start at location 0x00007000, and I don’t see any user app code located prior to 0x7000 - all good. I am trying to run directly out of flash - no vectors are remapped to RAM. When it gets a swi, it jumps to my swi_handler for my custom bootloader’s default swi handler at location 0xA8. Yikes!:
swi_handler:
b swi_handler

How could the user app be using the bootloader’s address for the swi handler?  I am not using the swi handler for any other purpose.  These builds are entirely separate.  In my user app, I tried modified the start-up code to explicitly call the handler (instead of relying on overriding the default swi handler), but these changes had no effect.  Thanks for any advice you might have!  I’m using the lpc2148 on an ngx mini-blueboard, Rowley crossworks IDE, and the freeRtos V6.0.5 gcc port to this processor.
Here are some excerpts from my startup assembly:

_vectors:
  ldr pc,   /* reset */
  ldr pc,   /* undefined instruction */
  ldr pc,     /* swi handler */
  ldr pc,  /* abort prefetch */
  ldr pc,  /* abort data */
#ifdef VECTORED_IRQ_INTERRUPTS
  .word 0xB9205F88
/* .word 0xB9205F88                               boot loader checksum */
  ldr pc,                          /* irq handler */
#else
  .word 0xB8A06F60
/*  .word 0xB8A06F60                               boot loader checksum */
  ldr pc,     /* irq handler */
#endif
  ldr pc,     /* fiq handler */

reset_handler_address:
#ifdef STARTUP_FROM_RESET
  .word reset_handler
#else
  .word reset_wait
#endif

undef_handler_address:
  .word undef_handler
swi_handler_address:
  .word swi_handler
pabort_handler_address:
  .word pabort_handler
dabort_handler_address:
  .word dabort_handler

/******************************************************************************
*                                                                            *
* Default exception handlers                                                 *
* These are declared weak symbols so they can be redefined in user code.     *
*                                                                            *
******************************************************************************/
undef_handler:
  b undef_handler
 
swi_handler:
  b swi_handler
 
pabort_handler:
  b pabort_handler
 
dabort_handler:
  b dabort_handler
 
fiq_handler:
  b fiq_handler

irq_handler:
  b irq_handler

  .weak undef_handler, swi_handler, pabort_handler, dabort_handler, fiq_handler, irq_handler
                                                   

richard_damon wrote on Thursday, January 27, 2011:

One question, have you told the hardware the new address for the SWI routine (can you change it?). Just because you moved the program, doesn’t mean the computer automatically knows to move the vector table. If you can’t tell the hardware a new address, then you need to update the bootloader code itself (or configure it if it already has the hooks) to redirect the SWI to your routine.

cynergizer wrote on Thursday, January 27, 2011:

Hi Richard,  Thank you for responding!  In the start-up assembly for my user app shown above, this line of code from my vector jump table is supposed to execute upon a SWI:    ldr pc,     /* swi handler */
Given that the irq vectors are found just fine and given that that my map file shows _vectors to be located at address 0x7000, it seems the hw should know the swi handler address?  Yes, the swi handler address is shown in the map file to be 0x0000be70 (different than my bootloader app).  If the bootloader app has to know about the address of the user app’s swi handler, then my builds are no longer decoupled.

richard_damon wrote on Thursday, January 27, 2011:

I will begin by saying that I am not familiar with the LPC series of processors, a quick check shows them to be ARM processors, which I have used other variations on. I quick look at the data sheet show that there is a Memory Map Control Register that controls where the interrupt vectors are. Just because the linker map shows the vector has been moved, doesn’t mean the hardware has been notified, it is worth double checking the setup for that.

I don’t know how much control you have over the placement of the interrupt vectors, but the data sheet does say that this processor allows mapping them to ram, so at the very least you program can set them up at the beginning of ram (which I assume is at least one of the options), and setup the hardware to use that address. This does put you at the risk that a program error can wipe out the vectors and crash your system, but a reboot would reestablish them.

cynergizer wrote on Thursday, January 27, 2011:

Richard, I think you have correctly identified my problem.  I had erroneously assumed that since the vectored IRQs were working properly, the user app was using the new vector table at location 0x7000.  The vectored IRQs were working because they have hw registers with the address of the handlers.  No such register for the swi handler.  I now see that my hardware doesn’t support relocating the vector table to a different part of flash.  My concern with using the REMAP feature is that it will blow away my custom bootloader’s vector table, which does need distinct interrupt handlers (plus, I’m terribly limited on RAM).  Can I use REMAP w/o blowing away my bootloader’s vector table (my custom bootloader always needs to run upon reboot)?  Thanks for the help Richard - you’re awesome!

richard_damon wrote on Thursday, January 27, 2011:

Again, I will preface with the disclaimer that I haven’t used this chip (but have used other ARM chips) and the following is based on a very short glance at the data sheet.

ARM processors take their vectors from the first words of memory. This chip has relocation hardware to place one of three different locations and place it into this vector table. At powerup it maps “boot loader” flash, which looks like it is at the end of the flash memory into this space, it can also leave the normal low memory there or map the beginning of ram there.

It looks like it is intended for the boot loader to be in high flash memory, but you mention your boot loader is at low memory. If you have added a second level of boot code, then it is using up the “main flash” vector table, and either your user program needs to set up the ram vectors (at a cost of 64 bytes of ram) for its use, or you need to define some way for your second level boot loader to know where the SWI vector is supposed to be for the user code (perhaps with a word of ram) and have it redirect to there.

Of course the best solution would be if your special boot loader could be made part of the architectures idea of what should be a boot loader and then your user program can be placed at 0 as the device expects a flash user program to be.

cynergizer wrote on Thursday, January 27, 2011:

Got it working. YAY!!!