EmbDev.net

Forum: ARM programming with GCC/GNU tools Firmware self-update


Author: jrmymllr jrmymllr (jrmymllr)
Posted on:

Rate this post
0 useful
not useful
I'm interested in writing C code to allow a firmware update to my 
project over the ethernet port instead of connecting the JTAG programmer 
every time.  I've done enough embedded C programming to have a good 
handle on most things, but this one seems a bit tricky.

I know the answer to this is very likely complex, but I'm only 
contemplating this right now, and there's no deadline.  In my case, 
copying the executable "firmware update" code to RAM so I have 
unrestricted write access to FLASH seems like the way to go.  What gets 
me is, how is this done in C?  How do I copy a function(s) in FLASH to 
RAM then suddenly pick up and start executing out of RAM with no regard 
to any previous RAM contents?

Or, is there no simple solution to this, and I have to get creative? 
The good thing is that at the point where I would initiate 
reprogramming, there would be over 80K of free RAM, so maybe I would 
have to copy to a specific region I know is free using a hard-coded 
address, then jump to that address.  The stack, etc would stay intact.

Any pointers?  I think I could work something out but maybe I can learn 
something here.

Author: 900ss D. (900ss)
Posted on:

Rate this post
0 useful
not useful
I've never done this for a STM32 but for a AVR Controller. There is a 
small bootloader at the top of the Flash. This can be activated and 
controls the download of the new firmware. A block is loaded into the 
ram and then copied to the flash. That with all blocks necessary for the 
firmware. Then jump to the new firmware (address 0) or a reset or .....

I'm not sure if this is also possible with the STM32 but I think so. I 
guess you will find also hints on the STM website for this theme.

Just my 2 cents
900ss

Author: jrmymllr jrmymllr (jrmymllr)
Posted on:

Rate this post
0 useful
not useful
900ss D. wrote:
> I've never done this for a STM32 but for a AVR Controller. There is a
> small bootloader at the top of the Flash. This can be activated and
> controls the download of the new firmware. A block is loaded into the
> ram and then copied to the flash. That with all blocks necessary for the
> firmware. Then jump to the new firmware (address 0) or a reset or .....
>
> I'm not sure if this is also possible with the STM32 but I think so. I
> guess you will find also hints on the STM website for this theme.
>
> Just my 2 cents
> 900ss

I should note that this is not for STM32, as I didn't mention the micro. 
It's for LM3S9bxx.  I know there's a bootloader available for these, but 
I wasn't thinking of a bootloader so much.  I wanted to be able to 
select to do a f/w update from a menu, although I suppose it doesn't 
make much difference how the user has to do it.

Author: 900ss D. (900ss)
Posted on:

Rate this post
0 useful
not useful
Jerry Milner wrote:
> I should note that this is not for STM32, as I didn't mention the micro.

Ah, yes :-)

> It's for LM3S9bxx. I know there's a bootloader available for these, but
> I wasn't thinking of a bootloader so much.

How you call that piece of program is the same I think ;-)

> I wanted to be able to
> select to do a f/w update from a menu, although I suppose it doesn't
> make much difference how the user has to do it.

Yes, I think you can write such a f/w loader which is located at the end 
of the flash. The problem is, if the download failed then there is no 
valid application where the reset vector points to. May be you can set 
the reset vector in general and fixed to the f/w loader and there you 
decide to start the application or the f/w loader itself. But at the 
moment I don't know if such a scenario is possible with the LM3Sxxx or 
also the STM32. The application needs also reset vectors but I guess 
with the base address of the vector table you can "play". But my 
experience for the Cortex is not enough to give a precise hint.

900ss

Author: Martin Thomas (Guest)
Posted on:

Rate this post
0 useful
not useful
As already pointed out by "900ss D." it can cause trouble if the 
update-code gets copied to RAM and deletes the old application during 
the update procedure. If update failes i.e. because of a power-failure 
the application code in flash and the update-code in RAM are lost and 
firmware has to be rewritten to flash using ohter channels (factory 
bootloader, JTAG...).

You might check the documentation how software-protection is 
implemented. Some target have limitations which flash-pages can be 
written from application code if protection. Even if it's possible 
disabling the protection temporarly might not be an option since this 
might open a security hole for a short time. Maybe there are also 
non-volatile settings or external pins to set the default start-address 
(I can not rememeber this for Stellaris devices. But maybe there are 
options like this.)

Possible appoaches:
(1)
- inital programming of the memory with the vector table at the start of 
flash and the update code (=bootloader) at the end of flash.
- the reset-address in the vector points to the update-code's 
reset/startup-routine
- the bootloader has its own vector-table to handle its interrupts and 
the first instructions of the update-code remap to this vector-table
- the update code tests for an update request. Maybe by waiting for a 
special package received over ethernet until a timeout of by checking if 
a key is pressed.
- if there is no update request the bootloader checks if there is a 
user-application in flash. This could be done by checking for a 
version-number or "magic-number" at a known memory address or simple by 
checking for empty flash
- if there is an update request the update code receives the flash-image 
and writes it to flash but changes the reset-vector address before 
writing the applications vector so the update-code is always started 
first. The reset address of the user-application gets stored at a known 
memory address, maybe in one of the reserved elements of the vector 
table.
- after update or after timout the bootloader sets the stack-pointers, 
remaps the vector-table to the default, reads the applications address 
from the known locations and finally jumps to it

The advantage of this approach is that there is no special memory layout 
needed for the user-application and no need to take care of remapping in 
the user-code. Everything "special" gets handled by the bootloader.

(2)
- bootloader including its vector-table gets installed at the beginning 
of the flash-memory
- bootloader always starts first, checks for update request as outlined 
above.
- user-application starts at a known address after the end of the 
bootloader-code.
- bootloader tests of update-request, receives new code, writes it to 
flash
- after update or if there is no update request the bootloader reads the 
reset-vector of the application from the known start-address, sets the 
stack-pointers and calls the user-applications reset-handler. Optionally 
the bootloader can already remap the vector-table address but this could 
be also done in the reset-handler of the user application
- the user-application needs to be linked to start at the known address. 
The address needs to be a valid postition for a vector-table (valid 
addresses/aligments should be listed in the documentation). For this 
minor modifcation are needed in the linker-script or special 
command-line options need to be passed to the linker

I have implemented both approaches successfully with STM32 devices where 
firmware updates get read from a SD-Card. So the basic concepts do work. 
But of cause TI/LMI Cortex M3 devices are different in terms of 
in-application-programming and there may be differences in handling the 
vector-table location/offset.

Hope this rather long post gives at least an idea.

Author: jrmymllr jrmymllr (jrmymllr)
Posted on:

Rate this post
0 useful
not useful
Thank you Martin for your reply.  I'm still investigating some of the 
points you make.

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.