----- Ursprüngliche Nachricht -----
Von: David Brown
Gesendet am: 17 Nov 2009 01:26:11
JMGross wrote:
>> I don't see, however, why functions in RAM shall not call any
>> function in FLASH (except when writing to flash is active)
>If your ram functions could call code in flash, there would (normally)
>be no point in putting them in ram in the first place! Flash
>programming functions are the main use of such code in user applications.
There could be something to be done before the actual flashing process. This
could include multiplications (thus implicitely calling a library function).
One could place this code outside the RAM function, but even if not, it is safe
to call flash functions from RAM except for two things:
- the flashing process is running or
- the flash has been erased and there are no more functions in flash.
> If you keep your ram functions small, this is not normally a problem.
> And (ab)using the .data section for your functions means you don't have
> to worry about loading the code, and you don't have to think about where
> the function is or how to call it - just treat it as a normal function.
> You can even step in and out of it with a debugger.
Okay, the debugger is a valid point.
I don't use a debugger, so I didn't think of that.
The debugger cannot stop radio waves or such, and most of my work is hard
realtime processing, so it is useless. An Oscilloscope and a toggled port pin
helps more. :)
Anyway, even with a temporarily copied function, you can at least single-step
through it. Of course not with direct source code reference, only disassembly
code.
----- Ursprüngliche Nachricht -----
Von: Rick Jenkins
Gesendet am: 17 Nov 2009 19:07:55
> Thanks to all who have replied to this enquiry. I must admit I'm somewhat
> astonished that there is not a simple answer to this.
I was too. Back in old BorlandC times, this was no problem. But with the
upcoming of optimizing compilers (and bigger and bigger ram), this
functionality has become more and more useless (even if it was just for the
lack of need for code efficiency).
The size of the code is no longer something the program cares for, as long as
the compiler/linker knows.
> I am entirely in agreement with JMGross that a global symbol emitted by .size
> is the perfect solution, provided that optimisation does not fool it. As a
> matter of fact, I'm not sure that "optimisation" is always as good as it
> should be. I've found instances where it produces a jump to a "RETI"
> instruction, which is a waste of code space and run time. Merely replacing
> the jump with a second "RETI" is clearly more efficient.
And all those (assmbler-generated ' never be executed' warnings)...
It happens because there is nop second optimisation run that analyzes beyond
the optimisation.
In you example above, the code jumps to the next part of the code, which
happens to be just the RETI but could be some more. Like some POPs or framing
work or stack cleanup.
Also, the jump could be a conditional jump (in fact, usually it is, even if it
is a condition which is intentionally always met).
>All in all, I think I'll stick with my somewhat kludgy use of a separate
>section for the function to be moved. The optimiser does not jump to code
>outside the section, and the linker reliably reports the memory address of
>the end of the section.
Yes, the end of the section, not the end of your function.
So this is equal to the 'copy from start of function as much as you can'
approach.
You have seen my assembly hack? If you put your fucntion into a separate object
file, it will be 100% safe, even with -o3.
Without any linker hacking.
----- Ursprüngliche Nachricht -----
Von: Rick Jenkins
Gesendet am: 17 Nov 2009 23:40:13
On Tuesday 17 November 2009 15:33:24 Nico Coesel wrote:
>> Why is your flash programming routine so large? Only the part that does the
>> actual flash programming has to be in ram. This is just a few lines of
>> code. Perhaps you need to split the function in a part that stays in flash
>> and a small part that does the actual programming.
> It's a field update for client-confidential code. The final decryption stage
> is done in the programming function.
That's a reason :)
But you could do different:
Put your whole download and decryption stuff into a separate section and point
the reset vector to it.
Then after a reset, check whether the last update has been done properly. If
so, just boot normally (copy variables, call main etc.)
When updating through this boot loader, only erase the part of flash that is
being updated (skipping its own area, unless really necessary) and update it.
This way, your update code can be as long as you wish. And you can recover from
a power fail, ESD caused reset or a loosened data cable while updating (shit
happens when working in the field).
And if you don't care for the flash writing speed, you can also do the flashing
from your flash code (well, then you cannot update the flash loader itself of
course).
JMGross