Boot/jump table access on xmega256a3u

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

Hello,

 

I have created a bootloader for use with the xmega256a3u and everything is working.  One of the functions in my jump table passes me an 8 byte git version of my bootloader:

 

#ifdef __GIT_VERSION__
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define VERSION TOSTRING(__GIT_VERSION__)
#else
#define VERSION "_NO_GIT_"
#endif

void printHerald(void) {
	printf("B:version:%s\n", VERSION);
}

void getBootVersion(char *version) {
//	memcpy(version, VERSION, 8);
// for (u8 i = 0; i < 8; i++){
//    version[i] = VERSION[i];
//}

    version[0] = VERSION[0];
    version[1] = VERSION[1];
    version[2] = VERSION[2];
    version[3] = VERSION[3];
    version[4] = VERSION[4];
    version[5] = VERSION[5];
    version[6] = VERSION[6];
    version[7] = VERSION[7];
    version[8] = 0;
}

 

The version prints just find as part of the boot startup.

 

However, if I use memcpy or a for loop to pass the VERSION back to application space I get nothing in return.  However, If I do it line by line as shown above it works fine.  Anyone explain to me why memcpy or a for loop wouldn't work in this case?

Last Edited: Thu. Oct 29, 2015 - 10:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

 

For Completeness here is my jump table on the bootloader side:

 

typedef struct {
	u16 writeUpgradeSection;
	u16 computeUpgradeSection;
	u16 getBootVersion;
	u16 saveFirmwareChecks;
} JumpTableStruct;

JumpTableStruct JumpTable __attribute((section(".vectors"))) = {
	(u16) (writeUpgradeSection),
	(u16) (computeUpgradeSection),
	(u16) (getBootVersion),
	(u16) (saveFirmwareChecks)
};

 

And on the application side:

 

#define ProgramReadWord pgm_read_word_far
#define JUMP_TABLE_LOCATION (BOOT_SECTION_START + _VECTORS_SIZE)
#define jumpTableIndex(k) (ProgramReadWord(JUMP_TABLE_LOCATION + 2UL * (k)))

enum {
	writeUpgradeSection = 0,
	computeUpgradeSection,
	getBootVersion,
	saveFirmwareChecks,
} JumpTable;

void jumpTableGetBootVersion(char *version) {
	u16 jumpPointer = jumpTableIndex(getBootVersion);
	EIND = 2;
	((void(*)(char *))jumpPointer)(version);
	EIND = 0;
}

 

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

VERSION is a macro, right? You #defined it, so when you write VERSION in the code you are doing a substitution. You can't treat it like an array that is stored somewhere, because it only exists at compile time. Furthermore, even if it was an array it would be stored in RAM by default, and variables stored in RAM get loaded by the invisible start-up code that the compiler creates. So if you try to access RAM based variables from the application, they probably won't work because code in the bootloader puts them there, and the application start up code will probably overwrite them.

 

You could try putting VERSION into flash memory, e.g.

 

__flash__ char version[] = VERSION;

 

Beware that the compiler will probably try to optimize it away though, so make it volatile and put a dummy read in your bootloader code.

 

Have a look here at an example of doing this that I wrote: https://github.com/mojo-chan/hid...

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

Just to clarify, I'm saying that VERSION is a pre-processor macro. It's not handled by the C compiler, it's substituted by the pre-processor. So say VERSION was "1.3.5", the code that the compiler actually compiles is:

 

memcpy(version, "1.3.5", 8);

 

The string "1.3.5" must be in RAM for this to work, and chances are either the bootloader start-up code that copies it into RAM wasn't run or the application overwrote that memory later.

 

Your other code works because

 

version[0] = VERSION[0];

becomes

version[0] = "1.3.5"[0];

which the compiler optimizes to

version[0] = '1';

 

Sorry, I have not yet had the required amount of coffee this morning.

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

Thanks for the response, that was a very informative response.

Last Edited: Fri. Oct 30, 2015 - 09:02 PM