
If you’re making (or disassembling) anything complicated, you might yearn for a better view inside. An oscilloscope or logic analyzer can be a vital tool for digital electronics, and also surprisingly useful for embedded software. Your code can help too, via messages logged to file or serial port. But sometimes you really need an interactive view of your programโs internals, and on an embedded system this means you need anย in-circuit debugger (ICD).
Some of you already know about source-level debugging from other contexts, like debugging desktop applications in Xcode or Visual Studio, using breakpoints and single-step functionality for scripts in a web browserโs console, or using a standalone debugger like the GNU Debugger, WinDbg, or LLDB. If youโre more used to Arduino, however, this kind of tool might be new to you.
Debuggerย generally refers to a system made up of debugging software on your PC, possibly software on the chip youโre testing, and usually some hardware both inside and outside the chip. Many microcontrollers have anย on-chip debugger (OCD)ย baked into the silicon.
A debugger can step through code one line or instruction at a time while showing the contents of variables, and can view or edit memory. You can run your program at full speed until it hits aย breakpointย โ an intentional pause in your code โ where it stops and the debugger resumes. With a debugger attached, you can also typically interact with a processorโs peripherals, load programs into flash memory, and read the flash contents (unless protections are in place to prevent this!).
Whatโs a Debug Server?
The debugger app on your PC keeps a detailed memory map for your code, but you also need some hardware โ or software โ on your microcontroller to provide for reading and writing memory, trapping breakpoints, and running instructions in a controlled way. One solution is aย debug server.
Theย GNU Debugger (GDB)ย defines an especially simple server protocol for use over a serial port or network, includingย localhost. Implementations of thisย gdbserverย exist for different operating systems. Traditionally this was a software-only component, but the protocol is now commonly used as a gateway to hardware devices or emulators.
Likewise, your IDE options now range far beyond a basic GDB command line, with tools like Eclipse, Visual Studio Code, and IDA Pro supporting the same GDB protocol.
Hardware Debug Ports
It would be convenient if the debug features built into silicon were directly compatible with the GDB protocol, but OCDs are optimized for minimum cost and impact on the overall processor design. Typically debug will be provided via the same port used for programming flash memory. Some chips use vendor-specific protocols, but two industry standards are worth knowing about:ย JTAGย andย SWD.
Whatever the protocol, some hardware is needed to convert back into USB. A wide range of adapters can be used as a debug server via the open sourceย OpenOCD software, even hookups you may already have like Raspberry Pi GPIOs or an FTDI serial breakout. And the Black Magic Probe (seeย โBug Squashers,โ right) is an open hardware device that implements the debug server in firmware, providing a virtual serial port you attach directly to GDB.
JTAG: The original standardย โ Itโs not a good name. Like JPEG, it doesnโt say what the standard does, just who designed it: the Joint Test Action Group. It was designed in the mid- to late 1980s and standardized in 1990, in response to complex circuit board assemblies too difficult to automatically test.
Electrically, theย JTAG standard (IEEE 1149.1)ย is a series of shift registers that you can daisy-chain between devices. You might attach your debugger directly to a single device, or to a chain of devices within a single chip or across multiple chips. JTAG looks superficially like SPI, with a shared clock and one-way data input and output pins. But then you see a Test Mode Select (TMS) pin. Is it a chip-select? No. This is where JTAG starts to get especially low-level. Itโs actually a bit pattern that drives aย state machineย specified by the standard, which chip makers build upon to create their own JTAG state machines.
The JTAG standard specifies states for selecting a device and reading its 32-bit ID code; and JTAGโsย boundary scanย protocol addresses pins on an IC for electrical testing of assembled PCBs. Beyond this, it gets device-specific: FPGAs and processors and memories each have their own protocols. This fragmentation mirrors the fragmentation you see in the whole embedded tools space!
With modern ARM processors, at least, the standards do us a favor. The ARM Debug Interface specification describes a standardย JTAG Debug Portย with a way to access memory, peripherals, and CPU state. From there, memory-mapped registers can modify breakpoints and control the CPU.
SWD: The newcomerย โ When ARM standardized a way of accessing memory and CPU debug features over JTAG, they also took the opportunity to develop a new alternative protocol:ย Serial Wire Debug (SWD), which uses a single bidirectional data pin and a modernized packet structure. The reduced pin count makes SWD ideal for smaller embedded processors like the popular ARM Cortex-M series, and it can share pins with JTAG when the processor supports both options.
Thatโs about all you need to know about SWD itself, if you only plan to wire up the debug port on a processor and run high-level tools like GDB. The details of configuring OpenOCD, GDB, and your specific debug adapter will differ by platform, so youโll want to find the configuration file included with OpenOCD that most closely matches your situation as a starting point.
If you want to understand how debugging and even how processors work at a deeper level, the debug port is an excellent place to start digging around!
- ยปย For more onย ARMโs debugging:ย
- ยปI wrote a simple web-based SWD memory browser for the ESP8266ย and an article inย PoC||GTFOย 10.5ย .
- ยปFind a more complete open source implementation of SWD, try the Black Magic Probe or Free-DAP .
ADVERTISEMENT