VSCode PIO debugger for AVR

Hello,

I use dwdebug GitHub - dcwbrown/dwire-debug: Simple stand-alone debugger for AVR DebugWIRE chips connected directly to an FT232R/CH340/DigiSpark/LittleWire on Linux or Windows. which works fine with a minimal wiring through a simple CH340 USB Serial adapter and a very simple hack wiring (see github for info).

Can run, breakpoint, disassemble, set and read ram, flash, eeprom etc… very powerful thanks to the amazing work from David C W Brown.

For convenience, I link my Arduino Nano with a raspberry pi, which is on the same network as my main windows 7 x64 workstation.

I read several messages that stated there had no gdb server for AVR. It happens that dwdebug can work as a gdb server, therefore my PI is somewhat equivalent to a blackmagic Ice.

I did not test yet transforming a raspberry PI ZERO in such a way it could mimic a blackmagic Ice, but given the price and availability of such device, I think the idea is quite pleasant.

Before opening the hood further on RPI, I would like to know what exactly miss on the platformio vscode piece of technology to make this work.

What do you suggest as the simple way to make this happens, i.e. having a similar interaction on VSCode with an AVR as we have on th ARM platform, including disassembly and one breakpoint , of course with DebugWire specific limitations?

Many thanks in advance

Many thanks.

2 Likes

Very, very interesting. I’ll try that myself and see whether I’ll get a work avr gdb debug server.

PlaltformIO code wise, when e.g. comparing STM32 and AVR platforms, you see that implementation of debug tools adds the reference to the binary that is started to get a gdb-server up and running. See here and the current code here (_add_default_debug_tools), together with debug information for the specific boards (see first link). Once the appropiate code for AVR has been added the pio debug command should be able to launch a GDB server for it and everything else should work out of the box. I’ll try and see what I can do.

I think the extension just talks to GDB which talks to the underlying GDB server, so all these specifics should be handled automatically.

1 Like

Very clear.

I think the basic things to do are
1-launching the ‘dwdebug gdbserver’ command that launch the debugger, connects it to the default serial USB and launch the gdbserver on port 4444
2-run a windows local avr-gdb that will connect to the RPI on port 4444.

That should be enough.
I have to figure out how to install avr-gdb on my windows machine. I am currently compiling it on the RPI to test on localhost on remote terminal.

I know you can also run remote gdb through vscode see:
https://www.hanselman.com/blog/VisualStudioCodeRemoteDevelopmentOverSSHToARaspberryPiIsButter.aspx

Used that already, works decently although I experienced some vscode bugs preventing a connection, apparently solved.

Investigate how this could help in further automating the stuff…

Just use PIO and compile any AtmelAVR sketch, like blinky for an Uno. The downloaded compiler toolchain contains avr-gdb already. It’s under a path like C:\Users\<user>\.platformio\packages\toolchain-atmelavr\bin\avr-gdb.

2 Likes

Hi,

It works!

Just added as you advised
debug_tool=custom ,
debug_server=the debug_server executable and
debug_init_cmds = target remote myRpi:4444

To test this, I had a simple blink project, and I uploaded manually the firmware.elf file to the PI using scp then flashed it using dwdebug out of gdbserver.

BUT there are at least 2 identified issues:
1-Breakpoints are somewhat wild, dwdebug is designed to handle only one, nobody told PIO this…
2-Disassembly is messy, preliminary investigations show me a possible byte inversion somewhere…

Not taking in consideration some compile flags, and the fact dwdebug is not able to handle the specific gdb avr command, say “info io_registers” command.

Many thanks for your advice, and again a big hurrah for David C W Brown.
nevertheless, I think I am on the right track. Once I am able to debug flawlessly code this way, I will attack the upload part of the story. In the mean time, I have also to greatly enhance my gdb skills, therefore the confinment period is some kind of blessed time and this project finally will help me supporting not to see my children and grandchildren.

1 Like

Do you have any progress on this?

My 2 cents about this.
I took another approach and successfully configured VSCode to work and debug a simulated AVR microcontroller.
The simulator used is simavr, a project which has been developed for a long time and is pretty usable and also supports GDB (very important). Also, it not only emulates the execution of the code but can emulate most of the peripherals, interruptions, and even create graphs of the registers.

Here some of the tweaks necessary to make it work with Platformio:

The microcontroller’s code itself doesn’t need any modification to work with simavr, but using some of the macros can help to get data out of the simulation and improve the debugging experience.

Hi,
I’ve been thinking about the stated problems and possible solutions.

Maybe the following gdb configurations would be enough:
set remote hardware-watchpoint-limit 1
set remote hardware-breakpoint-limit 1

As I understood that would tell gdb that the hardware itself can’t use more than a hardware breakpoint/watchpoint at a time.

I got a similar if not the same problem when testing the other two tools: simavr and avr-debugger. The final fix was just accepted less than a week ago, so it will take some time until the compiled binaries arrive.

Meanwhile, I got a workaround by casting the address like this:

disassemble (void (*)())0x000008ca, (void (*)())0x000008da

You can even create a custom definition, both for gdb or typedef for your firmware, so you don’t have to type that ugly cast every time:

Then just use the following on the gdb terminal.

di 0x000008ca 0x000008da

Or if you used the typedef definition

disas (faddr)0x000008ca, (faddr)0x000008da

I haven’t tested this dwire-debug tool yet, but I think it would make a great addition to the repertory. :wink:

1 Like

Hi,

I jump into this post to find some help.

This is my situation:

  • Arduino Uno
  • VS Code + Platformio
  • Ubuntu OS
  • I followed the instruction to use dwire-debug and I can connect to my Arduino via dwire and command line.
  • I’m also able to program Arduino Uno using dwire-debug

but I have some troubles with the debug.

When I execute gdbserver in dwire-debug I get this output:

/opt/dwire-debug-master$ ./dwdebug device ttyUSB0, gdbserver, qr
Connected to ATmega328P on /dev/ttyUSB0 at 124899 baud.
Target ready, waiting for GDB connection.

Info : avrchip: hardware has something
Use 'target remote :4444'

What does it mean Info :

avrchip: hardware has something

However I can start a debug session from Platformio.

This is my Platformio.ini

[env:ATmega328P_dwire_gdb]
platform = atmelavr
board = ATmega328P
framework = arduino
board_build.f_cpu = 8000000L

; Debug 
debug_tool = custom
debug_port = :4444
debug_server = /home/user/.platformio/packages/toolchain-atmelavr/bin/avr-gdb
debug_init_cmds =
    set remoteaddresssize 32
    set remote hardware-watchpoint-limit 1
    target remote $DEBUG_PORT

In this scenario, I can place a break point but when I try to step to the next instruction, the program behaves as I execute a Run and also I cannot step inside a function.

Basically I cannot perform a step-by-step debug.

Is there a limitation of dwire-debug or something that doesn’t work on my system?
Because with Microchip Studio (on Windows) I can perform step-by-step debugging through dwire interface.

The other question is to program the target before start the debugging.

To do that, I added this line to my Platformio.ini

; Debug 
debug_tool = custom
debug_port = :4444
debug_server = /home/user/.platformio/packages/toolchain-atmelavr/bin/avr-gdb
debug_init_cmds =
    file "$PROG_PATH"
    load
    set remoteaddresssize 32
    set remote hardware-watchpoint-limit 1
    target remote $DEBUG_PORT

but when I start the debug I get this error:

Reading symbols from /home/user/Documents/Test_Projects/Arduino_Blink/.pio/build/ATmega328P_dwire_gdb/firmware.elf…
done.
PlatformIO Unified Debugger → Redirecting...
PlatformIO: debug_tool = custom
PlatformIO: Initializing remote target…
.pioinit:13: Error in sourced command file:

Is there something can I do to solve these problems?

Thank you!

This is weird – The debug_server is the program that is supposed to open the GDB server for you – avr-gdb is the GDB client that will connect it. avr-gdb is automatically selected, you don’t need that.

If you started dwdebug in a seperate shell, you have too to leave debug_server empty (debug_server = ).

It may be because of optimizations. Try adding

build_type = debug

to the platformio.ini and re-upload the firmware. Then restart your dwdebug command use the “PIO Debug (skip pre-debug)” debugging configuration in VSCode.

For refernce, what exact hardware and components did you use to build the debugger probe to use with dwire?

Hello @maxgerhardt,

sorry for the late reply, I was very busy.

I followed your suggestion and I adapted my platformio.ini

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:ATmega328P_dwire_gdb]
platform = atmelavr
board = ATmega328P
framework = arduino
board_build.f_cpu = 8000000L

build_type = debug

; Debug 
debug_tool = custom
debug_port = :4444
debug_server =
debug_init_cmds =
    ;file "$PROG_PATH"
    ;load
    set remoteaddresssize 32
    set remote hardware-watchpoint-limit 1
    target remote $DEBUG_PORT

This is my procedure:

  1. Compile the program in VS Code
  2. Start dwdebug in a separate shell (CTRL + T) --> ./dwdebug device ttyUSB0
  3. Load the firmware through dwdebug --> using command “l” in dwdebug.
  4. Start gdb server --> using command “gdbserver” in dwdebug.
  5. And, using the PIO Debug (skip pre-debug) configuration I can run the debug.

When I set the breakpoint for the first time, I cannot longer remove it. I don’t know why.

Is it possible to load the firmware directly through Platformio instead dwdebug?

This is my setup:

  • Arduino UNO, modified with a jumper on the reset line.
  • AZDelivery FT232R USB UART
  • Bredboard
  • 1 Diode 1N4007

I use an Atmel-Ice to enable the debugWire Interface through Microchip Studio.

Did the debugwire manual say to use this setting?

It may otherwise be a bug in avr-gdb or dwire. Not sure, but I can test it out.

Hello Max, hello fedex03, what is the current state of this ? Does the setup now work for you as expected ? Many thanks !

AVR-Stub is working just fine on real hardware, and has been for a long time… How to debug on Arduino mega 2560 - #2 by maxgerhardt