Developing in C for the ATmega328: Setup Bloom and gdb for Hardware Debug

6 minute read

Where I illustrate how to setup using avr-gdb to debug code on the ATmega328P and replacing avarice with Bloom and the Atmel Dragon with the Microchip Snap.

Sources

Introduction

In a previous entry, I discussed using an Atmel Dragon (no longer available), avarice (an older application managing communication between the Dragon and gdb), and avr-gdb to debug a program running on a Uno (ATmega328P). My goal has been to find a suitable board which replaces the Dragon, however, at a reasonable (<$50) price point. The board would need to work with avarice or I need to find a replacement for avarice as well. This new combination needs to provide both the ability to debug as well as program the 328P.

The Microchip SNAP is that board. It supports the AVR, is supported by tools such as avrdude and Bloom and costs $34. While I had attempted to use the Microchip Snap before, I had not any luck. In my attempts to solve this problem, I ran across this link to Bloom: Enabling “AVR mode” on the MPLAB Snap. The article was great for two reasons, first, it explained why the Snap wasn’t working and provided detailed instructions as to how to fix the problem. Second, Bloom is a great replacement for avarice!!

This entry will describe how to setup and use gdb with an Arduino Uno, while this entry will provide examples of using Bloom with gdb.

Setup Debugging Process

These steps are required to setup a debugging workflow. The process is very similar to the process using avarice and Atmel Dragon. I’ll repeat it here, as this will more than likely become the standard process.

1. Cut the Reset trace

As debugWIRE uses the same pin as Reset, there is a trace on the Uno which must be cut. It’s easy and important, top is before and bottom is after. Doing so will change how easy it is to program the Uno, please review sources at the bottom of the page as to what will happen.

Cut the trace on RESET EN to disconnect Reset

Cut the trace on RESET EN to disconnect Reset

Large Version to see detail

3. Edit the Makefile for gdb

In your Makefile, you will want to ensure your compile parameter includes “-g -ggdb” so the proper code for debugging is added to your file. I use the following line in my Makefile.

# use below to setup gdb and debugging
CFLAGS = -Og -ggdb -std=gnu11 -Wall -Wundef

4. Add a .gdbinit file

It helps to have a .gdbinit file, it eases the loading and can automate some of the more tedious setup process. I setup loading the main.elf file and connecting to the target as well as a compile-link-load command, called cll. (More on cll later.) Save it in your $home folder:

file main.elf
target remote :1442
set listsize 0

define cll
make all_clean
make all
load main.elf
list
end

5. Setup Bloom as the gdb interface

Per the configuration guidance, you’ll need to create a JSON configuration file. The easiest approach is to follow the instructions and make minimal changes at the start. I have a Bloom JSON configuration file at the root of AVR_C as well.

# do this in your project folder
bloom init;

Here is my bloom.json file for the Snap:

{
  "environments": {
    "default": {
      "debugTool": {
        "name": "snap",
        "releasePostDebugSession": false
      },

      "target": {
        "name": "atmega328p",
        "variantName": "atmega328p-pu",
        "physicalInterface": "debug-wire"
      },

      "debugServer": {
        "name": "avr-gdb-rsp",
        "ipAddress": "127.0.0.1",
        "port": "1442"
      }
    }
  },

  "insight": {
    "enabled": true
  }
}

My Debugging Process

As of bloom 0.10.0, this new process is awesome! A simple overview is start bloom, start avr-gdb, begin to debug, edit the errors, reload and repeat! Bloom provides a complete full-cycle method to run-edit-reload a target, which is fantastic! Let’s begin.

1. Connect Snap to the Target

I used a AVR ISP Breadboard Adapter from Adafruit, which made the connection from the Snap SIL connector to the Uno much easier. Using the adapter, I connect 6 wires from the Snap to the breadboard like this:

Breadboard with Uno and Snap connected

Breadboard with Uno and Snap connected

Large Version to see detail

Wiring Details

Snap SIL Signal/Adapter Wire Color
1 NC none
2 VTG Red
3 GND Black
4 MISO Yellow
5 SCK Orange
6 RESET White
7 MOSI Green
8 NC none

Then connect the adapter to the Uno using a 2x3 ribbon cable. If you don’t have the 6 pin adapter, you could use male to female dupont cable, where one end would fit the pins on the Uno and the other into the single in-line connector on the SNAP.

2. Start bloom

You will want to start bloom before you start avr-gdb. Bloom doesn’t require a lot of attention, however, you will want to be able to view the window easily, as it will indicate if the connection with the target is broken. Make sure you start bloom in your project folder, as it will need to find the bloom.json file.

bloom # in project folder

3. Run avr-gdb using –tui

In the main window, preferably full-height, in the same folder as your makefile and source. Using the option –tui, provides a decent two window display of your code and commands. Its not an IDE, however, its sufficient for my purposes.:

avr-gdb --tui
# to show the main function in the top window (l as in list)
l 
# to begin running the program (c as in continue)
c 
# to stop execution
Ctrl-C
# to set a breakpoint, at a function name or set a lineno
br functionname | lineno
# to show values of variables etc
disp variablename

4. When you want to upload code

Ok, you’ve found a bug, edited your code and now you want to reload it on to the Uno… Here’s where it gets great with version 0.10! Do all of this in the comfortable confines of avr-gdb.

(gdb) cll # remember cll from above, this will compile-link-load your file back on to the Uno
(gdb) Ctrl-L # redraw screen, if using -tui
(gdb) c # begin execution to determine if fix worked! 

Its not fast as a small program might take a couple of seconds to load, however it is all automatic! The cll command comes from the .gdbinit file and performs the following:

  • make all_clean - deletes all non-source files
  • make all - recompiles all files to ensure the latest version
  • load main.elf - the magic step where bloom loads the program on the Uno
  • list - list the program again

The only step which needs to happen is a Ctrl-L to repaint the screen and a c to continue execution.

Example Display

avr-gdb --tui screen using Bloom after cll command

avr-gdb --tui screen using Bloom after cll command

Large Version to see detail

This screenshot is of avr-gdb, immediately after executing a cll command. You might notice the top half of the screen is a bit off (a Ctrl-L will clean that up). In the bottom half of the screen you will see the gdb prompt, followed by a cll. The first command to run is immediately following the cll is the delete command rm -f *.elf *.hex *.obj…. Then the commands to recompile the source are executed and once finished, a new main.elf is loaded into the Uno along with a new source/symbol file into the debugger.

At this point, the new file is in the Uno, the listing is in avr-gdb and the next step is to press Ctrl-L to clean up the screen and type c to continue with execution. Happy Debugging!

Additional Information

Links for understanding fuses and debugWIRE information:

Comments powered by Talkyard.