Best Way to Do In Field Firmware Updates with XMOS?

Technical discussions around xCORE processors (e.g. xcore-200 & xcore.ai).
User avatar
f_petrini
Active Member
Posts: 43
Joined: Fri Dec 11, 2009 8:20 am
Contact:

Post by f_petrini »

numBytes is most likely less than the size of the image so the supply function will be called multiple times to fetch all data. Therefore you need to keep track of what you have already copied. Currently you supply the same piece of data (from the start of the image) over and over.

Add a global offset variable and add that to the pointer before the copy loop.
After the loop you add the number of bytes copied to the offset so you know where to start the next time the function is called.

You should probably also handle the case where the remaining bytes in the source buffer is less than numBytes.

For example, if the length of the image is 1000 and numBytes is 400:
Call 1: Copy 400 bytes to the destination buffer from offset 0 in source buffer, return 400.
Call 2: Copy 400 bytes to the destination buffer from offset 400 in source buffer, return 400.
Call 3: Copy 200 bytes to the destination buffer from offset 800 in source buffer, return 200.


kster59
XCore Addict
Posts: 162
Joined: Thu Dec 31, 2009 8:51 am

Post by kster59 »

This is a good point so I updated the code:

Code: Select all

int gOffset=0;

unsigned int supplyData(void* userPtr, unsigned int numBytes,unsigned char* dstBuf)
{
	int i;
	fprintf(stderr,"numBytes=%d\n",numBytes);
	for (i=0;i<numBytes;i++)
		*(dstBuf+i)=*((unsigned char*)userPtr+i+gOffset);
			
	gOffset+=numBytes;
	
	return numBytes;	 
}
Ok it still doesn't work and it also doesn't run the line "fprintf(stderr,"numBytes=%d\n",numBytes);"

So plan B:

I tried using the following instead:

Code: Select all

/*	result=fl_startAddingBootImage(&bii,imageSize,0x1,0);
	if(result<0)
	{
		fprintf(stderr,"Error: First call.\n");
		fl_disconnect();
		exit(1);
	}
That gives me an error immediately!


Anyone from XMOS know what's wrong?

I set fl_setProtection(0); and then I called fl_eraseAll() and that works.

It's rather subtle but you need to set the protection off otherwise none of the write commands work.

Even with protection off, it doesn't work.

Also the following doesn't work either:

Code: Select all

if( 0 != fl_setBootPartitionSize(0xffff))
		{
			fprintf(stderr,"Can't set partition size.\n");
			fl_disconnect();
			exit(1);
		}
Which I think is very odd or a bug...
kster59
XCore Addict
Posts: 162
Joined: Thu Dec 31, 2009 8:51 am

Post by kster59 »

Any comments from the XMOS staff?

The writepage/readpage work fine. Both:

fl_startAddingBootImage(&bii,imageSize,0x1,0);
fl_addBootImage( &bii, imageSize, 0x1, &supplyData,(void*)inFile ) )

Again it's really puzzling that fl_startAddingBootImage doesn't work as it doesn't even write anything to the flash as far as I can tell.

At this point, I would settle for some specs on how the XFLASH generated binaries are copied to flash and roll my own. For example, is it a straight binary byte/byte copy of the file. What else to do/etc

Many people have asked about firmware updates over USB.
User avatar
wibauxl
Active Member
Posts: 35
Joined: Mon Dec 14, 2009 4:40 pm

Post by wibauxl »

kster59 wrote:Any comments from the XMOS staff?
I have seen that the folks at XMOS have start to put a forum on their web site with documentation and comments.
You could maybe post a link to your questions here on that support forum.
richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

The last version of supplyData() you posted looks good to me, and you are right that you need to disable the device protection before writing data.

Are you calling fl_setBootPartitionSize()? The flash is considered by libflash to consist of two partitions: a boot partition which holds upgrade images and a data partition that can be used for persistent storage of application data. You need to set the size of the boot partition in your program otherwise it will default to 64KB in 9.9.2. If you are not using the data partition then you can simply set the size of the boot partition to the size of your flash device.

fl_addBootImage() will error before calling the supplyData() callback if writing an image of the specified size would result in writing past the limit of the boot partition. Hopefully this explains the error you are getting.
kster59
XCore Addict
Posts: 162
Joined: Thu Dec 31, 2009 8:51 am

Post by kster59 »

Yes I /attempted/ to set the flash size but it doesn't work:

Code: Select all

fl_setProtection(0);
if( 0 != fl_setBootPartitionSize(0xffff))
{
 fprintf(stderr,"Can't set partition size.\n");
 fl_disconnect();
 exit(1);
}
This is immediately exits. 0xffff is 64kBytes so I assume it should work. I also tried 0x1fffe and other numbers. They all return error.

Also my program is small and it is only 5kBytes in size and the update is also 5kBytes so it should fit.

I'm not sure how to explain how both the above code and this code return errors:

Code: Select all

result=fl_startAddingBootImage(&bii,5128,0x1,0);
if(result<0)
{
 fprintf(stderr,"Error: First call.\n");
 fl_disconnect();
 exit(1);
}

The writePage and readPage functions work fine as I can write a page, turnoff the device and read it back.
richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

The boot partition must consist of a whole number of sectors. fl_setBootPartitionSize() will fail if the specified size would mean that the boot partition ends in the middle of a sector. Try setting the size using:

Code: Select all

fl_setBootPartitionSize(fl_getSectorAddress(fl_getNumSectors() - 1));
Could I also check which tools release you are using and which flash device you are trying to access.
kster59
XCore Addict
Posts: 162
Joined: Thu Dec 31, 2009 8:51 am

Post by kster59 »

I tried the code and it gives the same error:

Code: Select all

	if( 0 != fl_setBootPartitionSize(fl_getSectorAddress(fl_getNumSectors() - 1)));
	{
		fprintf(stderr,"Can't set partition size. \n");
		fl_disconnect();
		exit(1);
	}
I am using the XC-1A with the atmel flash chip. I am using the same chip for our new design.

Is it possible to have the specs or code behind the fl_startAddingBootImage, etc. That way I can just roll my own using the writePage/readPage.

I can send my entire project to someone at XMOS if they want to look at it. It's very simple, all I want to do is make an update from a flash file stored in an array.

The flash files were generated with xflash using the dump and upgrade options no problem. I just need to figure out how to copy these to the flash device so that the XMOS device boots from it.

I assume many manufacturers and designers like us want to use XMOS products in their design but a full jtag solution seems to add unnecessary cost and has IP issues.
richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

kster59 wrote:

Code: Select all

	if( 0 != fl_setBootPartitionSize(fl_getSectorAddress(fl_getNumSectors() - 1)));
	{
		fprintf(stderr,"Can't set partition size. \n");
		fl_disconnect();
		exit(1);
	}
There's a extra semi colon after the if which will cause the error message to always be printed regardless of the return value of fl_setBootPartitionSize(). Try the following:

Code: Select all

	if( 0 != fl_setBootPartitionSize(fl_getSectorAddress(fl_getNumSectors() - 1)))
	{
		fprintf(stderr,"Can't set partition size. \n");
		fl_disconnect();
		exit(1);
	}
If you are still having problems after this I suggest attaching your source to a support ticket so we can try and recreate issue.
kster59
XCore Addict
Posts: 162
Joined: Thu Dec 31, 2009 8:51 am

Post by kster59 »

Thanks for pointing out the error. Works well now!

However, I think it is odd because both (the original and update) of my flash images are 5kBytes. Total would be 10kBytes + bootloader which should fit in the 64kBytes original bootsize.

Perhaps the documentation should be updated to show this nuance.
Post Reply