Skip to content
kubi48 edited this page Feb 9, 2021 · 5 revisions

Welcome to the avr-assembler-optiboot wiki!

Introduction

The optiboot bootloader was developed with C language by Peter Knight and Bill Westfield. Version 6.2 was used as the basis for the revised assembler version described here. The optiboot bootloader was not completely redeveloped, but merely optimized and further developed. Parts of the STK500 communication protocol published in the AVR061 documentation by Atmel are used. The complete program was rewritten in the AVR assembly language and the generation of the .hex file was moved to a bash shell script. The program length is automatically processed further and the start address of the bootloader and the fuses of the ATmega are set accordingly. The aim for this step was mainly to get a bootloader that fits into 512 byte flash memory even if the ability to write to EEprom is integrated. A complete description of the investigations and the used methods can be found in German in the subdirectory Documentation/german and in English in the directory Documentation/english with the file name bootloader.pdf

Properties of the assembler version of optiboot

In order to avoid many pitfalls when creating an executable boot loader, the creation of the boot loader file has been largely automated. In addition, settings are also checked and generation is aborted with a corresponding error message if, for example, the selected operating frequency (AVR_FREQ) does not match the options for the clock set with the fuses (CKSEL, CKDIV8). Receipt of program data for optiboot is currently only possible via a serial interface.

Here are some of the capabilities of the optiboot program

  • Supports a large number of AVRs, almost all have been tested for function.
  • Supports loading data into the EEprom memory.
  • In most cases it fits in 512 bytes of flash memory.
  • The program size is adapted and the necessary fuses are changed automatically.
  • The start address, which depends on the program size and the AVR model, is calculated automatically and displayed on the screen.
  • Can emulate the serial interface via software. This means that ATtiny processors without UART are also supported. In addition, the TX and RX pins for SOFT_UART can be freely selected. You can select all serial interfaces available with the respective AVR processor. The first UART is always used as standard.
  • With the SOFT_UART solution, serial communication can also be done via just one AVR pin.
  • Can adjust the baud rate automatically. The baud time is measured from the first received data byte. Different methods of baud time measurement can be selected. If the optiboot configured in this way should still fit in 512 byte flash, the LED flash function must be deselected at the program start.
  • Can also be used for AVRs without bootloader support. This VIRTUAL_BOOT_PARTITION capability can of course also be used for AVRs that have bootloader support. The optiboot program becomes larger, but can then start on any flash memory page.
  • Makes a connected LED flash three times by default (LED_START_FLASHES=3). If serial data arrives, however, the flashing is normaly stopped immediately.
  • Instead of the LED flashing at start-up, you can also let the LED light up when waiting for serial data (LED_DATA_FLASH=1). Continuous lighting of the LED can also be selected with LED_DATA_FLASH=4. The LED only goes out after the watchdog reset.
  • The length of the generated program only depends on the selected AVR processor and the selected options. The version of the avr-gcc compiler does not matter if the assembler sources are used. This makes a subsequent check (verification) of the installed bootloader easier, even with a different PC.
  • Supports the adjustment of the oscillator frequency for the AVR internal RC oscillator. This enables the use of a bootloader with a fixed baud rate even in problem cases.
  • The loading of the optiboot program into the respective AVR processor can be done automatically with the avrdude program and a connected ISP programmer. All you need to do is enter ISP=1 when you call make. The alternative entry ISP=2 would cause a verification with avrdude. With ISP=3, the entire program memory (Flash) of the connected AVR is read out and with ISP=4, the entire EEprom memory of the connected AVR is read out.

The following capabilities apply only to the bootloader manufacturing process:

  • Customized C sources can also be used to generate the optiboot bootloader. Most functions are also possible here. Of course the generated optiboot program will be bigger!
  • The scope of the screen output when generating optiboot can be changed with the VerboseLev system variable. The value can be between 1 and 4, with 2 as default.
  • The screen output can be made more colorful with the WITH_COLORS=1 system variable. With WITH_COLORS=2, pure text is output.
  • The generation of the optiboot program is controlled in a bash script file, whereby the text file avr_params.def provides the necessary data for all supported AVR processors. This avr_params.def file also defines standard values for the fuses, operating frequency and baud rate for each supported processor.
  • The script file can find pin assignments available for the respective processors in the avr_pins directory in a suitable file. If necessary, standard values for the pins used by SOFT_UART and for the LED are also found here.
  • The generation of the optiboot program runs under Linux with installed avr packages. Generation under Windows 10 is possible if, in addition to the Arduino package, program packages are installed that provide the programs required for generation such as bash, bc, echo and others. I checked the Cygwin64 package on a Windows10 laptop with a previously installed Arduino package.
  • The selected parameters with program creation are recorded both at the end of an .lst file and in a .log file.

Options for the optiboot Makefile

The optiboot hex file is generated via a make call, which specifies the desired target processor or one of the supported boards as a parameter. Various options for the generation can also be specified, which are listed here:

  • F_CPU: Informs the program about the clock rate of the processor. The specification is made in Hz (waves per second). The example F_CPU=8000000 specifies a frequency of 8 MHz.
  • BAUD_RATE: Specifies the baud rate for serial communication. 8 data bits without parity are always used. Values <100 activate a measurement and adaptation of the baud rate with different methods. The advantage of the automatic adjustment is that you can easily switch to a lower baud rate if you get problems with a high baud rate.
  • SOFT_UART: Selects a software solution for serial communication.
  • UART_RX : Specifies the port and the bit number for the serial receive data. The example UART_RX=D0 takes bit 0 of the D port for the serial input.
  • UART_TX: Specifies the port and the bit number for the serial send data. The example UART_TX=D1 takes bit 1 of the D port for the serial output.
  • UART: Selects a serial interface number of the chip for communication. A selection presupposes the presence of several hardware interfaces, but works also with SOFT_UART.
  • INVERSE_UART: Inverts the levels of RX and TX signals. The option can only be used with software UART.
  • LED_START_FLASHES: Selects the number of flashing cycles for the control LED. With 1 or -1 the flashing is only once without repetition. Negative specifications mean that the RX bit of the serial interface is not monitored in the program loop. If the values are positive, the blink loop is terminated immediately after the detection of incoming RX data. Please note that flashing delays the start of the user program.
  • LED: Selects the port bit for the control LED. In the example LED=B3, an LED connected to bit 3 of port B would flash.
  • LED_DATA_FLASH: The control LED lights up while waiting for receive data from the serial communication if the value is set to 1. A value of 4 means that the LED is only switched on once at start-up. This mode also shows you, that the bootloader has been started with the effort, that much less space is required in the program memory.
  • LFUSE: Specifies a desired value for the low fuse of the AVR. Only two hex characters are allowed.
  • HFUSE: Indicates a desired value for the high fuse of the AVR. Only two hex characters are allowed.
  • EFUSE: Specifies a desired value for the extended fuse of the AVR. Only two hex characters are allowed.

Further options are usually only of interest for software examinations, frequency calibration of the RC generator and for processors without a bootloader area.

  • TIMEOUT_MS: This option specifies a time limit in milliseconds for the receipt of boot data. After this time, the boot process is aborted and an attempt is made to start the user program. Possible values for TIMEOUT_MS are 500, 1000, 2000, 4000 and 8000. The actual possible value can be limited to 2 seconds depending on the processor. If no TIMEOUT_MS is specified, the time limit is set to 1 second.
  • SUPPORT_EEPROM: Selects the read and write function for EEproms for the bootloader program. If the assembler program was selected as the source, the EEprom support is switched on without the option set, but can be switched off if the SUPPORT_EEPROM option is set to 0.
  • C_SOURCE : Selects the C program as the program source instead of the assembler program (0 = assembler). The assembler version requires less memory and supports all functions. The SUPPORT_EEPROM function must be switched on separately for the C source (standard = off).
  • BIGBOOT: Selects additional memory usage for the bootloader program. This is only used to test the automatic adjustment to the program size in the bash script.
  • VIRTUAL_BOOT_PARTITION: Changes the program data of a user program so that the boot loader is addressed on reset. Another interrupt vector is used to start the user program.
  • save_vect_num: Selects an interrupt vector number for the VIRTUAL_BOOT_PARTITION method.
  • OSCCAL_CORR: With the OSCCAL_CORR option, the internal RC generator of the AVR can be adjusted. Is ineffective with quartz operation or external clock! The correction value is subtracted from the preset OSCCAL byte. If the correction value is positive, the frequency will normally be lower. Since the baud rate generated depends directly on the processor clock, a correctly set processor clock is important for successful serial communication. Usually a value between -20 and +20 should be sufficient.
  • NO_EARLY_PAGE_ERASE: Prevents the deletion of the flash page before the data has been received via the serial interface. Since the deletion otherwise runs parallel to the data reception, programming the flash with this option is around 30% slower. Since the data comparison (verify) that is normally carried out takes about the same amount of time, the loss of time is not so significant. On the other hand, the optiboot bootloader saves around 14 bytes of space on the bootloader side, which in practice can mean halving the space requirement due to the AVR technology.

Quick start Guide

First you have to change the working directory to the optiboot directory (Change Directory - cd). Here you can display the options with make or with make help. You can get a list of the supported AVR processors with make pl. To create an optiboot hex file, you must specify one of the supported processors as a parameter when you call make. A make atmega328p creates a bootloader file with the name optiboot_atmega328p.hex. In addition, the files optiboot_atmega328p.lst and optiboot_atmega328p.log are also generated. The selected options are recorded in the .log file, the .lst is generated by disassembling the .elf file. When the .hex file is generated, information is displayed on the screen that should be particularly taken into account when selecting options.

The avrdude program is used to transfer the bootloader to the AVR target processor if the ISP=1 option is also specified. Depending on the connected ISP programmer, the port for avrdude (ISPPORT) must also be set. Newer programmers often use a serial interface attached to a USB device. These serial interfaces have the name /dev/ttyUSBx or /dev/ttyACMx under Linux. In Windows, serial interfaces have a COMx name. The x stands for a number assigned by the system. For a connected Diamex ISP-PRog-NG (AVR-ISP2) this would be e.g. /dev/ttyACM0 on Linux, so that a complete call to install the boot loader could be make atmega328p ISP=1 ISPPORT=/dev/ttyACM0. The default ISPPORT is usb, which would be suitable for a Diamex ALL-AVR ISP programmer (ERFOS AVRISP MkII Clone). For this type of programmer, the command make atmega328p ISP=1 without specifying a port would be sufficient.

Hints for building Optiboot

It makes sense to start with a standard setting for one of the AVR processors and check the screen output to see whether the presets are correct. For example, make atmega8 creates a bootloader for the ATmega8 microcontroller. From the screen output you can see that the bootloader has been configured for 16 MHz operation with a baud rate of 115200 of the serial interface. The pins used for the serial communication (RX and TX) are listed as well as the pin used for a control LED (PB5). With additional options in the make line you can change the settings and check the screen log again with this setting. You can also keep an eye on the size of the generated bootloader. If a suitable configuration has been found, the optiboot can be installed with the additional parameter ISP=1, when a correctly connected ISP programmer and the avrdude program is present.

First example with ATmega8 without quartz

If the ATmega8 is to be operated without a crystal, the standard setting of the low fuse must be changed, e.g. to LFUSE=E4 for the internal RC clock generator. But then both the preset clock rate and the baud rate no longer fit. So the correct call for generating the appropriate bootloader should then be make atmega8 LFUSE=E4 F_CPU=8000000 BAUD_RATE=57600. This bootloader should now also run without quartz operation. A prerequisite, however, is that the operating frequency of 8 MHz is maintained relatively precisely. If this is not the case, there are now two ways to solve the problem.

  • The first option uses the ability of the AVR processors to tune the RC oscillator. This can be used with the OSCCAL_CORR option for the Optiboot generation. However, this requires a way of checking the working frequency, such as a frequency counter or an oscilloscope. However, since this processor has no way of feeding out the clock frequency on an output pin, a test program would have to be written to check the frequency. The optiboot boot loader also has an option, TEST_OUTPUT, which is not documented any further. The boot loader with this option does nothing other than continuously output the same character U on the serial output pin. This would allow the oscillator frequency to be calibrated, but this is very laborious and of course has to be repeated for each copy of the ATmega8.
  • The second option uses a completely different feature of the optiboot, the automatic baud rate adjustment. The transmission time of the serial bits of the first received character is measured here and the appropriate baud rate is set. We can try this out next with make atmega8 LFUSE=E4 F_CPU=8000000 BAUD_RATE=32. Here the screen output tells us that a baud rate between 244 and 80k is possible. But unfortunately the program now needs 518 bytes and that would take up 1024 bytes of flash memory. The bootloader would run, but only 6 bytes have to be saved to get by with half the memory. With the BAUD_RATE=22 for measuring only 2 bits instead of 4 bits, you would only save 4 bytes and that would be the most economical variant of baud rate measurement. There are three other ways to save space. You could do without the ability to write to the EEprom (SUPPORT_EEPROM=0), you could do without the LED flashing at the start (LED_START_FLASHES=0) or you could do without the deletion of the flash memory page before data reception (NO_EARLY_PAGE_ERASE=1). All three possibilities lead to success, but also cost functionality. Another possible compromise would be to only blink once (LED_START_FLASHES=1) or to forego monitoring of the serial input when blinking (LED_START_FLASHES=-3). You can also completely deselect flashing (LED_START_FLASHES=0) and use the LED_DATA_FLASH function instead. Whatever you choose, the 6 bytes can easily be saved without losing much of functionality. The effort is manageable and you need no more memory with careful configuration.

Second example ATtiny84 with RC oscillator, autobaud and one-pin serial interface

Since standard operation is provided with quartz, we must first start the RC oscillator operation with a specification for the low fuse such as make attiny84 LFUSE=E2 F_CPU=8000000 BAUD_RATE=32. Here we learn from the screen log that 10 flash memory pages are used for the bootloader. There is no special boot area for this processor. Therefore the option VIRTUAL_BOOT_PARTITION does not need to be specified here. The software uses pins A3 and A4 for the serial interface. A UART is also not available with the ATtiny84. We only wanted to use one pin for serial communication. This is easily possible by naming the same pin for TX and RX. So the call must be make attiny84 LFUSE=E2 F_CPU=8000000 BAUD_RATE=32 UART_RX=A4 UART_TX=A4. If you don't want to have a flashing control LED, you can deselect it with LED_START_FLASHES=0. However, fewer memory pages are not used. For the operation of the serial interface with only one pin, an additional circuit must be used to ensure that the echoes of the transmission signal TXD of the PC to the reception signal RXD of the PC are suppressed. The STK500 protocol used by avrdude works in half-duplex mode. As a rule, it only sends one page at a time.

Please read the extra Wiki for a suitable special electronics to prevent local echos.

Examples of bootloader generation

The first example uses software for serial communication.

make atmega328p SOFT_UART=1

Optiboot for 16000000 Hz (16.00 Mhz) operation with Baudrate 115200 and EEprom support configured.
 >>> Start building optiboot for AVR atmega328p:
LED-Pin PB5 use Pin 19-PDIP28 17-TQFP32, with special functions: SCK PCINT5.
RX-Pin PD0 use Pin 2-PDIP28 30-TQFP32, with special functions: PCINT16 RXD.
TX-Pin PD1 use Pin 3-PDIP28 31-TQFP32, with special functions: PCINT17 TXD.`
avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=atmega328p  -fno-diagnostics-show-caret 
-DBAUD_RATE=115200 -DLED_START_FLASHES=3 -DSUPPORT_EEPROM=1 -DLED=pB5 -DUART=00 -DSOFT_UART=01 
-DUART_RX=pD0 -DUART_TX=pD1 -DF_CPU=16000000 -DHFUSE=hexDE -DLFUSE=hexFF -DBOOT_PAGE_LEN=512 
-DVerboseLev=2 -c -o optiboot.o optiboot.S


--------------------------------------------------------------------------------
BAUD RATE CHECK: Desired: 115200,  SoftUART_Real: 115107, Delay: 116*1, Difference=-.07%
--------------------------------------------------------------------------------
# # # # # # # # # # # # # # # # # # # # # #
Boot Loader start address: 0x7E00 = 32256
# # # # # # # # # # # # # # # # # # # # # #

  text	   data	    bss	    dec	    hex	filename
   504	      0	      0	    504	    1f8	optiboot.elf
Requires 1 Boot Page of 512 Bytes, which is 1.5% of Flash Memory
BOOTSZ=3, which means 1 Boot Page

The second example uses the automatic baud rate adjustment

make atmega328p BAUD_RATE=52 LED_START_FLASHES=0

Optiboot for 16000000 Hz (16.00 Mhz) operation with Auto-Baudrate and EEprom support configured.
 >>> Start building optiboot for AVR atmega328p:
RX-Pin PD0 use Pin 2-PDIP28 30-TQFP32, with special functions: PCINT16 RXD.
TX-Pin PD1 use Pin 3-PDIP28 31-TQFP32, with special functions: PCINT17 TXD.
avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=atmega328p  -fno-diagnostics-show-caret 
-DBAUD_RATE=52 -DLED_START_FLASHES=0 -DSUPPORT_EEPROM=1 -DLED=p -DUART=00 -DSOFT_UART=0 
-DUART_RX=pD0 -DUART_TX=pD1 -DF_CPU=16000000 -DHFUSE=hexDE -DLFUSE=hexFF -DBOOT_PAGE_LEN=512 
-DVerboseLev=2 -c -o optiboot.o optiboot.S`

--------------------------------------------------------------------------------
Simple Baudrate measurement with time limit implemented in optiboot! (4-bit, Clk/8)
UART Minimum 488 Baud, Difference surely less than 4% up to 160.0 kBaud
--------------------------------------------------------------------------------
# # # # # # # # # # # # # # # # # # # # # #
Boot Loader start address: 0x7E00 = 32256
# # # # # # # # # # # # # # # # # # # # # #

   text	   data	    bss	    dec	    hex	filename
    500	      0	      0	    500	    1f4	optiboot.elf
Requires 1 Boot Page of 512 Bytes, which is 1.5% of Flash Memory
BOOTSZ=3, which means 1 Boot Page

The third example uses the automatic baud rate adjustment with software UART

make atmega328p BAUD_RATE=52 LED_START_FLASHES=0 SOFT_UART=1 NO_EARLY_PAGE_ERASE=1

Optiboot for 16000000 Hz (16.00 Mhz) operation with Auto-Baudrate and EEprom support configured.
 >>> Start building optiboot for AVR atmega328p:
RX-Pin PD0 use Pin 2-PDIP28 30-TQFP32, with special functions: PCINT16 RXD.
TX-Pin PD1 use Pin 3-PDIP28 31-TQFP32, with special functions: PCINT17 TXD.
avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=atmega328p  -fno-diagnostics-show-caret 
-DBAUD_RATE=52 -DLED_START_FLASHES=0 -DSUPPORT_EEPROM=1 -DNO_EARLY_PAGE_ERASE=1 -DLED=p -DUART=00 
-DSOFT_UART=01 -DUART_RX=pD0 -DUART_TX=pD1 -DF_CPU=16000000 -DHFUSE=hexDE -DLFUSE=hexFF 
-DBOOT_PAGE_LEN=512 -DVerboseLev=2 -c -o optiboot.o optiboot.S

--------------------------------------------------------------------------------
Simple Baudrate measurement with time limit implemented in optiboot! (4-bit, Clk/8)
SoftUART Minimum 10302 Baud, Difference surely less than 4% up to 163.2 kBaud, Fast 8-Bit loop with N*6 cycles
--------------------------------------------------------------------------------
# # # # # # # # # # # # # # # # # # # # # #
Boot Loader start address: 0x7E00 = 32256
# # # # # # # # # # # # # # # # # # # # # #
 
   text	   data	    bss	    dec	    hex	filename
    506	      0	      0	    506	    1fa	optiboot.elf
Requires 1 Boot Page of 512 Bytes, which is 1.5% of Flash Memory
BOOTSZ=3, which means 1 Boot Page

Here the option NO_EARLY_PAGE_ERASE was used to save flash memory. Without this option the result would be:

make atmega328p BAUD_RATE=52 LED_START_FLASHES=0 SOFT_UART=1

Optiboot for 16000000 Hz (16.00 Mhz) operation with Auto-Baudrate and EEprom support configured.
 >>> Start building optiboot for AVR atmega328p:
RX-Pin PD0 use Pin 2-PDIP28 30-TQFP32, with special functions: PCINT16 RXD.
TX-Pin PD1 use Pin 3-PDIP28 31-TQFP32, with special functions: PCINT17 TXD.
avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=atmega328p  -fno-diagnostics-show-caret 
-DBAUD_RATE=52 -DLED_START_FLASHES=0 -DSUPPORT_EEPROM=1 -DLED=p -DUART=00 -DSOFT_UART=01 
-DUART_RX=pD0 -DUART_TX=pD1 -DF_CPU=16000000 -DHFUSE=hexDE -DLFUSE=hexFF -DBOOT_PAGE_LEN=512 
-DVerboseLev=2 -c -o optiboot.o optiboot.S

--------------------------------------------------------------------------------
Simple Baudrate measurement with time limit implemented in optiboot! (4-bit, Clk/8)
SoftUART Minimum 10302 Baud, Difference surely less than 4% up to 163.2 kBaud, Fast 8-Bit loop with N*6 cycles
--------------------------------------------------------------------------------
# # # # # # # # # # # # # # # # # # # # # #
Boot Loader start address: 0x7C00 = 31744
# # # # # # # # # # # # # # # # # # # # # #
 
   text	   data	    bss	    dec	    hex	filename
    522	      0	      0	    522	    20a	optiboot.elf
Requires 2 Boot Pages, 512 Bytes each, which is 3.1% of Flash Memory
BOOTSZ=2, which means 2 Boot Pages

The fourth example creates a bootloader for an ATtiny84

make attiny84

Optiboot for 8000000 Hz (8.00 Mhz) operation with Baudrate 57600 and EEprom support configured.
 >>> Start building optiboot for AVR attiny84:
LED-Pin PA4 use Pin 9-PDIP14 1-QFN20, with special functions: PCINT4 T1 SCL USCK ADC4.
RX-Pin PA3 use Pin 10-PDIP14 2-QFN20, with special functions: PCINT3 T0 ADC3.
TX-Pin PA4 use Pin 9-PDIP14 1-QFN20, with special functions: PCINT4 T1 SCL USCK ADC4.
avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=attiny84  -fno-diagnostics-show-caret 
-DBAUD_RATE=57600 DLED_START_FLASHES=3 -DSUPPORT_EEPROM=1 -DVIRTUAL_BOOT_PARTITION=1  
-DLED=pA4 -DUART=00 -DSOFT_UART=01 -DUART_RX=pA3 DUART_TX=pA4 -DF_CPU=8000000 -DHFUSE=hexDD 
-DLFUSE=hexFF -DBOOT_PAGE_LEN=64 -DVerboseLev=2 -c -o optiboot.o optiboot.S

--------------------------------------------------------------------------------
BAUD RATE CHECK: Desired: 57600,  SoftUART_Real: 57553, Delay: 116*1, Difference=-.07%
--------------------------------------------------------------------------------
# # # # # # # # # # # # # # # # # # # # # #
Boot Loader start address: 0x1D80 = 7552
# # # # # # # # # # # # # # # # # # # # # #

   text	   data	    bss	    dec	    hex	filename
    578	      0	      0	    578	    242	optiboot.elf
Requires 10 Flash Pages, 64 Bytes each, which is 7.8% of Flash Memory 
No Boot Pages present!

Two examples of an incorrect LFUSE setting

In the first example, the operating frequency 16 MHz does not match the selected RC oscillator mode. A call like make atmega328p LFUSE=E2 F_CPU=8000000 BAUD_RATE=38400 would be correct. However, it should be shown here that an attempt is made to avoid errors when creating the bootloader.

make atmega328p LFUSE=E2

Optiboot for 16000000 Hz (16.00 Mhz) operation with Baudrate 115200 and EEprom support configured.`
 >>> Start building optiboot for AVR atmega328p:`
LED-Pin PB5 use Pin 19-PDIP28 17-TQFP32, with special functions: SCK PCINT5.`
RX-Pin PD0 use Pin 2-PDIP28 30-TQFP32, with special functions: PCINT16 RXD.`
TX-Pin PD1 use Pin 3-PDIP28 31-TQFP32, with special functions: PCINT17 TXD.`
avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=atmega328p  -fno-diagnostics-show-caret 
-DBAUD_RATE=115200 -DLED_START_FLASHES=3 -DSUPPORT_EEPROM=1 -DLED=pB5 -DUART=00 -DSOFT_UART=0 
-DUART_RX=pD0 -DUART_TX=pD1 -DF_CPU=16000000 -DHFUSE=hexDE -DLFUSE=hexE2 -DBOOT_PAGE_LEN=512 
-DVerboseLev=2 -c -o optiboot.o optiboot.S`
In file included from optiboot.S:277:0:
check_fuses.h:212:5: error: #error "Int RC mode, wrong Lfuse setting for this frequency (ATmega...8)!"
Makefile:1192: recipe for target 'hex_file' failed
make: *** [hex_file] Error 1 

In the next example the operating frequency does not match the crystal operation with the /8 prescaler. A command like make atmega329p LFUSE=7F F_CPU=1000000 BAUD_RATE=9600 would be correct here. But here again to demonstrate the wrong command:

make atmega328p LFUSE=7F

Optiboot for 16000000 Hz (16.00 Mhz) operation with Baudrate 115200 and EEprom support configured.
 >>> Start building optiboot for AVR atmega328p:
LED-Pin PB5 use Pin 19-PDIP28 17-TQFP32, with special functions: SCK PCINT5.
RX-Pin PD0 use Pin 2-PDIP28 30-TQFP32, with special functions: PCINT16 RXD.
TX-Pin PD1 use Pin 3-PDIP28 31-TQFP32, with special functions: PCINT17 TXD.
avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=atmega328p  -fno-diagnostics-show-caret s
-DBAUD_RATE=115200 -DLED_START_FLASHES=3 -DSUPPORT_EEPROM=1 -DLED=pB5 -DUART=00 -DSOFT_UART=0 s
-DUART_RX=pD0 -DUART_TX=pD1 -DF_CPU=16000000 -DHFUSE=hexDE -DLFUSE=hex7F -DBOOT_PAGE_LEN=512 s
-DVerboseLev=2 -c -o optiboot.o optiboot.S
In file included from optiboot.S:277:0:
check_fuses.h:254:5: error: #error "LP Crystal mode, wrong Lfuse setting for this frequency (ATmega...8)!"
Makefile:1192: recipe for target 'hex_file' failed
make: *** [hex_file] Error 1

Bootloader for Arduino-Nano with automatic baud rate adjustment including avrdude call

make atmega328p BAUD_RATE=52 LED_START_FLASHES=0 ISP=1`

Optiboot for 16000000 Hz (16.00 Mhz) operation with Auto-Baudrate and EEprom support configured.`
 >>> Start building optiboot for AVR atmega328p:`
RX-Pin PD0 use Pin 2-PDIP28 30-TQFP32, with special functions: PCINT16 RXD.`
TX-Pin PD1 use Pin 3-PDIP28 31-TQFP32, with special functions: PCINT17 TXD.`
avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=atmega328p  -fno-diagnostics-show-caret 
-DBAUD_RATE=52 -DLED_START_FLASHES=0 -DSUPPORT_EEPROM=1 -DLED=p -DUART=00 -DSOFT_UART=0 
-DUART_RX=pD0 -DUART_TX=pD1 -DF_CPU=16000000 -DHFUSE=hexDE -DLFUSE=hexFF -DBOOT_PAGE_LEN=512 
-DVerboseLev=2 -c -o optiboot.o optiboot.S

--------------------------------------------------------------------------------
Simple Baudrate measurement with time limit implemented in optiboot! (4-bit, Clk/8)
UART Minimum 488 Baud, Difference surely less than 4% up to 160.0 kBaud
--------------------------------------------------------------------------------
# # # # # # # # # # # # # # # # # # # # # #
Boot Loader start address: 0x7E00 = 32256
# # # # # # # # # # # # # # # # # # # # # #

   text	   data	    bss	    dec	    hex	filename
    500	      0	      0	    500	    1f4	optiboot.elf
Requires 1 Boot Page of 512 Bytes, which is 1.5% of Flash Memory
BOOTSZ=3, which means 1 Boot Page

####### Start of program_target.sh for atmega328p #############
   The fuses in program_target.sh are set to lfuse=0xFF, hfuse=0xDE, efuse=0xFD
Bootloader HFUSE will be set to 0xDE, OK!
BootLoader Start is enabled to 0x7E00, 32256
##### erase the atmega328p and set fuses
avrdude  -C ./avrdude.conf -c avrisp2 -B 200 -p atmega328p -P usb -b 115200 -q -q -e -u  
 -U efuse:w:0xFD:m -U hfuse:w:0xDE:m -U lfuse:w:0xFF:m
##### write the optiboot bootloader to atmega328p and set the lock bits
avrdude  -C ./avrdude.conf -c avrisp2 -B 1.50 -p atmega328p -P usb -b 115200 -D 
 -U flash:w:optiboot_atmega328p.hex:i -U lock:w:0xef:m

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "optiboot_atmega328p.hex"
avrdude: writing flash (32768 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: 32768 bytes of flash written
avrdude: verifying flash memory against optiboot_atmega328p.hex:
avrdude: load data flash data from input file optiboot_atmega328p.hex:
avrdude: input file optiboot_atmega328p.hex contains 32768 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...`
avrdude: 32768 bytes of flash verified
avrdude: reading input file "0xef"
avrdude: writing lock (1 bytes):

Writing | ################################################## | 100% 0.01s

avrdude: 1 bytes of lock written
avrdude: verifying lock memory against 0xef:
avrdude: load data lock data from input file 0xef:
avrdude: input file 0xef contains 1 bytes
avrdude: reading on-chip lock data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of lock verified

avrdude: safemode: Fuses OK (E:FD, H:DE, L:FF)

avrdude done.  Thank you.