Run identical code in application section from non 0 location

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would like to have two copies of my firmware in my application section so that I could jump from the bootloader to either firmware.

 

I have an xmega256a3u and I have a bootloader (0x40000) that flashes the same memory to two different spots in the application sector (0x00000 and 0x20000).

 

I am naively thought that I could just set EIND = 1 and then I could jump to 0x20000 but this doesn't seem to run the code:

 

void (*sectionStart)(void) = (void (*)(void)) 0x0000;

int main(void) {
    ...
    if (...) EIND = 1;
    else EIND = 0;
    sectionStart();
}

 

Is it possible to have identical code that can reside in two different location in application section?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You could always use inline assembly code:

if (...) 
    // for 0x00000
    asm volatile("\n\t"
        "clr r30        \n\t"
        "clr r31        \n\t"
        "clr EIND       \n\t"
        "eijmp          \n\t"
        ::
    );
else
    // for 0x10000
    asm volatile("\n\t"
        "clr r30        \n\t"
        "clr r31        \n\t"
        "clr EIND       \n\t"
        "inc EIND       \n\t"
        "eijmp          \n\t"
        ::
    );

 

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

Make Xmega Great Again!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the code, I think the code works for jumping to different locations in flash, at least I know it works for jumping to 0.  I am wondering though if I will have to tweak my firmware to run at a non-zero address which is what I am hoping to avoid.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have a look at the disassembly for your code and check for changes to EIND, RAMPZ etc. I think this could be tricky.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Silly question but what are you going to do about interrupts. The location of the vector table in AVR is fixed and could therefore only "live" in one copy of your program. While it's possible to write MCU code without interrupts it's pretty unusual to have a real application that doesn't need them in some way.

 

The solution of course is to direct all the vectors through RAM based pointers and then replace those pointers according to where the "current" application is residing - but it's non-trivial.

 

We've seen endless threads about "more than one app in an AVR" here before now and to be honest the only really practical thing is to keep BOTH of the codes "out of the way" and then just SPM one of them to 0 when it is selected to be run.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I agree with clawson, just avoid doing it. The only other option is to have one application in the application section and the other in the bootloader section, assuming it will fit and you don't need the bootloader for anything else. The MCU supports remapping interrupt vectors to the bootloader section.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I imagine we all keep asking if it can be done cause of the large amount of unused flash.  Wishing that you could section off half of the application sector like you do the bootloader.

 

Thanks for the responses, saves me a lot of wasted time and effort.