Compact USB HID Bootloader for ATtiny85

I present to you the new compact Bootloader for AVR Tiny 45/85 . This autoloader is licensed under the GNU GPL, as required by the V-USB license. The basis for this autoloader was the ATtiny85 USB Boot Loader from Embedded Creations and its descendant micronucleus-t85, used by Digispark boards.
Like the above, TinyHID Loader is based on the V-USB library.

Key Features:

  • Works under ATtiny45 and ATtiny85
  • Compact (2kb with basic functions)
  • Expandable (there are a number of additional functions, the inclusion of which will increase the size)
  • No drivers required (which is especially important for new versions of Windows)
  • It does not work with AVRdude, instead uses a cross-platform API in C #
  • Able to update himself

And why the AVR Tiny 85?

The economy must be economical, gentlemen. And with the AVR Tiny x5, you save twice, and even in two ways. The first is the issue of price: tinky is cheaper than meg. But personally, the Tiny x5 has a PLL generator, which also allows you to abandon the quartz resonator. So we save on it and even on two capacitors. In addition, there is also the issue of space on the board. In the QNF body, a cockroach is 2.5 by 2.5 mm in size. And again, we do not need a resonator. The entire circuit can easily fit on a ridiculous 12x5 mm. As a summary, the use of the AVR Tiny 85 is always appropriate, and especially for USB devices until there is a need for functionality that this cockroach does not support (for example, when you need a lot of IO ports)

Why a special autoloader?

Autoloaders for the AVR Mega are a dime a dozen, but with the Tiny 85 it's not so simple. To understand these difficulties, I present the algorithm of the classics:

  • If the BOOTRST configuration bit is set to 0, then after the restart, the controller starts execution not from the zero address, but with the Boot Reset Address (specific for different models and can be configured).
  • According to the Boot Reset Address, the autoloader itself is located, which first of all moves the interrupt table to the Boot Reset Address.
  • the autoloader determines whether it needs to be loaded by itself or not. If necessary, it starts as usual firmware, although it is not located at the zero address.
  • If you do not need to load the autoloader, then it moves the interrupt table back to the zero address, and transfers control there, thereby loading the application firmware.
  • While writing data to Flash, the autoloader continues to work with the USB protocol, responding to host requests.
  • Also, the autoloader’s memory area is unrecordable, which prevents the autoloader from damaging itself.

And now the nuances of the 85th Tiny:

  • ATtiny is always loaded from the zero address; it cannot be configured to another address.
  • Interrupt vectors are also not transferred anywhere.
  • During recording, the controller pauses for 4.5 ms, and is unable to respond to anything.
  • Well, the autoloader also has no hardware protection against self-recording.

And workarounds.

  • The cleared memory is filled with units that are treated by the controller as NOP. And this means that after the reset, the control will reach the autoloader. At least 1,500 NOPs will be completed before this.
  • But for the functioning of the USB protocol, this is not enough. PCINT0 interrupt response is also needed. The interrupt vector table cannot be moved, but you can write the autoloader addresses to this table. Therefore, immediately after the first boot, the autoloader writes the address vectors of its handlers to RESET and PCINT0.
  • When recording application firmware, the autoloader also replaces the RESET and PCINT0 vectors.
  • The autoloader writes the initial RESET and PCINT of the applied firmware to the addresses immediately before the autoloader.
  • Modification of the V-USB processor PCINT0 in such a way that it can call the PCINT0 application firmware processor. The condition for the autoloader handler to work is TCCR1 == 0 && TCNT1 == 0xff. Otherwise, run the application handler.
  • The delay before recording or clearing memory. At this time, the controller manages to inform the host about the success of the operation, and the host does not lose it.
  • After the memory cleaning operation, the autoloader always writes its RESET and PCINT0 vectors.
  • Before writing the application firmware, the autoloader flushes the FLASH from end to beginning. This type of cleaning ensures that even if the cleaning / recording process is interrupted by an unexpected power outage, the autoloader will remain operational. Or the first page of FLASH is not yet overwritten / already recorded, and control on the autoloader will move on a vector. Either all the memory has been cleared and control will be transferred to the autoloader through a chain of NOPs.
  • A software check of the entry in the autoloader is performed instead of the hardware.

For more information on the features of the autoloader to the AVR Tiny 85 can be read on the website Embedded Creations in English

Why reinvent the wheel?

Using classic MEGA-based autoloaders on AVR tiny is not possible for the reasons described in the previous chapter. But even without them, there are 2 autoloader implementations: ATtiny85 USB Boot Loader and micronucleus-t85, and both of them emulate the once-popular USBasp programmer. And the aforementioned programmer runs on the host through the libusb library. This is a wonderful and multifunctional library, and its use under Mac OS or Linux is elementary as 2x2. And if you are going to use your creations yourself, then TinyHID Loader may appeal to you, perhaps, in more compact sizes. But under Windows 8.1 x64, installing the libusb driver is no longer a trivial task. Deep-deep in the settings there is an item that allows you to restart the computer once with the driver electronic signature verification disabled. And woe to that who will explain to a typical user this method. Therefore, the main idea was to create an autoloader capable of working through HID Feature Reports. For all HID devices, standard OS drivers are used, and you do not need to install additional ones. It also turned out that the failure to support avrdude brings an opportunity to reduce the weight of the bootloader. When disabling all options except for writing / clearing FLASH and program access to the application firmware, the autoloader weighs 2kb, which is less than that of competitors.

How to use?

First you need to configure the firmware. To do this, you need to adjust the firmware / usbloader / usbloader.h file to your scheme and your needs:

// Нога ATtiny, к которой подключен USB D-
// Нога ATtiny, к которой подключен USB D+
// Нога ATtiny, к которой подключен светодиод
// (можно раскоментить, но объём увеличится)
// #define LED_PIN 4
// Нога ATtiny, заземление которой приводит к старту загрузчика (экстренное включение загрузчика)
// (можно закоментить для сохранения места)
// Установить в 1, если требуется возможность очистки EEPROM (что заметно увеличит объём загрузчика)
// Установить в 1, если требуется возможность чтения FLASH (что заметно увеличит объём загрузчика)
#define CAN_READ_FLASH 0
// Установить в 0, если не нужен программный переход в прикладную прошивку (что уменьшит объём загрузчика)

At the same time, you do not need to take care that USB_CFG_DPLUS_BIT gets on the INT0 leg, since the PCINT0 interrupt is used by the autoloader, which can be configured on any leg.
In the above version, the bootloader fits in 2kb, although end-to-end. Enabling any additional options will take him beyond these limits, and at the same time you will have to change his location in memory. This is done differently depending on whether you use AtmelStudio or Makefile.

Atmel studio

Make sure Release is selected.
Open the project properties, go to the Toolchain tab, and in the "AVR / GNU Linker / Memory Settings" item, reduce the value ".text = 0xc00". You can reduce it only in portions of 32 words. That is, 0xbe0, 0xbc0, 0xba0. 0xba0 is enough for all available options to work, no further reduction. In addition to this, you must also reduce the value of the constant BOOTLOADER_WADDRESS. This can be done on the AVR / GNU C Compiler / Symbols page. The value must equal the value ".text =".
After configuration, you need to compile the project (F7) and you can upload it to the controller with an external programmer.


Open the Makefile, and reduce the constant BOOTLOADER_ADDRESS to the desired value. Only 64-byte portions can be reduced (AtmelStudio uses words, and Makefile uses bytes). That is, 17c0, 1780, 1740. 1740 is enough for all the available options to work, no further reduction.
After configuration, you need to compile the project by typing make in the command line and you can upload it to the controller with an external programmer.
Done, your programmer no longer needs an external programmer, go to the software on the computer.


The utility that uploads the firmware to the controller is written in C #, the project was developed in VisualStudio 2012, but it can also be opened in Xamarin for further work with MONO. The HidSharp cross-platform library is used to communicate with HID, which will make your MONO project truly cross-platform.
The download utility is extremely easy to use:
TinyLoaderCmd.exe firmware.hex

And after 3 seconds, the cockroach is stitched and ready to go. If the firmware was created with the default config, then starting the utility will not only flash the controller, but also, when ready, will launch the recorded firmware.
Alternatively, you can use the TinyHID Loader API from your C # project:
void UploadNewFirmware(string file)
	HexFile file = new HexFile(args[0]);
	Loader ldr = Loader.TryGetLoader(40);
	byte[] programm = new byte[Loader.LOADERSTART];
	for (int i = 0; i < programm.Length; i++) programm[i] = 0xff;
	ldr.WriteFlash(programm, 0);

And if you add the autoloader boot function in your firmware:
void runBootloader()
	TCCR1 = 0;
	TCNT1 = 0xff;
	asm volatile ("rjmp __vectors");

Then the flashing will turn for the user at the click of a button. And your project at that time:

  • Tells your firmware to load the autoloader.
  • It will wait (Loader.TryGetLoader) for the moment when the system picks up the autoloader.
  • Will record a new firmware.
  • Tells the autoloader to download firmware.
  • It will wait until the system picks up your new firmware.

And if you needed a different set of options?

Delivered a full set of options and the new firmware now does not fit? Or do you regret that you did not add the ability to read memory? Well, or does the TinyHID Loader not suit you at all, and without avrdude life is not nice? But the microcontroller is not only stitched, but also sealed. And I do not want to solder it at all. No question - TinyHID Loader can reshape itself!
The self-flashing algorithm is as follows:

  • From the command line, the user enters TinyLoaderCmd.exe reload bootloader.hex (as an option - no one enters anything, and you implement the process through the API from your software on the host)
  • The utility creates firmware for reloading. It includes the image of the new autoloader, summary information about it (destination address in FLASH and CRC16), as well as a special update utility (reloader).
  • The firmware is uploaded to the microcontroller in the usual way, like any other firmware.
  • The device reboots (maybe programmatically, if this option is not disabled), and control is transferred to reloader.
  • Reloader checks the correctness of the new autoloader by checking CRC16 as well as its size and ability to fit on the device.
  • If all checks succeed, reloader clears the first page of memory. From this moment there is no turning back. And if a power off occurs, control will not be transferred to the old bootloader.
  • The main stage is copying the new autoloader from the image to real addresses, as well as clearing the page directly in front of the autoloader (since all autoloaders use it)
  • And in the final - the transition along the RESET vector of the new autoloader - while the autoloader will reinitialize FLASH and begin work

The reloader’s security guarantees are CRC verification and the logic of the process, which will start again in case of unexpected termination. But an incorrect new firmware will turn a cockroach into a brick, and only the programmer can resurrect it. Therefore, be careful - check the settings are correct.
Also, using reloader, you can flash TinyHID Loader on a device with another programmer. That is, to replace any AVR Tiny 85 autoloader in general with any other.

Special thanks:

  • V-USB library for Atmel microcontrollers for the very possibility of working with USB
  • ATtiny85 USB Boot Loader from Embedded Creations for describing the intricacies of creating an autoloader for the AVR Tiny 85
  • autoloader micronucleus-t85 for the idea of reducing the volume.
  • BootloaderHID for the idea that switching to HID only seems expensive in terms of weight. Avrdude compatibility rejection allows you to win more.
  • Racially to the German FunkUsb for the idea of ​​changing osccal.c to osctune.h, which significantly reduces the weight of the code

Also popular now: