Is it possible to flash a .hex file on an AVR MCU, which already contains the Arduino bootloader, using an AVRISP mkII, without overwriting the bootloader?

In my concrete situation, I have an Arduino Uno that I would like to program sometimes over an AVRISP mkII, and sometimes using the built-in programmer (i.e. by just connecting the Uno via USB to a computer).

For reference, given a compiled .hex file, this is what I use to upload it using the built-in programmer:

avrdude -c arduino -p atmega328p -P/dev/ttyACM0 -b115200 -D -Uflash:w:_build/image.hex:i

By default, this works as expected. I can also use avrdude to upload it using the AVRISP:

avrdude -c avrisp2 -p atmega328p -U flash:w:_build/image.hex:i

This gets my image on the board as well; however, it also seems to overwrite the bootloader, i.e. after this, I can only use the AVRISP, and not the built-in one, to upload images. The only way back, at this point, is to re-flash the bootloader (via the AVRISP) on the Uno.

If I try to instruct avrdude to upload via the AVRISP without overwriting the bootloader:

avrdude -c avrisp2 -p atmega328p -D -U flash:w:_build/image.hex:i

then it fails in the verification phase:

avrdude: verification error; content mismatch

Based on @ChrisStratton's answer, I understand this means my problem actually starts before I even try to upload it, by the compiler emitting code which has addresses that should belong to the bootloader.

Here is the command I use to compile and link (I am not using the Arduino IDE at all)

avr-g++ -c -g -O3 -w -std=c++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -I.. -mmcu=atmega328p -DF_CPU=16000000L blinkPB5.cpp -o _build/blinkPB5.cpp.o -MMD -MF _build/blinkPB5.cpp.m
avr-g++ -Os -Wl,--gc-sections -mmcu=atmega328p -o _build/image.elf _build/blinkPB5.cpp.o
avr-objdump -S _build/image.elf
avr-objcopy -Oihex -R.eeprom _build/image.elf _build/image.hex

As explained above, I can use the same resulting .hex file both via the bootloader (by just uploading it via serial) and the AVRISP (by overwriting the bootloader).

1 Answer 1


To preserve the bootloader, you should use the -D option in the ISP command line just as it was used in the bootloader upload command line. This will disable usage of full-chip erase.

I expect you would end up with something like

avrdude -c avrisp2 -p atmega328p -D -U flash:w:_build/image.hex

However, it is important to add something which I overlooked when first posting this answer, which is that the ATmega series cannot do a partial flash erase via the ISP interface in the way that it can when the bootloader causes the chip to program itself. This effectively means that you only get one shot at loading a program to an already blank area of the chip this way - after that, to load a different one to the same area you will have to do a mass erase of the entire chip and reload both the bootloader and the sketch, or else command the bootloader to erase the blocks where the sketch would reside.

Of course you will also need a hex file for your sketch with no contents that conflict with the bootloader, as while the bootloader would refuse to overwrite any of its own blocks when programming a sketch, the ISP is perfectly happy to try to write over the top of the bootloader, which would likely result in a logical AND of the bits of two different pieces of code, and cause the chip to boot to nonsense. A typical Arduino board configuration reserves space for the expected bootloader, so if the one you are using matches the size reserved in the chosen configuration, you should not have a conflict.

Another option could be to combine the bootloader and sketch hex files, literally concatenating their contents one after the other into the same file.

  • Newer Arduino IDE version already create a hex file without and with bootloader
    – Gerben
    Dec 20, 2015 at 16:21
  • OK, I've tried that and that fails with verification error; content mismatch, so I guess that confirms that the compiled .hex file starts at the wrong address. I'll edit my question to include details of how I am compiling.
    – Cactus
    Dec 21, 2015 at 11:52
  • 1
    @Cactus - the verification issue might be a limitation I overlooked when first posting this, which is that an ATmega cannot be partially erased over ISP. So while this method would work the first time you load something to the sketch area, the second time you will get the garbled result of programing a new sketch over an old one without erasing it, which would indeed be likely to cause a verification error. Oct 19, 2016 at 5:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.