EmbDev.net

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

Author: jrmymllr jrmymllr (jrmymllr)
Posted on:

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:

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:

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:

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:

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:

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]




Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.


webmaster@embdev.netContactAdvertising on EmbDev.net