TFTP boot loader for Simplecortex is working

The problems I had with the TFTP boot loader last week are solved!

Last weekend I discovered that the InterruptTimer_CoIDE example project I used from the Simplecortex repo wasnt’t working that well as I thought. When I started with the TFTP boot loader, one of the first things I did was running that example unmodified frm the normal start address. I saw all the LEDs blinking, so there was no reason to think that something was wrong.  Then, last Saturday I read this post on the Simplecortex forum. Apparently timer interrupt 3 wasn’t doing what it should.. hmm, in my case, timer 3 was the only one that did work in TFTP mode – there must be some link between the 2 issues!

And I was right – after updating the InterruptTimer_CoIDE example from the repo, all the LEDs were still all blinking in non-TFTP mode of course, but in TFTP mode none of the 4 LEDs were blinking! That may sound bad but it isn’t; I’d rather have 4 timers not working than 3 that don’t and 1 that does 😉

Cause now I had a consistent behavior and not something completely inexplicable; now the user code didn’t function ‘a bit’ – no, now it didn’t function at all! That sounds like a better starting point to find the error. Somehow I had the feeling that the  interrupt vectors were wrong; but why?

The mistake I made was that I had a completely wrong perception of what was going on when the TFTP boot loader jumped to the user code:

/* Change the Vector Table to the USER_FLASH_START
in case the user application uses interrupts */
SCB->VTOR = (FLASH_START_ADDR & 0x1FFFFF80);

// Load contents of second word of user flash - the
// reset handler address in the applications
// vector table
p = (unsigned *)(FLASH_START_ADDR + 4);

// Set user_code_entry to be the address
// contained in that second word
// of user flash
user_code_entry = (void *) *p;

// Jump to user application
user_code_entry();

The vector table is set to the right address (line 3) and the user code is called.

Aarrgghh!

I don’t know why, but somehow I had the (wrong) idea that the user_code_entry() call jumped directly to main() in the user code – and this idée fixe withheld me from finding the solution, which was relatively simple as I found out later… Willem, someone I know from the Domoticaforum tried to help me and mentioned I should change the SystemInit() in system_LPC17xx.c. Well, the only thing I could think of was the following:

void SystemInit (void)
{

  ...
  ...

  //  Set Vector table offset value
  #if (__RAM_MODE__==1)
    SCB->VTOR  = 0x10000000 & 0x3FFFFF80;
  #else
    SCB->VTOR  = 0x00000000 & 0x3FFFFF80;
  #endif
}

This code sets the vector table back to the value needed for ‘normal’ operation, where the user code starts at 0x00000000. But… why bother, the user code doesn’t come here at all, right? After Willem mentioned SystemInit() a second time I decided to give it a try although I still didn’t think it would help… WRONG!

The moment I saw all the LEDs blinking at a different rate, suddenly 2 words in the comments caught my attention: reset handler.

Of course, how could I be so blind… the user_code_entry() call mentioned earlier doesn’t call main(), but the reset handler – so this effectively runs the same code as if the Simplecortex has been reset! And the default reset handler routine contains a call to SystemInit(), so the effect was that the vector table was overwritten by the user code…

Bingo!

 

Tagged . Bookmark the permalink.

2 Responses to TFTP boot loader for Simplecortex is working

  1. Willem says:

    You should have a little more fate in my debugging and analytic skills Robert 🙂 Glad to be of help.

    • LOL
      Well, most of the times my stubbornness helps me, sometimes it backfires – next time I’ll keep on asking “why” until I fully understand what you mean, instead of jumping to my own (wrong) conclusions 🙂
      Thanks again!

Leave a Reply

Your email address will not be published. Required fields are marked *