How to Install an ATtiny Bootloader With Virtual USB
Create an Arduino Board Definition
To be able to program the ATtiny84 from Arduino, we need to make a custom board definition. There are three main parts for a board definition, and we'll create each one:
- boards.txt -- Information about the microcontroller (clock speed, program space, etc.)
- platform.txt -- Extra information the compiler might need and which loader tool to use (e.g., AVRDUDE)
- pins_ardiuno.h -- Tells the compiler which pins in code map to which pins on the microcontroller
Additionally, we'll need to copy over the micronucleus loader tool from the micronucleus project directory to the Arduino directory. The loader tool will be used to send compiled firmware to the ATtiny84 (much as AVRDUDE does).
boards.txt
Navigate to \
In that directory, create another directory that corresponds to the target microcontroller family, "avr" in this case.
In the avr directory, create a file named boards.txt and copy in the following text:
menu.cpu=Processor ################################################################################ MyTiny.name=MyTiny (ATtiny84, 3.3V, 8Mhz) MyTiny.upload.using=micronucleusprog MyTiny.upload.protocol=usb MyTiny.upload.tool=micronucleus MyTiny.upload.maximum_size=6012 MyTiny.build.mcu=attiny84 MyTiny.build.f_cpu=8000000L MyTiny.build.board=MYTINY MyTiny.build.core=arduino:arduino MyTiny.build.variant=tiny14
platform.txt
In the avr directory, create a file named platform.txt and copy in the following:
name=MyTiny Boards version=0.0.1 # Default "compiler.path" is correct, change only if you want to overidde the initial value compiler.path={runtime.tools.avr-gcc.path}/bin/ compiler.c.cmd=avr-gcc compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -MMD compiler.c.elf.flags=-Os -Wl,--gc-sections compiler.c.elf.cmd=avr-gcc compiler.S.flags=-c -g -x assembler-with-cpp compiler.cpp.cmd=avr-g++ compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -MMD compiler.ar.cmd=avr-ar compiler.ar.flags=rcs compiler.objcopy.cmd=avr-objcopy compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 compiler.elf2hex.flags=-O ihex -R .eeprom compiler.elf2hex.cmd=avr-objcopy compiler.ldflags= compiler.size.cmd=avr-size # this can be overriden in boards.txt build.extra_flags= # AVR compile patterns # -------------------- ## Compile c files recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" ## Compile c++ files recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" ## Compile S files recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" ## Create archives recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} "{archive_file_path}" "{object_file}" ## Combine gc-sections, archives, and objects recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} -o "{build.path}/{build.project_name}.elf" {object_files} "{archive_file_path}" "-L{build.path}" -lm ## Create eeprom recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep" ## Create hex recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).* recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* # Micronucleus Loader # ------------------- tools.micronucleus.cmd.path={runtime.hardware.path}/../tools tools.micronucleus.upload.params.verbose=-verbose tools.micronucleus.upload.params.quiet= tools.micronucleus.upload.pattern="{cmd.path}/micronucleus" --timeout 60 "{build.path}/{build.project_name}.hex" #tools.micronucleus.upload.pattern="{cmd.path}/micronucleus" --run --timeout 60 "{build.path}/{build.project_name}.hex" #tools.micronucleus.upload.pattern="{cmd.path}" -cdigispark --timeout 60 -Uflash:w:{build.path}/{build.project_name}.hex:i # USB Default Flags # Default blank usb manufacturer will be filled it at compile time # - from numeric vendor ID, set to Unknown otherwise build.usb_manufacturer= build.usb_flags=
Pin Definitions
At this point, we need to create a custom pin definitions file. Create a directory in avr with the name variants:
Create another directory in variants named tiny14. In tiny14, create a file named pins_arduino.h.
Copy the following code into pins_arduino.h. Note that the original contents of this file come from the ATtiny cores for Arduino project.
/* pins_arduino.c - pin definitions for the Arduino board Part of Arduino / Wiring Lite Copyright (c) 2005 David A. Mellis This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA $Id: pins_arduino.c 565 2009-03-25 10:50:00Z dmellis $ Modified 28-08-2009 for attiny84 R.Wiersma Modified 09-10-2009 for attiny45 A.Saporetti */ // ATMEL ATTINY84 / ARDUINO // // +-\/-+ // VCC 1| |14 GND // (D 10) PB0 2| |13 AREF (D 0) // (D 9) PB1 3| |12 PA1 (D 1) // PB3 4| |11 PA2 (D 2) // PWM INT0 (D 8) PB2 5| |10 PA3 (D 3) // PWM (D 7) PA7 6| |9 PA4 (D 4) // PWM (D 6) PA6 7| |8 PA5 (D 5) PWM // +----+ const static uint8_t A0 = 0; const static uint8_t A1 = 1; const static uint8_t A2 = 2; const static uint8_t A3 = 3; const static uint8_t A4 = 4; const static uint8_t A5 = 5; const static uint8_t A6 = 6; const static uint8_t A7 = 7; // these arrays map port names (e.g. port B) to the // appropriate addresses for various functions (e.g. reading // and writing) const uint16_t PROGMEM port_to_mode_PGM[] = { NOT_A_PORT, (uint16_t)&DDRA, (uint16_t)&DDRB, }; const uint16_t PROGMEM port_to_output_PGM[] = { NOT_A_PORT, (uint16_t)&PORTA, (uint16_t)&PORTB, }; const uint16_t PROGMEM port_to_input_PGM[] = { NOT_A_PORT, (uint16_t)&PINA, (uint16_t)&PINB, }; const uint8_t PROGMEM digital_pin_to_port_PGM[] = { PA, /* 0 */ PA, PA, PA, PA, PA, PA, PA, PB, /* 8 */ PB, PB, }; const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { _BV(0), /* port A */ _BV(1), _BV(2), _BV(3), _BV(4), _BV(5), _BV(6), _BV(7), _BV(2), /* port B */ _BV(1), _BV(0), }; const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, TIMER1B, /* OC1B */ TIMER1A, /* OC1A */ TIMER0B, /* OC0B */ TIMER0A, /* OC0A */ NOT_ON_TIMER, NOT_ON_TIMER, };
If you look through the platform.txt file, you'll see that the loader tool is micronucleus and not avrdude. Because Arduino does not come with the micronucleus loader tool, we need to build it or copy it from the micronucleus project directory.
Build the Micronucleus Loader (Mac)
First, you'll need to make sure you have Homebrew installed. Then, open a command terminal and enter:
cd <micronucleus Directory>/commandline brew install libusb-compat make
Navigate to \
Build the Micronucleus Loader (Linux)
Navigate to the micronucleus project directory and make the loader:
cd <micronucleus Directory>/commandline sudo apt-get install libusb-dev make
Navigate to \
Copy the Micronucleus Executable (Windows)
Navigate to \