Skip to content
nseidle edited this page Oct 15, 2011 · 4 revisions

##How Auto-detect Works There are two parts to this repository, the faster bootloader called Screamer and the board auto-detect method. Here we discuss the auto-detect tricks. All of this was created by viewing the serial protocol using a logic analyzer. If you don't already have one, get one. It will save your life, or at least your sanity.

Boot loader type identification

The autodetect method works by pinging the attached board at different baud rates waiting for the STK500 bootloader to respond. For example:

  1. Computer opens COM port at 115200bps (common on newer board using Optiboot).
  2. Computer wiggles DTR to cause the board to reset.
  3. After waiting ~100ms (because Optiboot takes forever to wake up) the Computer sends two characters: 0x30 and 0x20 (STK Get Sync) + (CRC EOP).
  4. If the boards responds within ~500ms with the expected response of 0x14 and 0x10 (STK_INSYNC) + (STK_OK) then we know two things, that this board uses the STK500 bootloader and at what baud rate.
  5. If the board does not respond, the loop back up to #1 trying 57600 (Duemilanove, LilyPad, Yellow Jacket) and then 19200 (Diecimila, old LilyPad, etc).

IC type identification

Once we know that this board is using the STK500 bootloader, then we can query the board to give up its IC signature. We do this by:

  1. Computer sends characters 0x75 and 0x20
  2. Target board responds with 0x14 (SIG1) (SIG2) (SIG3) 0x10

Depending on the signature bytes, we can identify the IC on this board. Cool. Now we now what to pass the Arduino IDE so that it compiles the sketch correctly for the board you have attached. Signature bytes can be found in the file: \hardware\tools\avr\avr\include\avr\io****.h

Board frequency identification

So we know a lot, but there are some boards where the frequency could be 16MHz or 8MHz. How will we be able to tell the difference? Here's where things get really neat. We can load a very small program that transmits the letter X at 19200 with the assumption that the board is running at 16MHz. If we see X at 19200 then we know the board is indeed running at 16MHz. If it sees the X at 9600bps, then we know the board is running at 8MHz. And if we happen to see the X at 1200bps, then we know the board is running at 1MHz.

Loading a new sketch onto the board is straight forward, but by doing this we will be overwriting whatever sketch is currently on the board. I don't really want to mess up someone's sketch just trying to identify a board so before we put our little frequency test sketch on the target board, let's remember what was there. We can write it back when we are done. The test sketch is 256 bytes, so first we read the first 256 bytes on the target:

  1. Computer sends 0x50 0x00 0x00 0x20. This is the computer setting the page address to 0x000.
  2. Target board responds with 0x14 0x10. This is acknowledgment of the page address.
  3. Computer sends 0x74 0x00 0x80 0x46 0x20: 0x74 : PAGE_READ 0x00 : Upper byte of the number of bytes to read 0x80 : Lower byte of the number of bytes to read. 0x0080 = read 128 bytes to me. 0x46 : Some sort of STK500 command that is ignored 0x20 : Termination byte
  4. The target immediately responds with: 0x14 0C 94 61 ... 0x10 0x14: I_HEAR_YOU tag 0x0C: Firmware byte #0 0x94: Firmware byte #1 0x61: Firmware byte #2 ... 0x4C: Firmware byte #127 0x10: I_AM_DONE tag

Now we can read in and remember those 128 firmware bytes into a temporary array. Increase the page address from 0 to 128 and repeat for the next 128 bytes. We should now have the first 256 bytes of the user's sketch. Now we upload our special test program:

  • Computer: 0x55 00 00 20
  • Arduino: 0x14 10

Computer is loading an address (0x0000). Arduino confirms.

  • Computer: 0x64 00 80 46 0C 94...
  • Arduino: 0x14

Computer is sending PROGRAM_PAGE (0x64) followed by 128 bytes of firmware.

  1. 0x64 = PROGRAM PAGE. This causes Arduino to call getLen.
  • 0x00 = thrown out by getLen. (This may be the high byte for page sizes greater than 255)
  • 0x80 = length of data, 128 bytes in this case.
  • 0x46 = getLen returns 0x46 to the main function, but it is thrown out (not stored).
  • 0x0C = Byte 1 of firmware
  • 0x94 = Byte 2 of firmware
  • ...
  • Arduino responds with 0x14.

Repeat for the 2nd batch of 128 bytes.

The target board should now be loaded with the frequency test sketch. Reset the target board and listen for the X!

  1. Open COM port at 19200bps.
  • Wiggle DTR to cause the target to reset
  • If we detect an X then we know this is a 16MHz board. If not, close port and try again at 9600 and 1200bps.

Once we've found the X, we need to load the original 256 bytes back onto the target board.

  1. Wiggle DTR to cause the bootloader to fire
  • Send the correct STK500 commands to get into bootload mode
  • Tell STK500 a page address
  • Issue write command and push the 128 bytes of original sketch
  • Tell 2nd page address
  • Push the 2nd 128 bytes
  • Wiggle DTR to reset target board and return it to it's original state

###Guessing what board we have Once we know the bootloader type, baud rate, IC type, and board frequency we really don't care what board type it is. We have all the information we need to do a successful compile and boot load correctly to the target board. However, it may be nice for the end user to know what board they are talking to (for example if the board is buried deep in an enclosure).

Here is a partial list:

  • Uno: ATmega328 16MHz 115200bps
  • Duemilanove: ATmega328 16 57600
  • LilyPad ATmega328 8 57600
  • Yellow jacket: ATmega328 16 57600
  • Diecimila: ATmega168 16 19200
  • NG: ATmega8 16 19200