SimulAVR

From RepRap
Revision as of 18:07, 17 November 2013 by Traumflug (talk | contribs) (First part: up to attaching a debugger.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

SimulAVR is a simulator for AVR devices, including the ATmega328, ATmega644 and ATmega1284 commonly used in RepRap controllers.

Why talk about it here in the RepRap wiki? Well, it's an excellent tool for debugging and enhancing ATmega based controller firmwares like Teacup, Marlin or all other code which can be built from the command line. Doing so, you can:

  • attach a debugger (avr-gdb) to the running firmware,
  • communicate to the firmware through the serial line, i.e. attach Pronterface,
  • connect to other simulated devices, like a LCD display,
  • collect accurate pin change timings into a file.

The latter means, you can open this file with something like GtkWave and see accurately, which stepper does a step exactly when. Just great for verifying things like acceleration, smooth stepper movement or look-ahead.

Prereqisites

The weaknesses of SimulAVR are it's high number of dependencies on other software packages, a pretty complex mechanism for everything but attaching a debugger and an almost total lack of documentation.

To make things more simple, let me try to explain things here. For myself it took me almost a week until I got just the examples coming with SimulAVR running. The operating system of choice here is Debian/Ubuntu Linux. Stuff should apply similarly elsewhere, feel free to add such documentation.

Installation

There are several parts to do.

Compiler environment, software download

This should give you Git and basic compilers:

sudo apt-get install build-essentials git gcc-avr avr-libc

Next step is to fetch the most recent SimulAVR sources. Recent sources are important, as releases happen rarely and the packages coming with Debian/Ubuntu are even older.

git clone git://git.savannah.nongnu.org/simulavr.git

Standard build

cd simulavr
./bootstrap
./configure
make

After this, and assuming everything worked without errors, you have a working binary in src/, no need for installation.

Attaching a debugger

Assuming your installation went flawlessly, you run a simple firmware as following:

src/simulavr --device <your device> --file <your firmware>.elf

Here is:

<your device>: the ATmega you want to simulate, like "atmega644"
<your firmware>.elf: the ELF binary of your firmware. ELF binaries typically exist before .hex files are extracted from them, so you should have this already.

This runs your firmware. You won't see much, but if you hit ctrl-c, it'll stop and report how many CPU clocks it has executed.

To run the same inside a debugger, the simulator can serve as a debugger-server with the -g flag. What you then do is not to debug the simulator, but the firmware loaded inside it. This is very helpful if you look for backtraces, intermediate variable contents and such stuff.

"$" is the shell prompt, "(gdb)" the debugger promt. Type what you see behind these lines:

$ src/simulavr -g -d atmega644 -F 20000000 -f ../Teacup_Firmware/build/teacup.elf &  # <== note the &
Waiting on port 1212 for gdb client to connect...
$ avr-gdb -p 1212
[...]
(gdb) file ../Teacup_Firmware/build/teacup.elf
Reading symbols from /.../teacup.elf...done.
(gdb) target remote localhost:1212
Remote debugging using localhost:1212
[...]
(gdb) load
Loading section .text, size 0x4e24 lma 0x0
Loading section .data, size 0x3c lma 0x4e24
Loading section .eeprom, size 0x20 lma 0x810000
Loading section .mmcu, size 0x91 lma 0x910000
(gdb) cont
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x00002aca in queue_empty () at dda_queue.c:55
55	    result = ((mb_tail == mb_head) && (movebuffer[mb_tail].live == 0))?255:0;
(gdb) backtrace
#0  0x00002aca in queue_empty () at dda_queue.c:55
#1  0x00002caa in queue_wait () at dda_queue.c:196
#2  0x000034c2 in process_gcode_command () at gcode_process.c:156
#3  0x000031f8 in gcode_parse_char (c=10 '\n') at gcode_parse.c:347
#4  0x00004186 in main () at mendel.c:295
(gdb) [... etc. etc.]

As you can see, it works magnificent. All symbols are there as if you'd debug something directly on your PC. You can set breakpoints, show variables, do single stepping.