ISO 14229 UDS diagnostics stack for Zephyr and FreeRTOS. YAML-configured. ASIL-B-oriented architecture. DoIP + CAN.
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
Xaloqi EDS
Xaloqi Embedded Diagnostics Suite
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.檢視完整 README ↗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.25.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 run
examples/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.
Want a complete application built on EDS, not just the runtime? → Zephyr Reference ECU — a body-control-module app on real NUCLEO-H753ZI hardware: CAN and DoIP transports, MCUboot secure boot, and Eclipse SOVD/CDA interop, all driven from one
diagnostics_config.yaml.
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_halt
2. 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-gen
3. 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 flash
The 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.25.0
path: modules/eds
Then 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-0x04 0x06-0x0E 0x14 0x15 |
| 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. Running a UDS tick task alongside it? Register eds_doip_set_lock_callbacks() — see docs/INTEGRATION_GUIDE.md §5b; production builds enforce it. |
| 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 |
Safety properties verified by CI on every commit:
malloc/free grep 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_COUNT in generated headers matches YAML ground truthpip install west
west init -m https://github.com/Xaloqi/EDS --mr v1.25.0 eds-workspace
cd eds-workspace && west update
pip install -r tools/requirements.txt
No 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_freertos
For the full FreeRTOS integration guide (callbacks, NVM, reset, production porting), see docs/INTEGRATION_GUIDE.md.
Protocol conformance is checked against byte-level vectors we did not write, ported from three independently authored, MIT-licensed projects:
| Standard | Vector source | Test module |
|---|---|---|
| ISO 15765-2 (ISO-TP) | pylessard/python-can-isotp | tests/unit_runnable/test_isotp_conformance_vectors.c |
| ISO 13400-2 (DoIP) | jacobschaer/python-doipclient | tests/unit_runnable/test_doip_conformance_vectors.c |
| ISO 14229-1 (UDS SID framing) | pylessard/python-udsoncan | tests/unit_runnable/test_uds_sid_conformance_vectors.c |
They run as part of build_tests.sh, need no hardware, and each module's header
records the exact upstream tag it was ported from.
Why this exists: a stack validated only by its own vendor's tester proves consistency, not conformance. Porting these surfaced three real ISO 13400-2 defects in our own DoIP implementation (#369, #371, #368) on first contact — all three since fixed.
Scope limit, stated plainly: these cover protocol mechanics — framing, NRCs, sequence and timing behaviour. They are not an ISO conformance certification, and they say nothing about any particular ECU's DID or DTC content.
diagnostics_config.yaml is the single source of truth: it generates the C
handlers, the pytest suite, the SOVD CDA descriptor, and (Developer/
Professional tier) the CANoe CAPL suite. "Single source of truth" is an easy
claim to make and a cheap one to check — so here's a script that checks it:
bash scripts/demo_gtm18_one_did_change.sh
Changes one field in a scratch copy of examples/ardep_ecu's config (DID
0xF187's data_length, 11 → 14), regenerates every artifact from it, and
shows you the diff. Nothing is staged or faked — same codegen.py and
tools/testgen.py (when present) as any real run. Public tier gets the C
sources and the SOVD CDA descriptor; the pytest and CAPL sides need the
commercial toolchain, and the script says so plainly rather than silently
doing less than it claims.
One framing worth stating outright, since it's easy to hear as the opposite
claim: this generates to these four formats from a definition we own —
not from someone else's schema. sovd_cda.json is EDS's own CDA
configuration descriptor, not an ASAM SOVD or ISO 17978 artifact.
The independent conformance vectors above check protocol mechanics against known-good byte sequences. This checks something different: does EDS actually interoperate with somebody else's real, independent implementation of the other side of the wire — the real Eclipse OpenSOVD Classic Diagnostic Adapter (CDA), not a simulator standing in for it.
bash scripts/demo_can_sovd_cda_interop.sh
One command, no prior Zephyr/west setup required — the only host
prerequisite is Docker. It builds examples/basic_ecu_cda_demo for
Zephyr's native_sim against a real host SocketCAN device (not Zephyr's
in-process loopback, which can only ever talk to itself), builds the real
Eclipse OpenSOVD Classic Diagnostic
Adapter
from its own public source, and joins the two over a virtual CAN pair —
all inside containers this script builds and tears down itself. No sudo
required: the virtual CAN pair is created via docker run --cap-add=NET_ADMIN, not a host privilege escalation.
It then exercises what a fictional ODX test fixture can't, because nothing
answers on the other end of one: a real multi-frame ISO-TP read, session
control, SecurityAccess with real AES-128-CMAC cryptography (computed
independently from the real seed EDS sends over the wire), and
RoutineControl — all against real, unmodified core/, transport/ and
platform/ code, routed entirely through the CDA's own SOVD HTTP API.
Stated plainly: this is CAN only — the real CDA discovers DoIP gateways
exclusively by UDP Vehicle Identification, which EDS has never implemented
(EDS#392). And
examples/basic_ecu_cda_demo carries two diagnostic IDs chosen to match
the CDA's own shipped test fixture rather than EDS's own convention —
disclosed in that example's own README, not quietly carried. This proves
EDS is a real, runnable test target for SOVD/CDA tooling; it is not a
claim that EDS is "the" SoDeV diagnostics layer.
# 61 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.sh
A 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 2,038 of 3,102 collected cases in a Developer-tier checkout (this repo, as cloned) and 3,059 of 3,102 with the Professional-tierharness/build present — the gap is cases gated on commercial prerequisites (TestLab, the firmware harness, or thetools/templatescodegen ZIP), not failures. Not every executed case runs the C stack: the robustness campaign's protocol phases (B, C, E, G, H, I) check the generated suite's Python simulator, a model of the stack. The release gate ties that model to the compiled firmware; see what the protocol phases verify. 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/ | 61 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 | Evidence |
|---|---|---|---|---|---|
basic_ecu | 5 | 2 | 3 | native_sim, Nucleo-H743ZI2, FRDM-MCXN947, MR-CANHUBK3 | compile-verified (3 board targets + native_sim) |
basic_ecu_freertos | 5 | 2 | 3 | QEMU Cortex-M4, any FreeRTOS MCU | compile-verified (QEMU Cortex-M4) |
basic_ecu_doip | 5 | 2 | 3 | NUCLEO-H753ZI, native_sim (loopback), any Zephyr Ethernet board | hardware-validated (NUCLEO-H753ZI, real Ethernet) |
basic_ecu_doip_freertos | 5 | 2 | 3 | QEMU Cortex-M4, any FreeRTOS + LwIP Ethernet MCU (STM32H7, i.MX RT) | compile-verified (QEMU Cortex-M4) |
sensor_ecu | 7 | 4 | 2 | native_sim, any Zephyr sensor board | compile-verified (native_sim) |
sensor_ecu_freertos | 7 | 4 | 2 | QEMU Cortex-M4, STM32F4, Nucleo-H743ZI2 | compile-verified (QEMU Cortex-M4) |
safeboot_ecu | 5 | 3 | 2 | NUCLEO-H753ZI, Nucleo-H743ZI2 (MCUboot required) | hardware-validated (NUCLEO-H753ZI, CAN) |
safeboot_freertos_ecu | 5 | 3 | 2 | Nucleo-H743ZI2 / QEMU Cortex-M4 (FreeRTOS, no MCUboot) | compile-verified (QEMU Cortex-M4) |
robot_joint_controller_ecu | 10 | 5 | 3 | native_sim (simulated joint; loopback and SocketCAN variants) | compile-verified (native_sim); runtime smoke over vcan in CI; no hardware |
bms_ecu | 24 | 10 | 5 | native_sim | compile-verified (native_sim) |
motor_controller_ecu |
What the Evidence column means (added for #329 — before it, nothing in this repo said which targets had ever been flashed). Each example carries the strongest label that is true of it:
| Label | Means | Proof |
|---|---|---|
| hardware-validated | Flashed onto real silicon and exercised, with measurements recorded | docs/PERFORMANCE.md — DWT cycle-counter figures from a NUCLEO-H753ZI (Cortex-M7 @ 480 MHz, -Os): safeboot_ecu over CAN/ISO-TP, basic_ecu_doip over the board's onboard MAC+PHY |
| compile-verified | Compiled and linked in CI for the named target, and never flashed | CI jobs zephyr-native, zephyr-stm32, zephyr-nxp, zephyr-nxp-s32k, zephyr-stm32-safeboot, zephyr-examples-native, freertos-qemu, freertos-safeboot, freertos-examples, doip-integration |
All twelve examples are now at least compile-verified, and two have been on a bench. That became true on 2026-10-02 and was not true before, which is worth stating rather than quietly presenting as always-so:
basic_ecu_doip_freertos, had no CI coverage at all. Their
example-* jobs validate YAML and committed generated/ files and never
invoke a compiler — #98 ("7 of 12
examples are never built by any CI job") was closed by adding exactly those
jobs, so the gap it named outlived its own fix.ardep_ecu used an enum
deleted by an earlier MISRA cleanup, and sensor_ecu listed a source file
that does not exist and guarded its device lookups with DT_HAS_ALIAS, which
is not a Zephyr macro. All three are fixed; the jobs now keep them honest.Read compile-verified literally: it means the committed generated code
compiles and links against the stack on that target. It is not a claim that the
example has run anywhere, and for the native_sim entries it is not a claim
about the physical board named in the Boards column. All twelve ship complete,
committed generated code and are architecturally identical in how they wire the
stack — that is why they are useful as references — but only two have been on a
bench.
sensor_ecu_freertos joined this table on 2026-10-02; the example has existed
all along but the table listed only 11 of the 12.
Cross-transport behaviour against a real bus is proven separately, not here:
xaloqi-compatibility-tests
runs the UDS matrix over a real host vcan0 and a real DoIP/TCP bridge on
Zephyr targets, and its COVERAGE.md states exactly what is and is not claimed.
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) | Peer reviewed — current revision ships in the Professional package (CUSTOMER_NOTICE.md lists it) |
| Requirements Traceability Matrix | Every requirement (REQ-SAFE, DFU, DTC, flash, timing, …) with its ASIL, implementation, tests and coverage status |
| 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 decisionsSECURITY.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 policymain with warnings as errors (basic_ecu / basic_ecu_doip / safeboot_ecu on nucleo_h753zi, basic_ecu_doip on xenvm, the native_sim examples, plus a deprecation sweep; list in .github/zephyr-main/builds.tsv).arm-none-eabi-gcc (CI is pinned to ARM GNU Toolchain 13.3.rel1, which bundles newlib — a separate libnewlib-arm-none-eabi package is not required with that toolchain), CMake ≥ 3.20CONFIG_NETWORKING=y) for Zephyr targetspyyaml, jinja2, pytestJust want to see an ECU run?
west init -m https://github.com/Xaloqi/EDS --mr v1.25.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 run
Want to test UDS without implementing an ECU first? → Xaloqi TestLab Core
Want to generate your own ECU configuration? → xaloqi.com
--sovd flag: YAML → sovd_cda.json — DIDs, DTCs, routines, transport, all 19 services · SOVD-inspired field names, not a conformant ASAM SOVD / ISO 17978-3 capability description · DoIP ECUs include logicalAddress and port |
| 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 |
| 27 |
| 8 |
| 6 |
| native_sim |
| compile-verified (native_sim) |
ardep_ecu | 35 | 19 | 6 | ardep (custom board, ARDEP Zephyr workspace), native_sim | compile-verified (native_sim) |