Skip to content
Lesson 13.7Physical Memory, Machines, and Hardware

Hardware Debugging with JTAG

JTAG began as a board-test port and became a hardware debugging path through scan chains, the TAP controller, and SWD.

Lesson 13.7
Read or listenPrint chapter or book
About 18 minutes

Keyboard shortcuts

?
Open this guide
Alt + B
Show or hide the lesson list
Alt + O
Show or fold the lesson outline
Alt + N
Open or close notes
Alt + H
Toggle semantic colours
Alt + D
Toggle page brightness
Alt + C
Toggle code brightness
← →
Move through a focused code trace
Home End
First or final step in a focused trace
Escape
Close this guide or an open panel

Reader shortcuts pause while you type in a text field.

Cheatsheet for Lesson 13.7Key ideas, reference and questions

A one-page summary of “Hardware Debugging with JTAG” you can keep beside your notes. Plain Markdown.

Lesson 13.7 — Hardware Debugging with JTAG: cheatsheet

  • Remember: A hardware debug request reaches chip-level control, rather than asking the operating system to pause one selected thread.
  • Also useful: A shift register is a conveyor for captured bits: each clock moves them one place, allowing many pin readings to leave through one wire.

Key terms

  • traces: A circuit board is a sheet of fibreglass with copper wires, called traces, printed on it.
  • boundary-scan cell: A chip that supports JTAG places a small circuit called a boundary-scan cell between each pin and the chip's internal logic.
  • scan chain: Chips on the same board are linked the same way, the output wire of one chip feeding the input wire of the next, so the whole board forms one long shift register called a scan chain.
  • Test Access Port: The JTAG connection on each chip is called the Test Access Port, or TAP.
  • TAP controller: The chip solves this with a small state machine called the TAP controller: a circuit that is always in exactly one of a fixed list of states.

Review

  • Q: A device maker wants its own failure-analysis lab to be able to debug returned units, and nobody else. Which design does that? A: Keep it locked; open it only for a signature over a fresh nonce and the unit's ID
  • Q: A phone's kernel marks a page holding a key as readable only in kernel mode. An engineer halts the processor through an open JTAG port and reads that page. Why did the kernel's protection not stop the read? A: The debug logic reads memory over the bus itself, and the kernel's rules need a running core
Download cheatsheet (.md)

Every debugger in this book so far has been a program asking other software for permission. The debugger of Lesson 6.10 asks Windows to pause a thread, and Windows agrees because the debugger holds the right access. Lesson 12.4 showed the processor enforcing a boundary between user mode and the kernel, and Lesson 13.3 put a hypervisor underneath the kernel. This lesson goes below all of them, to a debugger that asks no software at all, because it is wired into the chip.

A console’s boot and signing rules can restrict software tools. A physical debug port crosses a different boundary, which is why shipped devices usually lock it too. To see how the port gained such reach, start with its original job: finding bad solder joints.

A circuit board is a sheet of fibreglass with copper wires, called traces, printed on it. Chips are soldered on top, and every pin of every chip must make a good electrical joint with its trace. A factory building thousands of boards a day always produces some bad joints: a blob of solder that bridges two pins, or a pin that never touches its pad. Every connection has to be checked before a board ships.

For decades the check was a bed of nails: a fixture of spring-loaded metal pins pressed onto test points all over the board, so a tester could drive a signal into one end of a trace and measure it at the other. That approach struggled in the 1980s as surface-mounted chips packed their pins closer together, and it became hopeless once packages hid their connections underneath. A ball grid array, for example, joins the board through a grid of solder balls on its underside, and once it is soldered down no probe can reach them.

In 1985 a group of electronics companies formed the Joint Test Action Group to solve the problem. Their design was standardised in 1990 as IEEE 1149.1, and everyone calls it JTAG after the group. The idea was to stop probing the board from outside and build the probes into the chips.

A chip that supports JTAG places a small circuit called a boundary-scan cell between each pin and the chip’s internal logic. In normal operation the cell is transparent: signals pass straight through, and the chip behaves as though the cell were not there. In test mode the cell can do two other things:

  • capture: record the level currently on its pin, 1 or 0;
  • drive: put a chosen level onto the pin, overriding the chip’s own logic.

The cells are wired one after another into a shift register: a row of one-bit cells in which, on every clock tick, each cell takes its neighbour’s value, so a new bit enters at one end and the bit at the far end falls out. The captured levels can therefore leave one at a time through a single wire while a new pattern arrives through another. This row is the chip’s boundary-scan register, and Lesson 13.8 shifts a four-pin chip’s register one clock at a time.

Chips on the same board are linked the same way, the output wire of one chip feeding the input wire of the next, so the whole board forms one long shift register called a scan chain.

The JTAG connection on each chip is called the Test Access Port, or TAP. It uses four signals:

Signal Name Direction Job
TCK Test Clock into the chip every action happens on a tick of this clock
TMS Test Mode Select into the chip steers the port from one state to the next
TDI Test Data In into the chip bits enter the chain here
TDO Test Data Out out of the chip bits leave the chain here

An optional fifth signal, TRST (Test Reset), resets the port directly.

Every chip receives the same TCK and TMS, while the data runs in series, from the debugger’s TDI through each chip in turn and back from the last chip’s TDO:

Two chips on one JTAG chainThe clock and mode lines go to both chips at once. The data goes through them one after the other.
  1. 1 Data runs through the chips in series

    Data path, debugger TDI to debugger TDO
    TDIdebugger
    Chip A
    Chip B
    TDOdebugger

    TDI feeds chip A, chip A feeds chip B, and chip B returns the data on TDO. Each clock moves every bit one place along the chain.

  2. 2 TCK and TMS reach both chips in parallel

    TCK and TMS, in parallel
    Debugger
    Chip A and Chip B at the same time

    One clock and one mode line branch to every chip, so all of them step together.

The clock and mode lines go to both chips at once. The data goes through them one after the other.

TDI
A's TDO feeds B's TDI
TDO
TCK and TMS reach every chip
copper trace under test:
A's output pin to B's input pin
debugger
chip A:
a cell on every pin
chip B:
a cell on every pin

Testing the thick trace takes two passes. Load a 1 into the cell on chip A’s pin and switch A’s cells to drive; switch chip B’s cells to capture; then shift everything out and look at the cell on B’s pin. A good joint reads 1. Then repeat with a 0, because a pin accidentally joined to the power supply would read 1 whatever A drove. The two patterns together catch a trace stuck at 1 and a trace stuck at 0. Test software computes patterns that check every trace on a board at once.

Captured pin bits leave through one wire. This step-by-step trace needs JavaScript. Here is the code and where the run ends.

capture selected 4-bit pin pattern
out = register & 1
register = register >> 1
put incoming bit in position 3
repeat for four clocks
report outgoing bits and new register

Result: outgoing 1011, new register=0000. The original pattern left low bit first.

Final values: pattern = 13; incoming = 0; register = 0; outgoing = 1011; clock = 4.

Read every step of the lesson’s example
  1. Step 1, line 1. Start with the selected inputs. Follow the highlighted operation and the changing state below.

    pattern = 13; incoming = 0.

  2. Step 2, line 1. The four captured cells are shown from high bit to low bit.

    pattern = 13; incoming = 0; register = 13; outgoing = .

    Memory: b3 = 1; b2 = 1; b1 = 0; b0 = 1.

  3. Step 3, line 2. Clock 1 emits the old low bit 1.

    pattern = 13; incoming = 0; register = 13; outgoing = 1; clock = 1.

    Memory: b3 = 1; b2 = 1; b1 = 0; b0 = 1.

  4. Step 4, line 3. Move the remaining bits toward the output.

    pattern = 13; incoming = 0; register = 6; outgoing = 1; clock = 1.

    Memory: b3 = 0; b2 = 1; b1 = 1; b0 = 0.

  5. Step 5, line 4. Insert the chosen new bit at the high end.

    pattern = 13; incoming = 0; register = 6; outgoing = 1; clock = 1.

    Memory: b3 = 0; b2 = 1; b1 = 1; b0 = 0.

  6. Step 6, line 2. Clock 2 emits the old low bit 0.

    pattern = 13; incoming = 0; register = 6; outgoing = 10; clock = 2.

    Memory: b3 = 0; b2 = 1; b1 = 1; b0 = 0.

  7. Step 7, line 3. Move the remaining bits toward the output.

    pattern = 13; incoming = 0; register = 3; outgoing = 10; clock = 2.

    Memory: b3 = 0; b2 = 0; b1 = 1; b0 = 1.

  8. Step 8, line 4. Insert the chosen new bit at the high end.

    pattern = 13; incoming = 0; register = 3; outgoing = 10; clock = 2.

    Memory: b3 = 0; b2 = 0; b1 = 1; b0 = 1.

  9. Step 9, line 2. Clock 3 emits the old low bit 1.

    pattern = 13; incoming = 0; register = 3; outgoing = 101; clock = 3.

    Memory: b3 = 0; b2 = 0; b1 = 1; b0 = 1.

  10. Step 10, line 3. Move the remaining bits toward the output.

    pattern = 13; incoming = 0; register = 1; outgoing = 101; clock = 3.

    Memory: b3 = 0; b2 = 0; b1 = 0; b0 = 1.

  11. Step 11, line 4. Insert the chosen new bit at the high end.

    pattern = 13; incoming = 0; register = 1; outgoing = 101; clock = 3.

    Memory: b3 = 0; b2 = 0; b1 = 0; b0 = 1.

  12. Step 12, line 2. Clock 4 emits the old low bit 1.

    pattern = 13; incoming = 0; register = 1; outgoing = 1011; clock = 4.

    Memory: b3 = 0; b2 = 0; b1 = 0; b0 = 1.

  13. Step 13, line 3. Move the remaining bits toward the output.

    pattern = 13; incoming = 0; register = 0; outgoing = 1011; clock = 4.

    Memory: b3 = 0; b2 = 0; b1 = 0; b0 = 0.

  14. Step 14, line 4. Insert the chosen new bit at the high end.

    pattern = 13; incoming = 0; register = 0; outgoing = 1011; clock = 4.

    Memory: b3 = 0; b2 = 0; b1 = 0; b0 = 0.

  15. Step 15, line 6. Result: outgoing 1011, new register=0000. The original pattern left low bit first.

    pattern = 13; incoming = 0; register = 0; outgoing = 1011; clock = 4.

    Memory: b3 = 0; b2 = 0; b1 = 0; b0 = 0.

The TAP controller: steering with one wire

Section titled “The TAP controller: steering with one wire”

The debugger has one wire, TMS, for giving orders, yet it needs to say “capture now”, “shift”, and “update”. The chip solves this with a small state machine called the TAP controller: a circuit that is always in exactly one of a fixed list of states. On every tick of TCK it moves to one of two next states, and the level of TMS, 0 or 1, picks which, so a sequence of levels on TMS walks the controller wherever the debugger needs it.

Reading or loading a register follows the same main path every time:

repeat until every
bit has moved
Test-Logic-Reset:
test logic off, the chip works normally
Run-Test/Idle:
resting between scans
Capture:
load the register
Shift:
move one bit per clock
Update:
copy the new pattern out
  • Capture loads the register from its inputs: for the boundary-scan register, the levels on the pins.
  • Shift moves the register one place toward TDO per clock, so a 32-bit register takes 32 clocks, its old contents leaving through TDO as new bits arrive from TDI.
  • Update copies the new pattern to the register’s outputs in one step, so the pins never see the in-between patterns the register passes through while bits ripple along.

The path above exists twice: once for a data register, such as the boundary-scan register, and once for the instruction register, described next. Lesson 13.8 draws all 16 states, including the ones that choose between the two copies and pause a scan, and follows them one clock at a time.

One more property makes the controller impossible to lose: from any state, five clocks with TMS at 1 reach Test-Logic-Reset, as Lesson 13.8 checks state by state. A debugger unsure where the controller is sends five 1s on TMS and starts again from a known place.

Instructions choose which register sits in the chain

Section titled “Instructions choose which register sits in the chain”

Scanning through the instruction register’s copy of the path loads each chip’s instruction register, and the instruction decides which data register the data copy works on. The standard requires a few instructions and leaves the rest to each chip’s designer:

  • BYPASS selects a one-bit register. It shrinks a chip to a single bit in the chain, so the debugger can reach other chips without shifting through this one’s long registers.
  • EXTEST and SAMPLE/PRELOAD select the boundary-scan register for board tests like the one above.
  • IDCODE is optional but nearly universal. It selects a 32-bit register holding a number that identifies the chip: its manufacturer, its part number, and its version. A chip that has one selects it automatically on reset.

Those two small registers let a debugger explore a board it knows nothing about. Right after reset, one data scan reads the ID of every chip that has one. And with every chip in BYPASS, each chip adds exactly one bit to the chain, so timing a single 1 from TDI to TDO counts the chips. Lesson 13.8 does both on a two-chip board.

The standard left room for chip designers to add private instructions and data registers, and designers used that room to connect the TAP to on-chip debug logic. Through the same four wires, a debugger can then:

  • halt the processor core, stopping it between two instructions whatever it is running, the kernel included;
  • single-step, running exactly one instruction and halting again;
  • read and write the core’s registers, including the program counter;
  • read and write memory, through a debug unit that issues reads and writes on the chip’s internal bus exactly as the CPU does;
  • set hardware breakpoints and watchpoints, comparators that halt the core when it fetches from, or accesses, a chosen address. They work like the x86 debug registers of Lesson 2.4, except that they are programmed from outside the chip.

The difference from Chapter 5 is where the request goes. A Windows debugger asks the operating system to pause one thread. A JTAG debugger stops the whole processor, and the operating system has no say, because it is no longer running.

JTAG debugger
four wires
halts
debug logic
inside the chip
debugger wired to
the chip's test pins
the whole core,
kernel included
software debugger, Chapter 5
asks
pauses
Windows
debugger program
one thread;
everything else runs on

Arm’s Cortex-M processors, found in a great many microcontrollers, the single-chip computers inside things like keyboards and game controllers, show how ordinary the mechanism is: one memory write into a debug control register stops the core before its next instruction. Lesson 13.8 follows how the debugger makes that write and builds its value bit by bit.

Four signals, or five with TRST, are a lot for a small microcontroller with twenty pins. Arm designed Serial Wire Debug, SWD, which needs two: SWCLK, a clock, and SWDIO, a single data wire that the debugger and the chip take turns driving. Instead of walking a state machine, SWD sends packets.

Every transaction begins with an 8-bit request that names a register and says whether it will be read or written. The wire then turns around, and the chip answers with a 3-bit acknowledgement: OK, WAIT, or FAULT. A read then delivers 32 data bits and a parity bit, an extra bit chosen to make the number of 1s even, so that a single bit damaged on the wire shows up as an odd count:

request8 bits
turnaround
ack3 bits
data32 bits
parity1 bit
turnaround
sent by the debugger
sent by the chip
One SWD read on the single data wire, in time order from left to right. During each turnaround neither side drives the wire, so it can change hands.

Many chips offer both protocols on shared pins, with SWDIO on the TMS pin and SWCLK on the TCK pin, and a special bit sequence switches the port from one to the other. Behind either protocol sits the same debug port, so halting, stepping, and memory access work the same way. Lesson 13.8 builds the first request a debugger usually sends, bit by bit.

Everything above needs one thing: an open debug port. The debug logic does not care what software the chip runs. A debugger that can halt the core and read memory can read whatever that memory holds, such as encryption keys, a game console’s decrypted code, or a phone owner’s data. It can also write memory, so it can change code that secure boot (Lesson 13.6) checked a moment earlier. The protections of Chapters 11 and 12 — privilege levels, memory protection, the kernel boundary — are all enforced by the processor that the debugger has just stopped.

So production devices close the port, in layers from weakest to strongest:

  • Leave out the connector. Makers often omit the header and leave unmarked pads. That only adds effort, because the traces are still there.
  • Turn debug off in early boot code. The first software to run disables the debug logic. It protects only from that moment on, and only if nothing can run earlier.
  • Blow a fuse. An eFuse is a one-time programmable bit: a tiny link on the chip that the factory can change once, from 0 to 1, and that nothing can change back. Hardware reads the fuses at power-on, before any software runs, and a fuse that says “debug disabled” keeps the debug logic off. Many microcontrollers offer levels: fully open, memory reads blocked while a debugger is attached, and debug permanently disabled.
  • Require authentication. The port stays present but locked until the debugger proves it is allowed in.

Secure debug authentication is a challenge and a signed answer:

Maker's signing serviceLocked chipDebugger in the maker's labMaker's signing serviceLocked chipDebugger in the maker's labcheck it with the public keyanchored in ROM or fusesrequest debug accesschallenge: a fresh random nonce and the chip's unique IDnonce and chip ID, with the lab's credentialssignature over this nonce and this chip IDthe signaturedebug enabled until the next reset

Each part closes a specific gap. The nonce, a number used once (Lesson 10.10), makes old answers useless, because a recorded signature covers a different number. The chip ID makes each answer good for one unit, so a signature leaked from a repair bench unlocks nothing else. The private key never leaves the maker, so knowing exactly how the protocol works, as you now do, does not help anyone forge an answer.

The lock follows the chip through its life. Chips usually leave the chip factory open for manufacturing tests, are locked as the last step before a product ships, and may enter a return-for-analysis state, reachable only through authentication, if a unit comes back broken. Each step is a one-way fuse change. The hardware that reads those fuses is built to fail closed: designers assume someone will try to disturb the check itself, so any fuse reading other than a clean “open” leaves debug off.

A product shipped with its debug port open is a well-known and often repeated mistake. Fixing it costs almost nothing at the factory and is nearly impossible once the devices are in customers’ hands. Development boards sold for learning embedded programming are the opposite case: they leave SWD open on purpose and document it, because their owners are the developers.

The JTAG lab is in Lesson 13.8: a simulated two-chip scan chain that you drive one clock at a time.

Knowledge check

Lock the port, keep the repair bench

A device maker wants its own failure-analysis lab to be able to debug returned units, and nobody else. Which design does that?

Finished Lesson 13.7?

Mark it done and the lesson list shows a beside it. A chapter whose lessons are all done is marked done too. Progress is saved in this browser only.

Chapter 13: 10 lessons

This book grew out of the original Game Hacking Academy by attilathedud and has been rewritten as a beginner-first course. Like the original repository, its source is published under the Apache License 2.0.