Repository navigation
LibUDS 2.0.0
UDSLib v2.0.0
Universal Diagnostics Stack for Embedded Systems
What's New
Architecture release: response emission, suppression, and reset ordering move
into the dispatch framework, and the runtime context is regrouped. All ISO
14229 conformance from 1.20.0 is preserved; this release changes the handler
API, not the wire behaviour.
It also lands an architecture-hardening pass: a real two-context concurrency
model (an RX/input context running concurrently with uds_process), buffer-bound
hardening on every response path, configuration single-source-of-truth, and new
configurability. The wire behaviour is unchanged and no public function signature
changed; two integrator-visible behaviours are refined (see Changed).
Breaking
-
Service handlers use a result-descriptor contract. A handler registered
viaconfig.user_servicesis now
void handler(uds_ctx_t*, const uint8_t*, uint16_t, uds_result_t *out): it
writes the positive payload intotx_bufferand describes the outcome via
uds_ok(out, len)/uds_nrc(out, nrc)/uds_pending(out)/
uds_none(out)instead of callinguds_send_response/uds_send_nrc/
returningUDS_PENDING. The framework (execute_handler) is the single
authority for emission, suppressPosRsp, and the deferred ECUReset.
uds_send_response/uds_send_nrcremain public for application code that
emits outside a handler. Migration:return uds_send_response(ctx, n);→
uds_ok(out, n);;return uds_send_nrc(ctx, sid, nrc);→uds_nrc(out, nrc);;
return UDS_PENDING;→uds_pending(out);. -
Runtime
uds_ctx_tfields regrouped into sub-structs (not API): fields
now live undersession/security/server/client/scratch
(e.g.ctx->active_session→ctx->session.active,ctx->security_level→
ctx->security.level). Affects only code that readuds_ctx_tfields
directly. The per-dispatchscratchis reset at the start of every top-level
request, so no per-request flag can leak into the next. -
Client role moved to
uds_client_ctx_t(uds/uds_client.h): the server
uds_ctx_tno longer carries client state or auto-routes responses.
uds_client_requesttakes auds_client_ctx_t*; feed incoming responses to
uds_client_handle_response(returns true if consumed).uds_response_cb's
first argument is nowuds_client_ctx_t*.
Added
- ISO-TP generic SDU sink
uds_isotp_set_sdu_handler(iso, fn, cookie):
reassembled SDUs are delivered to a custom handler instead of the server
uds_input_sdu, so one ISO-TP channel can feed a UDS server or a UDS client.
Default (no handler) preserves server delivery. - ECUReset (0x11) — wait for the response to be on the wire before resetting: a new optional
fn_tx_complete(ctx)config hook lets the library hold the reset until the positive0x51response has physically left the transport (TX mailbox drained), not merely been queued. It is bounded by the newreset_tx_wait_msbudget (0=UDS_DEFAULT_RESET_TX_WAIT_MS, 50 ms) so a stuck transport can never hang the ECU; when the hook is unset, behaviour is unchanged (immediate reset). This closes a real-hardware race: afn_resetthat callsNVIC_SystemReset()could reboot before the FDCAN frame was arbitrated onto the bus, so a tester saw silence after11 01and only11 81(suppressPosRsp) appeared to work. The H5 example now polls FDCANTXBRPinfn_tx_completeand performs a realNVIC_SystemReset. (#88) - Configurable S3 session timeout via
uds_config_t.s3_ms(0=
UDS_S3_TIMEOUT_MS, 5000 ms). Previously the S3 revert was a fixed
compile-time constant. - ISO-TP receiver Block Size / STmin setters
uds_tp_isotp_set_block_size()
anduds_tp_isotp_set_st_min()let the receiver advertise its own BS/STmin in
the Flow Control frame (defaults unchanged: BS 8, STmin 0). uds_initvalidates buffer sizes: atx_buffer_sizeorrx_buffer_size
belowUDS_MIN_TX_BUFFER_SIZE/UDS_MIN_RX_BUFFER_SIZE(8) is rejected with
UDS_ERR_INVALID_ARGinstead of risking an overflow later.- Two-context concurrency (OSAL): with the mutex hooks supplied, an RX/input
context (uds_input_sdu/ ISO-TP RX) may run concurrently with the
uds_processcontext. Cross-context state isvolatile-qualified and
fn_tp_sendruns outside the critical section. The mutex must be an ISR-safe
critical section if RX runs in an interrupt (see OSAL.md); thefreertos_demo
example is the canonical two-context reference.
Changed
- A handler that returns without describing a result now fails closed
(generalReject 0x10) instead of emitting whatever is intx_buffer. - The deferred ECUReset is owned by the framework: it runs strictly after the
response is emitted, never during a captured 0x84/0x86 inner dispatch, is
cancelled if the response fails to encode or send (the tester gets an NRC /
nothing, so the ECU does not reboot), and never fires from a captured
ResponseOnEvent dispatch. - P2/P2* resolved once at
uds_init(single source of truth) from
p2_ms/p2_star_ms, with the legacyp2_server_max/p2_star_server_max
pair folded in. The 0x10 response derives its advertised timing from the
resolved values; mutating the P2 config fields afteruds_initno longer
changes the advertised timing. fn_tp_send'sdatamay be a private snapshot, not a pointer into
config->tx_buffer, for responses ≤UDS_TX_FLUSH_SNAPSHOT_MAX(512 bytes);
larger frames are sent fromtx_bufferunder the lock. Applications must use
thedata/lengiven and must not assumedata == tx_buffer.
Fixed
- Bounded every response-buffer copy: ResponseOnEvent setup echo, the async
ResponseOnEvent (0xC6) emit, and the periodic (0x2A) scheduler now check
tx_buffer_sizebefore writing — an oversized one is rejected (responseTooLong)
or skipped instead of overflowingtx_buffer. - Concurrency correctness (found and fixed under ThreadSanitizer): a staged
responsePending (0x78) is no longer clobbered by a periodic/ROE frame on the
sameuds_processtick; the post-TX action (ECUReset/LinkControl) flag
bookkeeping is serialized under the lock so a deferred reset can no longer race
its own cancellation; and the client request path snapshots its frame like the
server path. The transport call and the reset/link callbacks remain outside the
lock.
Known limitations
- SecuredDataTransmission (0x84) shares
config->tx_bufferwith its copied-out
inner dispatch; this is safe because a dispatch is serialized under the OSAL
lock (the two-context model protects whole-request dispatch, not arbitrary
reentrancy). - The handler-result contract is the stable surface; the
uds_ctx_tfield
layout is not part of the API contract and may evolve. - The test suite is host-simulation based (mocked transport + virtual clock).
Test Results
All Tests Passed
- Total Tests: 74
- Passed: 74
- Failed: 0
Build Information
- Version: 2.0.0
- Build Date: 2026-06-23 12:59:52 UTC
- Compliance: ISO 14229-1 (UDS)
- Platform Support: Bare Metal, FreeRTOS, Zephyr, Linux, Windows
Supported Services
UDSLib v2.0.0 implements 16 ISO 14229-1 services:
| Service | Description | SID |
|---|---|---|
| Diagnostic Session Control | Session management | 0x10 |
| ECU Reset | Reset operations | 0x11 |
| Clear Diagnostic Information | DTC clearing | 0x14 |
| Read DTC Information | DTC reporting | 0x19 |
| Read Data By Identifier | Data reading | 0x22 |
| Read Memory By Address | Memory access | 0x23 |
| Security Access | Seed/Key exchange | 0x27 |
| Communication Control | TX/RX control | 0x28 |
| Authentication | Certificate exchange | 0x29 |
| Write Data By Identifier | Data writing | 0x2E |
| Routine Control | Routine execution | 0x31 |
| Request Download | OTA init | 0x34 |
| Transfer Data | Block streaming | 0x36 |
| Request Transfer Exit | OTA completion | 0x37 |
| Write Memory By Address | Memory writing | 0x3D |
| Tester Present | Keep-alive | 0x3E |
| Control DTC Setting | DTC ON/OFF | 0x85 |
Installation
Download Pre-built Binaries
Download the attached artifacts:
uds_host_sim- Host-based ECU simulatorunit_tests- Complete test suite
Build from Source
git clone https://github.com/w1ne/udslib.git
cd udslib
git checkout v2.0.0
mkdir build && cd build
cmake ..
make
ctestDocumentation
Licensing
- Community: PolyForm Noncommercial 1.0.0 (noncommercial use). See LICENSE.
- Commercial: 5,000 EUR for production/commercial use, includes integration + 1 year support.
- Contact: andrii@shylenko.com for commercial terms and support.
Report Issues
Found a bug? Open an issue
Full Changelog
See CHANGELOG.md for complete version history.
Code Coverage
Line Coverage: 93.8% · Function Coverage: 99.1%
Summary coverage rate:
lines......: 93.8% (2090 of 2229 lines)
functions..: 99.1% (107 of 108 functions)
branches...: no data found
Full coverage report available in release artifacts.