On Friday 14 January 2005 21:24, mspgcc-users-requ...@lists.sourceforge.net 
> > My thanks to all 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...

That's a danger, but for the code I need it turns out to be no problem. Using 
16-bit integer arithmetic with the hardware multiplier (or no multiplies) 
and no divides pretty well does the trick. Gcc provides an excellent 
facility for this, since one can compile with the -S switch, and look at the 
assembly code. This allows a check on all usage of absolute addresses, so 
one can be sure none are in 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'm sure you are right, but somehow I just can't see how to force the 
__asm__() function to use the PC relative addressing mode for a call. 
Something like 

#define PI_CALL(f) asm("call %0"::"?"(f))

ought to do it, if there was a suitable constraint to sub in for the ?

> 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.

Assembler is clearly the correct solution, but the client doesn't like it... 

I've just about got it going, in 492 bytes of RAM including a CRC16 check and 
a segment write. It's all in C, but at present uses no functions. With 
functions I could cut the code down a bit. 

> 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.

Another bit of preparation before launch is to shut down *all* interrupts.
Resetting the stack with the WRITE_SP() macro from iomacros.h before entry 
allows recovery of used stack space, since after reprogramming it makes no 
sense to return. The easy way to start the new code cleanly in pure C is 
with

WDTCTL = 0;

Which forces a PUC, jumping to the new code start via the new reset vector.

> i'have to see if i can release my code.

Me too.

> 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...

Before writing my RAM code I thought long and hard on this one, since it has 
a lot of advantages. The downside is that you can't update the updater, and 
I just can't work up enough arrogance to believe that my updater is so 
perfect that I'll never want to do so. To me, this is the perfect solution 
provided 

a) You have complete confidence in your code, and 

b) The added latency is not a stopper.

Perhaps when I've run the updater for a while, I'll change it to work like 
this.

Some other microprocessors have the vectors in RAM, and copy them over from 
ROM during boot (or some equivalent dodge). I rate this as a great 
architectural feature.

-- 
Rick Jenkins <r...@hartmantech.com>
Hartman Technica           http://www.hartmantech.com 
Phone +1 (403) 230-1987 voice & fax
221 35 Avenue. N.E., Calgary, Alberta, Canada T2E 2K5

Reply via email to