Rick Jenkins wrote:
My thanks to both the people who responded to my query.
Rolf's suggestion is a good one, since it is easy enough to compute the new
address of a function after it has been moved. With -O2 it calls via a
register variable, and is completely position-independent. It has the minor
disadvantage of needing extra code to figure out the address of any
function to be called, and RAM space is dreadfully tight in the smaller
machines.
Bill Knight's suggestion is excellent if the code is to be RAM-resident,
since it is completely transparent. However, my need is for code which is
not normally used, but is moved to RAM during a code update, to reprogram
the flash. With restricted RAM space it is not practical for me to leave the
code in RAM at all times.
with both solutions you have no control over the helper functions that
the compiler uses internaly. gcc links some helper functions from libgcc
that are used transparently. consider what happens when your update
function calls one of these thats still in the - now erased - flash...
I'd still like to find a way to produce the PC-relative call, since it is a
perfect solution. If it exists as a legal opcode, surely there should be a
way to access it?
you can write any assembler you want inline with gccs __asm__() function.
i'd write that update function as pure assembler module - hey wait...
that's what i have done ;-)
it isn't hard to do if your protocol and hardware interface to receive
the update is not too complicated. e.g. doing what the ROM BSL does, is
possible in less than 500 bytes of position independent assember code.
you don't need to set up the hardware in that loader, you can do that
before you copy it into the RAM and launch it.
i'have to see if i can release my code.
an other aproach is that you reserve a few flash segments that you dont
erase. you can place your updater code there. however it has some
downsides too. if you let gcc link all the utility functions in the
updater and your application it gets a little easier. useful is when the
bootlaoder is in the upper memory, so that the reset vector can launch
the updater when there is no application, that way you can always
reproram a device, even after a power failure during an update. but in
this case you need to redirect all interrupts (adding some latency)
but if you have enough flash, that's probably a nice solution that
allows powerfull features with (almost) no special programming tricks...
chris