# avr-gdb doesn't stop at breakpoint

I'm trying to debug code on an 8 bit AVR microcontroller (Atmega328P) via debugWIRE using AVaRICE, avr-gdb and the JTAGICEmkII debugger.

I'm doing the following steps:

Compile the code with g2 debugging info in stabs format with no optimizations:

avr-gcc -Wall -g2 -gstabs -O0 -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega328p -DF_CPU=1000000UL

Create hex:

avr-objcopy -R .eeprom -O ihex lambda.elf lambda.hex

avrdude -pm328p -cjtag2isp -B10 -Uflash:w:lambda.hex:a

Start AVaRICE:

avarice -2 -w -B10 -j usb :4242
AVaRICE version 2.11, Jan 17 2014 02:51:59

JTAG config starting.
Found a device: JTAGICEmkII
Serial number:  07:00:00:00:5c:3c
Reported debugWire device ID: 0x950F
Configured for device ID: 0x950F atmega328p
JTAG config complete.
Preparing the target device for On Chip Debugging.
Waiting for connection on port 4242.


Start avr-gdb:

avr-gdb lambda.elf

Reading symbols from lambda.elf...done.
(gdb) target remote localhost:4242
Remote debugging using localhost:4242
0x00000000 in __vectors ()


Set a breakpoint inside the main loop in main()

(gdb) break lambda.c:74
Haltepunkt 1 at 0x2ae2: file ../lambda.c, line 74.


And contiune, hoping for the program to stop at the breakpoint:

(gdb) continue
Continuing.


The program starts fine but never stops. I can stop it with CTRL+C:

^C
Program received signal SIGINT, Interrupt.
0x00002d2e in getTime () at ../interrupts.c:51
51                      time = ints >> 5;


What puzzles me then is that if I look at the debug info dumped with

avr-objdump -g lambda.elf > debug.txt

at the same line of code, there is another address:

/* file ../interrupts.c line 51 addr 0x2d10 */

and even if I set a breakpoint at exactly that address 0x00002d2e where the program was interrupted (function getTime() is called repeatedly):

(gdb) break *0x00002d2e
Haltepunkt 2 at 0x802d2e


the program will never stop - and why is the breakpoint set at 0x802d2e?

Is it normal that the addresses don't match or could this be the reason for the breakpoints not working? Do I need to set some address offset?

Originally I tried to debug from Eclipse with the avr-eclipse plugin, and it shows the exact same behaviour, which I guess is not surprising since it uses the same tools behind the scenes.

• Have you tried Atmel Studio? It appears you have all the right tools, and should be much simpler. – DigitalNinja Mar 10 '16 at 23:45
• Yes I tried Atmel Studio but I'm using Linux and if I could get this to work I could debug in Eclipse which would be pretty simple, too... it is a shame because everything else (building, programming, ...) works just great and debugging almost works! – Torsten Römer Mar 10 '16 at 23:52
• Is the function declared static perchance? Static functions have one copy per translation unit . The offset is probably due to code relocation after linking (Code placed in flash at offset) – crasic Mar 11 '16 at 0:51
• Have you been able to break at any point in the code? – crasic Mar 11 '16 at 1:13
• @crasic the program consists of several modules, most of them contain static but also non-static functions. I was not able to break anywhere in the code yet and if I interrupt the location seems wrong, sometimes functions that should not have been called, variables have wrong/uninitialized values and so on. I think I'll try with a very simple program and see if it works then. – Torsten Römer Mar 11 '16 at 2:56

So I'll try to answer my question myself (for now).

UPDATE: As mentioned in this tutorial, compiling with option -ggdb should solve the issue, but I haven't been able to try it so far.

It seems the BREAK instructions that cause the AVR CPU to enter stopped mode are not inserted, maybe AVaRICE somehow fails to do that.

For testing, I inserted a "permanent" breakpoint using inline assembler at the end of the line of code where I want to break:

asm("break");

And see there, execution is stopped:

(gdb) target remote localhost:4242
Remote debugging using localhost:4242
0x00000000 in __vectors ()
(gdb) continue
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
measure () at ../sensors.c:110
110             asm("break");


when trying to step:

(gdb) next
measure () at ../sensors.c:110
110             asm("break");
The program is stopped at a permanent breakpoint, but GDB does not know
how to step past a permanent breakpoint on this architecture.  Try using
a command like return' or jump' to continue execution.


and jumping to the next line of code works, so that's at least a workaround, also usable in Eclipse:

So now it is about to find out why those BREAK instructions are not inserted...

As for the address mismatch, there seems to have been an issue in the build process. I started out building in Debug configuration in Eclipse, and somehow the command "avr-objcopy" to create the .hex for flashing was prefixed with a "-" in the Eclipse configuration and thus failed, and I was probably flashing an older version.

For now I created the .hex manually, now the addresses in gdb and the disassembly match.

• Substituting a break instruction is quite disadvantageous in a flash-based MCU, so it is quite understandable if a tool neglects to do so trivially, though it would be nice if the failure were not silent. Is there no address-comparator type hardware breakpoint capability on this part? – Chris Stratton Mar 11 '16 at 13:35
• Yes, Atmel mentions that inserting these software breakpoints causes wear and should be used prudently. I'll try running AVaRICE in debug mode, maybe that reveals something. And no, using debugWire, hardware breakpoints are unfortunately not available. With JTAG, there are three. – Torsten Römer Mar 11 '16 at 13:57