“Is it possible to download the contents of an ATmega168/328, essentially backing it up so that it can somehow be restored later?
For example: Let’s say I have lost the source code to a very useful program currently residing on a 328, but I need to flash it with a different sketch temporarily, then restore that original sketch. This would be useful in the case that the chip was soldered directly onto a board – a big mess to try to replace.
Is this possible in some way, perhaps by altering an ISP programmer?”
The answer is that yes indeed, it is possible– with a couple of exceptions that are worth mentioning. And on occasion, it’s even very useful.
Reading out the flash memory is straightforward with an AVR ISP programmer, such as the USBtinyISP, using avrdude from the command line.
You’ll need to have a copy of the AVR toolchain– or at least avrdude –installed on your computer. There are easy installers available for Mac (Crosspack) and Windows (MHV AVR Tools) that include this software, along with the other open source tools for AVR development. Linux packages for AVR development are also available.
Reading the flash
To read out the contents of the flash memory of your AVR, you just need to hook up your ISP programmer to the target board, and run an appropriate avrdude command to read out the flash. For “dumping” out the contents of an ATmega328P, for example, you might use the command:
avrdude -p m328p -P usb -c usbtiny -U flash:r:flash.bin:r
Where, “atmega328p” is the name of the chip, written exactly as found in the avrdude documentation, “-P usb” means that we’re using a usb-connected programmer, and “usbtiny” is the programmer type (again, taken from the list in the documentation).
The real heart of the command is the last part, -U flash:r:”flash.bin”:r. This tells avrdude to read the contents of the flash (“flash:r”), save it to a file named “flash.bin,” and specifies the format (“:r”), in this case raw binary.
Writing the flash
To write the contents of that file, “flash.bin,” we use a similar command, only now telling it to write the contents “flash:w…”:
avrdude -p m328p -P usb -c usbtiny -U flash:w:flash.bin
Again, the exact command line needs to be tailored to your particular chip, programmer, and file name.
So, when would this kind of method be useful? Yes, it’s possible that you’ve lost the source code to a piece of software– but perhaps that’s an esoteric case. We have actually found this method to be very helpful in daily use as a sort of “disk image” file.
You can, for example, read and write the full flash contents of an Arduino device that has both the Arduino bootloader and a program on top of that. Then, deploying an additional copy of that program becomes as simple as executing a single command to write the flash file. For “production programming” — that is, making many clones of an AVR program –it has the added benefits of being fast and reliably consistent, as compared with individually compiling and installing firmware for each device.
As we mentioned earlier, there are a couple of exceptions that are worth mentioning:
1.) It is possible to intentionally lock the contents of the flash memory, such that the contents cannot be read out*. You can do this by setting the lock bits of the AVR according to the values listed in the datasheet, and the lock bits cannot be reset except by erasing the whole device.
*There are known ways of getting around this, so please don’t consider lock bits sufficient defense if you are worried about someone stealing your code as a means of industrial espionage.
2.) These commands, as written, only back up the contents of the flash (program) memory. Reading out the EEPROM or fuse byte values can be done in similar ways. You can read more about the avrdude command line options in the avrdude documentation, or in the tutorial at Adafruit.
For production programming, the single avrdude statement can set the fuse bytes and also write the flash, or a makefile can be written to give multiple avrdude statements, for sequencing the order of writing flash and fuse and/or lock bits.