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 OKft245r: bitclk 230400 -> ft baud 115200
avrdude: AVR device initialized and ready to accept instructionsReading | ################################################## | 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 verifiedavrdude 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 OKft245r: 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 OKft245r: 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 OKft245r: 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.