The featured image of this blog post is based on vector graphics by captainvector at 123RF.
What keeps people from using a debugger? Well, it is mostly that one has initial costs in terms of setting up the debugging environment and of learning how to use the debugging tool. Hopefully, the next iteration of my hardware debugging tool dw-link, which is able to debug classic ATtinys and ATmegaX8s, will somewhat ease that burden, in particular, because you can buy the accompanying hardware now at Tindie.
The Arduino IDEs do not offer any support when it comes to debugging classic ATtinys or ATmegaX8s. For this reason, I came up with dw-link, which turns your Arduino UNO into a debugWIRE hardware debugging probe that provides a gdbserver interface. I also described two ways to set up a debugging environment. Unfortunately, one of them is somewhat complex, and the end results of both are not completely satisfying.
Meanwhile, I have simplified the setup procedure and the end result is more satisfying. In addition, entering and exiting the debugWIRE mode is now fully automatic. The debugger became more useful because it acts now as an ISP programmer as well. Finally, the hardware part is easier to build, and you can buy a PCB, kit, or fully assembled board at Tindie.
Let us start with the end results. One setup is the integration into the PlatformIO IDE. This works smoothly and setting up the relevant INI file is very easy. However, the IDE changes the way you have to write and maintain your code completely. In particular, you cannot rely on the Arduino magic any longer and have to write pure C++ code. Further, the handling of libraries is quite different and the selection of target MCUs needs more thought. Although the changes were not dramatic, I could not bring myself to accept them. However, if you are happy with PlatformIO, the setup process itself is easy and the GUI (basically Visual Studio Code) is pleasant. The only drawback is that PlatformIO has a lot of bells and whistles, which makes working with it sometimes a bit confusing. Personally, this is not my favorite solution.
The alternative setup leads to the console-based interface of GDB, meaning you have to memorize a large number of commands, you have to type a lot, and you have to list the program text over and over again. Most people do not like this these days. And if you debug only occasionally, remembering all the GDB commands is a challenge. However, in contrast to the PlatformIO solution, you can stay in the Arduino universe and do not need to change the way you work.
What one really would like to have is a lightweight GDB GUI. And I finally found one, namely, Gede. It is easy to build, and the interface is simple and intuitive. Unfortunately, this solution works only under Linux and macOS.
As stated, setting up debugging for PlatformIO is as easy as copying an INI file into the project folder. For the GDB solution, things were more complicated. You had to edit some of the internal parameter files in order to be able to produce debug-friendly binaries in the sketch folder. This is something I simplified dramatically by providing board definition files derived from the MiniCore and ATTinyCore cores. In addition, I came up with a quick-start guide, which should make it easy to set up an initial debugging experiment.
Entering and exiting debugWIRE mode
There is a very annoying feature when dealing with debugWIRE, the protocol used for hardware debugging the classic AVR MCUs. One can enter this mode by setting the
DWEN fuse and then power-cycling the target, which means that with “professional” debuggers (e.g., SNAP or ICE), you have to manually switch the target power off and on again.
One leaves the mode by sending a particular debugWIRE command and then unprogramming the
DWEN fuse. If you forget to do this before you leave the debugger, then the MCU cannot be programmed with an ISP programmer anymore. You have to enter the debugger again and leave the mode.
The dw-link debugger usually provides the supply to the target and can therefore power-cycle, so that a user does not need to be aware of power-cycling. Furthermore, when leaving the debugger regularly, the hardware debugger will now exit the debugWIRE mode by itself. So, all in all, one does not need to care about this process anymore. In case, you want to power the target with a separate supply, this automatic process can be disabled using a jumper.
The hardware part of the hardware debugger
The only way the hardware debugger will become an integral part of my workflow is if
- it can deal with 3.3 V systems, i.e., it can do conditional level-shifting,
- it has enough juice to source power-hungry boards up to 300 mA (in order to do the automatic power-cycling),
- it disconnects the ISP lines when they are not active, and
- it can act as an ISP programmer.
The new design satisfies all of the above requirements. Additionally, it is easy to build, and the needed parts are very common. Apart from 3 SMD MOS-FETs, one can populate the board with THT parts. The PCB, a kit, and a fully assembled board are offered at the Tindie store.
The electronic design is minimalistic. It uses just three MOS-FETs, one LED, one voltage regulator, and some passive components. We need to level-shift the RESET line in a bidirectional manner and the SPI lines unidirectionally. One needs to shift the MISO line from 3.3-5 V up to 5 V, and the MOSI and SCK lines from 5 V down to 3.3-5 V. For the former two cases, no level shifting is done at all, relying on the fact that the input pins of the hardware debugger recognize a logical one already at 3.0 V. This means that this hardware debugger cannot deal with systems that use a supply voltage of less than 3 V, though.
For downshifting, we use the output pins of the hardware debugger in an open drain configuration and have pull-up resistors connected to the target supply voltage. These resistors have to be particularly strong because a number of possible target boards, e.g., the Arduino UNO, use the SCK line for driving an LED with a series resistor of 1 kΩ. For this reason, we use 680 Ω pull-up resistors which guarantee that the signal level is above 3 V on the SCK line, when we supply the board with 5 V. These pull-ups will be disabled when no ISP programming is active, giving full control of the two lines to the target system. The schematic looks as follows.
As mentioned above, I also integrated an ISP programmer (it is just the Arduino as ISP code) into the firmware. The cool thing is that the hardware debugger recognizes whether it is addressed as a debugger or as an ISP programmer by the communication speed that is used and by the initial command that is sent.
With the new design, it should be easier to build (or buy) a debugWIRE debugger probe and to set up a satisfying debugging environment easily.