[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-gcc-list] Re: Sharing code between a bootloader and an application.

From: Spiro Trikaliotis
Subject: [avr-gcc-list] Re: Sharing code between a bootloader and an application.
Date: Mon, 5 Jan 2009 11:45:58 +0100
User-agent: slrn/ (Debian)

Hello Jim,

Jim Brain wrote:
> Spiro Trikaliotis wrote:
>> There is also a specific firmware available which can update the
>> bootloader itself.
> I'm looking at the /xu1541/update-bootloader/ area on SF, but I don't 
> understand what I am looking at:
>     * Are you stating that this code will allow a firmware image to
>       update a bootloader?  Can you clarify how it does this?

Yes, I am stating this.

Of course, the firmware image needs some help of the bootloader in order
to be able to do it. And: I am clearly aware that this is not very good
documented yet.

Here is some text I wrote in July 2007 on the OpenCBM mailing list
(aren't you there, too?) about this approach: 

Note0: I use the names BIOS and bootloader unterchangeable.

Note1: When speaking about addresses, I am counting the
       addresses in octets, not in the 16-bit-numbering scheme as seen
       by the processor itself

Note2: There is a jumptable in the bootloader code at $1FF0 (cf.
       bootloader/biostable.S, called "biosdata")

Note3: The spm() subroutine which gives a SPM command from the
       bootloader area must reside somewhere in $1880-$1FFF; its address
       is part of the jumptable at $1FF0 (cf. note 2)
Note4: My Bootloader region is too small. Thus, I have some additional
       data in the area $1700-$17FF which I consider to be part of the
       bootloader, although technically, it is not.

Note5: The bootloader determines if a firmware is available by checking
       $0000-$0001. If there is $FFFF (like after clearing the flash
       page), then no firmware is available, and the bootloader will not
       call the firmware. If there is anything but $FFFF, the bootloader
       will call the firmware, unless a special input pin is low.

------- begin description from July 2007 ----

How is the update done? From the ATMega8 data sheet, one finds out that
the command SPM is needed for programming. That program is only valid
from the bootloader region ($1800-$1fff).

Thus, there is a subroutine in that region for every bootloader. When I
want to update the bootloader, the following steps are performed:

A. Program $1800 (the reset "vector") to contain JMP $0; that is, if
   we crash in this procedure, the updater will be started again.
   This programming is done with the help of the spm() subroutine in the

B. Now, program a *new* spm() subroutine into $1840-$187f.

C. From now on, use the *new* spm() subroutine in the bootloader to:

   C1. reprogram $1880-$1FFF. This will also reprogram the "old" spm()
       subroutine, which is somewhere in that region.
   C2. reprogram $1700-$17ff.

D. Now, switch back to the spm() subroutine of the bootloader again.
   Remember, the bootloader is "almost" completely rewritten, only
   $1800-$187F is missing. If the spm() subroutine is not in that area,
   it will be available again.
   Thus, we have to make sure that spm() is *never* placed into the
   $1800-$187f area!

E. Reprogram $1840-$187f, overwriting the "new" spm() (which is not
   needed anymore)

F. As last step, reprogram $1800-$183f. This will remove our RJMP $0
   from $1800; instead, the reset vector will point back to the

G. Delete the first page ($0000-$003F). This makes sure the updater will
   not be called anymore.

H. Restart the bootloader by resetting the ATMega8.

This routine is "almost" secure against power failure. It is criticial
against a power failure while in step A. or F.; if this happens, the
RESET vector might end being corrupt. There is nothing we can do against

Note that step B. first checks if the new spm() is already available.
For this, a byte-by-byte compare is performed. If the new spm() is
identical to what would have been written, spm() is not written! This
way, we prevent a problem in case the new spm() had already been written
and some other pages, too, and then a power failure occurred. In this
case, the "original" spm() might be corrupt, so, we would not be able to
write the new spm(), but crash.

Additionally, note that after each flash of a page, the system checks if
everything was written correctly. This way, I want to prevent problems
because of low power as much as possible. After three tries, the system
will stop with a continuously flashing LED. Most probably, this will
occur when the system power is low.

The approach works perfectly here, and I think I do not have any races
against power failure anymore (but  A. and F.; but, as I told, these are
the only problematic steps, and I fear I cannot prevent this).

Any thoughts, comments, any races I did not think about?

------- end description from July 2007 ----


Spiro R. Trikaliotis                              http://opencbm.sf.net/
http://www.trikaliotis.net/                     http://www.viceteam.org/

reply via email to

[Prev in Thread] Current Thread [Next in Thread]