I²C ↔ SPI Bridge: Register Maps, Queues, and Recovery
← Back to: I²C / SPI / UART — Serial Peripheral Buses
An I²C↔SPI bridge turns I²C transactions into deterministic SPI command sequences so a low-pin MCU can reliably control SPI peripherals. The practical goal is predictable mapping, bounded latency, and recoverable operation via clear status/queue/error observability.
Definition & Scope: What an I²C↔SPI Bridge is (and isn’t)
An I²C↔SPI bridge is an I²C-addressable slave that executes SPI master transactions on behalf of an MCU, usually through a register-window model or a command-queue model.
Functional roles (system view)
- I²C slave front-end: exposes registers/windows/FIFOs; provides busy/ready, error codes, and back-pressure (e.g., NACK/ready flags).
- SPI master engine: generates CS/SCLK/MOSI timing; executes command/address/data phases and returns read data through RX windows.
- Optional GPIO/IRQ/RESET: event signaling (RX ready/error/threshold) and deterministic recovery (reset domains and safe defaults).
Two implementation families (programming model)
Register-window bridge
- Mechanism: MCU writes config/data windows → bridge triggers an SPI transfer → results appear in RX/status windows.
- Best fit: configuration-centric peripherals and short bursts; simple drivers; predictable behavior.
- Common limit: small-transaction overhead can dominate (I²C framing + per-transfer setup).
Command-queue bridge
- Mechanism: MCU pushes descriptors (CS, phases, dummy, length, flags) → bridge batches/schedules SPI sequences → status/counters provide observability.
- Best fit: mixed workloads; higher throughput via batching; cleaner recovery workflows with per-command error attribution.
- Common requirement: stronger visibility (queue depth, last error, counters) and stricter driver sequencing.
Scope boundaries (to prevent cross-page overlap)
- Covered here: translation models, register maps/queues, latency & throughput budgeting, error propagation and recovery, bring-up/production test hooks.
- Not covered here: detailed I²C timing/rise-time math, SPI mode tutorials and long-trace SI design, generic level shifting/protection/isolation/EMC (link to sibling pages).
Figure: Scope map keeps this page focused on bridge programming models, budgets, and recovery—while redirecting bus-spec details to sibling pages.
Exit links: I²C timing/rise-time → Standard / Fast / Fast+ / Hs-Mode; SPI mode/SI → CPOL/CPHA Modes, Long-Trace SI.
System Placement & Topologies: Where the bridge sits
Placement defines the bridge’s real constraints: ownership (who may enqueue commands), fanout (how many SPI slaves and CS lines), and observability (IRQ/reset hooks to avoid polling-only designs).
Topology A: Single MCU → one bridge → multiple SPI slaves (multi-CS)
- Constraint: CS fanout is finite; decide whether CS lines are native, muxed, or externally decoded.
- Risk: MISO contention if multiple slaves are not guaranteed to tri-state correctly.
- Minimum strategy: define per-device “profiles” (address width, dummy cycles, CS hold) and serialize access through a single driver queue.
Topology B: Multi-master I²C sharing a bridge (shared resource)
- Constraint: commands from different masters can interleave and corrupt SPI sequencing unless ownership is enforced.
- Risk: ambiguous fault attribution (who caused the error) without per-owner IDs and counters.
- Minimum strategy: implement an ownership token (lock/lease), reject enqueues when not owned, and expose “last error + owner” in status.
Exit link: detailed multi-master arbitration and bus-stall recovery → 7-bit / 10-bit Addressing & Multi-Master.
Topology C: Add IRQ + RESET hooks (event-driven + fast recovery)
- IRQ return path: signal RX-ready, queue threshold, and fault events to avoid poll loops and reduce latency/power.
- Reset domain: ensure reset clears the bridge state machine/queues without breaking unrelated rails; define safe power-up defaults.
- Minimum strategy: provide “clear queue + re-init profiles + probe read” as a deterministic bring-up sequence.
Figure: Placement variants highlight what must be designed explicitly: CS fanout, multi-master ownership, and IRQ/reset hooks for stable bring-up and recovery.
Minimal bring-up sequence (placement-aware)
- Identify bridge capability: read version/feature flags; verify expected programming model (window vs queue).
- Initialize global SPI parameters: set mode, max SCLK, and default CS policy (no deep SPI tutorial here).
- Apply per-device profiles: address width, dummy cycles, and safe CS hold/release rules per slave.
- Clear queues/FIFOs: ensure a known empty start state; reset sticky errors if present.
- Probe with a non-destructive read: read ID/status register to validate translation end-to-end.
- Enable IRQ thresholds (if available): RX-ready/fault events; avoid polling-only loops.
- Enter normal operation: enforce ownership/locking policy if multi-master sharing exists.
Bridge Architecture Deep-Dive: Blocks & data paths
A robust I²C↔SPI bridge is defined less by “bus labels” and more by the internal blocks that shape translation semantics, throughput/latency, and recoverability. The architecture below highlights what must be verified for both selection and implementation.
Block responsibilities (what each block must guarantee)
I²C front-end (address match + register file)
- Addressing behavior: fixed vs configurable address; optional multi-address pages for data ports.
- Control vs data surfaces: clear separation between config registers and TX/RX data ports (window or FIFO port).
- Back-pressure: explicit behavior when queues/FIFOs are full (fail-fast via status/NACK, or bounded stretching used only for internal safety).
- Failure mode to avoid: ambiguous “busy” clearing rules that create firmware deadlocks under concurrency.
Command engine (microcode/script/state machine)
- Capability tiers: single transfer → multi-segment sequence (cmd/addr/dummy/data) → batching/scheduling across descriptors.
- Atomic execution: defines “trigger” and “completion” semantics; enables cancel/flush paths for recovery.
- Failure mode to avoid: no deterministic queue flush/abort, leaving systems unrecoverable after partial faults.
SPI master (CS policy + phases + continuous transfers)
- CS policy: per-command CS assertion/hold, guard-time (X) between CS switches, and per-slave profiles.
- Phase coverage: support for dummy cycles and multi-segment reads that require CS hold across phases.
- Failure mode to avoid: CS toggling that splits a logical read into multiple physical transactions.
Buffers (TX/RX FIFO + descriptor FIFO + optional per-device queues)
- Data FIFOs: stabilize throughput and reduce MCU service rate; expose bytes-available and watermarks.
- Descriptor FIFO: isolates control-plane bursts from SPI execution timing; enables batching and priority.
- Per-device queue (if present): prevents cross-slave interleaving and simplifies error attribution.
Observability (status + counters + error codes + optional timestamp)
- Minimum set: busy/ready, queue depth, last error, sticky error, and a clear mechanism.
- Strongly recommended: per-slave success/fail/retry counters; timeout counters for field diagnostics.
- Optional: timestamps for “rare, periodic, thermal” fault correlation without logic analyzer capture.
Figure: Internal blocks define real-world behavior: back-pressure, batching, CS policy, and observability for stable recovery and field diagnostics.
Exit links: I²C timing/rise-time → Standard / Fast / Fast+ / Hs-Mode; SPI mode tutorial / SI routing → CPOL/CPHA Modes, Long-Trace SI.
Translation Model: How I²C transactions become SPI sequences
Translation is defined by two semantics: trigger (when execution starts) and completion (when results are committed and readable). A stable bridge exposes both explicitly to prevent “half-configured” execution and firmware deadlocks.
Three common mapping patterns (I²C → SPI)
Pattern 1: Register configure → single SPI transfer
- I²C action: write parameters (CS, phase, length) into control registers or a data window.
- Trigger: a commit/go bit (preferred) or a final register write that is documented as “execute.”
- Completion: busy clears and status-ready asserts; RX window becomes readable.
- Typical pitfall: execution starts before all parameters are consistent (lack of atomic commit).
Pattern 2: I²C burst → TX FIFO → SPI burst
- I²C action: stream payload into a TX FIFO/data port with a known byte count.
- Trigger: a length write + commit, or a doorbell register that starts the burst.
- Completion: transfer-done status + optional IRQ; read-back may use RX FIFO or status bytes.
- Typical pitfall: FIFO underflow/overflow without watermarks or clear error counters.
Pattern 3: Command descriptor → multi-segment SPI sequence
- I²C action: push a descriptor that encodes cmd/address/dummy/data phases and CS policy.
- Trigger: enqueue (immediate) or doorbell (batched); both must be explicit.
- Completion: per-descriptor status (success/fail), queue depth updates, and read-back data committed to RX FIFO/window.
- Typical pitfall: CS hold not supported, breaking multi-phase reads into incorrect transactions.
Two translation details that determine correctness
- Addressing encapsulation: encode register address width (8/16/24-bit) and R/W semantics (bit flag vs distinct opcodes) using per-device profiles or descriptor fields.
- CS lifecycle + read-back path: define whether CS is held across cmd/addr/dummy/data phases; return data via RX FIFO/window with a clear status-ready indicator and byte-available reporting.
Figure: A descriptor-driven read highlights the three correctness gates: multi-phase sequencing, CS hold, and a status-ready read-back contract.
Exit links: deeper SPI command conventions (opcodes/RW conventions) should be handled per peripheral datasheet; SPI mode specifics → CPOL/CPHA Modes.
Register Map Strategy: Designing a usable bridge programming model
A bridge register map is not “documentation detail” — it defines the programming contract for batch configuration, atomicity, and diagnosability. A clean partitioned map prevents half-configured execution and makes field failures explainable.
Minimal register groups (structure, not addresses)
Global config
- Core SPI policy: mode, SCLK limit, default CS policy, and guard-time (X).
- Timeout contract: bounded execution timeouts (X ms) so a peripheral fault cannot lock the bridge indefinitely.
- Interrupt controls: enable/mask for RX-ready, done, error, and watermark events (if supported).
Device profiles (per slave)
- Phase templates: command bytes, address width, dummy cycles, and direction conventions (flag vs opcode).
- CS behavior: CS id, CS-hold enable across phases, and per-device overrides when needed.
- Why profiles matter: pushes “easy-to-misconfigure” details out of ad-hoc firmware packing into a single audited place.
Data windows / ports
- TX/RX access: window ports or FIFO ports with clear byte-count and bytes-available reporting.
- Read-back hygiene: RX reads must be gated by status-ready/bytes-available to avoid stale data or alignment drift.
Status / error / counters
- Must-have fields: busy, queue depth, last errcode.
- Field diagnostics: sticky error + clear mechanism; timeout counters; per-device success/fail/retry counters.
Two register-map patterns that prevent “hidden” firmware failures
- Indirect addressing (index + data): compact for large spaces, but requires an atomic access path or a lock/latched index to avoid multi-thread/multi-owner races.
- Atomic commit (shadow → apply): multi-byte updates must not execute mid-write; use a commit/apply gate so updates become visible all-at-once.
Versioning & compatibility guardrails
- Regmap version: a single register that changes whenever field meanings or group layouts change.
- Feature flags: capability bits (queue support, CS-hold, timestamps, per-device queues) that allow firmware to choose a safe path.
- Forward-compat rule: unimplemented bits read as a defined value and ignore writes, preventing accidental behavior shifts.
Figure: A partitioned regmap keeps control-plane configuration, data-plane ports, and diagnostics separate — enabling atomic updates and predictable recovery.
Exit links: I²C multi-master arbitration details → 7-bit / 10-bit Addressing & Multi-Master; SPI electrical/signal-integrity details → Long-Trace SI.
Command Queue & Scheduling: Descriptor format, batching, DMA hooks
A command queue turns “many small transactions” into a predictable execution pipeline. The key is a descriptor contract that supports batched triggers, clear completion, and back-pressure without stalling the entire I²C domain.
Descriptor fields (concept-level, grouped by purpose)
- Target & policy: CS id, optional mode/SCLK override, CS-hold flag.
- Phases: cmd bytes, addr bytes, dummy cycles (multi-segment reads).
- Payload: length, direction (R/W), TX source, RX destination (FIFO/window).
- Control flags: fence/barrier, IRQ-on-done, auto-increment (if supported).
- Identity: sequence/tag id to bind completion and error attribution to the correct request.
Queue strategy (performance without cross-device contamination)
- Single queue: simplest, but risks interleaving that complicates CS policy and error attribution.
- Per-device queue: isolates slaves, enables fair scheduling, and preserves phase/CS constraints more safely.
- Priority: control-plane (short/latency-sensitive) ahead of data-plane (bulk throughput) with starvation prevention.
- Batching: merge adjacent compatible descriptors (same slave, same phase policy) into a larger SPI burst.
CPU load control & back-pressure (must be explicit)
- IRQ + watermarks: RX-ready / queue-threshold events reduce polling and stabilize latency.
- DMA / zero-copy hooks (if supported): bulk ports or DMA-friendly windows cut CPU service rate for large blocks.
- Back-pressure options: status code (preferred), bounded stretch (only as internal safety), or NACK on enqueue when full.
Figure: Scheduling adds determinism: descriptors enter a FIFO, a scheduler applies priority and batching, and explicit status/IRQ provide back-pressure and completion.
Exit links: I²C rise-time and pull-up sizing details → Open-Drain & Pull-Up Network; protocol analyzer usage patterns → Logic / Protocol Analyzer.
Performance Budgeting: Throughput, latency, and worst-case analysis
Bridge performance is determined by end-to-end latency components and the effective payload bandwidth on both buses. A practical budget prevents “link-speed thinking” from hiding small-transaction overheads and queue-driven tail latency.
End-to-end latency decomposition (budget template)
- T_total = T_I²C + T_bridge + T_SPI + T_return
- T_I²C: frame overhead (start/address/ACK/stop) + payload bytes; dominates for small ops.
- T_bridge: enqueue/commit + queue wait; tail latency grows with depth and priority policy.
- T_SPI: CS policy + phase bytes (cmd/addr/dummy/data) + guard time (X).
- T_return: readback and completion method (poll vs IRQ) + host service interval (X).
Bottleneck identification (use effective bandwidth)
- Small transactions: effective throughput is limited by I²C framing + round trips; batching (descriptor commit) reduces overhead per operation.
- Bulk transfers: effective throughput is limited by SPI phase overhead (cmd/addr/dummy/CS) and by bridge service (FIFO depth + watermarks).
- Practical ceiling: overall payload rate ≤ min(effective I²C, internal move, effective SPI, return-path service).
FIFO depth & watermark sizing (worst-case-driven)
- Cover the worst burst: depth must absorb the largest batched operation (B_worst) without overflow.
- Cover service gaps: add headroom for the worst host/IRQ service interval (Δt_service = X) when fill exceeds drain.
- Watermark hysteresis: define WM_high and WM_low (X% / X%) to avoid IRQ thrash and stabilize tail latency.
Margin & timeouts (bridge-specific contract)
- SCLK margin: configure SPI clock with headroom vs peripheral max (X%), accounting for phase overhead and CS policies.
- T_busy_max (I²C-side): maximum time to wait for busy to clear before triggering recovery.
- T_spi_max (SPI-side): maximum execution time per descriptor/burst for watchdog/abort (if supported).
Figure: Use a latency waterfall to expose tail contributors (queue wait, return path) and compare effective payload bandwidth to locate the true bottleneck.
Exit links: I²C mode limits and timing details → Standard / Fast / Fast+ / Hs-Mode; SPI line integrity constraints → Long-Trace SI.
Robustness & Recovery: Error taxonomy + recovery state machine
Bridge systems fail when errors are not observable and recovery lacks a bounded plan. A robust design defines error surfaces (sticky/attributed/counted) and a staged recovery ladder that prevents repeated execution of destructive commands.
Error taxonomy (bridge-visible symptoms)
I²C-side (bridge impact)
- NACK: queue full, busy, or bridge in ERROR/RECOVER state.
- Timeout / hang: busy never clears, or bus cannot complete a transaction (bounded by T_busy_max = X).
- Arbitration loss (multi-master): partial writes must not trigger execution; commit/apply gates are required.
SPI-side
- Peripheral no-response: MISO stuck, readback all-0/all-1, or status never becomes ready (bounded by T_spi_max = X).
- Integrity alarms: CRC/check failures (if available) should be counted and attributed (cs/seq).
- CS policy violations: unintended CS toggles can desynchronize peripheral state machines.
Power-side
- Brown-out: partial configuration and sticky faults; safe restart must re-apply profiles and re-probe key peripherals.
- Write-protect windows: destructive write/erase sequences require idempotent guards (seq/fence) and explicit confirmation before retry.
Error propagation model (must be visible to firmware)
- Immediate: last error code + last completed/failed seq id.
- Sticky: sticky error latch with explicit clear; prevents “error overwrite” during cascading faults.
- Attribution: last CS id (or device id) + seq/tag allows correct ownership and postmortem mapping.
- Trends: counters for timeouts/retries/NACKs/aborts to expose chronic instability.
Recovery ladder (bounded actions + exit criteria)
- Soft retry: retry up to N times (X) for transient errors; require seq-tag matching on completion.
- Re-init SPI engine: rewrite mode/SCLK/profile subset, flush queues/FIFOs; pass when probe readback matches (X).
- Toggle reset domain: assert reset pin, clear sticky error, re-apply profiles; pass when bridge returns to IDLE and counters stabilize.
- Power-cycle domain: for persistent brown-out/lockups; cold-start and re-probe before accepting traffic.
Preventing repeated destructive execution (idempotency guard)
- Sequence/tag: each write-class command carries a seq; completion must echo the same seq before it can be acknowledged.
- Fence/barrier: separate “state-changing” ops from batched traffic; do not merge across a fence.
- Commit semantics: prefer shadow→apply for configurations; on failure, do not apply partial state.
Low-power wake & sticky-state handling
- Freeze: block new enqueues until bridge state is known-good.
- Flush: clear descriptor and data FIFOs; increment flush counters for field visibility.
- Re-probe: read a lightweight status/id register on critical peripherals before resuming normal scheduling.
Figure: A bounded recovery machine prevents “hung forever” behavior and makes failure modes visible through sticky errors, attribution, and counters.
Exit links: Multi-master corner cases → 7-bit / 10-bit Addressing & Multi-Master; low-power coordination → Low-Power Hooks.
Hardware Implementation Hooks: levels, CS routing, MISO tri-state, protection
Bridge-specific board hooks focus on mixed signaling behavior (I²C open-drain vs SPI push-pull), multi-slave selection integrity (CS fanout), and shared-line safety (MISO contention). The goal is stable bring-up and bounded recovery without pulling in full level-translation or protection design guides.
Bridge-only hardware pitfalls (what to lock down early)
Level domains & pin tolerance (I²C vs SPI)
- I²C side: open-drain inputs must tolerate external pull-ups to the intended rail; define a safe default state across power sequencing.
- SPI side: push-pull edges can overshoot; confirm SPI I/O tolerance and any separate VIO pins for I²C vs SPI domains.
- Bridge contract: define which rail owns pull-ups and which rails may be unpowered while signals toggle (avoid undefined behavior).
CS fanout & routing integrity
- Default CS state: ensure CS lines remain deasserted during reset and brown-out; avoid accidental peripheral selection.
- Fanout method: bridge-native CS vs GPIO decode/expansion must preserve ordering, guard time (X), and non-overlap.
- Edge control: CS series-R reduces ringing that can look like extra edges to sensitive peripherals.
MISO contention (multi-slave shared line)
- Tri-state guarantee: confirm each slave releases MISO when CS is high; “almost-tri-state” behaviors cause intermittent faults.
- Idle definition: add a weak pull (PU/PD) to define MISO idle level and make analyzer traces interpretable.
- Isolation hook: reserve 0Ω links or jump points to isolate branches during debug when a device drives MISO unexpectedly.
Minimal protection & damping (bridge-relevant only)
- SCLK/MOSI/CS: series-R near the driver to tame overshoot; prevents false sampling and CS “double-tap” effects.
- MISO: low-cap ESD + optional weak pull; avoid turning shared-line protection into a bandwidth limiter.
- I²C: keep protection capacitance consistent with rise-time budgets; do not silently consume the bus capacitance margin.
Reset & power-up defaults (avoid ghost-powering)
- Reset reachability: provide a controllable reset path for the bridge and critical slaves (GPIO/RESET pin).
- Quiet outputs: keep SPI outputs quiescent until rails are valid; do not clock unpowered devices through IO clamp paths.
- Defined defaults: CS deasserted, SCLK idle, and stable pull-ups prevent accidental command parsing during boot.
Figure: Bridge wiring emphasizes CS non-overlap, shared MISO safety, and minimal damping/protection hooks without expanding into a full protection or translation guide.
Exit links: detailed voltage-domain translation → Level Translation; port hardening and surge/ESD strategy → Port Protection.
Engineering Checklist: design → bring-up → production (with pass criteria placeholders)
A bridge is production-ready when the programming model is deterministic, worst-case buffering is covered, and recovery is bounded and observable. The checklist below is organized as three gates with pass criteria placeholders (X).
Design Gate
- Atomic config: shadow→apply or commit gates; version and feature flags are readable before enabling traffic.
- Worst-burst coverage: queue/FIFO depth covers worst-case burst (B_worst) under service interval Δt_service = X.
- Bounded timeouts: T_busy_max and T_spi_max defined; recovery ladder is staged (retry → re-init → reset → power-cycle).
- CS/MISO safety: CS default deasserted, MISO contention hooks exist (PU/PD, isolation links), reset/INT reachability defined.
- Observability: busy, queue depth, last/sticky error, and counters exist for field diagnosis.
Pass criteria (X): No FIFO overflow at worst-burst assumptions; recovery bounded to X ms; CS remains deasserted across reset/brown-out.
Bring-up Gate
- Golden trace: logic analyzer shows I²C write → bridge execute → SPI phases (cmd/addr/dummy/data) with expected CS behavior.
- Completion integrity: status-ready and readback data align with seq/tag; no “old data” reuse across transactions.
- Fault injection: remove a slave, force MISO low, or induce NACK/queue-full; system transitions to RECOVER and returns to IDLE.
- Recovery validation: flush/abort/reset actions clear busy; sticky errors remain readable and clearable; counters increment predictably.
Pass criteria (X): Golden waveform matches across X repetitions; injected faults recover within X ms without stuck busy; seq/tag attribution is consistent.
Production Gate
- BIST/loopback (if available): verifies SPI engine and readback path without external dependencies.
- Counter strategy: define clear-on-boot rules, sampling/log intervals, and alarm thresholds (X) for field diagnostics.
- Power-cycle & brown-out: repeated cycles do not produce partial-apply states; cold-start re-probe is stable.
- Aging & regression: long-run tests keep error counters bounded; anomalies remain attributable (device/seq).
- Version control: firmware checks regmap version/feature flags; prevents cross-version misinterpretation in production.
Pass criteria (X): Power-cycle/brown-out pass X cycles; counters enable actionable diagnosis of top X failures; acceptance tests remain repeatable across builds.
Figure: Gate-based acceptance converts bridge design into repeatable artifacts (waveforms/logs/counters) and measurable pass criteria placeholders (X).
Applications: proven I²C↔SPI bridge patterns (constraint-first)
This section lists repeatable usage patterns for I²C-to-SPI bridging and the constraints that decide success (throughput, tail latency, multi-slave behavior, diagnostics). Each pattern names the must-have bridge features and includes concrete part-number examples.
- Main constraints: CS fanout, MISO tri-state correctness, small-transaction overhead (I²C round-trips).
- Must-have features: multiple CS outputs (or CS expansion), predictable CS hold behavior, readable status/last-error.
- Practical hooks: queue/batch small reads, add per-device retry limits, log last CS / last seq / error counters.
- Main constraints: configuration consistency, safe retries, and read-back verification loops.
- Must-have features: atomic commit model (shadow→apply), sticky error + last-error code, explicit busy/ready.
- Practical hooks: sequence numbers for idempotency; never auto-retry destructive commands unless confirmed safe.
- Main constraints: intermittent connectivity, power cycling, and “stuck” states after brown-out.
- Must-have features: abort/flush, counters, sticky error reporting, controllable reset pin behavior.
- Practical hooks: graded recovery policy: soft retry → SPI re-init → toggle reset → power-cycle domain.
- Main constraints: I²C transaction overhead dominates when payloads are small and frequent.
- Must-have features: command queue + batching, deep FIFO, watermark IRQ, deterministic busy semantics.
- Rule-of-thumb gates (placeholders): if required throughput > X kbps with tail latency < X ms, consider direct SPI or a different topology.
Many “bridge” parts are direction-specific. For the reverse case (SPI host controlling I²C devices), a dedicated option is NXP SC18IS604 (SPI→I²C bridge; not a drop-in replacement for I²C→SPI use).
IC Selection Notes: spec checklist + feature sets (with concrete part numbers)
The goal is to translate system constraints into a bridge requirement set. Use the checklist to prevent hidden bottlenecks (queue depth, FIFO, busy behavior) and to ensure recoverability (error codes, counters, reset strategy).
- I²C interface: supported mode up to X, configurable target address pins, back-pressure policy (NACK vs stretch vs status polling).
- SPI engine: max SCLK, supported modes, CS count, CS hold/keep-asserted capability, dummy/continuous transfer support.
- Queue/FIFO: descriptor depth, TX/RX FIFO depth, readable queue depth, watermark IRQ, deterministic busy semantics.
- Reliability/observability: last error code, sticky error, per-device error tagging, counters, abort/flush, reset strategy and power-on defaults.
- Electrical: VDD range, 5-V tolerant I/O, I/O type expectations (open-drain vs push-pull), ESD/IEC targets (specify your required level).
- Power: Iq, sleep/wake behavior, wake source (pin/IRQ/register), post-wake re-init cost.
- Clear busy/ready + last-error reporting
- Predictable CS behavior (assert/deassert)
- Reset strategy and safe power-on defaults
Example parts: NXP SC18IS606, NXP SC18IS603IPW,112/128.
- Descriptor queue + watermark IRQ
- Deep TX/RX FIFO + readable queue depth
- CS hold + multi-segment transfers
Example parts: NXP SC18IS606 (validate queue/FIFO against worst-case burst X).
- Sticky error + counters + per-device tagging
- Abort/flush + reset pin control
- Defined post-brownout re-init path
Example parts: NXP SC18IS606 (+ ESD parts below for field robustness).
- I²C→SPI bridge ICs: NXP SC18IS606, NXP SC18IS603IPW,112/128, NXP SC18IS602B (noted as no-longer-manufactured on vendor page; use only if already qualified).
- SPI→I²C bridge (reverse direction): NXP SC18IS604 (SPI host to I²C devices; direction-specific).
- Optional CS expansion / extra GPIO: TI TCA9535PWR, NXP PCA9555 (use for CS decode/enable lines when bridge CS pins are insufficient).
- Low-cap ESD protection examples: TI TPD4E02B04 (multi-channel array), Nexperia PESD5V0L1BA-Q (single-line; pick working voltage to match your rail).
Tip: keep the bridge list short and constraint-driven. If a dedicated “parts catalog” page is needed later, split it out to avoid inflating this subpage.
Recommended topics you might also need
Request a Quote
FAQs: I²C↔SPI bridge troubleshooting (data-driven, no fluff)
Each answer is structured for fast debug closure: Likely cause → Quick check → Fix → Pass criteria. Replace X with project thresholds (time, retries, queue depth, error-rate).
“I²C writes ‘succeed’ but the SPI peripheral register does not change—check busy/commit or the SPI sequence first?”
Likely cause: Write staged into a shadow/window but never committed; or SPI engine executed with wrong CS/profile (cmd/addr/dummy).
Quick check: Read BUSY, COMMIT/APPLY, LAST_CS, LAST_ERR immediately after write; capture one transaction to confirm CS↓ → cmd → addr → data → CS↑.
Fix: Enforce a commit bit (shadow→apply) and block new writes while BUSY=1; validate per-device profile (addr width, dummy) and CS mapping.
Pass criteria: For X consecutive writes, BUSY clears within X ms, LAST_ERR=0, and read-back matches expected value; error counters Δ<X/hour.
“Performance collapses with many tiny transactions—check batching/descriptor merge or I²C overhead first?”
Likely cause: I²C framing dominates (start/addr/stop per tiny op); queue/descriptor path not merging segments; excessive polling on BUSY.
Quick check: Compare ops/sec vs average payload bytes; measure I²C bus utilization (% time active) and queue depth; check whether multiple small ops become one SPI burst on the wire.
Fix: Enable descriptor batching (merge adjacent regs, keep CS asserted when safe); use watermark IRQ instead of tight polling; increase FIFO watermark hysteresis (WM_high/WM_low).
Pass criteria: Achieve throughput ≥X kbps with CPU overhead ≤X%; average queue wait ≤X ms; I²C utilization ≤X% at target load.
“Queue occasionally deadlocks and only a reboot helps—check sticky error or a missing recovery step?”
Likely cause: Sticky error latched with BUSY stuck; abort/flush path not executed; recovery ladder missing “SPI re-init” or “reset toggle”.
Quick check: Read STICKY_ERR, BUSY, Q_DEPTH, LAST_ERR; verify driver calls ABORT/FLUSH after timeout and before re-queue.
Fix: Implement graded recovery: soft retry (N<=X) → abort/flush → SPI re-init → toggle RESET pin → power-cycle domain; make recovery idempotent and bounded.
Pass criteria: Under forced-fault tests, system returns to IDLE within X ms without reboot; stuck BUSY occurrences = 0 over X hours; recovery count logged.
“Multiple SPI slaves interfere sporadically—check CS timing or MISO tri-state contention?”
Likely cause: CS overlap (two slaves selected); a slave fails to tri-state MISO; CS default state floating during reset/brown-out.
Quick check: Capture MISO during “no slave selected” (should be defined by PU/PD); verify CS lines never overlap; log LAST_CS and correlate with errors.
Fix: Enforce CS mutual exclusion in scheduler; add CS pull resistors; add MISO weak pull + isolation option; ensure reset forces CS high before any SCLK activity.
Pass criteria: Over X transactions across X slaves, CS overlap events = 0; MISO idle level stable; error counter Δ<X/hour.
“Read-back is occasionally misaligned—check dummy cycles/address width profile or RX FIFO alignment?”
Likely cause: Wrong per-device profile (addr bytes, dummy cycles, continuous-read rules); RX FIFO read pointer not synchronized to transaction boundaries.
Quick check: Compare expected SPI phase lengths vs captured waveform; read RX_COUNT/RX_LEVEL and verify driver drains RX only after STATUS READY with a matching SEQ/TAG.
Fix: Use tagged transactions (SEQ) and read RX via “data-valid + length” contract; reset/flush RX FIFO on error; validate dummy/addr settings per slave profile.
Pass criteria: For X reads, payload length matches expected exactly; misalignment count = 0; RX overflow/underflow counters stay at 0.
“The first few accesses after power-up always fail—check power-on defaults/reset pin or peripheral ready time?”
Likely cause: Bridge starts driving SPI before slaves are ready; CS lines float during reset; peripheral requires tREADY/tBOOT before accepting commands.
Quick check: Log reset release timestamps; confirm CS held inactive until after tREADY; check LAST_ERR shows timeout/invalid response only in early window.
Fix: Add explicit init barrier: hold RESET low for X ms, then delay X ms before first SPI; define CS default with pull resistors; run an idempotent “probe/read ID” before config.
Pass criteria: Cold boot success rate = 100% over X cycles; first access occurs ≥X ms after reset release; early-window errors = 0.
“I²C-side timeouts occur—check stretch/back-pressure policy or SPI peripheral response time?”
Likely cause: Bridge blocks I²C too long while waiting for SPI; back-pressure mismatched (polling vs stretch vs NACK); SPI timeout not bounded.
Quick check: Measure I²C low/high stretches and compare to T_busy_max; check SPI execution time per op against T_spi_max; verify queue-full behavior is consistent (NACK or status code).
Fix: Bound both domains: set T_busy_max=X ms, T_spi_max=X ms; prefer NACK-on-full + status polling; use watermark IRQ to avoid long stretches.
Pass criteria: I²C timeouts = 0 over X ops; 99.9% SPI ops finish <X ms; queue-full events handled without bus hang.
“After power loss recovery, the peripheral enters an unknown state—check idempotent init or commit/rollback?”
Likely cause: Partial configuration applied; retries replay destructive commands; init sequence not idempotent; shadow registers applied without validation.
Quick check: Check whether init can be run twice safely; confirm commit happens only after all writes are staged; log “init seq id” + “commit count” + “brown-out count”.
Fix: Make init idempotent (read ID/state → write only when needed); use commit/rollback gates; on brown-out, force reset + re-init and clear queues/FIFOs before new ops.
Pass criteria: After X brown-out cycles, device reaches the same known state; init completes <X ms; no duplicated destructive ops (seq monotonic, commit count bounded).
“Logic analyzer shows correct SPI waveforms, but software still reports errors—check errcode attribution or concurrency lock?”
Likely cause: Error propagation model ambiguous (shared LAST_ERR overwritten); driver reads status from the wrong transaction; concurrency violates atomic commit/SEQ ordering.
Quick check: Validate every transaction has a SEQ/TAG and status is read back with the same SEQ; check locks around submit/commit/readback; log LAST_ERR + LAST_SEQ.
Fix: Add per-transaction attribution (SEQ, CS, len, timestamp); serialize commit/apply steps; move from “single shared last-error” to “sticky + counters + per-device last-error”.
Pass criteria: No “false errors” in X stress runs; SEQ mismatch count = 0; status readback latency <X ms; counters correlate 1:1 with injected faults.
“Same firmware becomes unstable after swapping bridge silicon revision—check feature flags/version or register compatibility layer?”
Likely cause: Regmap differences (field moved/changed semantics); optional features not present; default values differ (CS polarity, dummy rules, busy behavior).
Quick check: Read REGMAP_VERSION and FEATURE_FLAGS at boot; verify driver gates behavior by flags (queue, CS hold, dummy) rather than assuming availability.
Fix: Add a compatibility shim: detect version/flags → select profiles/timeouts accordingly; enforce known-safe defaults on init; keep a per-version “golden trace” test.
Pass criteria: Across supported revisions, boot init passes X cycles; feature detection selects correct path 100%; regression tests show identical functional results and error-rate Δ<X.
“Field failures are hard to reproduce—what counters/log fields deliver the best ROI?”
Likely cause: Missing attribution (which CS/which op/which timing) turns rare faults into “unknown”; recovery hides root-cause without breadcrumbs.
Quick check: Ensure logs include: timestamp, SEQ, CS_ID, op type, len, LAST_ERR, STICKY_ERR, Q_DEPTH.
Fix: Add counters: i2c_nack_count, i2c_timeout_count, spi_timeout_count, fifo_overflow_count, recover_count, reset_toggle_count; snapshot on error and once per X minutes.
Pass criteria: For top X failure modes, logs uniquely attribute root bucket (CS/op/timeout) within X events; mean-time-to-diagnose <X minutes.
“Bridging fails for a high-throughput data stream—how to quickly decide to switch to native SPI/DMA instead of a bridge?”
Likely cause: I²C overhead + bridge scheduling adds tail latency and caps throughput; RX/TX FIFO too shallow; CPU wakeups dominate power and timing.
Quick check: Compute required payload rate and worst-case tail latency; compare to measured end-to-end: T_total = T_i2c + T_queue + T_spi + T_readback; identify the dominant term.
Fix: If bottleneck is structural (I²C framing dominates), pivot to native SPI + DMA or a different topology; if close, enable batching + deeper FIFOs + watermark IRQ and re-measure.
Pass criteria: Bridge is “fit” only if sustained throughput ≥X kbps, tail latency P99.9 ≤X ms, and CPU overhead ≤X% at target load; otherwise, migrate.