Software Bill of Materials: sbom.json (CycloneDX 1.4)
UDS without AUTOSAR — production-grade ISO 14229 diagnostics for Zephyr RTOS and FreeRTOS, configured in YAML, generated in seconds.
No AUTOSAR Classic RTE/COM stack to adopt just to get session control,
security access, and DTC handling. Describe your DIDs and DTCs once. Get ISO 14229-compliant C code, ASIL-B safety wrappers, a full pytest suite, and CANoe CAPL scripts — all from a single diagnostics_config.yaml. No boilerplate. No hand-rolled session logic. Runs on native_sim in CI and on real CAN hardware the same day.
Clone the repo, build the committed basic_ecu example, run it under
Zephyr's native_sim. No CAN hardware, no commercial license:
pip install west
west init -m https://github.com/Xaloqi/EDS --mr v1.15.0 eds-workspace
cd eds-workspace && west update
pip install -r tools/requirements.txt
west build -b native_sim examples/basic_ecu \
-- -DDTC_OVERLAY_FILE=boards/native_sim/native_sim.overlay \
-DDIAG_SKIP_CODEGEN=ON
west build -t runexamples/basic_ecu/generated/ is committed to the repo, so this builds
and runs on the GPL v2 runtime alone. Regenerating from your own YAML is
the licensed step, not evaluating the runtime — see
Open-core: what's free, what's licensed
below. More boards (STM32 Nucleo, NXP FRDM/S32K) and the full generator
walkthrough: Quick start.
-DDIAG_SKIP_CODEGEN=ON tells the build to use the committed generated/
output as-is instead of trying to regenerate it — required here, since a
fresh checkout has no commercial templates. Without it the build fails
outright rather than silently falling back (confirmed against a real CI
checkout — EDS#198).
Want to test UDS without writing an ECU first? → Xaloqi TestLab Core — a free Python UDS client and ECU simulator,
pip install xaloqi-tester.
Building a UDS diagnostics stack from scratch on Zephyr means solving ISO-TP framing, session state machines, security access, DID dispatch, DTC persistence, and ASIL-B safety wrappers yourself. Most teams do it once per project, inconsistently, with no reuse.
EDS replaces that with a configuration-driven workflow. Define your ECU's diagnostic interface in YAML. Run the generator. The complete C implementation drops into your Zephyr build.
EDS is dual-licensed. The runtime stack is GPL v2 and the whole thing builds and runs out of the box — the commercial license is for generating your own configs and shipping proprietary firmware.
| Free — GPL v2 (runtime) / Apache-2.0 (examples) | Licensed — Developer / Professional |
|---|---|
Full runtime stack: UDS server, ISO-TP, DoIP, security access, ASIL-B safety chain (core/, transport/, config/, platform/) |
The code generator's templates — tools/codegen.py is readable and runs, but needs the commercial tools/templates/ to produce output |
Every bundled example including its committed generated C — west build and run today, no license needed |
Test generator (testgen.py), ARXML importer, VS Code extension, MCP server, AI assistant |
| Study, modify, and redistribute under GPL v2 | Generating code for proprietary firmware; shipping closed-source firmware |
| Safety documentation package (Professional tier) |
In short: clone this repo and you can build, run, and study the full stack and every example for free. A Developer license adds the generator templates (regenerate from your own YAML) and the right to ship proprietary firmware. Full boundary: COMMERCIAL_NOTICE.md.
On linking, explicitly: a commercial license permits you to statically or dynamically link the GPL-licensed runtime stack (core/, transport/, config/, platform/) into closed-source ECU firmware and distribute the resulting binary to your OEM or end customer — with no GPL source-disclosure obligation for your own firmware code. Full terms: LICENSE_COMMERCIAL.txt §5 ("GPL v2 Runtime and Commercial License Relationship").
1. Describe your ECU's diagnostic interface:
# diagnostics_config.yaml
ecu:
name: "body_controller"
dids:
- id: "0xF190"
name: "VIN"
data_length: 17
access: [read]
min_session: default
read_security_level: 0
write_security_level: 0
- id: "0xF187"
name: "PartNumber"
data_length: 10
access: [read, write]
min_session: extended
read_security_level: 0
write_security_level: 1 # requires SecurityAccess unlock
dtcs:
- code: "0xD00101"
description: "Battery voltage above threshold"
severity: check_at_next_halt2. Generate everything:
Licensed step —
tools/codegen.pyrequires an EDS Developer or Professional license; the code-generation templates are the commercial deliverable. The runtime stack and the committed example outputs (examples/*/generated/) are fully GPL. See COMMERCIAL_NOTICE.md or xaloqi.com.
python3 tools/codegen.py \
--config diagnostics_config.yaml \
--out generated/ \
--safety-wrappers \
--asil-level B \
--test-gen3. Build and run:
# Simulator (CI, no hardware)
west build -b native_sim examples/basic_ecu \
-- -DDTC_OVERLAY_FILE=boards/native_sim/native_sim.overlay \
-DDIAG_SKIP_CODEGEN=ON
west build -t run
# STM32 Nucleo-H743ZI2
west build -b nucleo_h743zi examples/basic_ecu \
-- -DEXTRA_CONF_FILE=boards/nucleo_h743zi/nucleo_h743zi.conf \
-DDTC_OVERLAY_FILE=boards/nucleo_h743zi/nucleo_h743zi.overlay
west flash
# NXP FRDM-MCXN947
west build -b frdm_mcxn947/mcxn947/cpu0 examples/basic_ecu \
-- -DEXTRA_CONF_FILE=boards/frdm_mcxn947/frdm_mcxn947.conf \
-DDTC_OVERLAY_FILE=boards/frdm_mcxn947/frdm_mcxn947.overlay
west flash
# NXP MR-CANHUBK3 (S32K344 — also covers S32K312, S32K396)
west build -b mr_canhubk3 examples/basic_ecu \
-- -DEXTRA_CONF_FILE=boards/mr_canhubk3/mr_canhubk3.conf \
-DDTC_OVERLAY_FILE=boards/mr_canhubk3/mr_canhubk3.overlay
west flashThe generator produces: DID handler stubs, ASIL-B safety wrappers, DTC registration tables, a complete UDS init sequence, a pytest suite for every DID and DTC, and optionally CANoe CAPL scripts. Regenerate any time the YAML changes — output is deterministic and CI-verifiable.
Use EDS as a west module. Add it to your application's west.yml:
manifest:
remotes:
- name: xaloqi
url-base: https://github.com/Xaloqi
projects:
- name: EDS
remote: xaloqi
revision: v1.15.0
path: modules/edsThen run west update. Zephyr picks up the Kconfig symbols from zephyr/module.yml automatically — CONFIG_UDS_*, CONFIG_ISOTP_*, and CONFIG_DIAG_* are available in your prj.conf without any manual include path changes.
Each EDS example has its own self-contained CMakeLists.txt. To add EDS to your own app, add the EDS sources directly:
# In your app's CMakeLists.txt, after find_package(Zephyr):
add_subdirectory(${ZEPHYR_EDS_MODULE_DIR}/core eds_core)
add_subdirectory(${ZEPHYR_EDS_MODULE_DIR}/transport eds_transport)The ZEPHYR_EDS_MODULE_DIR variable is set automatically by west when the module is registered.
| Capability | Detail |
|---|---|
| UDS stack | 19 services: 0x10 0x11 0x14 0x19 0x22 0x23 0x27 0x28 0x2A 0x2E 0x2F 0x31 0x34 0x35 0x36 0x37 0x3D 0x3E 0x85 · SID 0x23: direct memory read · SID 0x2A: periodic push (SLOW/MEDIUM/FAST) · SID 0x3D: direct memory write · SID 0x19 sub-functions: 0x01 0x02 0x03 0x04 0x06 0x0A 0x0B 0x19 |
| ISO-TP transport | SF / FF / CF / FC · N_As / N_Bs / N_Cr timing · STmin sub-ms range |
| DoIP transport | DoIP diagnostic server subset (ISO 13400-2 routing activation + diagnostic messaging) — Routing Activation · DiagnosticMessage dispatch · Positive/Negative Ack · Alive Check · Zephyr (zsock_*) and FreeRTOS+LwIP bindings · same UDS core, no code changes. Vehicle identification, vehicle announcement, and entity status are out of scope — see the DoIP Feature Matrix in docs/ARCHITECTURE.md §6.2. |
| ASIL-B safety chain | 5-step DID validation enforced at codegen time — cannot be bypassed at runtime |
| Security | AES-128-CMAC seed / 4-byte key response (threat model) · TRNG-backed · configurable per-session levels · lockout with NVM persistence |
| DTC persistence | NVM mirror survives power cycles · 0x14 ClearDTC · 0x19 ReadDTCInformation |
| Code generation | YAML → 18 Jinja2 templates · CLI · reproducible deterministic output |
| Test generation | YAML → pytest suite per DID and DTC · simulator mode (no hardware) · firmware harness mode |
| CANoe CAPL | YAML → .can scripts for CANoe import · per-DID, per-DTC, core services |
| SOVD CDA | --sovd flag: YAML → OpenSOVD 1.0 sovd_cda.json — DIDs, DTCs, routines, transport, all 19 services · DoIP ECUs include logicalAddress and port · Eclipse SDV / OEM SOVD clients |
| VS Code extension | Inline YAML validation · hover docs · one-click codegen · auto-run on save · status bar indicator |
| MCP server | tools/mcp_server.py — exposes generate_did_config, run_codegen, validate_asil_b, explain_uds_error to Claude, Cursor, and any MCP host. Included with Developer and Professional licenses. |
| ECU examples | basic · basic_doip · basic_freertos · basic_doip_freertos · BMS · motor controller · ARDEP · sensor · safeboot · robot joint — 5–35 DIDs each, Zephyr and FreeRTOS |
| Wireshark dissector | extras/wireshark/eds.lua — UDS service names · NRC descriptions · ISO-TP frame types · DoIP payload decode · load in 3 steps |
| CI pipeline | GitHub Actions — unit tests · integration tests · Zephyr builds (native_sim + STM32) · FreeRTOS ARM · MISRA analysis · DoIP integration · SOVD CDA · full robustness campaign (439 tests) |
Safety properties verified by CI on every commit:
- Zero dynamic memory allocation (
malloc/freegrep gate) uds_safety_self_test()present and abort-guarded in every generated init file (ISO 26262-6 §9.4.3)ASIL_B_REQUIRE_WRITE_SECURITY = True— write-capable DIDs without a security gate are a fatal codegen errorGEN_SAFETY_DID_COUNTin generated headers matches YAML ground truth
pip install west
west init -m https://github.com/Xaloqi/EDS --mr v1.15.0 eds-workspace
cd eds-workspace && west update
pip install -r tools/requirements.txtNo license? Skip the codegen step. This example's generated code is committed under
examples/basic_ecu/generated/— pass-DDIAG_SKIP_CODEGEN=ONtowest build(below) to use it as-is on the GPL runtime, no commercial templates needed. Thecodegen.pystep below regenerates it and requires a Developer/Professional license (templates are commercial — see COMMERCIAL_NOTICE.md).
# Generate code from the bundled example config (licensed step — see note above)
python3 tools/codegen.py \
--config examples/basic_ecu/diagnostics_config.yaml \
--out examples/basic_ecu/generated/ \
--safety-wrappers --asil-level B --test-gen
# Build and run in simulator (works without a license — generated/ is committed)
west build -b native_sim examples/basic_ecu \
-- -DDTC_OVERLAY_FILE=boards/native_sim/native_sim.overlay \
-DDIAG_SKIP_CODEGEN=ON
west build -t run# Clone FreeRTOS kernel
git clone --depth=1 https://github.com/FreeRTOS/FreeRTOS-Kernel.git /opt/freertos-kernel
# Generate code (same YAML as basic_ecu)
# Licensed step — requires a Developer/Professional license (templates are commercial).
# No license? This example's generated/ is committed; skip straight to west build.
python3 tools/codegen.py \
--config examples/basic_ecu_freertos/diagnostics_config.yaml \
--out examples/basic_ecu_freertos/generated/ \
--safety-wrappers --asil-level B --no-manifest
# Build for QEMU ARM Cortex-M4
cmake -B build_freertos \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain/arm-none-eabi.cmake \
-DEDS_PLATFORM=freertos \
-DFREERTOS_DIR=/opt/freertos-kernel \
-DBOARD=qemu_cortex_m4 \
-GNinja \
examples/basic_ecu_freertos
ninja -C build_freertosFor the full FreeRTOS integration guide (callbacks, NVM, reset, production porting), see docs/INTEGRATION_GUIDE.md.
# 45 Unity unit tests (host-native, no Zephyr SDK needed)
bash build_tests.sh
# 68 harness integration tests (Professional tier — requires harness/ sources)
# bash build_harness.sh
# Generated pytest suite (simulator mode) — requires the commercial xaloqi-tester
# (TestLab) package for the simulator/live-transport tests below; see
# docs/TESTING_STRATEGY.md for what pytest --collect-only's full count breaks down into
# and which subset runs with only tools/requirements.txt installed.
cd examples/basic_ecu/generated/tests
pip install -r requirements_testgen.txt # xaloqi-tester — separate from tools/requirements.txt
pytest test_services.py test_did_*.py -v --can-interface=simulator
# Whole Python suite (repo tests/ + every example, each correctly scoped) —
# the canonical entrypoint; prints a PASS/BLOCKED/FAIL summary per suite
# (ADR-005 execution-truth semantics — BLOCKED means "ran, but below its
# declared floor or no floor declared", never a silent pass)
bash run_python_tests.shA bare
pytestfrom the repo root only collectstests/(seepytest.ini) — every example'sgenerated/tests/is its own self-contained pytest project and must be run scoped to its own directory, exactly as shown above.run_python_tests.shruns all of them for you. It executes 1,958 of 2,981 collected cases in a Developer-tier checkout (this repo, as cloned) and 2,782 of 2,981 with the Professional-tierharness/build present — the gap is cases gated on commercial prerequisites (TestLab, the firmware harness, or thetools/templatescodegen ZIP), not failures. See docs/TESTING_STRATEGY.md for the per-suite breakdown.
Included in Developer and Professional tiers — not part of the open-source runtime. Get access → xaloqi.com
Eight panels: DIDs (read/write with live sparklines) · DTCs (active faults + status byte) · Security (seed/key exchange) · Routines (start/stop/results) · Raw Frames (ISO-TP log) · Console · Configurator · Overview. Demo mode runs without hardware — no CAN hardware required.
diagnostics_config.yaml
│
▼ python3 tools/codegen.py (licensed — Developer/Professional)
┌─────────────────────────────────────────┐
│ Generated C (ASIL-B) │
│ did_handlers.c did_safety_wrappers.c │
│ uds_init.c safety_config.h │
└────────────────┬────────────────────────┘
│
┌────────────────▼────────────────────────┐
│ UDS Server Core (core/) │
│ 19 service handlers · session FSM │
│ security manager · ASIL-B dispatcher │
└────────────────┬────────────────────────┘
│
┌────────────────▼────────────────────────┐
│ Transport (transport/) │
│ ┌─────────────────────────────────┐ │
│ │ ISO-TP (isotp.c) │ │
│ │ SF/FF/CF/FC · full timing │ │
│ └─────────────────────────────────┘ │
│ ┌─────────────────────────────────┐ │
│ │ DoIP (transport/doip/) │ │
│ │ ISO 13400-2 · TCP/IP │ │
│ └─────────────────────────────────┘ │
└────────────────┬────────────────────────┘
│
CAN bus / Ethernet
No dynamic memory. No recursion. Static buffers only.
Every DID access passes a 5-step ASIL-B chain generated from YAML:
Step 1 DID exists? → NRC 0x31 requestOutOfRange
Step 2 Session allows it? → NRC 0x7F serviceNotSupportedInActiveSession
Step 3 Security level met? → NRC 0x33 securityAccessDenied
Step 4 Access type permitted? → NRC 0x6F conditionsNotCorrect
Step 5 Data length correct? → NRC 0x13 incorrectMessageLengthOrInvalidFormat
| Directory | Contents |
|---|---|
core/ |
UDS server, session manager, security manager, service handlers |
transport/ |
ISO-TP state machine, CAN driver binding · transport/doip/ — DoIP server (ISO 13400-2), Zephyr and FreeRTOS+LwIP platform bindings |
config/ |
DID database, DTC database, NVM mirror |
platform/ |
Platform abstraction layer — platform/zephyr/ (Zephyr HAL) · platform/freertos/ (FreeRTOS HAL) · platform_api.h (shared interface) |
tools/ |
codegen.py, testgen.py, 18 Jinja2 templates |
ide/vscode-extension/ |
YAML validation, hover docs, Run Codegen command (Developer/Professional tier) |
examples/ |
basic_ecu · basic_ecu_doip · basic_ecu_freertos · basic_ecu_doip_freertos · sensor_ecu · sensor_ecu_freertos · safeboot_ecu · safeboot_freertos_ecu · robot_joint_controller_ecu · bms_ecu · motor_controller_ecu · ardep_ecu · each with its own generated/ subfolder |
gui/ |
React/TypeScript configurator + live dashboard (Developer/Professional tier) |
tests/ |
45 Unity unit tests, harness, Python integration tests |
Every example ships with its generated C committed — clone, build, and inspect without a license.
Building a BMS? → examples/bms_ecu/ ·
Motor controller? → examples/motor_controller_ecu/ ·
Working with DoIP? → examples/basic_ecu_doip/ ·
Using FreeRTOS? → examples/basic_ecu_freertos/ ·
Need safe firmware update? → examples/safeboot_ecu/
| Example | DIDs | DTCs | Routines | Boards |
|---|---|---|---|---|
basic_ecu |
5 | 2 | 3 | native_sim, Nucleo-H743ZI2, FRDM-MCXN947 |
basic_ecu_freertos |
5 | 2 | 3 | QEMU Cortex-M4, any FreeRTOS MCU |
basic_ecu_doip |
5 | 2 | 3 | native_sim (loopback), any Zephyr Ethernet board |
basic_ecu_doip_freertos |
5 | 2 | 3 | Any FreeRTOS + LwIP Ethernet MCU (STM32H7, i.MX RT) |
sensor_ecu |
7 | 4 | 2 | native_sim, any Zephyr sensor board |
safeboot_ecu |
5 | 3 | 2 | Nucleo-H743ZI2 (MCUboot required) |
safeboot_freertos_ecu |
5 | 3 | 2 | Nucleo-H743ZI2 / QEMU Cortex-M4 (FreeRTOS, no MCUboot) |
robot_joint_controller_ecu |
10 | 5 | 3 | native_sim, any Zephyr CAN board |
bms_ecu |
24 | 10 | 5 | native_sim |
motor_controller_ecu |
27 | 8 | 6 | native_sim |
ardep_ecu |
35 | 19 | 6 | native_sim |
Each example ships with a complete generated test suite. Run pytest against the simulator in under 60 seconds, no CAN hardware needed.
TODO [APPLICATION] convention: every hardware/NVM-backed DID or routine accessor in these examples is tagged in-code, e.g. /* TODO [APPLICATION]: Read VIN from NVM. */ in examples/basic_ecu/src/main.c. This marks exactly where a customer's application must supply real hardware I/O. The examples demonstrate integration architecture, not complete or certified ECU functionality — do not treat them as evidence that final vehicle behavior is correct.
EDS targets ASIL-B candidate status (ISO 26262-6:2018). The following work products are included with the current release:
| Work product | Status |
|---|---|
| Safety Manual (EDS-SM-001) | Rev 1.1 — peer reviewed |
| Requirements Traceability Matrix | 14 rows, REQ-SAFE-001–007 + DFU/DTC/flash |
| MISRA C:2012 deviation log | Complete — zero open violations |
| ASIL-B 5-step wrapper chain | Generated, CI-verified on every codegen run |
uds_safety_self_test() |
Present in every generated init sequence |
| WCET analysis | Host x86-64 figures available; Cortex-M7 figures pending HiL |
AES key placeholder notice: core/uds_security_algo.c ships with placeholder AES-128 keys. A compile-time gate (CONFIG_DIAG_PLACEHOLDER_KEYS_ONLY) and a runtime guard in the generated init sequence prevent accidental deployment. See the Security Integration Guide (Professional tier — xaloqi.com) for the OEM key injection procedure.
EDS is the build side of the Xaloqi workflow. Xaloqi TestLab Core
is the test side — a free, Apache-2.0 Python UDS client and ECU
simulator (pip install xaloqi-tester).
diagnostics_config.yaml
│
▼
┌──────────────┐
│ Xaloqi EDS │ BUILD
└──────┬───────┘
│ generated C / native_sim / real hardware
▼
┌──────────────┐
│ TestLab │ TEST
└──────────────┘
Not just a diagram: Xaloqi Compatibility Tests
runs the same UDS campaign against every combination of transport (CAN,
DoIP) and RTOS (Zephyr, FreeRTOS) this repo ships examples for, using
TestLab Core's Python client against EDS's C runtime — a genuine
cross-language, cross-implementation check, not two halves of one
codebase validating each other. Honestly: the virtual-ECU check
there is green and reproducible by anyone; the real-transport matrix
(including this repo's own DoIP Integration CI job, see
EDS#230) is still being
wired up — tracked openly rather than claimed prematurely.
Want to test a UDS ECU before implementing one? → Xaloqi TestLab Core
| Tier | License | Price | Includes |
|---|---|---|---|
| Community | GPL v2 | Free | Runtime stack + examples |
| Developer | Commercial | €690 / year | Codegen + testgen + all examples + integration guide |
| Professional | Commercial | €1,990 / year | Developer + Safety Manual + MISRA log + RTM |
The runtime stack (core/, transport/, config/, platform/) is GPL v2.
ECU examples (examples/) are Apache 2.0.
Code generation tools and Safety Manual require a commercial license.
Unlike alternatives that use PolyForm Noncommercial (which prohibits production use without a paid license), the EDS runtime is GPL v2 — you can ship it in a commercial product for free.
→ Commercial licenses
→ License activation & tier details
docs/GETTING_STARTED.md— zero-to-running in 15 minutesdocs/COMMERCIAL_ONBOARDING.md— license activation, ZIP contents, CI/Docker setup, tier comparisondocs/ARCHITECTURE.md— full module map and design decisions- the Security Notice — seed entropy requirements — TRNG requirements, all-zero seed rejection, development-mode LFSR fallback vs. production fail-closed behaviour (see also
SECURITY.md). Full OEM key injection and HSM offload guide is included with the Professional tier (xaloqi.com). docs/Safety_Model.md— ASIL-B architecture, REQ-SAFE-* traceabilitydocs/TESTING_STRATEGY.md— test layers, coverage targets, HiL plandocs/AI_CONTEXT.md— MCP server setup, tool reference, Claude/Cursor integration guideCONTRIBUTING.md— contribution guideSECURITY.md— vulnerability disclosure policy
- Zephyr RTOS: v3.7+, West 1.2+, CMake ≥ 3.20
- FreeRTOS: FreeRTOS-Kernel (any recent release),
arm-none-eabi-gcc+libnewlib-arm-none-eabi, CMake ≥ 3.20 - DoIP (optional): LwIP 2.x (any MCU with Ethernet) for FreeRTOS targets; Zephyr networking stack (
CONFIG_NETWORKING=y) for Zephyr targets - Python 3.9+ with
pyyaml,jinja2,pytest - Node.js 18+ (GUI only)
Just want to see an ECU run?
west init -m https://github.com/Xaloqi/EDS --mr v1.15.0 eds-workspace
cd eds-workspace && west update
west build -b native_sim examples/basic_ecu \
-- -DDTC_OVERLAY_FILE=boards/native_sim/native_sim.overlay \
-DDIAG_SKIP_CODEGEN=ON
west build -t runWant to test UDS without implementing an ECU first? → Xaloqi TestLab Core
Want to generate your own ECU configuration? → xaloqi.com