\chapter{The optiboot boot-loader for AVR Micro-controllers}

\section*{}
The optiboot Boot-loader has been created with C language by Peter Knight and
Bill Westfield. I have used the version 6.2 as base
for the here described revised Assembler version.
I would like to underline, that I did not reinvent the
optiboot boot-loader. I have just done some optimizing.
Many adaptions to several target processors and special
board level systems are present with the version 6.2.
The program use parts of the STK500 communication protocol,
which is released with AVR061~\cite{stk500} from Atmel.


\section{Changes and enhancements to the version 6.2}
Basically I have translated the total program in the assembler language
and have adapted the Makefile, that the program length will
be processed automatically to select the start address of the boot-loader
and set the right fuses for the program length.
The selected solution generates some small files during some
interim steps, which are required to solve the following steps
to select the right start address and the right fuses.
The start address of the boot-loader for any target processor
depends on the present flash size, the flash requirement
of the boot-loader code and the tile size, which is supported
by the target processor for bootlace.
The tile size is the smallest boot-loader size, which can be supported
by the selected target processor.


For processors like the ATtiny84, which don't support the boot-loader start function,
the page size of the flash memory is used for this calculation.
For the ATtiny84 this are 64 Bytes. Therefore the start address of
the boot-loader is always located at the begin of a flash page.

For all other supported target processors the boot-loader area can be
selected with the fuse bits BOOTSZ1 and BOOTSZ0 (each with the values 0 and 1).
If you put together the both bits, you get a coded boot-loader size
with values between 0 and 3.
Always the value of 3 select the smallest possible boot-loader area.
A value of 2 select a double size, the value 1 the quadruple size
and the value 0 select a size of eight times the smallest size.
The table~\ref{tab:bootsz} at page~\pageref{tab:bootsz} shows a 
overview for the several target processors.

\section{Automatic size adaption in the optiboot Makefile}

The boot-loader start address and the required boot-loader size will
be adapted automatically with the Makefile.
For the calculation some interim files are created,
which is only possible together with some Linux tools:

\begin{description}
\item [bc] a simple calculator, which can operate with input and output-
values in decimal and hexadecimal values.
\item [cat] put the file content to the standard output.
\item [cut] can select part of lines of a text.
\item [echo] shows the specified text at standard output.
\item [grep] shows only lines of a text file which contain the specified string.
\item [tr] can replace or erase characters.
\end{description}

Until now this function of the Makefile is only tested with a Linux system.
Probably a use with the Windows system is only possible,
if you install the Cygwin package.

You don't handle the different interim files in normal case.
Here I would like to refer the names and the meaning:
\begin{description}
\item [BootPages.dat] hold the count of required pages by the boot-loader.
For processors which support the boot-loader start feature, the value can be only 1, 2, 4, or 8 and
specifies how many times the minimum size of the boot-loader area (tile) is used.
With the virtual boot-loader support the number can be any value and
specifies the count of required flash pages.
\item [BOOTSZ.dat] hold a number between 0 and 3 for selection of the  BOOTSZ0 and BOOTSZ1 bits.
\item [BL\_StartAdr.dat] hold the start address of the boot-loaders with hexadecimal format.
The start address is computed with the flash size of the selected target processor and
the count of required page or tile size.
\item [EFUSE.dat] hold the value for the efuse in hexadecimal format.
The Makefile determine depending of the target processor type,
if this file is used or not.
\item [HFUSE.dat] hold the value for the hfuse in hexadecimal format.
The Makefile determine depending of the target processor type,
if this file is used or not.
\end{description}

\section{target selection for the optiboot Makefile}

The control of steps for generating the program data from
the source code is defined in the Makefile.
Except the main Makefile there are three additional extension Makefiles,
which are included by the main Makefile:
Makefile.1284, Makefile.atmel, and Makefile.extras .
There can exist different configurations for the same processor type.
The table~\ref{tab:processors} shows different basic configuration
for several target processors.
In principle this list can be extended.
You can select some parameters also with the make call or by setting
a environment variable  of the shell.

\begin{table}[H]
  \begin{center}
    \begin{tabular}{| c | c | c | c | c | c | c | c | c |}
    \hline
             Name  & MCU & AVR\_ & total & Flash & BP\_ & LFUSE & HFUSE & EFUSE  \\
                   &     & FREQ  & Flash & page  & LEN  &       &       &        \\
                   &     &       &  size & size  &      &       &       &        \\
    \hline
    \hline
         attiny84 & t84   & 16M? &  8K   &  64   & (64) &  62   &  DF   & FE \\
    \hline
         atmega8  & m8    & 16M  &  8K   &  64   & 256  &  BF   &  CC   &  - \\
    \hline
         atmega88 & m88   & 16M  &  8K   &  64   & 256  &  FF   &  DD   &  04 \\
    \hline
       atmega16   & m16   & 16M  &  16K  & 128   & 256  &  FF   &  9C   &  - \\
    \hline
       atmega168  &  m168  & 16M  &  16K & 128   & 256  &  FC   &  DD   &  04 \\
       atmega168p &  m168p & 16M  &  16K & 128   & 256  &  FC   &  DD   &  04 \\
    \hline
       atmega32   &  m32   & 16M  &  16K & 128   & 256  &  BF   &  CE   &  - \\
    \hline
       atmega328  &  m328  & 16M  &  32K & 128   & 512  &  FF   &  DE   &  05 \\
       atmega328p & m328p & 16M  &  32K  & 128   & 512  &  FF   &  DE   &  05 \\
    \hline
       atmega644p & m644p & 16M  &  64K  & 256   & 512  &  F7   &  DE   &  05 \\
    \hline
     atmega1284  & m1284  & 16M  & 128K  & 256   & 512  &  F7   &  DE   &  05 \\
     atmega1284p & m1284p & 16M  & 128K  & 256   & 512  &  F7   &  DE   &  05 \\
    \hline
     atmega1280  & m1280  & 16M  &  128K & 256   & 1K   &  FF   &  DE   &  05 \\
    \hline
    \end{tabular}
  \end{center}
  \caption{Processor targets for optiboot Makefile}
  \label{tab:processors}
\end{table}

All size values are shown in byte units, the values for fuses are shown with hexadecimal values.
The frequency values must be specified in Hz units, 16M is the same as 16000000 Hz.
The standard baud rate of the serial interface is always 115200.

Additional to the universal processor configurations you can also select
configurations for special boards or operational environment.
The table~\ref{tab:boards} shows the different adjustments.

\begin{table}[H]
  \begin{center}
    \begin{tabular}{| c | c | c | c | c | c | c | c | c | c | }
    \hline
             Name  & MCU & AVR\_ & BP\_ & L     & H     & E     & BAUD\_ & LED & SOFT\_ \\
                   &     & FREQ  & LEN  &  FUSE & FUSE  &  FUSE & RATE &     & UART \\
    \hline
    \hline
       luminet     & t84 &  1M   & 64v &  F7   &  DD   &  04   & 9600 & 0x  &  -   \\

    \hline
         virboot8  & m8    & 16M & 64v &       &       &       &      &     &      \\
    \hline
       diecimila  &  m168 & (16M) &     &  F7   &  DD   &  04   &      & 3x  &  -   \\
       lilypad    &  m168  & 8M  &      &  E2   &  DD   &  04   &  -   & 3x  &  -   \\
       pro8       &  m168  & 16M &      &  F7   &  C6   &  04   &  -   & 3x  &  -   \\
       pro16      &  m168  & 16M &      &  F7   &  DD   &  04   &  -   & 3x  &  -   \\
       pro20      &  m168  & 16M &      &  F7   &  DC   &  04   &  -   & 3x  &  -   \\
    atmega168p\_lp&  m168  & 16M &      &  FF   &  DD   &  04   &  -   &     &  -   \\
   xplained168pb  &  m168  &(16M)&      &       &       &      & 57600 &     &      \\
    \hline
       virboot328  & m328p & 16M & 128v &       &       &       &      &     &  -   \\
    atmega328\_pro8& m328p & 8M  &      &  FF   &  DE   &  05   &  -   & 3x  &  -   \\
   xplained328pb  &  m168  &(16M)&      &       &       &      & 57600 &     &      \\
   xplained328p   &  m168  &(16M)&      &       &       &      & 57600 &     &      \\
    \hline
        wildfire  & m1284p & 16M &      &       &       &      &   -   & 3xB5 &      \\
    \hline
       mega1280    & m1280 & 16M &      &  FF   &  DE   &  05   &  -   &     &  -   \\
    \hline
    \end{tabular}
  \end{center}
  \caption{configured targets for the optiboot Makefile}
  \label{tab:boards}
\end{table}

\section{The Options for the optiboot Makefile}

With the options you can select the feature of the optiboot boot-loader.
For example you can select with the option SOFT\_UART, that a software solution
is used for the serial communication.
Without this option a integrated hardware UART is used for serial communication.
The pin TX (Transmit) is used for serial output and the pin RX (Receive) is used
for serial input. If more than one UART is present at the target processor,
the first interface with the number 0 is used.
But you can also select every other present UART by specify the number with
the option UART (UART=1 for the second present UART).
For the hardware UART interfaces the pins for transmit and receive are fixed
to the specific pins. For the serial communication with software you can
select any pins, which are able to do digital input and output.
More details for the available options you can find in the tables~\ref{tab:options1}
and \ref{tab:options2}

\begin{table}[H]
  \begin{center}
    \begin{tabular}{| c | c | l |}
    \hline
   Name of        & Example         & Function                                            \\
   the Option         &                &                                                     \\
    \hline
    \hline
    F\_CPU         & F\_CPU=8000000 & Tell the program the clock frequency of the processor. \\
                   &                & The value is specified in Hz units (cycles per second). \\
                   &                & The example specifies a frequency of 8 MHz. \\
    \hline
    BAUD\_RATE     & BAUD\_         & Specifies the baud-rate for the serial communication. \\
                   &  RATE=9600     & Always 8 data bits without parity is used. \\
    \hline
    SOFT\_UART     & SOFT\_UART=1   & Select a software solution for the serial communication. \\
    \hline
    UART\_RX        & UART\_RX=D0   & Specifies the port and bit number used for the serial input. \\
                   &                & The example select bit 0 of PIND as serial input. \\
                   &                & You can use this option only with the software UART. \\
    \hline
    UART\_TX        & UART\_TX=D1   & Specifies the port and bit number used for the serial output. \\
                   &                & The example select bit 1 of PORTD as serial output. \\
                   &                & You can use this option only with the software UART. \\
    \hline
    UART           & UART=1         & Select a hardware UART used for the serial communication \\
                   &                & You can only select a UART if more than one is present. \\
                   &                & This option can not be used with the SOFT\_UART Option. \\
    \hline
 LED\_START\_      & LED\_START\_   & Select a repetition count of flashing cycles for the \\
   FLASHES         &   FLASHES=3    & control LED.                            \\
    \hline
 LED               & LED=B3         & Select a port and bit number for the control LED. \\
                   &                & The example would select the bit number 3 of the \\
                   &                & port B for the LED connection. With the option \\
                   &                & LED\_START\_FLASHES  this LED will flash the \\
                   &                & specified count before the communication start. \\
                   &                & With the option LED\_DATA\_FLASH the LED will glow \\
                   &                & during wait for serial input. \\
    \hline
 LED\_DATA\_       & LED\_DATA\_    & The control LED will glow during waiting for \\
      FLASH        &    FLASH=1     & serial input data. \\
    \hline
    \end{tabular}
  \end{center}
  \caption{Important options for the optiboot Makefile}
  \label{tab:options1}
\end{table}

More options are listed in table~\ref{tab:options2} . 
Some of these options are only interesting for software checks and
for processors without the boot-loader support.

\begin{table}[H]
  \begin{center}
    \begin{tabular}{| c | c | l |}
    \hline
   Name of        & Example        & Function                                            \\
   the Option     &                &                                                     \\
    \hline
    \hline
    SUPPORT\_      & SUPPORT\_      & Select the EEprom read and write function for the  \\
    EEPROM         &  EEPROM=1      & boot-loader. If the assembly language is selected as \\
                   &                & source, the EEprom support is enabled without  \\
                   &                & this option, but can be switched off by setting \\
                   &                & the SUPPORT\_EEPROM Option to 0. \\
                   &                & For the C-source the function must be switched \\
                   &                & on (default = off). \\
    \hline
 C\_SOURCE         & C\_SOURCE=1    & Select the C language as source instead of the  \\
                   &                & assembly language (option 0 = assembly).\\
                   &                & The assembly version requires less program space. \\
    \hline
 BIGBOOT           & BIGBOOT=512    & Select additional space usage for the compiled \\
                   &                & program. This is used only for tests of the \\
                   &                & automatic adaption to the program size. \\
    \hline
VIRTUAL\_          & VIRTUAL\_       & Changes the interrupt vector table of a user program, \\
 BOOT\_            & BOOT\_          & that the boot-loader is called with a Reset. \\
 PARTITION         & PARTITION       & For the start of the user program another \\
		   &                 & interrupt vector is used.          \\
    \hline
 save\_vect\_      & save\_vect\_    & Choose a interrupt vector number for the  \\
      num          &    num=4        & VIRTUAL\_BOOT\_PARTITION method.        \\
    \hline
    \end{tabular}
  \end{center}
  \caption{More options for the optiboot Makefile}
  \label{tab:options2}
\end{table}

\section{Usage of optiboot without a boot-loader area}

For processors without a special boot-loader area in the flash memory, for example the ATtiny84,
a solution is selectable to use the optiboot anyway.
This function can be selected with the VIRTUAL\_BOOT\_PARTITION option.
To start the boot-loader first with every Reset of the processor, the interrupt
vector table of the application program is changed.
At the reset vector location a jump to the optiboot program is registered.
The original start address of the application program will be moved to
another interrupt vector the ''replacement reset vector''.
This interrupt vector should not be used by the application program.
If the boot-loader does not receive any data from the serial interface within
a appropriate time, the boot-loader jump to the location of the replacement
reset vector and start the application program.
The figure~\ref{fig:VectorMove} should illustrate these changes.

\begin{figure}[H]
\centering
\includegraphics[]{../FIG/VectorMove.eps}
\caption{Changes of program data by optiboot}
\label{fig:VectorMove}
\end{figure}

At the left side the content of the program data file (.hex) is shown.
Just to the right the content of the flash memory is shown, as it is modified by the
optiboot boot-loader. At two interrupt vector addresses the content is changed.
At the reset vector address 0 the jump is modified to select the optiboot start address 
as jump target.
At the ''replacement vector address'' 4 the original jump target address of the application
program's reset vector is used as new jump target address of this vector.
One of the problems with this modification is, that usually the program data
is verified by the host after write is finished.
To provide any error message by verify the program data, the optiboot return the
program data without its own modification, not the real content of the interrupt vector table.
The jump target address of the reset vector can be reconstructed with the content
of the replacement vector address.
But the original content of the replacement vector would be lost because there is no
place to save the original content in the flash memory.
Therefore optiboot use the last two places of the EEprom memory to save this original
content of the replacement vector. 
So the verify of the program data is possible without errors, as long as the application
program do not use one of the last two EEprom locations.
Even if the application program use one of the last two EEprom locations,
the boot-loader will be unaffected. Only the program verify by the host is
no longer possible without a error message.
An error message will occur at the location of the replacement interrupt vector.

For processors with more than 8 kByte flash memory two instruction words are used for every
interrupt vector. Normally every of this double words hold one JMP instruction with the
proper jump target address. The optiboot program can respect these JMP vector table too.
But if you use the linker avr-ld with the option --relax, all JMP instructions are replaced
by a RJMP, if this is possible for the target address.
This replacement of JMP instruction in the vector table by RJMP is not respected
by the optiboot program.
The optiboot program assume, that all interrupt vector numbers of a processor with
more than 8 kByte flash hold a JMP instruction.
For that reason a optiboot program with the VIRTUAL\_BOOT\_Partition option will not
work with a application program, which is linked with the --relax option.
The same problem exist, if the application program itself use a RJMP instruction in
one of the two critical interrupt vector positions.

Further you should notice, that you don't activate the BOOTRST fuse together with
with the usage of the VIRTUAL\_BOOT\_PARTITION option.
The reason is, that the start address of the boot-loader can be located to other
addresses with the VIRTUAL\_BOOT\_PARTITION option than without this option.
With the VIRTUAL\_BOOT\_PARTITION the start address can be placed to every
begin of a flash page. For the normal boot-loader support of the AVR the
start address can only respect the single, double, quadruple or octuple size of
a minimum boot-loader size as shown in figure~\ref{fig:pages} at page~\pageref{fig:pages}.
