I'm trying to understand exactly how AVRDUDE communicate with the AVR Programmer, for example USBtiny or Arduino itself as a programmer, to send the firmware to the microcontroller.

As a motivation to my question, suppose that I want to build an USB In-System Programmer for an AVR microcontroller from scratch. So, using another microcontroller, I build an ISP that can load code to the AVR.

Now, what if I want to use AVRDUDE to send to my ISP some code to load into my microcontroller? What kind of protocol will AVRDUDE use to send the code via USB, so I could read it correctly and generate the correct SPI to program the AVR? How the people who created USBtiny, for example, knew (or specified) the protocol avrdude would use to send the data to USBtiny, so they could interpret it correctly?

Any help is appreciated!


  • 2
    \$\begingroup\$ Avrdude is an open-source program. I would start by looking in its source repo. If youre lucky, there'll be protocol documentation. If not, Use The Source, Luke. \$\endgroup\$ Dec 22, 2016 at 3:37
  • \$\begingroup\$ In my experience, not very well. \$\endgroup\$
    – Matt Young
    Dec 22, 2016 at 4:05

3 Answers 3


This is more belongs to stackoverflow and this is more related to the device drivers. However,

Nowadays USB device drivers are written in ring3 instead of ring0. In English they are user mode drivers. Any modern operating system exposes interface level functionality of USB stack to the user mode by API. And there are libraries like libusb , winusb to access them in user mode, so in theory, you only need to study how to use a library like libusb.

So the AVR dude, with enough permissions , it can access it's endpoints and write and read from them. So that's how it works.

And from the avrdude source, this is the file which defines the how to communicate with my programmer, ( sorry I'm using usbasp ). http://svn.savannah.nongnu.org/viewvc/trunk/avrdude/usbasp.c?root=avrdude&view=markup

You can see that it's using libusb if on Linux.

void usbasp_initpgm(PROGRAMMER * pgm)
  strcpy(pgm->type, "usbasp");

   * mandatory functions

  pgm->initialize     = usbasp_initialize;
  pgm->display        = usbasp_display;
  pgm->enable         = usbasp_enable;
  pgm->disable        = usbasp_disable;
  pgm->program_enable = usbasp_spi_program_enable;
  pgm->chip_erase     = usbasp_spi_chip_erase;
  pgm->cmd            = usbasp_spi_cmd;
  pgm->open           = usbasp_open;
  pgm->close          = usbasp_close;
  pgm->read_byte      = avr_read_byte_default;
  pgm->write_byte     = avr_write_byte_default;

   * optional functions

  pgm->paged_write    = usbasp_spi_paged_write;
  pgm->paged_load     = usbasp_spi_paged_load;
  pgm->setup          = usbasp_setup;
  pgm->teardown       = usbasp_teardown;
  pgm->set_sck_period = usbasp_spi_set_sck_period;


You can see that each programmer supported by avrdude have to support those functions, so you can understand this abstraction and how the usbasp.c file convert them into programmer specific. I encourage you to read the source code of your programmer. Good luck.

FYI: For your programmer usbtiny, the source is here:

  • \$\begingroup\$ Thanks for the answer. So, since I would have to implement the USB device driver and also the whole set of functions you mentioned avrdude needs, it's actually possible to create your own "protocol" to communicate between avrdude and the programmer, right? The only requirement is to implement avrdude functions \$\endgroup\$
    – felipeek
    Dec 24, 2016 at 14:22
  • 1
    \$\begingroup\$ There are some changes in core to add your programmer to the existing programmer list. And also to makefiles to include your driver file. But I'm pretty sure , you will be easily figure it out. Read the source feel the force. \$\endgroup\$ Dec 25, 2016 at 6:36

You need to read AVRDude in concert with the Atmel documentation on the AVRISP II

AVRDude does not program the AVR MCU, it sends commands/packets/blocks to the programmer over a serial channel in the case of the Arduino as an example.
The programmer (On Arduino the bootloader acts just like an AVRISP II) manages the Flash (self) programming of the device (the ATMega328 on Arduino) while leaving the bootloader intact.

It's not clear from your question exactly what you want to do. However you could:

  1. Build your own bootloader for an AVR MCU, and send it serial data via the uart or USB/serial
  2. Build and program your own SPI or HV programmer (to act like an AVR ISP II) based on an AVR MCU and send serial (or USB/serial) data to that. The programmers could then use ICSP/SPI to program your final device.

For good ideas on what to do for your project investigate the Arduino Nano schematic (this is a bootloader based implementation with USB/serial data) or the Arduino UNO schematic which uses a separate AtMega16u2 AVR as the programmer (the ATMega16U2 emulates an AVRISP II, USB/serial. It programs the final device as serial to bootloader)


(the ATMega16U2 emulates an AVRISP II, USB/serial. It programs the final device as serial to bootloader)

If that's the case that the atmega18U2 acts like a programmer in itself and not as a USB to serial converter, why is it so that whenever the bootloader of 328p is corrupted we need to re-upload it using ICSP headers? Hence the 18U2 must be acting just as a USB to serial converter.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.