Inspiration

Embedded development is one of the few remaining disciplines where debugging still happens after compilation. You write code, upload it to a microcontroller, and only then discover that a pin was wrong, your I2C address was invalid, you overflowed RAM, or the ESP32 silently rebooted because a strapping pin was misconfigured.

This workflow is slow, unclear, and often frustrating—especially for beginners and even more so for production firmware engineers.

I wanted to fix that.

My inspiration for Sentinel came from a simple question:

“Why doesn’t embedded development have real-time diagnostics, the same way modern languages have type checking?”

Every other domain has intelligent tooling. Hardware developers still rely on trial and error. Sentinel makes embedded development feel modern. It moves error detection from after compilation to as you type.


What it does

Sentinel is a hardware-aware VS Code extension that prevents embedded system bugs before they happen.

It uses a custom Language Server Protocol (LSP) to perform:

Real-time memory analysis (±3% accuracy)

  • RAM + Flash estimation before compilation
  • Global variable + stack analysis
  • Dynamic allocation tracking
  • Framework overhead calibration (Serial/Wire/SPI/WiFi/BLE)

Pin conflict detection

  • Tracks all pin assignments across files
  • Detects overlapping usage: digital/PWM/analog/UART/SPI/I2C
  • ESP32 strapping pin warnings
  • Boot-mode interference alerts

Protocol validation

  • I2C address checking (0x08–0x77)
  • Conflict detection for shared buses
  • SPI clock compatibility
  • UART baud validation
  • Pull-up resistor reminders
  • 200+ I2C device address autocompletion

Hardware-aware IntelliSense

  • Device register suggestions
  • Board-specific pin hints
  • Parameter hints based on hardware constraints

Visualization tools

  • Pin usage map (color-coded)
  • Live RAM bar in the status bar
  • Post-build Flash/RAM charts

How I built it

Sentinel consists of two major components:

1. The VS Code Extension (Frontend)

  • Built with TypeScript
  • Uses Webviews for the sidebar panel
  • Provides UI for:
    • Memory bars
    • Pin assignment maps
    • Build/Flash actions
    • Global variable breakdown
  • Integrates with arduino-cli to compile and upload firmware

2. The Embedded Language Server Protocol (Backend)

A custom LSP built in Node.js that performs:

Static code analysis

  • Parses .ino and .cpp into an AST
  • Walks declarations, functions, and library calls
  • Tracks global variables, stack usage, and dynamic allocation

Hardware model

Maintains state for:

  • Pin assignments
  • I2C/SPI/UART configuration
  • ESP32 strapping rules
  • Arduino memory limits

Validation engine

  • Runs 50+ hardware-specific rules
  • Validates code incrementally (<100ms), re-checking only changed nodes

Calibration pipeline

To estimate memory accurately, Sentinel:

  • Collected 100+ Arduino sketches
  • Compiled them with arduino-cli
  • Parsed .map files
  • Matched real memory usage to static estimates
  • Tuned the model until accuracy hit ±3%

Challenges I ran into

1. Memory estimation is extremely hard

Static analysis can't know runtime stack size perfectly. Achieving ±3% required:

  • Multi-pass analysis
  • Calibrating for framework overhead
  • Reverse engineering compiler behavior
  • Handling recursion, mutual calls, and unused globals

2. Parsing embedded code reliably

Arduino code mixes:

  • Preprocessor macros
  • Header includes
  • C++ classes
  • .ino autowiring rules

I had to build a custom parser layer on top of a standard TypeScript-based AST engine.

3. ESP32 strapping pin rules are messy

Espressif’s documentation is inconsistent. I had to test behaviours manually:

  • GPIO0/GPIO2/GPIO12/GPIO15 during boot
  • WiFi stack placement on Core 0
  • PSRAM-induced memory fragmentation

4. Real-time performance

LSP diagnostics must run under 100ms or VS Code becomes sluggish.
I rewrote several algorithms using:

  • Incremental parsing
  • AST diffing
  • Cached symbol tables
  • Memoized hardware state

5. Building something this large in a hackathon timeline

This is more of a dev tool startup than a typical weekend script. Balancing scope vs quality was tough.


Accomplishments that I'm proud of

  • Built a custom Language Server Protocol from scratch
  • Achieved ±3% RAM/Flash accuracy
  • Wrote a 50-rule hardware validation engine
  • Created real-time pin conflict detection
  • Designed a full-featured VS Code sidebar UI
  • Added Arduino + ESP32 support
  • Implemented hardware-aware IntelliSense
  • Delivered a tool that genuinely improves embedded development

Sentinel works, it’s fast, and it solves a real problem.


What I learned

  • How to build a full LSP system and integrate it with a VS Code extension
  • Deep insights into Arduino’s memory model, ESP32 boot rules, and microcontroller constraints
  • How compilers allocate global variables and stack frames
  • How to design UI/UX for developer tools
  • How to optimize static analysis to run in <100ms
  • How to build something that feels like a real product, not just a hack

What's next for Sentinel

Near-Term

  • Full ESP32 memory analysis (IRAM/DRAM/PSRAM breakdown)
  • ESP32 pin map visualization
  • Support for Arduino Mega, Nano, ESP8266, STM32, Raspberry Pi Pico
  • Power consumption estimator
  • Serial plotter + oscilloscope integration
  • Multi-board project workflows

Long-Term

  • A universal embedded developer platform
  • Cloud-based hardware simulation
  • Real-time emulator for AVR + ESP32
  • AI-assisted firmware auto-fixing
  • Marketplace for new board definitions

Sentinel has the potential to become the modern toolchain for embedded systems, similar to how VS Code transformed web development.

Built With

Share this project:

Updates