Skip to content

Repository files navigation

zigEFI

Bare-metal engine management firmware written in Zig.

zigEFI takes a different approach to ECU firmware. Instead of runtime configuration through GUI tuning software, your engine tune lives in code — version-controlled, diffable, and validated at compile time.

Philosophy

Projects like rusEFI and Speeduino have done incredible work making open-source engine management accessible. zigEFI builds on that foundation with a focus on the software engineer's workflow:

  • Config as code. Fuel maps, ignition tables, sensor calibrations, and engine parameters are defined as Zig comptime structs. Change your target AFR at 3000 RPM and full load? Edit a number, rebuild, flash. Review a tune change? git diff.

  • Compile-time validation. Invalid sensor calibrations, out-of-range table values, and misconfigured peripherals are caught by the compiler — not discovered at 6000 RPM.

  • Feature selection, not feature flags. Pick what your engine needs and the rest doesn't exist in your binary. No dead code paths for features you'll never use. No runtime branches for hardware you don't have.

  • Minimal and auditable. The firmware is small enough to read and understand. Every instruction between power-on and your first injector pulse is visible and intentional. No RTOS, no HAL library, no code generators — just Zig and registers.

Quick Start

# Build for Black Pill dev board (default)
make
# Build for uaEFI production board
make BOARD=uaefi
# Build for uaEFI PRO (STM32F767)
make BOARD=uaefi_pro
# Build smallest binary
make release
# Flash via ST-Link
make flash
# See available boards
make list-boards
# Check firmware size
make size

Requires Zig 0.15.x and st-flash (from stlink) for flashing.

Project Structure

zigEFI/
build.zig Build system with board selection
Makefile Convenience targets
linker/ Linker scripts per MCU
docs/ Project documentation
src/
main.zig Application entry point
start.zig Vector table and startup code
hal/ Hardware abstraction (GPIO, clocks, MMIO)
board/
blackpill/ STM32F401 dev board config + pinout docs
uaefi/ rusEFI uaEFI production board config (STM32F407)
uaefi_pro/ rusEFI uaEFI PRO board config (STM32F767)
engine/
config.zig Engine configuration schema and default tunes

Engine Configuration

Your tune is a const EngineConfig struct in src/engine/config.zig. Everything is evaluated at compile time.

pubconstsbf_tbi_302=EngineConfig{
.name="SBF 302 TBI",
.cylinders=8,
.displacement_cc=4942,
.rev_limit=5500,
.injector= .{
.flow_cc_per_min=325,
.num_injectors=4,
.simultaneous=true,
.dead_time_us= .{ 1500, 1350, 1200, ... },
},
.ve_table= .{ ... }, // 16x16 volumetric efficiency (RPM x MAP)
.afr_table= .{ ... }, // 16x16 target air-fuel ratio
.warmup_enrichment_pct= .{ 80, 70, 60, ... },
// ...
};

Change a value, rebuild, flash. The compiler ensures every field is present and every value is in range.

Ignition Modes

zigEFI supports a progression of ignition control strategies — pick the one that matches your hardware. Set ignition.mode in your engine config.

ModeWhat it doesHardware needed
.disabledDistributor handles all timing. ECU does fuel only.Stock distributor with mechanical/vacuum advance
.distributorECU controls timing via advance table. Single ignition output, distributor routes spark. Replaces the factory ignition module.Locked-out distributor + VR pickup wired to ECU
.coil_on_plugFull ECU-controlled ignition with individual coil outputs. (Not yet implemented.)Crank trigger wheel + cam sync sensor + coil pack/COPs

Most builds start with .disabled for fuel tuning, then move to .distributor once the fuel map is dialed in. This is a natural progression — each mode builds on the previous one, and the VR input does double duty for RPM and position reference.

.ignition= .{
.mode=.distributor,
.advance_table= .{ ... }, // 16x16 degrees BTDC (RPM x MAP)
.dwell_us=3000, // coil charge time
.distributor_ref_angle=10, // VR pickup angle with advance locked out// ...
},

See docs/IGNITION.md for wiring diagrams, timing math, and the coil-on-plug architecture.

Board Support

zigEFI is designed to be portable across MCU architectures. Board-specific pin maps, clock configurations, and HAL implementations are selected at build time with zero runtime overhead — Zig's comptime generics make the abstraction free.

Active

BoardMCUCoreClockFlashTarget Use
blackpillSTM32F401CCU6Cortex-M4F84 MHz256 KBDevelopment and bench testing
uaefiSTM32F407VGT6Cortex-M4F168 MHz1 MBProduction ECU (rusEFI uaEFI)
uaefi_proSTM32F767VIT6Cortex-M7F216 MHz2 MBProduction ECU — PRO variant, 2x CAN, 512 KB SRAM

Planned (WIP — contributions welcome)

BoardMCUCoreClockNotes
esp32s3ESP32-S3Dual Xtensa LX7240 MHzWiFi/BLE for wireless tuning and telemetry
arduino_dueATSAM3X8ECortex-M384 MHzEasiest non-STM32 port, 2x CAN built in
teensy40i.MX RT1062Cortex-M7600 MHz1 MB SRAM, 3x CAN FD, double-precision FPU

See docs/BOARDS.md for details, platform implementation checklists, and instructions on adding new boards.

Status

Early development. The build system, startup code, HAL, and board abstraction are in place. The core EFI control loop (speed-density fuel calculation, sensor reading, injector scheduling) is next.

Acknowledgments

Standing on the shoulders of:

  • rusEFI — comprehensive open-source ECU firmware and hardware. The uaEFI board is our primary hardware target.
  • Speeduino — accessible Arduino-based engine management that proved open-source EFI is practical for everyone.

Both projects provide excellent references for EFI algorithms and hardware design. zigEFI wouldn't exist without their work.

License

MIT

About

Zig-based ECU firmware for STM32 and more— config-as-code engine management

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages