Blog: How Tos

Reading Atmel AVR MCUs

David Lodge 23 Jan 2016

I was recently trying to clear enough space in my office in order to find places to put other stuff. This is a sisyphean task, which I think can only be completed if I buy a bigger house.

Anyway, this quickly resulted in a pile of old technology and stuff to take apart. One of the things in this pile was an old Logitech wireless mouse where I had lost the dongle that plugs into the computer.

As I was removing the batteries to throw those into the battery recycle, I noticed that there were 8 test pads under one of the batteries.

What am I to do? You know this, take it apart! It was a lot harder than I thought as it had a number of sub-boards which were soldered to the main board. After a “gentle” extraction I got the motherboard out.

Unfortunately; I forgot to take a photo earlier in the process, so here’s the motherboard after I soldered some wires to the test pads. (For those of you who noticed how dirty my keyboard was in the past, you may be pleased to note that it has been cleaned).

That chip in the middle is an Atmel ATMEGA324PA MCU. Internally it has an AVR core, 32KB of flash memory (the 32 in the version number) and 1KB EEPROM.

Those of you who read our articles will know what I’m thinking: can I read the Flash and EEPROM memory out? Of course we can; otherwise this wouldn’t be a very exciting article.

Trying to read the chip

Those eight pads were labelled up, which read out:

GND O O SCLK
MOSI O O RESET
NCS O O MISO
VBAT O O VCC

 

Those of you who have touch SPI before might recognise SCLK, MOSI and MISO; but may notice a lack of ENABLE (or SS). This is because the AVR In Serial Programming protocol is based on SPI, which doesn’t use ENABLE, but has an extra pin, RESET, which is used to reset the MCU and enable ISP.

As you can see from the datasheet, the protocol is relatively simple, but it’s a tiny bit more complex that normal SPI. Fortunately a tool already exists to do this hard stuff for use: avrdude.

Avrdude can use a number of programmers to talk to an AVR chip, including a bus pirate and a generic Linux GPIO connection. Because I already use a Raspberry Pi for reading SPI flash, I thought I’d use this to do my reading.

You can obtain avrdude from a Raspbian package, but this hasn’t got linuxgpio compiled in; it has got linuxspi, which is meant to use the SPI pins on the PI; but I found that this was flaky and wouldn’t get a decent read. So the first step is to download it and compile it with linuxgpio enabled:

pi@raspberrypi:~/tools $ cd avrdude-6.2/
:~/tools/avrdude-6.2 $ ./configure --enable-linuxgpio
checking build system type... armv7l-unknown-linux-gnueabihf
checking host system type... armv7l-unknown-linux-gnueabihf
checking target system type... armv7l-unknown-linux-gnueabihf
checking for a BSD-compatible install... /usr/bin/install -c
[…]
Configuration summary:
----------------------
DON'T HAVE libelf
DO HAVE    libusb
DO HAVE    libusb_1_0
DON'T HAVE libftdi1
DON'T HAVE libftdi
DON'T HAVE libhid
DO HAVE    pthread
DISABLED   doc
DISABLED   parport
ENABLED    linuxgpio
pi@raspberrypi:~/tools/avrdude-6.2 $ make
make  all-recursive
make[1]: Entering directory '/home/pi/tools/avrdude-6.2'
Making all in .
[…]
pi@raspberrypi:~/tools/avrdude-6.2 $ sudo make install
make  install-recursive
make[1]: Entering directory '/home/pi/tools/avrdude-6.2'
Making install in .
make[2]: Entering directory '/home/pi/tools/avrdude-6.2'
make[3]: Entering directory '/home/pi/tools/avrdude-6.2'
/bin/mkdir -p '/usr/local/lib'
[…]

There are a selection of libraries that you will need to install before it will make; unfortunately I didn’t note these down, so you have the joy of finding these out for yourself!

The next step is to tell avrdude which pins we’re going to use. I chose a cluster around the PI SPI pins, just to make it easier. Many guides on line will say to connect up VCC to the 5V output from the Pi (pins 2 and 4). I chose not to do this for a number of reasons:

  1. Didn’t want to stress the Pi’s power supply
  2. A 3.3 V output is near the SPI pins

So, here’s my avrdude configuration, note that the pin numbers are the GPIO number, not the actual pins themselves. Anyway, append this to the end of /usr/local/etc/avrdude.conf using your favourite editor (i.e. vi):

programmer
 id = "linuxgpio";
 desc = "Use the Linux sysfs interface to bitbang GPIO lines";
 type = "linuxgpio";
 reset = 25;
 sck = 11;
 mosi = 10;
 miso = 9;
;

Now we need to wire it up – most of it is simple, only we will need to wire MOSI to MISO and MISO to MOSI:

Raspberry PI Device
Pin number Use
17 3.3v VCC
19 GPIO10, MOSI MISO
20 Ground GND
21 GPIO 9, MISO MOSI
22 GPIO 25 RESET
23 GPIO 11, SCK SCK

 

This looks a bit like this (I just want to highlight my clean keyboard really):

So let’s see whether it works. We call avrdude supplying the programmer with the -c (strange choice) flag as “linuxgpio” and the chip type, with the -p (another strange choice) flag as m324pa. You can get a list of supported chips by missing out the -p flag.

pi@raspberrypi:~ $ sudo avrdude -c linuxgpio -p m324pa

avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e9511 (probably m324pa)

avrdude: safemode: Fuses OK (E:FE, H:90, L:62)

avrdude done.  Thank you.

The above shows that we have had a successful connection to the chip and it has responded with the signature we’ve expected.

Avrdude has also read three of the device’s four fuses, these are configuration bytes that configure how the device acts, the values can be found by looking in the datasheet, or by using an online site.

For our purposes the one fuse it doesn’t show is actually the most important one for our purposes: the lock fuse. This configures whether the device can be read or written. We can read this separately using the rather strangely formatted -U flag.

The -U flag takes a number of colon (:) separated parameters, in the order of:

source:action:destination:format

For our purposes, we want to the source to be the lock fuse (lock), we want to read it (r) and write it to stdout (-) as a hex value (h). Also it would be useful if we suppress all other text, which conveniently is written to stderr:

pi@raspberrypi:~ $ sudo avrdude -c linuxgpio -p m324pa -U lock:r:-:h 2>/dev/null
0x2c

If you decode the value of the lock fuse, this shows:

The most important for use is that bottom entry – Mode 3. This means that we cannot read out the flash, as we can show by attempting to read the raw value out to a file, out.bin:

pi@raspberrypi:~ $ sudo avrdude -c linuxgpio -p m324pa -U flash:r:out.bin:r

avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e9511 (probably m324pa)
avrdude: reading flash memory:

Reading | ################################################## | 100% 10.90s

avrdude: Flash is empty, resulting file has no contents.
avrdude: writing output file "out.bin"

avrdude: safemode: Fuses OK (E:FE, H:90, L:62)

avrdude done.  Thank you.

As we can see, the highlighted bit above shows that a read failed. That’s not good and it’s non-trivial to bypass the fuse value. That’s not really a good demonstration. So, just to round this off I’ll take a reading from another popular Atmel device. In this case, an Arduino Leonardo I just had hanging around from a failed project.

The Arduino has a well defined ICSP header that I can just connect the Pi pins to. Whilst connecting I’d advise placing VCC last, as connecting this will power up the Arduino.

Now we can attempt to read it, using avrdude. My Leonardo is running with a slightly different processor than the mouse – an Atmega32U4, so we’ll need to change the -p flag appropriately:

pi@raspberrypi:~ $ sudo avrdude -c linuxgpio -p m32u4

avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e9587 (probably m32u4)

avrdude: safemode: Fuses OK (E:CB, H:D8, L:FF)

avrdude done.  Thank you.

As the Arduinos are designed to be programmed and messed with, the lock fuse should be set appropriately:

pi@raspberrypi:~ $ sudo avrdude -c linuxgpio -p m32u4 -U lock:r:-:h 2>/dev/null
0x2f

Which translates to:

Cool; so a read should work:

pi@raspberrypi:~ $ sudo avrdude -c linuxgpio -p m32u4 -U flash:r:out.bin:r

avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: reading flash memory:

Reading | ################################################## | 100% 11.63s

avrdude: writing output file "out.bin"

avrdude: safemode: Fuses OK (E:CB, H:D8, L:FF)

avrdude done.  Thank you.

pi@raspberrypi:~ $ ls -l out.bin
-rw-r--r-- 1 root root 32730 Oct  6 10:29 out.bin
pi@raspberrypi:~ $ hexdump -C out.bin | tail
00007f50  23 36 00 01 00 02 01 00  01 09 02 3e 00 02 01 00  |#6.........>....|
00007f60  80 32 09 04 00 00 01 02  02 01 00 05 24 00 10 01  |.2..........$...|
00007f70  04 24 02 04 05 24 06 00  01 07 05 82 03 08 00 ff  |.$...$..........|
00007f80  09 04 01 00 02 0a 00 00  00 07 05 04 02 10 00 01  |................|
00007f90  07 05 83 02 10 00 01 04  03 09 04 22 03 41 00 72  |...........".A.r|
00007fa0  00 64 00 75 00 69 00 6e  00 6f 00 20 00 4c 00 65  |.d.u.i.n.o. .L.e|
00007fb0  00 6f 00 6e 00 61 00 72  00 64 00 6f 00 00 00 18  |.o.n.a.r.d.o....|
00007fc0  03 41 00 72 00 64 00 75  00 69 00 6e 00 6f 00 20  |.A.r.d.u.i.n.o. |
00007fd0  00 4c 00 4c 00 43 00 00  00 00                    |.L.L.C....|
00007fda

Yep; that looks like it worked!