This page looks best with JavaScript enabled

Debugging AVR Code with Simulavr

 ·  ☕ 3 min read

    When writing AVR code, it can be difficult to debug problems, especially when adding Serial.printf() calls means that the bug vanishes! Actually, only Serial.begin() is required to make the bugs vanish.

    WARNING: The simulator hangs if you let the code run and there’s a delay() call in the code. This may be an artefact of running under gdb – I have yet to test what happens if I just run the code. Might be worth bearing this in mind.

    GDB Tutorial

    See https://www.gdbtutorial.com/gdb_commands for a useful gdb tutorial

    Configuration and Execution

    In order to use the option Sketch->Optimize for Debugging in the Arduino IDE, you need to do a little configuration of the IDE to allow that option to have any effect on Arduino boards using the ATmega328P microcontroller. See this post from the future for details. Once the IDE is correctly configured, you may proceed.

    1. In the Arduino IDE, Sketch->Optimize for Debugging. Then rebuild the sketch with verbose compilation enabled in preferences.
    2. In a bash session cd /tmp/arduino/sketches/LONG_HEX_NUMBER which you can see in the compilation output from the previous step.
    3. simulavr -g -d atmega328 -f SKETCH.ino.elf to start the simulator. You do not need the Arduino board to be running, we are simulation it.
    4. Your terminal will hang, so open another [tab] and run:
      1
      2
      3
      4
      5
      
      cd /tmp/arduino/sketches/LONG_HEX_NUMBER
      avr-gdb
      file SKETCH.ino.elf
      target remote localhost:1212
      load
      

    You are now running the sketch in the simulator, and using gdb to set breakpoints etc in the normal manner.

    Useful gdb commands

    See also https://www.gdbtutorial.com/gdb_commands

    • b location - sets a breakpoint at location.
    • ir - displays all 32 registers.
    • ir r18 r25 - displays registers r18 and r25 only.
    • p variable - displays the value of a variable.
    • p (short)variable - displays the value of a variable as a short data type.
    • continue, cont or c - resumes execution after a breakpoint stop.
    • step - steps into the next executable instruction.
    • next - same as step but will treat a function call as a single instruction and will stop when the function returns, unlike step.
    • x/FMT ADDRESS - displays a memory dump of ADDRESS in the specified FMT

    FMT Specifiers

    The FMT specifier for the x command is in three parts:

    1. An optional counter to specify how many “data types” will be displayed.
    2. The format of the output:
      • o = octal
      • d = decimal
      • x = hexadecimal
      • u = unsigned int
      • s = string
      • t = binary
    3. The data type:
      • b = bytes
      • h = half words (16 bit)
      • w = words (32 bit)
      • g = double word (64 bits).
    Share on

    Norman Dunbar
    WRITTEN BY
    Norman Dunbar
    Oracle DBA & developer. (Retired). Now a published book author!