On ATMega328 Bootloading With FTDI Bitbang Method

I have been using the FTDI bitbang method piloted by Kimio Kosaka and improved by others (1,2,3) to flash Arduino bootloader onto blank ATMega328p for a while and thought I would share my experience with everyone.

The reason to use Kimio’s method is that no separate AVR programmer is needed as this method essentially turns the Arduino board (the FTDI module on the Arduino board to be precise) into an AVR writer (for more information, please see articles listed here on the Arduino site.)

There seems to be another method (ArduinoISP) that could be used to burn bootloaders onto blank MCUs but I haven’t been able to use it successfully. My understanding is that this method is similar to the FTDI bitbang method in that it generates the signals necessary to burn the bootloader via software. The main difference is that instead of programming the ft232r chip, this method generates the signaling via the MCU itself. The advantage is that no code changes and recompilation is necessary. I am not sure if anyone has had any luck with this method. So please post your detailed step-by-step instructions if you managed to get it to work.

Anyway, I am using Ubuntu 9.10 64 bit. And following the excellent directions mentioned by Nate and David, I got the FTDI bitbang method working on both avrdude 5.3.1 and avrdude 5.10.

There are a lot of variations of commands (covered in the references I listed above) that you can use to invoke avrdude to flash bootloader. Here’s the command I use to burn the bootloader (assuming you are within the directory where you have the FTDI bitbang patched avrdude. The bootloader HEX file and the configuration file are also in the same directory from which avrdude is launched). Note that the baud-rate is defaulted to 115200.

sudo ./avrdude -C avrdude.conf -c duemilanove -p m328p -u -U lock:w:0x3f:m -U efuse:w:0x05:m -U hfuse:w:0xDA:m -U lfuse:w:0xFF:m -U flash:w:ATmegaBOOT_168_atmega328.hex -U lock:w:0x0f:m

And here’s the sample output for a successful run:

avrdude: BitBang OK
avrdude: pin assign miso 3 sck 5 mosi 6 reset 7
avrdude: drain OK

ft245r: bitclk 230400 -> ft baud 115200
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
ft245r: bitclk 230400 -> ft baud 115200
avrdude: reading input file “0x3f”
avrdude: writing lock (1 bytes):

Writing | ################################################## | 100% 0.02s

avrdude: 1 bytes of lock written
avrdude: verifying lock memory against 0x3f:
avrdude: load data lock data from input file 0x3f:
avrdude: input file 0x3f contains 1 bytes
avrdude: reading on-chip lock data:

Reading | ################################################## | 100% 0.02s

avrdude: verifying …
avrdude: 1 bytes of lock verified
avrdude: reading input file “0x05″
avrdude: writing efuse (1 bytes):

Writing | ################################################## | 100% 0.02s

avrdude: 1 bytes of efuse written
avrdude: verifying efuse memory against 0x05:
avrdude: load data efuse data from input file 0x05:
avrdude: input file 0x05 contains 1 bytes
avrdude: reading on-chip efuse data:

Reading | ################################################## | 100% 0.02s
avrdude: verifying …
avrdude: 1 bytes of efuse verified
avrdude: reading input file “0xDA”
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.02s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xDA:
avrdude: load data hfuse data from input file 0xDA:
avrdude: input file 0xDA contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.02s

avrdude: verifying …
avrdude: 1 bytes of hfuse verified
avrdude: reading input file “0xFF”
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.02s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xFF:
avrdude: load data lfuse data from input file 0xFF:
avrdude: input file 0xFF contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.02s

avrdude: verifying …
avrdude: 1 bytes of lfuse verified
avrdude: reading input file “ATmegaBOOT_168_atmega328.hex”
avrdude: input file ATmegaBOOT_168_atmega328.hex auto detected as Intel Hex
avrdude: writing flash (32670 bytes):

Writing | ################################################## | 100% 17.72s

avrdude: 32670 bytes of flash written
avrdude: verifying flash memory against ATmegaBOOT_168_atmega328.hex:
avrdude: load data flash data from input file ATmegaBOOT_168_atmega328.hex:
avrdude: input file ATmegaBOOT_168_atmega328.hex auto detected as Intel Hex
avrdude: input file ATmegaBOOT_168_atmega328.hex contains 32670 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 8.08s

avrdude: verifying …
avrdude: 32670 bytes of flash verified
avrdude: reading input file “0x0f”
avrdude: writing lock (1 bytes):

Writing | ################################################## | 100% 0.05s

avrdude: 1 bytes of lock written
avrdude: verifying lock memory against 0x0f:
avrdude: load data lock data from input file 0x0f:
avrdude: input file 0x0f contains 1 bytes
avrdude: reading on-chip lock data:

Reading | ################################################## | 100% 0.02s

avrdude: verifying …
avrdude: 1 bytes of lock verified

avrdude done. Thank you.

The bootloading process is extremely fast and takes only around a minute to finish.

One thing I found that you need to pay special attention to is that if you are flashing bootloader onto a brand new ATMega328p chip (i.e. it hasn’t been bootloaded before), you will need to do it at a slower baud rate and if you use the above command you will get the following error message:

avrdude: BitBang OK
avrdude: pin assign miso 3 sck 5 mosi 6 reset 7
avrdude: drain OK

ft245r: bitclk 230400 -> ft baud 115200
avrdude: ft245r_program_enable: failed
avrdude: initialization failed, rc=-1
Double check connections and try again, or use -F to override
this check.

If you add the -F switch as suggested by the error message, you will receive this error instead:

avrdude: BitBang OK
avrdude: pin assign miso 3 sck 5 mosi 6 reset 7
avrdude: drain OK

ft245r: bitclk 230400 -> ft baud 115200
avrdude: ft245r_program_enable: failed
avrdude: initialization failed, rc=-1
avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x000000
avrdude: Yikes! Invalid device signature.
avrdude: Expected signature for ATMEGA328P is 1E 95 0F
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.

After some investigation, I found out that when bootloading a new chip, the -B parameter is mandatory. The following command (with -B setting) can be used in this case:

sudo ./avrdude -C avrdude.conf -c duemilanove -p m328p -B 1.0 -u -U lock:w:0x3f:m -U efuse:w:0x05:m -U hfuse:w:0xDA:m -U lfuse:w:0xFF:m -U flash:w:ATmegaBOOT_168_atmega328.hex -U lock:w:0x0f:m

But with the -B 1.0 parameter, the flashing process is significantly slower as the baud rate is automatically set to 2400 and it would take about 6 minutes for the whole process to finish.

avrdude: BitBang OK
avrdude: pin assign miso 3 sck 5 mosi 6 reset 7
avrdude: drain OK

ft245r: bitclk 4800 -> ft baud 2400
avrdude: AVR device initialized and ready to accept instructions

After some research, it turned out that only the fuse and lock bit settings need to be done at a slower baud rate for new chips. Thus, you can split the command into the following two commands (the first one set the fuse and lock at the slow baud rate, the second one burns the bootloader at the higher baud rate) to speed things up:

sudo ./avrdude -C avrdude.conf -c duemilanove -p m328p -B 1.0 -u -U lock:w:0x3f:m -U efuse:w:0x05:m -U hfuse:w:0xDA:m -U lfuse:w:0xFF:m

sudo ./avrdude -C avrdude.conf -c duemilanove -p m328p -u -U flash:w:ATmegaBOOT_168_atmega328.hex -U lock:w:0x0f:m

So in summary, you can use the above two commands to load bootloaders onto either new chips or chips that already have bootloaders on them. Use the following command on chips that are previously bootloaded only if you want a succinct command:

sudo ./avrdude -C avrdude.conf -c duemilanove -p m328p -u -U lock:w:0×3f:m -U efuse:w:0×05:m -U hfuse:w:0xDA:m -U lfuse:w:0xFF:m -U flash:w:ATmegaBOOT_168_atmega328.hex -U lock:w:0×0f:m

Update:
It seems that someone had managed to get the Arduino as ISP function working, but I haven’t tried it yet.

Be Sociable, Share!

7 Comments

  1. [...] and the ArduinoISP, I didn't have access to another Arduino. So I pieced together 3 different guides, I finally got it [...]

  2. gmm says:

    i tried using an ft232r breakout board from sparkfun http://www.sparkfun.com/commerce/product_info.php?products_id=718 for programming an attiny15 following this method. however, every time i try to read the fuses i get:
    avrdude: BitBang OK
    avrdude: pin assign miso 3 sck 5 mosi 6 reset 7
    avrdude: drain OK

    ft245r: bitclk 4800 -> ft baud 2400
    avrdude: ft245r_program_enable: failed
    avrdude: initialization failed, rc=-1
    Double check connections and try again, or use -F to override
    this check.
    when i use an atmega 328p i get no errors. i’ve checked my connections and i’m using the correct part (t15). any suggestions?
    attiny 15 datasheet: http://www.atmel.eu/dyn/resources/prod_documents/doc1187.pdf

    • kwong says:

      I assume that you have set the -p parameter to t15? Were you able to flash bootloader using the ft232r breakout board with other AVRs?

    • Brian Stott says:

      I’d tried this many times. I gave up and got a USBasp which, I finally got to work after some effort. Seems there may have been a common problem.

      The point I’d like to put forth is not necessarily to get a programmer but, note what I found.

      I found that the target chips were not seating well enough into my breadboard. When I pushed down with a fair amount of pressure along the full length of the chip – the programming worked on bare chips in a breadboard.

      I think many of my problems with this method were solely because of poor connectivity between my breadboard and the target chip. Note: The breadboard works well with general circuits – just not well enough for consistent avr programming. I may get a ZIF if I do anymore chips.

      I will try again – eventually….

  3. [...] reference material and projects implementing that feature: Introduction to FTDI bitbang mode On ATMega328 Bootloading With FTDI Bitbang Method libFTDI – FTDI USB driver with bitbang mode FT232: FTDI's Bit Bang using Python I assume you [...]

  4. [...] – La question du langage : WOrkshop encore est revenue, et même comment traduire le mot ‘bitbang methode’ (explose un peu…) (pour bruler le chargeur de démarrage) .. grâce a g$$gle : http://translate.google.com/translate?u=http%3A%2F%2Fwww15.atwiki.jp%2Farduino%2Fpages%2F23.html&sl=ja&tl=en&hl=ja&ie=UTF-8 d’ailleur c’est quoi ce truc .. http://www.kerrywong.com/2010/04/02/on-atmega328-bootloading-with-ftdi-bitbang-method/ [...]

Leave a Reply