Bootloader Differences

Hi all,

I am trying to understand Bootloaders, what all it contains and how to go about writing one.

Can someone clear some of doubts I have when I started exploring the same?

  1. Why are there two folders named arduino-usbdfu and arduino-usbserial in the Arduino Firmwares folder? What is different in those 2 versions?

  2. In say Arduino Uno or Mega, from my understanding, the onboard Atmega16u2 chip is just for USB to serial conversion between PC and the Atmega328 or Atmega2560 chip. Or does it do something else too?

If its just that, why is there again 2 different bootloading files of Atmega16u2 of Mega and UNO(Arduino-usbserial-mega.hex and Arduino-usbserial-uno.hex in arduino-usbserial folder)? Why is this chip dependent?

  1. Is there a tutorial or writeup somewhere on how to go about writing a Arduino bootloader(for a new chip) because I really would like to know the process?

Thanking you guys in advance :slight_smile:

  1. Is there a tutorial or writeup somewhere on how to go about writing a Arduino bootloader(for a new chip) because I really would like to know the process?

Look at the datasheet for the part you want to use. Atmel has sample code for a bootloader in the datasheets I have seen.
For example, in the 328P:

27.8.13 Simple Assembly Code Example for a Boot Loader
;-the routine writes one page of data from RAM to Flash
; the first data location in RAM is pointed to by the Y pointer
; the first data location in Flash is pointed to by the Z-pointer
;-error handling is not included
;-the routine must be placed inside the Boot space
; (at least the Do_spm sub routine). Only code inside NRWW section can
; be read during Self-Programming (Page Erase and Page Write).
;-registers used: r0, r1, temp1 (r16), temp2 (r17), looplo (r24), 
; loophi (r25), spmcrval (r20)
; storing and restoring of registers is not included in the routine
; register usage can be optimized at the expense of code size
;-It is assumed that either the interrupt table is moved to the Boot
; loader section or that the interrupts are disabled.
.equ PAGESIZEB = PAGESIZE*2 ;PAGESIZEB is page size in BYTES, not words
.org SMALLBOOTSTART
Write_page:
; Page Erase
ldi spmcrval, (1<<PGERS) | (1<<SPMEN)
call Do_spm
; re-enable the RWW section
ldi spmcrval, (1<<RWWSRE) | (1<<SPMEN)
call Do_spm
; transfer data from RAM to Flash page buffer
ldi looplo, low(PAGESIZEB) ;init loop variable
ldi loophi, high(PAGESIZEB) ;not required for PAGESIZEB<=256
Wrloop:
ld r0, Y+
ld r1, Y+
ldi spmcrval, (1<<SPMEN)
call Do_spm
adiw ZH:ZL, 2
sbiw loophi:looplo, 2 ;use subi for PAGESIZEB<=256
brne Wrloop
; execute Page Write
subi ZL, low(PAGESIZEB) ;restore pointer
sbci ZH, high(PAGESIZEB) ;not required for PAGESIZEB<=256
ldi spmcrval, (1<<PGWRT) | (1<<SPMEN)
call Do_spm
; re-enable the RWW section
ldi spmcrval, (1<<RWWSRE) | (1<<SPMEN)
call Do_spm
; read back and check, optional
ldi looplo, low(PAGESIZEB) ;init loop variable
ldi loophi, high(PAGESIZEB) ;not required for PAGESIZEB<=256
subi YL, low(PAGESIZEB) ;restore pointer
sbci YH, high(PAGESIZEB)
Rdloop:
lpm r0, Z+
ld r1, Y+
cpse r0, r1
jmp Error
sbiw loophi:looplo, 1 ;use subi for PAGESIZEB<=256
brne Rdloop
; return to RWW section
; verify that RWW section is safe to read
Return:
in temp1, SPMCSR
sbrs temp1, RWWSB ; If RWWSB is set, the RWW section is not ready yet
ret
; re-enable the RWW section
ldi spmcrval, (1<<RWWSRE) | (1<<SPMEN)
call Do_spm
rjmp Return
Do_spm:
; check for previous SPM complete
Wait_spm:
in temp1, SPMCSR
sbrc temp1, SPMEN
rjmp Wait_spm
; input: spmcrval determines SPM action
; disable interrupts if enabled, store status
in temp2, SREG
cli
; check that no EEPROM write access is present
Wait_ee:
sbic EECR, EEPE
rjmp Wait_ee
; SPM timed sequence
out SPMCSR, spmcrval
spm
; restore SREG (to enable interrupts if originally enabled)
out SREG, temp2
ret

You will need an ISP Programmer to access the memory via the SPI pins to install the bootloader, and set up the fuses for the clock type you using, brownout levels, etc. if you want to use something besides the factory programming.

  1. Why are there two folders named arduino-usbdfu and arduino-usbserial in the Arduino Firmwares folder? What is different in those 2 versions?

The usbdfu is the (USB) Bootloader for the 16u2, so that you could load new firmware onto that chip.
The usbserial code is the "application" for the 16u2, that does the USB/Serial conversion.
(Note that neither of these is the bootloader for the Arduino AVR itself (the m328 or m2560.) Those are in the "bootloaders" directory.)

  1. In say Arduino Uno or Mega, from my understanding, the onboard Atmega16u2 chip is just for USB to serial conversion between PC and the Atmega328 or Atmega2560 chip. Or does it do something else too?

It CAN be loaded with firmware that allows the Arduino to appear as other types of USB devices (keyboard, mouse, MIDI port, gamepad, etc.) At one time, this was expected to be important, but I think it has fallen behind boards like the Micro and Leonardo that can support such applications in a more obvious fashion.

  1. Is there a tutorial or writeup somewhere on how to go about writing a Arduino bootloader(for a new chip) because I really would like to know the process?

[http://www.avrfreaks.net/forum/faq-c-writing-bootloader-faq?skey=bootloader%20tutorial](http://"http://www.avrfreaks.net/forum/faq-c-writing-bootloader-faq?skey=bootloader tutorial")
In addition, Atmel has some App Notes (AVR109 being famous?) and a lot of the bootloaders are open-source, so you can look at them. The overall outline is pretty simple:

  1. figure out how to start the bootloader.
  2. Read the file to be programmed from "somewhere."
  3. Write the data to flash using the self-programming feature and "SPM" instruction (for AVRs, anyway.)
  4. figure our how to exit the bootloader and start the application code.

Sorry for the delay... Been away for the last couple of days.

Thank you for your responses.. :slight_smile:

@Crossroads
Thanks for pointing me to the sample codes. Will check the assembly code out.

@Westfw
Those two links to documents really helped. I am going through them in detail now.

I am just linking them here for future use. :slight_smile:

http://www.avrfreaks.net/sites/default/files/bootloader_faq.pdf
http://www.atmel.com/images/doc1644.pdf -- AVR109 Self Programming

But I guess writing a bootloader from scratch might be a bit too tough for me at the moment. I will start with bootloader codes given with Arduino firmware and start understanding & modifying them.

Few more doubts:

The usbdfu is the (USB) Bootloader for the 16u2, so that you could load new firmware onto that chip.
The usbserial code is the "application" for the 16u2, that does the USB/Serial conversion.
(Note that neither of these is the bootloader for the Arduino AVR itself (the m328 or m2560.) Those are in the "bootloaders" directory.)

So what hex file is burnt into atmega16u2 chip in Arduino UNO? Is it the Arduino-COMBINED-dfu-usbserial-atmega16u2-Uno-Rev3.hex file?
And how would this be different from MEGA-dfu_and_usbserial_combined.hex ? Are there any major differences? (Except for the fact that one is for UNO and one for MEGA and when both of them are plugged in they show up as respective devices in Device Manager?) Is there any other change?(like would bootloader+application burnt on Atmega16u2 chip depend on the chip its trying to program like Atmega328p and Atmega2560 in this case?)

Following is the whole goal of this exercise...

I am trying to make an open source board with Atmega128RFa1 and atmega16u2 and make it work with Arduino IDE so that I can program the board like an UNO or Mega.
I got hooked onto Atmega128RFa1 with a development board from Sparkfun(Link). They have a bootloader and an way for IDE integration for the board. It programs via a FTDI chip with Arduino IDE. I am trying to make it with a Atmega16u2 chip such that it shows up as a Atmega128RFa1 board in device manager.

Can you help me figure out what might needed for this?
I currently have a working bootloader from Sparkfun for the Atmega128RFa1.

Thanking you guys in advance.

I guess writing a bootloader from scratch might be a bit too tough for me

Writing a bootloader is not especially difficult, except for the part where you try to make it "as small as possible", in spite of compiler changes, added features, and so on.

So what hex file is burnt into atmega16u2 chip in Arduino UNO? Is it the Arduino-COMBINED-dfu-usbserial-atmega16u2-Uno-Rev3.hex file?

I would expect so...

And how would this be different from MEGA-dfu

USB Product ID? From the makefile:

# Specify the Arduino model using the assigned PID.  This is used by Descriptors.c
#   to set PID and product descriptor string
# Uno PID:
ARDUINO_MODEL_PID = 0x0001
# Mega 2560 PID:
#ARDUINO_MODEL_PID = 0x0010

Everyone who makes a USB-connectable product is supposed to have a vendor id (VID), and a product id (PID.) You have to register to get a vendor id (~$2000/year) (a major hurdle for individuals and small developers. Some chip vendors are letting prototype and hobbyist apps use their vendor ID. I don't recall whether Atmel is one of them. You should NOT use Arduino's vendor ID on an unofficial product...) (FTDI-based boards get to use the FTDI VID, because the conversion chip IS the product.)

I got hooked onto Atmega128RFa1 with a development board from Sparkfun(Link). They have a bootloader and an way for IDE integration for the board. It programs via a FTDI chip with Arduino IDE. I am trying to make it with a Atmega16u2 chip such that it shows up as a Atmega128RFa1 board in device manager.

FTDI has a utility that lets you change the VID, PID, and etc ("Description") to arbitrary values (for customers who want to use their chip, but want similar "custom-appearing" drivers/etc.) that might be an easier path. (FT_PROG, I think. here: Utilities - FTDI

Thanks @Westfw for the info on the differences in bootloaders. I understood the USB PID differences(which causes it show up as different devices to the PC I believe)

Do you think there is any other difference between those 2 bootloaders? I had a quick glance at Arduino-usbserial.c and Arduino-usbdfu.c couldnt see specific chip specific code for UNO or MEGA.

If there is no other difference, I guess it should work with Atmega128RFa1 too I suppose.

FTDI has a utility that lets you change the VID, PID, and etc ("Description") to arbitrary values (for customers who want to use their chip, but want similar "custom-appearing" drivers/etc.) that might be an easier path. (FT_PROG, I think. here: Utilities - FTDI

But I would like to do it with a Atmega16u2 chip as I already made the hardware for it.
I am going through
https://github.com/sparkfun/ATmega128RFA1_Dev/blob/master/firmware/Arduino/hardware/128RFA1-DEV/bootloader/atmega/ATmegaBOOT.c
to see if there is something which would make it non-working programming with a atmega16u2 via USB.
Any pointers on the same is highly appreciated :slight_smile:

PS: @Westfw Cool display picture by the way. :smiley: I have always remembered you by the old display picture for as long as I can remember :smiley:

Edit: Checked out both ATmegaBoot.c in arduino folder and Sparkfun's Atmega128RFA1 bootloader code.
Very basic changes only there. (See differences here: https://www.diffchecker.com/xnn2tkba)

Can some confirm which among the bootloader is burnt in the UNO or Mega(from the bootloaders folder in Arduino software)? Or will any of the bootloaders work(I see many folders inside that.)?