Home/Collections/Embedded Systems/USB-C PD Confusion: A Field Guide to Getting Negotiation Wrong
article
May 28, 2023
27 min read
358 views

USB-C PD Confusion: A Field Guide to Getting Negotiation Wrong

USB Power Delivery negotiation looks simple in the spec and feels impossible on real hardware. Three boards, two oscilloscopes, and one blown FUSB302.

USB-C PD Confusion: A Field Guide to Getting Negotiation Wrong

USB Power Delivery negotiation looks simple in the spec and feels impossible on real hardware. Three boards, two oscilloscopes, and one blown FUSB302 later — a field guide to getting negotiation wrong less often.

Problem statement

Design: USB-C sensor puck, STM32G4 + FUSB302B (I2C PD PHY), 5 V / 9 V / 15 V request for heater load, battery charge path via BQ25798.

Symptom: device booted on some chargers (Apple 20 W), failed on Anker 65 W (no contract), smoked FUSB302 on one lab supply "PD" port that lied about capabilities.

Spec vs. bench

USB PD 3.1 spec is 800+ pages. What mattered on the bench:

  1. CC line termination — Rd for UFP sink, correct value (5.1 kΩ ±10%), on both CC pins if receptacle (only one active CC — detect which).
  2. Message timing — GoodCRC within tReceiverResponse 15–30 ms; we missed deadlines when I2C bus blocked by display driver.
  3. Caps mismatch — Request 15 V when source only offers 9 V → hard reset loop.
  4. VBUS hot-plug — inrush without ideal diode control tripped OCP on marginal sources.

Oscilloscope on CC (split termination test points) + VBUS — use trigger cheat sheet pulse mode for BMC edges after hard reset.

Failure taxonomy (our three boards)

Board A: wrong Rd

Used 4.7 kΩ "because we had reels." Some sources detected UFP; others didn't. Fix: 5.1 kΩ 1% on CC1/CC2. Immediate.

Board B: FUSB302 interrupt storm

INT_N shared with barometer on same I2C ISR — GoodCRC TX delayed. PD stack entered ErrorRecovery every 400 ms.

Fix: dedicated EXTI line for FUSB302, priority above sensor poll; PD stack on dedicated workqueue thread (Zephyr) / highest bare-metal priority.

Lesson overlaps I2C glitch debug — bus contention is PD timing failure.

Board C: blown FUSB302

Lab PSU marketed "PD" — emitted 9 V on VBUS before Accept message. FUSB302 VBUS pin abs max 28 V but internal front-end not hot-switch rated for abuse.

Fix: high-side load switch with OVP clamp; software never enables load until PSSourceOn state; power sequencing — 3.3 V MCU rail before FUSB302 I2C init.

Negotiation flow we implemented (sink)

Attach Rd → detect CC → wait Capabilities → Send Request → Accept → PS_RDY → enable load

Logged state transitions to RTT (deft). Most bugs visible as oscillation between Capability and HardReset — Saleae USB PD decoder (beta) helped on Keysight; on Rigol we counted BMC bit times manually — painful but educational.

PDO selection policy

Don't greedily max voltage — heater needs 12 W; requesting 15 V @ 3 A angered sources that renegotiated when actual draw 0.5 A. Request fixed PDO matching power need with headroom, not max headline number.

// Pseudocode — pick lowest sufficient fixed PDO
for (i = 0; i < cap_count; i++) {
  if (pdo_type_fixed && voltage_mv >= 9000 && max_ma >= 1500)
    select(i);
}

Tools and parts

ItemRole
FUSB302B + eval boardgolden compare
USB-C PD trigger tester (ZY12PDN class)source spoof
Apple 20 W, Anker 735, Dell 130 Wcompatibility matrix
Nordic Power Profiler Kit IIinrush capture

Keep a charger wall in lab — label negotiated voltage/current per device.

Compliance vs. bring-up

Formal USB-IF PD compliance — separate budget ($ + time). Pre-compliance: eye diagram on CC BMC optional for sink-only low power; do verify inrush per USB BC 1.2 / PD load rules.

EMI note: PD messaging noise on CC couples to nearby sensitive analog — see EMI bench testing; ferrite on CC optional, layout separation better.

Integration with OTA

Fleet OTA over USB-C while charging — policy: only negotiate 5 V during flash write unless heater off and PMIC confirms margin. Brownout during OTA tied to one brick in OTA lessons.

What I'd do next

Replace bit-banged PD policy with vendor stack on STM32G4 UCPD peripheral for rev D — FUSB302 fine for gen 1, not where I'd start greenfield in 2026.

Build automated charger matrix CI — robot isn't needed; intern + spreadsheet + nightly script logging contract voltage.

Document per-charger quirks in support wiki — customers blame our puck when Anker firmware update changed PDO order.

USB-C PD is a protocol stack and an analog problem. Debug both simultaneously or lose a PHY.

FUSB302 register debug sequence

When negotiation fails silently, read in order:

  1. STATUS0 / STATUS1 — attach, BC level
  2. INTERRUPT / INTERRUPTa — clear pending
  3. SWITCHES0 — pull-downs enabled on correct CC
  4. CONTROL0 — ensure not in hard reset loop

Log over RTT at state transition — not in hot path I2C read during GoodCRC window.

Charger compatibility matrix (partial)

ChargerContractNotes
Apple 20 W9 V 2.2 Abaseline gold
Anker 7359 V only after re-plugPD 3.0 PPS noise
Dell 130 W15 V offeredwe request 9 V fixed
Fake PD lab PSU9 V before Acceptblew PHY once

What I'd do next

Manish Bookreader

Electronics enthusiast, Embedded Systems Expert, Linux/Networking programmer, and Software Engineer passionate about AI, electronics, books, and cooking.

You Might Also Like

Mini Self-Balancing Robot
Electronics

Mini Self-Balancing Robot

A miniature two wheeled self balancing robot using a XIAO ESP32C3, an MPU6050 gyro/accelerometer, and 3V gear motors.

Apple’s iPhone 18 Pro Features: Launching
Tech News

Apple’s iPhone 18 Pro Features: Launching

Apple's September 2026 iPhone 18 Pro drops the flashiness for smarter fundamentals: a 2nm A20 chip that powers true AI features, variable aperture cameras that rival DSLRs, a Dynamic Island cut nearly in half, and batteries pushing 5,200mAh. It's incremental on paper, but the pieces add up to exactly what people actually want from their phones.

Keyestudio Stone Thrower
Electronics

Keyestudio Stone Thrower

A STEM kit for building a small catapult (stone thrower) that can be controlled by a Micro:bit or ESP32 board, using servos and sensors.