Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Logic Analysis on a Linux SBC with espctl

Turn an ESP32-S3 into a protocol-grade logic analyzer, run PulseView or sigrok-cli directly on your Linux SBC, and drive builds and captures through any of 18 AI coding agents — all with a single espctl binary that weighs under 15 MB, ships no runtime dependencies, and runs unmodified on x86_64, ARM64, ARMv7, and RISC-V Linux.


Why a Linux SBC as the debug host

A Raspberry Pi 4, OrangePi 5, or any RISC-V board running a mainstream Linux distro is a capable logic-analysis workstation once you shed the assumption that a $200+ desktop is required:

  • PulseView and sigrok-cli have packaged ARM64 and ARMv7 builds in every major distro (apt install pulseview sigrok-cli on Debian/Ubuntu/Raspbian).
  • The USB connection between the ESP32-S3 analyzer and the SBC host adds no measurable latency to captures — SUMP sample upload is bounded by SRAM size, not USB bandwidth.
  • espctl itself is a single statically-linked binary. Copy it, chmod +x, done. No pip, no npm, no Rust toolchain, no ESP-IDF needed on the SBC.

espctl on Linux SBC — install in one line

# ARM64 / RISC-V / x86_64 — same command
curl https://esphome.cloud/espctl/install.sh | sh

The installer detects your architecture, downloads the matching binary, and places it in ~/.local/bin. On a fresh Raspberry Pi OS Lite this takes under 10 seconds.

Verify:

espctl version
# espctl 1.x.x  linux/arm64

espctl connects to the remote build farm over HTTPS — your SBC needs outbound port 443 but nothing else. The build toolchain (ESP-IDF, arm-none-eabi-gcc, Rust cross) runs entirely on the farm.


Step 1 — Add the sigrok component to your firmware

In the esphome.cloud wizard, open your ESP32-S3 project and add the Sigrok Logic Analyzer component. Or add it directly to your project config:

{
  "target": "esp32s3",
  "components": ["sigrok"]
}

Firmware-level hard limits (compile-time):

ParameterValue
Channel count8 (fixed)
Default sample rate1 MHz
Max sample rate10 MHz
Capture buffer depth~32 K samples
Trigger modesImmediate; pattern match (with optional edge detection)

Sample rate is runtime-adjustable from the host over the SUMP protocol. Channel count and buffer depth are compile-time fixed and cannot be changed at runtime. There is no PSRAM extension path, no 16-channel mode, and no pre-trigger-ratio config field.

The component is validated on ESP32-S3 only — the capture core uses the S3’s parallel-GPIO sampling capability (reads 8 GPIOs in a single CPU cycle). C3/C6 can in principle host a low-channel-count low-speed SUMP device, but the sigrok firmware itself has not been ported to those targets. Full hardware-capability breakdown: PulseView & Sigrok Firmware.


Step 2 — Build and flash from the SBC

# Build remotely — no local ESP-IDF needed
espctl build . --target esp32s3

# Flash over USB
espctl flash build/flash_bundle.tar.gz

Build time on a warm cache is typically under 30 seconds. The SBC is only the coordinator; all compilation happens on the remote farm. RAM usage on the SBC during a build is under 50 MB.


Step 3 — Connect PulseView or sigrok-cli

Plug the flashed ESP32-S3 into the SBC’s USB port. It appears as /dev/ttyACM0 (or similar).

Verify device recognition:

sigrok-cli --driver=ols:conn=/dev/ttyACM0 --scan
# Found: ESP32-S3 sigrok, 8 channels, max 10 MHz

Start PulseView:

pulseview &

In PulseView: File → Connect to device → OLS → /dev/ttyACM0 → Scan. The device appears with the configured channel count and sample rate ceiling.

Headless capture with sigrok-cli (no display required):

# Capture 100 K samples at 1 MHz, save as sigrok session
sigrok-cli \
  --driver=ols:conn=/dev/ttyACM0 \
  --config samplerate=1MHz \
  --samples 100000 \
  --output-format srzip \
  --output-file capture.sr

# Decode I2C immediately after capture
sigrok-cli \
  --driver=ols:conn=/dev/ttyACM0 \
  --config samplerate=4MHz \
  --samples 50000 \
  --protocol-decoder i2c:scl=0:sda=1 \
  --protocol-decoder-annotation i2c:address-read,address-write,data-read,data-write

Headless sigrok-cli is especially useful on SBCs without a display — pipe output to a file, ssh into the SBC from your laptop, and inspect captures remotely.


Trigger modes

Triggering is configured at runtime by PulseView / sigrok-cli over the SUMP protocol — not by a JSON field at build time. The firmware implements two modes:

ModeWhat it does
ImmediateFires on arm; no pre-trigger window
PatternFires when (sample & mask) == value. With edge detection enabled, fires only on the transition into that value (pattern-match used to emulate edge triggering).

The pre-trigger / post-trigger sample split is also runtime-controlled through SUMP — the host tells the firmware “after the trigger fires, collect N more samples”; the rest of the buffer is reserved for pre-trigger context. It is not a build-time config field.

PulseView and sigrok-cli render the above as a “Trigger when this pattern matches” toggle, a “Detect edges” option, and numeric sliders; the OLS/SUMP driver handles the mapping.


Protocol decoders

PulseView and sigrok-cli ship 131 protocol decoders via libsigrokdecode. Six are validated end-to-end with the ESP32-S3 sigrok component:

ProtocolTypical useDecoder name in PulseView
I2CSensor buses (BME280, SHT4x, MPU-6050)i2c
UARTSerial debug output, GPS NMEA, AT commandsuart
SPIFlash, displays, DACsspi
1-WireDS18B20 temperature sensorsonewire
WS2812RGB LED stripsws2812
IR (NEC)Remote controls, IR receiversir_nec

Any of the other 125 decoders (CAN, LIN, I2S, PWM, JTAG, SMBus, …) will work as long as the protocol fits within the channel count and sample rate limits.


AI agent integration on the SBC

espctl includes a built-in MCP server. Run it on the SBC and point any supported AI coding agent at it — the agent can then trigger builds, read logs, download firmware, and interact with the sigrok component through the same 42 MCP tools available in the cloud.

# Start the MCP server on the SBC
espctl mcp serve

Getting the install snippet

Every supported agent has a ready-to-paste config snippet available via the install:// MCP resource. Fetch it from within any MCP session:

resources/read  install://<agent-slug>

For example, install://claude-code returns the exact JSON block to paste into .claude/settings.json. No manual config writing required.

Supported agents (18 with full install snippets)

AgentSnippet availableNotes
Claude Codeinstall://claude-code
Cursorinstall://cursor
Claude Desktopinstall://claude-desktop
Codex CLIinstall://codex
OpenCodeinstall://opencode
DeepSeek-TUIinstall://deepseek-tui
Oh My Piinstall://oh-my-pi
AstrBotinstall://astrbot
nanobotinstall://nanobot
Reasonixinstall://reasonix
Langcliinstall://langcli
Kilo Codeinstall://kilo-code
WorkBuddyinstall://workbuddy
Deep Codeinstall://deep-code
Hermesinstall://hermes
Crushinstall://crush
GitHub Copilotinstall://github-copilotVS Code extension
OpenClawinstall://openclaw

Two additional agents (GitHub Copilot CLI, Pi) are documented with alternative connection paths; see their individual client pages.

Example: Claude Code on a Raspberry Pi 4

// ~/.claude/settings.json
{
  "mcpServers": {
    "esp-idf": {
      "command": "espctl",
      "args": ["mcp", "serve"]
    }
  }
}

With this in place, Claude Code running on the Pi can:

  • Ask build to compile new firmware after you change the sigrok channel config
  • Ask logs.tail to stream the build output
  • Ask flash.run to flash the new firmware to the connected ESP32-S3
  • Read capture results if you pipe sigrok-cli output into the MCP artifacts surface

Resource footprint on SBC hardware

espctl is designed to run comfortably on the smallest practical SBC:

OperationSBC RAM usageCPU usage (peak)Disk
espctl mcp serve (idle)< 20 MB< 1 %0
espctl build . (coordinator only)< 50 MB< 5 %~30 MB temp
espctl flash< 30 MB< 10 %0
espctl monitor< 20 MB< 2 %0

The build toolchain never runs on the SBC — all compilation is on the remote farm. A Raspberry Pi Zero 2 W (512 MB RAM) can run espctl mcp serve while simultaneously running sigrok-cli captures without hitting memory pressure.

Tested SBC hardware:

BoardArchitectureRAMWorks
Raspberry Pi 4 / 5ARM642–8 GBFull workflow
Raspberry Pi Zero 2 WARM64512 MBFull workflow
OrangePi 5ARM644–16 GBFull workflow
BeagleBone BlackARMv7512 MBBuild + flash + MCP
Milk-V Duo SRISC-V512 MBBuild + flash + MCP
Generic ARMv7 (any)ARMv7≥ 256 MBBuild + flash

┌──────────────────────────┐
│ Linux SBC (e.g. Pi 4)    │
│                          │
│  espctl mcp serve  ──────┼──── Claude Code / Cursor / any MCP agent
│  PulseView / sigrok-cli  │
│                          │
│  USB port 1  ────────────┼──── ESP32-S3 (sigrok analyzer)
│  USB port 2  ────────────┼──── ESP32-S3 / STM32 (device under test)
└──────────────────────────┘

One ESP32-S3 acts as the logic analyzer. A second ESP32-S3 (or STM32, or any target) is the device under test. The SBC sits between them, running espctl for builds and sigrok-cli / PulseView for captures.


See Also