Best Way to Do In Field Firmware Updates with XMOS?

Technical discussions around xCORE processors (e.g. xcore-200 & xcore.ai).
kster59
XCore Addict
Posts: 162
Joined: Thu Dec 31, 2009 8:51 am

Best Way to Do In Field Firmware Updates with XMOS?

Post by kster59 »

I'm developing my own board and I need USB connectivity so settled on using an FTDI FT232R or FT245R. However, I need to provide in field firmware updates.

I'd rather not include the JTAG interface if possible to keep the cost down so I've been thinking about making a bootloader.

I would store the FLASH update in a buffer then overwrite the SPI flash. After reboot then it would just boot up on the SPI flash with the new code.

Are there any examples of doing something like this? I need to program the OTP to make sure if the device fails then it can still load the firmware.

It would even be better if I could just load firmware without an SPI flash as my device is connected directly to a PC at all times.

Any suggestions? Thanks.


User avatar
shawn
XCore Addict
Posts: 238
Joined: Thu Dec 17, 2009 5:15 am

Post by shawn »

like Bootp over Ethernet or USB seems doable.
So you need a few threads and a little encryption.
very small CSP DB linked OTP monitor that pips
new firmware to virtual shell, tests before being
effective. This is just one of many schemes, read
around, check @ Xmoslinkers, most likely what you
are looking for , someone may be on it, or its been
done. Perhaps you need a link on the JTAG, "err?".
Hardware people, comment please?
kster59
XCore Addict
Posts: 162
Joined: Thu Dec 31, 2009 8:51 am

Post by kster59 »

Looking to bump this question.

Does XMOS have a ready to use boot loader code that can write to flash over usb/rs232 or other?

Thanks.
User avatar
trousers
Active Member
Posts: 44
Joined: Fri Dec 11, 2009 10:20 am
Contact:

Post by trousers »

Xflash has support for in-field upgrades in that it allows multiple boot images to be held in the flash and one is chosen at boot time. This facilitates a safe upgrade proceedure because it doesn't require you to clear the flash before writing the new one. Xflash can produce an upgrade image from an XE file.

It doesn't, however, provide the mechanism for reading the upgrade image from the host over UART or USB; you have to do that bit yourself.
Best friends with the code fairy.
User avatar
shawn
XCore Addict
Posts: 238
Joined: Thu Dec 17, 2009 5:15 am

Post by shawn »

trousers wrote:Xflash has support for in-field upgrades in that it allows multiple boot images to be held in the flash and one is chosen at boot time. This facilitates a safe upgrade proceedure because it doesn't require you to clear the flash before writing the new one. Xflash can produce an upgrade image from an XE file.

It doesn't, however, provide the mechanism for reading the upgrade image from the host over UART or USB; you have to do that bit yourself.
I kinda of figured it could ISP in field, sure we would have to provide extra mechanisms for UART,USB
etc, ISPing, but seeing how its updates all ready, makes those task secondary, knowing what is possible and not.

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

Post by kster59 »

I am back to trying to get this in field upgrade to work.

This post will probably save other people a lot of time so here are the steps as I see them:
1) Compile .xc program with xcc to produce myfile.xe file
2) Use "xflash myfile.xe --dump-image mybin.bin --makeupgrade 1000" to produce a binary upgrade file with id= 1000.
3) Transfer mybin.bin byte by byte to the XMOS device using my communication protocol.

Questions:
1) In my ".xe master program" running on the xmos device, I want to write mybin.bin into the flash memory byte by byte. I am not clear how to use the libflash routines and compile it into my application. Is the code for libflash listed somewhere?
2) I can send mybin.bin to from the PC to the xmos device using an RS232 library that I wrote. I can't store the whole file into memory since the program is too large. So say I can store 4kBytes. What's the best way to program this into the flash? Should I use the SPI flash write routines to store the code in 4kByte block writes?
3) How do I figure out what starting address if I do this block write? Is copying the data byte by byte into flash sufficient to make this work?
4) Upon reboot, does the XMOS device just scan all boot images for the largest id number and boot from there? Thanks for the answers.
kster59
XCore Addict
Posts: 162
Joined: Thu Dec 31, 2009 8:51 am

Post by kster59 »

I looked at the libflash example more closely and think I am very close now.

As a test, I generated a .h file with the byte by byte copy of my output2.bin dump file from xflash.

Now, in my XC code I have:

Code: Select all

#include <xs1.h>
#include <platform.h>
#include <print.h>
#include <flashlib.h>
#include "header.h"//has flash file

extern int ctestfunc();
/* Declaration of port structure for fl_connect. */
fl_PortHolderStruct spiPorts =
{
	PORT_SPI_MISO,
	PORT_SPI_SS,
	PORT_SPI_CLK,
	PORT_SPI_MOSI,
};

int flashUpdate(char inFile[], int imageSize);

int main()
{
	flashUpdate(gArray, 5128);
}
In my libflashtest.c file I have:

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <flashlib.h>

extern fl_PortHolderStruct spiPorts;
/*
* User supplied function which is called-back by flashlib
*/
unsigned int supplyData(void* userPtr, unsigned int numBytes, unsigned char* dstBuf)
{
	//return( fread(dstBuf, 1, numBytes, (FILE*)userPtr) );
	
	//point to array
	dstBuf=(unsigned char*)userPtr;
	return 0;
}

int flashUpdate(unsigned char* inFile, int imageSize)
{
	printf("Image size is %d\n",imageSize);

	// Connect to the flash chip 
	if( 0 != fl_connect(&spiPorts) )
	{
		fprintf(stderr,"Error: Cannot recognise attached flash device.\n");
		exit(1);
	}
	// Locate the factory boot image 
	  
	fl_BootImageInfo bii;
	if( 0 != fl_getFirstBootImage( &bii ) )
	{
		fprintf(stderr,"Error: Cannot locate factory boot image.\n");
		fl_disconnect();
		exit(1);
	}

	// Add a boot image after the factory one using data supplied by supplyData() function
	if( 0 != fl_addBootImage( &bii, imageSize, 0x1, &supplyData,(void*)inFile ) )
	{
		fprintf(stderr,"Error: Cannot add new boot image.\n");
		fl_disconnect();
		exit(1);
	}
	printf("Boot image added.\n");
}
The fl_connect and fl_getFirstBootImage works fine but the fl_addBootImage fails.

I think my problem is in supplyData. From what I read, the original function uses fopen to copy the data into the array pointed by dstBuf.

In my code, I have a large "unsigned char gArray[5128]={xx,xx,xx}" for all the contents of the upgrade flash file.

So shouldn't my assignment of dstBuf=(unsigned char*)userPtr;
be ok?

Am I doing anything wrong here?

Once I have this solved, I can just copy byte by byte into gArray at runtime and do an update as a subroutine call to "int flashUpdate(unsigned char* inFile, int imageSize);"
User avatar
wibauxl
Active Member
Posts: 35
Joined: Mon Dec 14, 2009 4:40 pm

Post by wibauxl »

kster59 wrote:

Code: Select all

unsigned int supplyData(void* userPtr, unsigned int numBytes, unsigned char* dstBuf)
{
...
	return 0;
}
Normaly fread returns the number of bytes read. Maybe you should not return 0?
User avatar
f_petrini
Active Member
Posts: 43
Joined: Fri Dec 11, 2009 8:20 am
Contact:

Post by f_petrini »

I have not yet had time to use libflash myself but I from what I think I understand while reading the documentation I might have some input...

The first thing I noticed in your code is that you reassign the dstBuf pointer which is not going to have the effect you are looking for. The dstBuf variable only exists in the scope of the supplyData function so you can't change it and have the caller use your buffer. You need to copy data from your buffer into the destination buffer.

I assume the supplyData function will be called multiple times to fetch a small part of the boot image at a time. The size of the destination buffer is numBytes so that is the maximum number of bytes you can copy into the destination buffer each time supplyData is called.
The supplyData function probably also need to return the number of bytes copied to the destination buffer.
kster59
XCore Addict
Posts: 162
Joined: Thu Dec 31, 2009 8:51 am

Post by kster59 »

Ok based on comments here I have updated the code of supplyData:

Code: Select all

unsigned int supplyData(void* userPtr, unsigned int numBytes, unsigned char* dstBuf)
{
	int i;
	for (i=0;i<numBytes;i++)
		*(dstBuf+i)=*((unsigned char*)userPtr+i);
	
	return numBytes;
}
I think that should be equivalent to fread now since it copies all the bytes and returns numBytes.

Still says cannot add new boot image.

Anything else wrong possibly?
Post Reply