How to flash bootloader *and* a sketch at the same time? [SOLVED]

I've made my own Arduino derivative for a project. I'd like to build a few of these that both have the Arduino bootloader and a custom sketch uploaded, so I started putting together a jig with a ZIF socket and 6-pin ISP header to program the ATMega328p chips quickly.

The only problem is, if I recall, the Arduino environment lets you burn the bootloader via ISP, but if you program via ISP, you wipe the bootloader (normally a good thing because you get extra memory).

But I want to ship with both an Arduino bootloader and a custom sketch preloaded. Is there a way to do that all in one step via the ISP port?

vputz:
I've made my own Arduino derivative for a project. I'd like to build a few of these that both have the Arduino bootloader and a custom sketch uploaded, so I started putting together a jig with a ZIF socket and 6-pin ISP header to program the ATMega328p chips quickly.

The only problem is, if I recall, the Arduino environment lets you burn the bootloader via ISP, but if you program via ISP, you wipe the bootloader (normally a good thing because you get extra memory).

But I want to ship with both an Arduino bootloader and a custom sketch preloaded. Is there a way to do that all in one step via the ISP port?

I suspect that you can't do it via the Arduino IDE. I would think you would need to somehow combine the hex files of the compiled sketch and the desired bootloader into one hex file and use AVRDUDE vial command line.

Do all your 'clients' you the same chip type, thus the same bootloader?

Others have ideas?

Lefty

Right--all the boards will be using the 328p (it's an RBBB-derived interface for an old serial gaming device; I want it to come programmed as a basic joystick for "plug it in and it works!" fun but let the end users upload their own sketches for mouse/keyboard emulation, other configuration, etc).

AVRDUDE would be fine, if anyone can point me toward how to do this (generate the correct files, etc).

The .hex files are essentially text, and it's pretty easy to manually merge two .hex files in the easy case where they don't overlap. IIRC, it's mostly a matter of removing the "end" record from one of the files and appending the other.

There are some tools and procedures around for merging .hex files (search for "hex merge avr"), but IMO they're no-so-easy kludges (usually involving conversion to some other file format, appending, and converting back), and you'd be better off learning enough about the .hex file format to do it manually.

westfw is right about the .hex files. You should be able to find directions here or on avrfreaks on how to merge the two hex files if you need more info. I suggest using a hex editor such as HxD (Windows) to ensure you don't leave any stray characters but notepad should work too if you're careful. Essentially, you'll do the following:

  1. Open your firmware file and remove the entire last line beginning with the : character and including CRLF 0x10 0x13
  2. Append the entire bootloader hex file contents to the end of your firmware
  3. Save this new merged file as something like "MyFirmware_with_Optiboot.hex"

Once you've created this single .hex containing your firmware and optiboot you'll use avrdude to flash it in one step. I've pasted the .bat file I use to do this below which includes everything you need to take a MCU from new/blank to ready to rock. You'll need to customize slightly with the right ISP frequency for your programmer (-B option), the path to your firmware (-u option), COM port (-P option) and make sure those fuse settings match what you want. It should save you a lot of time though with the syntax. Note that this is setup to use Pololu's AVR ISP programmer (my favorite ISP programmer by far and highly recommended) and I've made a couple changes to BOD and LOCK bits from standard Arduino. The last line (rundll) just adds a system "ding" to get your attention when it's done.

@echo off
rem Atmel Studio
rem high=0xDE
rem low=0xFF
rem extended=0xFC
rem lock=0xCC
rem
rem -B 1 (1500 Khz, Use pololu config utility)
rem -B 2 (750  Khz, Use pololu config utility)
rem -B 3 (200  Khz, pololu programmer default)

cls
avrdude -B 3 -v -p m328p -c avrispv2 -C c:\arduino-1.0.1\hardware\tools\avr\etc\avrdude.conf -P\\.\COM4 -b 115200 -U flash:w:"c:/Firmware/MyFirmware_with_Optiboot.hex":i -U lfuse:w:0xff:m -U hfuse:w:0xde:m -U efuse:w:0x04:m -U lock:w:0x0C:m
@rundll32 user32.dll,MessageBeep -1

Many thanks to CraigKC and westfw. I actually solved my problem with the simple expedient of "backing up" and "restoring" the whole chip with AVRDude, which may not be elegant but it seems to be working for my purposes.

avrdude -C ..\etc\avrdude.conf -p m328p -c usbtiny -U flash:r:backup_flash.bin:r
avrdude -C ..\etc\avrdude.conf -p m328p -c usbtiny -U eeprom:r:backup_eeprom.bin:r
avrdude -C ..\etc\avrdude.conf -p m328p -c usbtiny -U hfuse:r:backup_hfuse.bin:r
avrdude -C ..\etc\avrdude.conf -p m328p -c usbtiny -U lfuse:r:backup_lfuse.bin:r
avrdude -C ..\etc\avrdude.conf -p m328p -c usbtiny -U efuse:r:backup_efuse.bin:r

and then swapping chips and doing

avrdude -C ..\etc\avrdude.conf -p m328p -c usbtiny -U flash:w:backup_flash.bin
avrdude -C ..\etc\avrdude.conf -p m328p -c usbtiny -U eeprom:w:backup_eeprom.bin
avrdude -C ..\etc\avrdude.conf -p m328p -c usbtiny -U hfuse:w:backup_hfuse.bin
avrdude -C ..\etc\avrdude.conf -p m328p -c usbtiny -U lfuse:w:backup_lfuse.bin
avrdude -C ..\etc\avrdude.conf -p m328p -c usbtiny -U efuse:w:backup_efuse.bin

It didn't seem to work with just "flash", so I added everything else. Perhaps overkill, but it works.

"backing up" and "restoring" the whole chip with AVRDude

Well, that's an obvious way to create "production" files for a known-good chip setup.
I'm embarrassed not to have thought of it :frowning: