Electrical – avr-gdb doesn’t stop at breakpoint

avrdebuggingdebugwire

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

Upload 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.

Best Answer

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:

enter image description here

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.