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

6 minute read

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



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.

While I had attempted to use the Microchip Snap before, I had not any luck. In my continuous attempt 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 page will describe how to setup and begin using gdb, 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. The debugging work flow is down below the setup.

1. Set the debugWIRE fuse

Before starting to debug using debugWIRE, you must set up the Uno for hardware debugging. You do this by setting the bit 6, DWEN of the High Byte Fuse. And by setting, you will clear the bit. This can be done quite easily via avrdude using a Dragon or similar programmer.

# this changes the High Fuse from DA (1 in bit 6) to 9A (0 in bit 6)
avrdude -c dragon -p atmega328p -c dragon_isp -P usb -U hfuse:w:0x9A:m 

That said, I’ll be augmenting these instructions shortly by using the Snap or another Arduino. Here are two recommended methods, if you are impatient:

Links for understanding fuses and debugWIRE information:

2. Cut the Reset trace

As debugWIRE using 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.

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.

Enable gdb symbols in Makefile

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

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 use the following with my Snap debugging, its much shorter than the Dragon version as the Snap has issues with programming. I’ll discuss these issues later in this entry. Save it in your $home folder.:

file main.elf
target extended-remote :1442
set listsize 0

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;

To use the Snap, per the instructions here, you will need to add/edit two entries in your bloom.json file. Here is my entire file, make a note of adding “disableDebugWirePreDisconnect” and “releasePostDebugSession”.

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

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

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

  "insight": {
    "enabled": true

My Debugging Process

This process is a bit sub-optimal as I want to demonstrate a process which uses a low-cost debugger (MPLAB Snap, $30) as compared to a professional debugging tool (Atmel ICE, $150). This means for the time being, there are some minor glitches.

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.

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.

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
# answer y to query as to loading symbol file
# to show the main function in the top window
l main
# to begin running the program
# to stop execution
# to set a breakpoint
br functionname | lineno
# to show values of variables etc
disp variablename

4. When you want to upload code

Here’s what it becomes a bit laborious. The process to upload code is this:

  1. Close bloom and avr-gdb
  2. make all_clean && make flash_snap
  3. Cycle power
  4. Open bloom and avr-gdb and begin to debug anew

To ease cycling power, I connect both the Uno and the Snap to a powered USB hub with a switch.

Example Display

Inital *avr-gdb* --tui screen using Bloom

Inital *avr-gdb* --tui screen using Bloom

Large Version to see detail

Setup Memory Regions

In the new release 0.5, Insight added the ability to display values in memory. A great feature of this ability is to allocate memory, assigning names and types to specific locations in memory. This makes it easy to understand the values in memory and eases determining if they are correct.

To allocate memory follow the image steps below:

  1. In avr-gdb, make sure execution has been stopped and you are at the (gdb) prompt, also Insight will indicate Stopped in the lower left-hand corner.
  2. Click on the first icon, the Tool Tip will say “Manager Memory Regions”
  3. A new window will appear, click on the "+" to create a new memory region. A short drop down will appear, click on the top line “Focused Region” (not shown.)
  4. Enter a name for the region, typically it will be the variable you wish to identify by name.
  5. Enter the specific location for the variable. This you will need to determine via your .map file or other means.
  6. Click OK to complete.
  7. View your memory regions as shown. In this view, I created a region for each element of the struct.
    Setup Memory Regions in Insight

    Setup Memory Regions in Insight

Large Version to see detail

Comments powered by Talkyard.