One of the more challenging aspects of writing code for microcontrollers is not being able to liberally sprinkle your code with PRINT statements to show the state of variables and whatnot at particular moments.
If you’re working with Arduino-type devices you can always fire up the Serial library and print stuff that way – back down the wire to a serial terminal. But that’s even worse than sticking PRINT statements in, say, Python or Basic code when it comes to cleaning up after yourself. Because, when the code’s written and working perfectly, you need to pick your way through and get rid of all that superfluous stuff. (Or comment it out, knowing you’ll need it again for debugging when you find the code isn’t as perfect as you thought.)
But what if you’re not doing the whole bootloader/serial Arduino thing? There is an option – and a powerful one at that. You just need the right tools.
I program for AVR ATMEGA microcontrollers using Atmel Studio running on Windows. In fact, it’s the main reason I have a Windows 10 VM running on my iMac. And I burn the code into the AVR chips using the Atmel-ICE programmer.
You can code for AVR chips the hairy-chested way, and save money in the process. I hear that ‘Real’ AVR programmers do everything from the Linux command line. And I respect these people even though I have no desire to be one of them. Humanity is a tool-using species, and I like that.
If you don’t yet use Atmel Studio and the ICE programmer, but are planning to do so, one quick tip – make sure you fully install Studio before ever attaching the ICE to a USB port. The reason is that Atmel provides you with the drivers you need for the ICE. If you plug the ICE into your computer without Studio installed, Windows will attempt to install its own drivers and your life will become harder than it needs to be.
So, armed with an ICE and Atmel Studio you have an almost embarrassing array of riches when it comes to debugging tools.
Get into the mode
To get started, load your project and pull up its properties (right-click the project name and select ‘Properties’). Normally, when you’re programming your chip, you’ll see something like this:
Note how the Interface section says ‘ISP’. You need to change this to: debugWIRE.
You should also ensure the overall setting for your project is Debug mode rather than Release mode. (You’ll often be in this mode anyway while developing the code.)
Then, go to the Debug menu and select: ‘Start Debugging and Break’ (or hit Alt-F5).
In all likelihood you’re going to encounter a pop-up error box with the title ‘Launch Failed’ and the message: Failed to launch debug session with debugWIRE. This could be caused by reset line circuitry or disabled debugWIRE interface. Make sure that the reset line is free before continuing. Do you want to use SPI to enable the DWEN fuse?
You sure do. Click ‘Yes’.
The next pop-up box – ‘Cycle Power’ – is more encouraging. It should say: debugWIRE is enabled. Toggle target power then clock OK.
You should do exactly what it says. Turn off the power for your project board. Then turn it on again. (Most of life’s problems are solved this way.) Some people also recommend cycling the power for the Atmel-ICE at the same time. And this has got me out of problems when getting error messages when already in debug mode (see below about possible issues).
At this point you’ll be dropped into debugging mode and the program will most likely have halted just at the beginning of your main() function.
In the screenshot above, the yellow arrow shows where the program has reached. The red circle is a breakpoint that I’ve set. You can have as many of these as you like and they’re handy so you can check the status of registers and variables at a given point in the program.
Clicking the Continue button (green triangle) runs the code (at least as far as the next breakpoint, if any). Hit the pause button to stop.
You can still work on your code while in debugging mode. Just hit the ‘Stop debugging’ button (red square), make the changes, then hit the Continue button (green arrow) to download and run the code again.
There are many pieces of information available to you now. Some of the most useful are available from the Debug menu bar.
The rectangle icon containing ‘0X’ brings up a list of the registers and their current contents.
Three icons to the right (which looks like some kind of graph) is the one I find most useful – an I/O window with tons of information about the ports and pins, presented in a handy graphical format.
From the Debug menu, QuickWatch allows you to enter the names of variables and monitor their values, which can produce a few surprises.
You can even drag & drop variables from your code into this window. There’s also a separate window for local variables.
And there’s all the usual stuff you might expect – the ability to single step, step into, step over and much, much more.
When you’re done debugging, select Debug -> Disable debugWIRE and Close.
(This may be greyed-out if you’ve used ‘stop debugging’. Try ‘Attach to Target’ to start debugging again first.)
Your AVR chip will now be back to normal, in ISP mode, running the program you loaded.
It’s generally said that you have to be very cautious about leaving your programming session without reverting to the normal programming mode (ie, ISP). There’s a fuse that gets set when working in debugWIRE mode – called DWEN. And if you just shut down while in debugWIRE mode and leave this fuse set then your chip will be bricked until you use a high-voltage programmer (which you don’t own) to reset it.
At least, that’s what they say. Actually, the situation isn’t quite that grim.
If you do happen to shut down and turn off everything without having reset to ISP mode you can usually recover. What you do is:
- Fire up Atmel Studio
- Plug in your Atmel-ICE. If it’s already plugged in and powered, try unplugging and plugging back in to cycle the power.
- Plug in your board to the Atmel-ICE device.
- Power up your board.
- In Atmel Studio, go to: Debug -> Attach to target.
And you should be back in debugging mode. That said, you should get into the habit of shutting down properly the ‘Disable debugWIRE and Close‘ way, because who wants to tempt fate?