Intro: Debugging AVR Code in Linux With Simavr
I recently started programming AVR chips, namely the ATTiny85. They can be programmed using C, compilers are readily available in Ubuntu, and you can do a LOT with them - just search for avr on this site! Anyway, I was having some trouble with my project today - the LED wouldn't flash! I couldn't figure out what was going on, as debugging these things is non-trivial. That is, until I discovered simavr.
It's a simulator for AVR in Linux that can take your ELF or HEX code and run it as if it's actually on-chip, but gives you hooks and the possibility of dumping trace files. I'll go through a simple example.
Step 1: Git It
sudo apt-get install avr-libc libelf-dev \ libglut3-dev gtkwave git build-essentialI had to remove some crappy Mesa symlink for OpenGL in 10.10. Only do this if you have problems compiling related to -lGL,
sudo rm /usr/lib/libGL.so cd /usr/lib sudo ln -s libGL.so.1 libGL.so cdFinally, use git to download the source code:
git clone git://gitorious.org/simavr/simavr.gitNow, build it.
cd simavr makeIf you get any errors, leave me a comment. I'd be happy to help. You should have a new program called run_avr in the simavr subdirectory once that completes.
Step 2: Try a Test
./run_avr ../tests/atmega88_example.axfYou should see something like this:
AVR_MMCU_TAG_VCD_TRACE 00c6:00 - UDR0 AVR_MMCU_TAG_VCD_TRACE 00c0:20 - UDRE0 Loaded 1760 .text Loaded 114 .data Loaded 4 .eeprom Starting atmega88 - flashend 1fff ramend 04ff e2end 01ff atmega88 init avr_eeprom_ioctl: AVR_IOCTL_EEPROM_SET Loaded 4 at offset 0 Creating VCD trace file 'gtkwave_trace.vcd' Read from eeprom 0xdeadbeef -- should be 0xdeadbeef.. Read from eeprom 0xcafef00d -- should be 0xcafef00d.. simavr: sleeping with interrupts off, quitting gracefullyNotice it made a VCD trace file? Let's see what that looks like in GTKWave!
gtkwave gtkwave_trace.vcdYou can drag and drop the Signals on the left into the Signals list by the Waves dialog to make them show up. You can also right click the Signals and change their properties (like making them display in binary).
Step 4: How It Worked for Me
run_avr -mcu attiny85 -freq 8000000 -t ~/repos/life/code/avr/tutorials/ctc_ledblink.oThis produced this wonderful output:
AVR_MMCU_TAG_VCD_TRACE 0053:00 - TCCR0B AVR_MMCU_TAG_VCD_TRACE 004a:00 - TCCR0A AVR_MMCU_TAG_VCD_TRACE 0038:01 - tick AVR_MMCU_TAG_VCD_TRACE 0038:02 - reset_timer AVR_MMCU_TAG_VCD_TRACE 0038:08 - OC0A Loaded 136 .text Starting attiny85 - flashend 1fff ramend 025f e2end 01ff attiny85 init Creating VCD trace file 'gtkwave_trace.vcd' avr_timer_configure-0 TOP 31250.00Hz = 256 cycles avr_timer_configure-0 TOP 488.28Hz = 16384 cycles avr_timer_configure-0 TOP 488.28Hz = 16384 cycles avr_timer_configure-0 A 2450.98Hz = 3264 cycles avr_timer_configure-0 TOP 31250.00Hz = 256 cycles avr_timer_configure-0 A 156862.75Hz = 51 cycles simavr: sleeping with interrupts off, quitting gracefullyNow that I had the trace file, I looked at it with gtkwave like in step 3. I used my datasheet and compared the registers with what I expected, and I was setting my timer registers backwards! Whoops! Anyway, it would have taken me a much longer amount of time to solve it without simavr - this way it only took a few minutes to get it up and running and find my problem. I highly recommend you try it out!
If you'd like to see some sample code, here's the source for the test I did above: