Quickstart guide: dw-link & ATtiny85
This quickstart guide demonstrates how to set up a PlatformIO project for debugging on an ATtiny85 without requiring you to invest in a debug probe.
It explains
-
how to install the PyAvrOCD GDB server,
-
how to turn an Arduino UNO R3 into a debugWIRE debug probe using the dw-link firmware,
- how to set up the breadboard with the ATtiny85 on it, and
- how to use PlatformIO for debugging a program on the ATtiny.
Required hardware
- Arduino Uno (will become the debug probe)
- USB cable
- ATtiny85 as the target
- In order to connect the debug probe to the target, you need:
- a breadboard together with
- 11 Jumper wires (male-to-male)
- 2 LEDs
- 3 Resistors (10 kΩ, 220Ω, 220Ω)
- 2 Capacitors (100 nF, 10 µF)
Step 1: Installing PyAvrOCD
Go to the PyAvrOCD GitHub repo and click on the Latest button below Releases on the right side of the page.
This will open the latest release page with all its assets.
Here you can download the debug server executables for your platform. If there is nothing for you, there is an alternative way to install PyAvrOCD described below. After downloading the archive, extract the files (for Windows, I assume, you use the Windows PowerShell):
> tar xvzf avrocd-tools-X.Y.Z-architecture.tar.gz
Once you have downloaded the archive and uncompressed it, you need to decide where to place the files contained in it. I prefer the folder ~/.local/bin/ (where ~ signifies the user folder). Move the three items that you find in the tools folder of the uncompressed archive to this folder (or any other place you have chosen):
pyavrocd[.exe] - the debug server executable,pyavrocd-util- a folder with auxiliary code and data that should always be stored alongside the executable, andavr-gdb[.exe] - a current version (16.3) of the GDB debugger for AVR chips with a minimal amount of dependencies on dynamic libraries.
> mkdir ~/.local
> mkdir ~/.local/bin
> rm -rf ~/.local/bin/pyavrocd-util
> mv tools/* ~/.local/bin/
Windows
On Windows, use rmdir instead of rm -rf above.
Linux
Under Linux, you need to install udev rules so that the debug probes can communicate with the host. Either execute sudo pyavrocd --install-udev-rules once or install these rules manually (see pyedbglib README).
macOS
On a Mac, files downloaded through a browser or from an email are marked as potentially dangerous, and the system may not allow them to be executed. In this case, use the command xattr -d com.apple.quarantine FILE in order to remove the extended attribute com.apple.quarantine from the binary executable FILE.
Step 1a: An alternative way of installing PyAvrOCD
When you are not happy with the choices provided to you above, when the PyAvrOCD binaries will not start because of incompatibilities, or when you have a compatible Python installation that you do not want to duplicate, it is also possible to install PyAvrOCD from PyPI, the Python Package Index. The preferred way of doing that is using pipx, which will install an executable in the folder ~/.local/bin/ and a virtual Python environment with all the required modules in ~/.local/pipx/. Although this is, in theory, platform agnostic, you may encounter problems when USB and HIDAPI libraries have to be built from source. Note that Linux users need to install udev rules (see above).
Assuming that you have been successful in installing PyAvrOCD using pipx, we also want to download SVD files that we will need during our IDE debugging sessions. Create the folder pyavrocd-util in the folder ~/.local/bin , download the SVD archive into it, and extract the folder:
> cd ~/.local/bin
> mkdir pyavrocd-util
> cd pyavrocd-util
> wget https://github.com/felias-fogg/PyAvrOCD/releases/latest/download/svd.tar.gz -O svd.tar.gz
> tar xvzf svd.tar.gz
Step 2: Replace the outdated avr-gdb client
The avr-gdb client in the AVR toolchain, as delivered by PlatformIO, is seriously outdated (version 7.8 from 2014). Even worse, under recent versions of macOS and Ubuntu, it will not start because of incompatibilities. For this reason, it makes sense to employ a more recent version of avr-gdb. Either use the one obtainable from your OS or make use of the binary downloaded in Step 1. The folder you need to copy the client to is ~/.platformio/packages/toolchain-atmelavr/bin:
cp ~/.local/bin/avr-gdb .platformio/packages/toolchain-atmelavr/bin/
Step 3: Turn an UNO into a debug probe
Download the dw-link firmware. This means you should
- go to the dw-link GitHub repo,
- as in Step 1, click on the
Latestlabel below Releases, - download the Source Code, either zip or tar.gz,
- extract the project files using
unziportar -xvzf.
In order to install the firmware,
- connect the Arduino Uno to your computer with a USB cable,
- open VSCode/PlatformIO,
- open the folder
dw-link-x.y.zwith the extracted project files in VSCode, - and load the program
dw-link-x.y.z/src/dw-link.inointo the editor (ignore the warnings from PlatformIO), - compile the program and upload it to the Uno.
The Uno now acts as a debug probe providing a GDB RSP interface. If you configured the serial line to the Uno as 115200 baud, and click on Monitor in the PROJECT TASK menu, select the Terminal window, and then type a minus sign into this window, you should get the response "$#00". If you type Ctrl-E, the probe should respond with "dw-link".
Step 4: Set up the example project
Since PyAvrOCD is a custom debug solution, a number of things have to be specified in the PlatformIO configuration file platformio.ini, too long to present here. You can clone a project containing this file, together with a small program, from
https://github.com/felias-fogg/pio-attiny85-example
After opening a new window, click on Clone Git Repository... and type the above line into the input field. Perhaps VS Code asks you to log in to GitHub first.
The repo will be cloned, and you have to provide a destination for it.
Step 5: Set up the hardware
You need to set up the hardware on a breadboard and use six wires to connect the ATtiny to your Uno, turned into a hardware debugger. Note that the notch or dot on the ATtiny is oriented towards the left.
In reality, this could be like in the following photo.
Here is a table of all the connections so that you can check that you have made all the connections.
| ATtiny pin# | Arduino Uno pin | component |
|---|---|---|
| 1 (Reset) | D8 | 10k resistor to Vcc |
| 2 (D3) | ||
| 3 (D4) | 220 Ω resistor to target (red) LED (+) | |
| 4 (GND) | GND | red and yellow LED (-), decoupling cap 100 nF, RESET blocking cap of 10µF (-) |
| 5 (D0, MOSI) | D11 | |
| 6 (D1, MISO) | D12 | |
| 7 (D2, SCK) | D13 | |
| 8 (Vcc) | 5V | 10k resistor, decoupling cap 100 nF |
| RESET | RESET blocking cap of 10 µF (+) | |
| D7 | 220 Ω to system (yellow) LED (+) |
The yellow LED is the system LED, and the red one is the ATtiny-LED. The system LED gives you information about the internal state of the debugger:
- debugWIRE mode disabled (LED is off),
- waiting for power-cycling the target (LED flashes every second for 0.1 sec),3.
- debugWIRE mode enabled (LED is on),
- ISP programming (LED is blinking slowly),
- error state, i.e., not possible to connect to target or internal error (LED blinks furiously every 0.1 sec).
Step 6: Debug the program
If you have not activated the debug environment, now is the time to do it.
And then we are ready to go into business seriously. First, click the debug symbol (bug in front of the triangle) in the left side bar, which will bring up the debug panes on the left side. Then, click the green triangle at the top.
This will start the debugging process and open the TERMINAL window below the editor window. Click on the DEBUG CONSOLE label, so that this console will be opened. There, you will probably see that you should power cycle the target.
After having done that, the ATtiny is in debugWIRE mode, the executable will be loaded, and after that, execution is started. As required, execution will stop in the setup function, which is signified by the yellow triangle and the highlighted line (A). The most crucial control panel (B) is now the one shown on the right side at the top. It enables you (from left to right) to
- continuing/suspending execution,
- stepping-over, i.e., making a step to the beginning of the following source line in the same function,
- stepping-in, that is, making a step to the following source line (entering perhaps a new function),
- stepping-out, that is, executing the current function until it returns to the calling function,
- resetting the MCU, and
- terminating the debugging session.
From here on, I believe, you know your way around. Otherwise, consult, e.g., the debugging section of another quickstart guide.
Step 7: Start over or terminate the debugging session
If you have found the bug you were hunting, you can now leave the editor (red square), edit the program, and start again at step 6. Note that you always have to restart the debugger before any changes you made to the program are effective. In fact, changing the source text while you are debugging is not a good idea, because the correspondence between the compiled code and the source code will be lost.
Instead of starting a new edit/compile/debug cycle, you may want to call it a day and end debugging. In this case, you may wish to switch the MCU back into normal mode, in which ordinary SPI programming is possible. This can be accomplished by typing the command monitor debugwire disable into the input line of the DEBUG CONSOLE window (1) just before terminating the debugger (2).
Potential Problems
There is always the chance that something goes south, either debugging does not start at all, or something funny happens while debugging. If so, it is a good idea to have a look at the output in the DEBUG CONSOLE. Messages with the prefix [CRITICAL] often tell what went wrong. It may also be a good idea to consult the Troubleshooting and the Limitations sections.