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
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.
To compile the firmware using the make command you will need to install the AVR toolchain from Atmel:
Now we are going to obtain the source code for the Arduino boot loader firmware:
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).
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:
# MCU name MCU = atmega16u2 MCU_AVRDUDE = atmega16u2 MCU_DFU = atmega16u2
# 28 Pins PID: ARDUINO_MODEL_PID = 0x6051
F_CPU = 8000000
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.
#elif (ARDUINO_MODEL_PID == FA28PINS_PID) .Header = {.Size = USB_STRING_LEN(21), .Type = DTYPE_String}, .UnicodeString = L"28pins DFU" #endif
#define FA28PINS_PID 0x6051
/** 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
# MCU name MCU = atmega16u2 MCU_AVRDUDE = atmega16u2 MCU_DFU = atmega16u2
# 28 Pins PID: ARDUINO_MODEL_PID = 0x6051
F_CPU = 8000000
.VendorID = 0x1d50, // LUFA .ProductID = 0x6051, // FA28PINS USB-to-serial programmer
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 };
#elif (ARDUINO_MODEL_PID == FA28PINS_PID) .Header = {.Size = USB_STRING_LEN(8), .Type = DTYPE_String}, .UnicodeString = L"28pins" #endif
#define FA28PINS_PID 0x6051
/** 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)
In this step, we will change the clock frequency of the ATMEGA328p.
bootloader:
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
#define BAUD_RATE 57600
In this step, we will compile the 3 different binaries:
USBDFU
cd {working dir}\LUFA\Projects\28pins\usbdfu\
Clean out the previous binaries, and compile
make clean make
USBserial
cd {working dir}\LUFA\Projects\28pins\usbserial\
Clean out the previous binaries, and compile
make clean make
328p bootloader
cd {working directory}\hardware\arduino\avr\bootloaders\atmega
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.
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.
################################################################# 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 ##############################################################
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.