PlatformIO Community

Another tool for debugging AVR microcontrollers

After the positive simavr reception, I decided to keep exploring methods to enhance even more the coding experience with Arduino and AVR in general. As software can’t simulate hardware at 100% and sometimes there is no choice but to develop and test using the real thing, then the lack of proper debugging tools returns.

That’s why I’m going to explain another tool or better said library I found interesting. This library already had support for Arduino so I went ahead and registered it on PlatformIO, if it gets accepted then it will be available under the name avr-debugger. The library doesn’t have any dependencies, however, it needs the ISRs enabled, which Arduino already does by default, but a bare-metal configuration would need the sei() command.

The library has two relevant functions, debug_init() and breakpoint(), and as their name suggests the former will configure the related hardware and the later is only needed to add fixed breakpoints. So a main.cpp and platformio.ini would look like this:

The library has a couple of options that configure the mechanism used for debugging and also for enabling some extra capabilities, those are found here

#define AVR8_BREAKPOINT_MODE	(1) // Selects RAM of Flash breakpoints
#define AVR8_SWINT_SOURCE	(0) // Select ISR source, 0 -> INT0
#define AVR8_LOAD_SUPPORT	(0) // Enables load command for GDB, requieres modified bootloader
#define AVR8_USER_BAUDRATE	(115200) // Changes the baudrate of the GDB server

This library has two mechanisms to determine if a breakpoint was reached.
The first and default one, called RAM breakpoint mode, enables an ISR like INT0, configs it to trigger at a low level, and then puts the related pin at a low level. That will trigger the ISR constantly, however, the AVR core will always execute one instruction in the main code before jumping into ISR even if the interrupt is pending, allowing to step instructions. Its main drawback is that execution will be slower.

The second mechanism, called Flash breakpoint mode, is very similar to the technique that uses the debugWIRE protocol to set breakpoints, which involves the re-writing of the instruction where the breakpoint is set with the break instruction, and then the debugger regularly verifies if the CPU was stopped. The main difference with debugWire is that as there is no external hardware that can detect said condition then it uses the clever idea of enabling the watchdog and uses a jump instruction that jumps to itself where the breakpoint was placed, creating an infinite loop that hangs the program.

The second mechanism would have no performance penalty and give the same results as if a real external debugger was connected, however, it would also have its same drawbacks, like the faster wearing of the Flash memory.

I haven’t tested the Flash breakpoint mode yet, but for what I’ve read it would involve replacing the bootloader and having to change some fuses that enable the re-writing of flash memory.

3 Likes

Update
I got the Flash mode working. Now is possible to place breakpoints inside an ISR, so the experience should be almost as complete as if a real external debugger was used.

To make this possible the modified bootloader was a key piece, otherwise, the MCU just hangs. The author already had published its source code, but as it was meant to be built using eclipse, things got a bit harder.

I didn’t like the idea of having to install and use another IDE just for this and ended up porting the eclipse project to PlatformIO, project here, with all the configurations flags, fuses and lock bits as the author documented. The platformio.ini was configured for a crystal-less atmega328p in a breadboard, nonetheless, it should be easy to change it for any other model.

Now, to upload the bootloader and test this library to its full potential is as easy as to connect any supported external programmer to an Arduino Uno or Nano board and do:

pio run # to build the project
pio run -t fuses # to set the fuses
pio run -t program # to upload bootloader

Once done you are running the modded bootloader and the define AVR8_BREAKPOINT_MODE inside avr8-stub.h can be changed to 0 to use the Flash breakpoint mode.

Also, I could verify that the modded bootloader still works like the old one and is able to load firmware using the regular tools, so once you are done debugging just remove/comment the library.

I couldn’t test the library for any other board besides Arduino Nano and crystal-less atmega328p, and as it has the same MCU it should work with the Uno too. It would be great if somebody could test for the Mega as I don’t have one at hand to test it myself. :frowning_face:

What I could also verify was that it works fine without the Arduino framework. However I had to make my own version of the lib with a modified library.json file and comment out the framework field, otherwise, the library manager refused to add it as a dependency.

Edit: Part of the procedure was updated, better follow the instructions in the next post.

1 Like

Update,
I wrote a better howto explaining the compiling and programming procedure for the bootloader and also uploaded a ready to test example.

I found that setting up lib_compat_mode to off does the trick and no modification is required. link

1 Like

Maybe it’s better to modify library.json to explicitly state that no framework is required?

1 Like

That’s ok if you own the file… setting the lib_compat_mode in your platformio.ini is much easier if you don’t and you know it’s a ‘false positive’ :wink:

1 Like

True. Though, I could prepare a pull request to the original library.json if someone pointed me towards it.

1 Like

You’d have to ask @msquirogac about that… since he registered it, probably with a custom library manifest since it doesn’t seem to have it’s own?

The underlying issue could be the library might work without the Arudino framework, the author only supports/intended it for Arduino, so this seems to be going beyond the scope intended…

Yeah, that’s the main problem. The library was registered as an Arduino one and doesn’t have a library.json but a library.properties file.
Nonetheless, as the author likes the idea of his library working on PlatformIO, then proper support outside Arduino isn’t ruled out yet.
I was also thinking of the possibility to add this tool as an official one just like simavr, however, that’s something @ivankravets has to decide/confirm first.

1 Like

Derp… obviously didn’t go far enough down the rabbit hole :wink:

Since it’s a library + bootloader, I suspect it will remain a third-party method, but a well documented one, since you’ve basically got it in a ready to go state. But as you said, that’s for Ivan to determine.

I’ll have to dig a Mega out later and give that a try… oh, dammit… you said Mega1280, not the Mega2560… well, that won’t work! :laughing: :man_facepalming: Although, on second reading of the repo, it does say Mega2560 support… will have to investigate further now. Plus, I see this mention in a code comment (my emphasis):

Example for debugging with avr8-stub.c in plain C language, without Arduino libraries.

Could you summarize what should be done from PlatformIO side? Thanks!

Hi @ivankravets

First, as we recently got a proper library.json file, could you tell the crawler to use that new manifest?

Second, would be great if we could invoke this tool with a simple

debug_tool = avr-debugger

Instead of this long thing

debug_tool = custom
debug_port = /dev/ttyUSB0
debug_load_cmds = preload ; Force to load the firmware before debugging
debug_init_break =; Can't breakpoint on main because the stub isn't initialized yet
debug_init_cmds =
  define pio_reset_halt_target
  ; Void until support for the monitor command is included
  end
  define pio_reset_run_target
  ; Void until support for the monitor command is included
  end
  file "$PROG_PATH"
  set remotetimeout 1
  set serial baud 115200
  set remote hardware-breakpoint-limit 4 ; To determine how many breakpoints support the stub, limit to 4 to be safe
  set remote hardware-watchpoint-limit 4 ; To determine how many watchpoints support the stub, limit to 4 to be safe
  target remote $DEBUG_PORT

Third, we need help with testing, especially with AVR microcontrollers that aren’t the atmega328p. The minimum necessary for this library to work is an available UART port and an external ISR. There is a number of models that comply with that, yet we don’t have the hardware to verify it.

Finally, I think the bootloader should be put aside for now. Certainly, it adds some interesting features (flash breakpoint mode), but for what I tested is still quite experimental and only supports the atmega328p. However, even without the bootloader the library still has the RAM breakpoint mode which is pretty usable.

1 Like

Hi, @ivankravets
I know you are pretty busy these days, so I decided to give a hand and implement it myself. All my advances are in this fork and I think we will be ready to create a PR soon.

We’ve been working on avr_debugger to improve its compatibility and usability with platformio and pretty much the user experience got to the point is almost as good as using simavr, but this time we are talking about the real hardware and not a simulation. :slight_smile:

Please, give it a shot and tell me your opinion.

3 Likes

Yes, crazy summer :slight_smile: We want to release the next projects this month:

P.S: This topic is already added to our TODO list where we plan to back soon after releases mentioned above. Sorry for the delay :frowning: All releases above are blockers.

1 Like