How To Compile Firmware for 3V3 28Pins Variant

On this page you will learn how to compile the firmware inside ATMEGA16U2, so it can use a 8 MHz clock frequency so the MCU can be supplied from 3.3 V. The ATMEGA328P can be used with a 10 MHz clock frequency to reliably run from a 3.3 V source

Content

Why recompile the boot loader?: If you read the datasheet of the ATMEGA16U2 and the ATMEGA328P from Atmel, you can find that the AVR MCU's can be operated from a source voltage of 1.8 V to 5.5 V DC. However operating the MCU from a lower source voltage limits the maximum clock frequency we can actually reliably use. In the Speed grade section of the datasheets we can find a graph of the different clock frequencies to source voltages. From there we can select a safe clock frequency of 10 MHz for the ATMEGA328P and 8 MHz for the ATMEGA16U2 for a source voltage of 3.3 v.  The Arduino boot loader is configured to use a 16 MHz clock frequency, so we must recompile the firmware to use the new clock frequencies. Below are the exact steps how to do it.

Install AVR tool chain

To compile the firmware using the make command you will need to install the AVR toolchain from Atmel:

  1. Download AVR tool chain from http://www.atmel.com/tools/atmelavrtoolchainforwindows.aspx
  2. Install the AVR tool chain (just follow the installation wizard).
  3. For windows users we need to add the binaries directory to the path variable; For more information see http://geekswithblogs.net/renso/archive/2009/10/21/how-to-set-the-windows-path-in-windows-7.aspx

Download the Arduino source code

Now we are going to obtain the source code for the Arduino boot loader firmware:

  1. Download the source code from the Arduino Git Hub.
    Alternatively: The source code can be found in the Arduino IDE program files, usually located in 'C:\Program Files (x86)\Arduino\hardware\arduino\avr'
  2. It is a good idea to copy the firmware into another folder, in case you make an error and want to get back the original source code. We will refer to this as the working directory.

Download the LUFA project

The ATMEGA16u2 firmware uses the LUFA project for the USB to serial interface. 

Important: We need to use an older version of the LUFA project (version 100807).

  1. Download the LUFA project from http://www.fourwalledcubicle.com/files/LUFA/LUFA-100807.zip
  2. Copy the files from the .zip file into your working directory.
  3. Copy the arduino source code into the LUFA projects folder, such as; "{working directory}\LUFA\Projects\28pins"

Editing the source code for the ATMEGA16u2

In this step, we will change the clock frequency of the ATMEGA16u2. There are 2 firmwares we need to edit, the USBDFU and the USBserial.

USBDFU:

  1. Open the makefile in '{working directory}\LUFA\Projects\28pins\usbdfu\' in your favourite text editor
  2. Edit the following;
     # MCU name
    MCU = atmega16u2
    MCU_AVRDUDE = atmega16u2
    MCU_DFU = atmega16u2
  3. Add the following;
    # 28 Pins PID:
    ARDUINO_MODEL_PID = 0x6051
  4. Change CPU frequency;
    F_CPU = 8000000
  5. Change bootloader address;
    BOOT_START = 0x3000

    Note: this address is specific for the ATMEGA16u2, if you are using a different AVR you will need to find the bootloader start address from the datasheet.

  6. Open descriptors.c in '{working directory}\LUFA\Projects\28pins\usbdfu\'
  7. Add the following;
    #elif (ARDUINO_MODEL_PID == FA28PINS_PID)
    .Header = {.Size = USB_STRING_LEN(21), .Type = DTYPE_String},
    
    .UnicodeString = L"28pins DFU"
    #endif
  8. Open descriptors.h in '{working directory}\LUFA\Projects\28pins\usbdfu\'
  9. Add the following;
    #define FA28PINS_PID 0x6051
  10. Open LEDS.h in '{working directory}\LUFA\Projects\28pins\usbdfu\boards'
  11. Change RX LED to pin 4;
    /** LED mask for the first LED on the board. */
     #define LEDS_LED1 (1 << 5)
    
    /** LED mask for the second LED on the board. */
     #define LEDS_LED2 (1 << 4)

USBserial

  1. Open the makefile in '{working directory}\LUFA\Projects\28pins\usbserial\'
  2. Edit the following;
     # MCU name
    MCU = atmega16u2
    MCU_AVRDUDE = atmega16u2
    MCU_DFU = atmega16u2
  3. Add the following;
    # 28 Pins PID:
    ARDUINO_MODEL_PID = 0x6051
  4. Change CPU frequency;
    F_CPU = 8000000
  5. Open descriptors.c in '{working directory}\LUFA\Projects\28pins\usbserial\'
  6. Change PID;
     .VendorID = 0x1d50, // LUFA
     .ProductID = 0x6051, // FA28PINS USB-to-serial programmer
  7. Add the following;
    const USB_Descriptor_String_t PROGMEM ManufacturerString =
     {
     #if (ARDUINO_MODEL_PID == FA28PINS_PID)
     .Header = {.Size = USB_STRING_LEN(8), .Type = DTYPE_String},
    
    .UnicodeString = L"28PINS"
     #else
     .Header = {.Size = USB_STRING_LEN(32), .Type = DTYPE_String},
    
    .UnicodeString = L"Fedevel Academy (www.28pins.com)"
     #endif
     };
  8. Also add the following;
    #elif (ARDUINO_MODEL_PID == FA28PINS_PID)
     .Header = {.Size = USB_STRING_LEN(8), .Type = DTYPE_String},
    
    .UnicodeString = L"28pins"
     #endif
  9. Open descriptors.h in '{working directory}\LUFA\Projects\28pins\usbserial\'
  10. Add the following;
    #define FA28PINS_PID 0x6051
  11. Open LEDS.h in '{working directory}\LUFA\Projects\28pins\usbserial\boards'
  12. Change RX LED to pin 4;
    /** LED mask for the first LED on the board. */
     #define LEDS_LED1 (1 << 5)
    
    /** LED mask for the second LED on the board. */
     #define LEDS_LED2 (1 << 4)
  13. We are now ready to compile the firmware for the ATMEGA16u2

Editing the source code for the ATMEGA328P

In this step, we will change the clock frequency of the ATMEGA328p.

bootloader:

  1. Open the makefile in '{working directory}\hardware\arduino\avr\bootloaders\atmega'
  2. Add the following;
    atmega328_28pins_10MHz: TARGET = atmega328_28pins_10MHz
    atmega328_28pins_10MHz: MCU_TARGET = atmega328p
    atmega328_28pins_10MHz: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600
    atmega328_28pins_10MHz: AVR_FREQ = 10000000L
    atmega328_28pins_10MHz: LDSECTION = --section-start=.text=0x7800
    atmega328_28pins_10MHz: $(PROGRAM)_atmega328_28pins_10MHz.hex
    
    atmega328_28pins_isp: atmega328_28pins
    atmega328_28pins_isp: TARGET = atmega328_28pins_10MHz
    atmega328_28pins_isp: MCU_TARGET = atmega328p
    atmega328_28pins_isp: HFUSE = DA
    atmega328_28pins_isp: LFUSE = FF
    atmega328_28pins_isp: EFUSE = 05
    atmega328_28pins_isp: isp
  3. Open atmegaboot_168.c in '{working directory}\hardware\arduino\avr\bootloaders\atmega'
  4. Edit the following
    #define BAUD_RATE   57600

Compiling the Source Code

In this step, we will compile the 3 different binaries:

USBDFU

  1. Open up the command prompt and change the directory to the location of the USBDFU files
    cd {working dir}\LUFA\Projects\28pins\usbdfu\
  2. Clean out the previous binaries, and compile
    make clean
    make

USBserial

  1. Change the directory to the location of the USBSerial files
    cd {working dir}\LUFA\Projects\28pins\usbserial\
  2. Clean out the previous binaries, and compile
    make clean
    make

328p bootloader

  1. Change the directory to the location of the USBSerial files
    cd {working directory}\hardware\arduino\avr\bootloaders\atmega
  2. Clean out the previous binaries, and compile
    make clean 
    make atmega328_28pins_10MHz

Congratulations, you have just successfully compiled the binaries for the 28pins board. But we are not finished completely, to use this board with the Arduino IDE we will need to make some changes to the IDE settings.

Adding the newboard to the Arduino IDE

In this step, we will add our custom board into the Arduino IDE so we can compile sketches for our new clock frequencies and also upload sketches directly.

  1. Open boards.txt file in 'C:\Program Files (x86)\Arduino\hardware\arduino'
  2. Add the following under another board definition;
    #################################################################
    
    28pins.name=28pins
    
    28pins.upload.tool=avrdude
    28pins.upload.protocol=arduino
    28pins.upload.maximum_size=30720
    28pins.upload.speed=57600
    
    28pins.bootloader.tool=avrdude
    28pins.bootloader.unlock_bits=0x3F
    28pins.bootloader.lock_bits=0x0F
    
    ## Arduino 28pins (3.3V, 10 MHz) w/ ATmega328
    ## --------------------------------------------------
    28pins.menu.cpu.10MHzatmega328=ATmega328 (3.3V, 10 MHz)
    
    28pins.menu.cpu.10MHzatmega328.upload.maximum_size=30720
    28pins.menu.cpu.10MHzatmega328.upload.maximum_data_size=2048
    28pins.menu.cpu.10MHzatmega328.upload.speed=57600
    
    28pins.menu.cpu.10MHzatmega328.bootloader.low_fuses=0xFF
    28pins.menu.cpu.10MHzatmega328.bootloader.high_fuses=0xDA
    28pins.menu.cpu.10MHzatmega328.bootloader.extended_fuses=0x05
    28pins.menu.cpu.10MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_28pins_10MHz.hex
    
    28pins.menu.cpu.10MHzatmega328.build.mcu=atmega328p
    28pins.menu.cpu.10MHzatmega328.build.f_cpu=10000000L
    28pins.menu.cpu.10MHzatmega328.build.board=AVR_28PINS
    28pins.menu.cpu.10MHzatmega328.build.core=arduino
    28pins.menu.cpu.10MHzatmega328.build.variant=standard
    
    ## Arduino 28pins (5V, 16 MHz) w/ ATmega328
    ## --------------------------------------------------
    28pins.menu.cpu.16MHzatmega328=ATmega328 (5V, 16 MHz)
    
    28pins.menu.cpu.16MHzatmega328.upload.maximum_size=30720
    28pins.menu.cpu.16MHzatmega328.upload.maximum_data_size=2048
    28pins.menu.cpu.16MHzatmega328.upload.speed=57600
    
    28pins.menu.cpu.16MHzatmega328.bootloader.low_fuses=0xFF
    28pins.menu.cpu.16MHzatmega328.bootloader.high_fuses=0xDA
    28pins.menu.cpu.16MHzatmega328.bootloader.extended_fuses=0x05
    28pins.menu.cpu.16MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_28pins_16MHz.hex
    
    28pins.menu.cpu.16MHzatmega328.build.mcu=atmega328p
    28pins.menu.cpu.16MHzatmega328.build.f_cpu=16000000L
    28pins.menu.cpu.16MHzatmega328.build.board=AVR_28PINS
    28pins.menu.cpu.16MHzatmega328.build.core=arduino
    28pins.menu.cpu.16MHzatmega328.build.variant=standard
    
    ##############################################################
  3. Save the file, and reload the IDE to check the new 28pins board is there.
  4. You should now be able to compile and upload the sketches to the board with the correct timings for the new clock.

Appendix

Flashing the firmware using AVRdude

The 28pins board can be flashed with AVRdude by using another Arduino board as an AVRISP.

An example AVRdude command to flash the USBSerial firmware to the ATMEGA16U2 is as follows: (where comX is the com port number of the AVRISP)

avrdude -p m16u2 -F -P comX -c arduino -b 19200 -U flash:w:28pins-usbserial.hex -U lfuse:w:0xFF:m -U hfuse:w:0xD9:m -U efuse:w:0xF4:m -U lock:w:0x0F:m

To include the USBDFU firmware we can use the following AVRdude command; Notice the -D switch.

avrdude -p m16u2 -F -P comX -c arduino -b 19200 -U flash:w:28pins-usbdfu.hex -D -U lfuse:w:0xFF:m -U hfuse:w:0xD9:m -U efuse:w:0xF4:m -U lock:w:0x0F:m

To flash the bootloader to the ATMEGA328P we can use the following AVRdude command:

avrdude -p m328p -F -P comX -c arduino -b 19200 -U flash:w:atmegaboot_168.hex -U lfuse:w:0xFF:m -U hfuse:w:0xDA:m -U efuse:w:0x05:m -U lock:w:0x0F:m

Note: Initially 16U2 will run in the Atmel Studio mode, if you would like to change it, Fit and Unfit a Link on ICSP1 between pins 5-6 (this will reset the 16U2 and it will change the mode, you will see the LEDs blinking 4-5 times). If you are using Arduino Uno R3, you will need to pull HWB pin to +5V before you use the Reset Link, otherwise your 16U2 will go into DFU mode and will not toggle between Atmel Studio and Avrdude mode.


For further instructions on flashing the firmware, please see this article; How To FLASH 28Pins Firmware