courses

Hardware Communications Protocols

Why this matters

Every embedded device is a small network of chips talking to each other, and almost none of that traffic is protected. The designers assumed the conversation was private because it happens on copper a few millimetres long, inside a plastic case. Attach a logic analyzer and it is not private any more.

This page is the map. It covers what the four buses you will meet actually are, how to tell them apart on an unfamiliar board, and which one to reach for when you want a particular kind of access. Each has its own page with the detail:

The four buses at a glance

  UART I2C SPI JTAG/SWD
Wires 2 (+GND) 2 4 + 1 CS per device 4–5 / 2
Clock None — both ends agree a rate Shared, driven by controller Shared, driven by controller Shared
Addressing None — point to point 7-bit, in band Out of band, via chip select Out of band, via TAP
Typical speed 9.6–115.2 kbaud 100 kHz – 3.4 MHz 1–100+ MHz 1–10+ MHz
What you get Whatever firmware prints Sensor and config traffic Firmware, display, radio data The silicon itself
Usual target Console, GPS, modems EEPROM, RTC, sensors, codecs NOR flash, displays The CPU

The last row is the one that matters for planning an assessment. These are not four flavours of the same thing — they give you four different levels of access, and they are worth attacking roughly in that order because the effort rises as you go right.

Telling them apart on a scope

Before you know what a bus is, you can often tell from its shape. Put a logic analyzer on the candidate pins, power-cycle the board, and look:

Two wires, one idling high, bursts of activity with no separate clock. UART. The idle-high line is TX; there is no clock to find because there is not one. See UART.

Two wires, one clearly a clock, activity in bursts of nine bits. I2C. The nine-bit grouping is the giveaway: eight data bits plus an acknowledge. Look for the START condition — SDA falling while SCL is high, which is illegal for a data bit and therefore unmistakable. See I2C.

Three or four wires, one a clock, one going low around each burst. SPI. The line that frames the burst is chip select. Data on the other two moves in both directions simultaneously. See SPI.

Four or five closely-grouped pins, often on an unpopulated header, silent until you drive them. JTAG or SWD. Unlike the others, a debug port does not usually talk unprompted — you have to initiate. That silence is why it gets missed. See JTAG and SWD.

Choosing what to attack

The buses differ in what they can give you, and the difference is not subtle.

UART gives you what the firmware chose to say. That is a limitation and also a gift, because firmware engineers are chatty. A boot log frequently includes the kernel version, the partition table, the hardware inventory, and sometimes a root shell. Cheap to attempt, high payoff, always try it first.

I2C and SPI give you what the firmware says to its own peripherals. It did not intend for you to read this. That is where configuration secrets, sensor calibration, and — critically — the entire firmware image live, because bulk storage sits on SPI.

JTAG gives you the silicon, independent of what the firmware wants. Halt the core mid-instruction, read any address, single-step, dump internal flash. When it is available and unlocked, everything else becomes unnecessary.

A rough decision order:

  1. Is there a UART? Read the boot log. It often tells you where everything else is.
  2. Is there an external flash chip? Its contents are the whole firmware. See Dumping flash.
  3. Is there a debug port, and is it locked? If unlocked, you are done.
  4. Is there interesting I2C traffic? Usually configuration rather than code, but EEPROMs hold secrets.

Voltage, and the mistake everybody makes once

Modern embedded I/O runs at 3.3 V or 1.8 V. Older and simpler devices run at 5 V. Nothing on the board tells you which, and the pins look identical.

Connecting a 5 V adapter to a 1.8 V pin will, at best, do nothing, and at worst destroy the pin, the pad, or the part. There is no undo.

⚠️ Measure before you connect. Find ground with a multimeter in continuity mode, referenced against a shield can or the negative terminal of a large electrolytic capacitor. Then measure the idle voltage on the line you intend to probe. Thirty seconds of measurement against a destroyed board is not a close decision.

Tools with a voltage-select jumper — the Tigard, most Bus Pirate models — have one specifically because this mistake is so common that the hardware is designed around it.

Worked example: identifying an unknown bus from a capture

You have a four-channel capture from an unlabelled header and no idea what it is. Work it structurally rather than guessing.

CH0  ‾‾‾‾\_/‾\_/‾\_/‾\_/‾\_/‾\_/‾\_/‾\_/‾‾‾‾    regular, symmetric
CH1  ‾‾‾\__/‾‾‾‾‾\___/‾‾‾‾‾‾‾‾\_/‾‾‾‾‾‾‾‾‾‾‾    irregular, data-like
CH2  ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾    idle high, never moves
CH3  ‾‾‾‾\_______________________________/‾‾    one long low, framing the rest

Reason it through:

  1. CH0 is a clock. Regular, symmetric, and it only runs while something else is happening. That rules out UART immediately.
  2. CH3 frames the whole burst. One transition down at the start, one up at the end. That is a chip select, which means SPI rather than I2C — I2C has no such line.
  3. CH1 is data. With CS on CH3 and clock on CH0, CH1 and CH2 are MOSI and MISO.
  4. CH2 never moves. Either nothing replied, or you have MISO on a device that was only written to.

Count the clock edges between the CS transitions. If it is a multiple of eight, you have whole bytes and the decode will line up. If it is 9, 18, 27 — go back and reconsider I2C, because that nine-bit grouping is the acknowledge.

Now set the decoder to SPI, assign the channels, and try mode 0 first; if the output is garbage but the framing looks right, work through the four SPI modes.

Passive first, always

There is an enormous difference between listening to a bus and driving it, and the difference is measured in destroyed hardware.

A bus already has a controller. If you attach a second one and both drive the same line in opposite directions, you have connected the supply rails together through two output transistors. The mild outcome is a corrupted transaction; the severe one is a dead driver on a chip you cannot replace.

⚠️ Sniff before you interact. Capture the bus with a logic analyzer, which is high-impedance and cannot drive anything, until you understand what is on it. Only then consider becoming a controller — and when you do, hold the original controller in reset first.

This is why the Tools of the Trade page distinguishes analyzers from interfaces. A Saleae or Bitscope can only listen. A Bus Pirate can talk, which makes it more useful and more dangerous.

Key takeaways

References


Related course pages: Schedule · Tools of the Trade · UART · I2C · SPI · JTAG and SWD · Dumping flash

🛠️ Maintenance note: the bus standards on this page are stable — I2C and SPI predate most of the students — so the content that ages is the tooling. Re-check the logic-analyzer software names and the Tigard/Bus Pirate model lineup each offering, and note that UM10204 Rev 7.0 replaced the master/slave terminology with controller/target, which older tutorials and decoder UIs still use.