Skip to content

BMCLI A2L and XCP on CAN/CAN FD

Reference version: BMCLI 1.6.3. Command names, parameters and machine-readable fields retain their source spelling.

BMCLI treats A2L as a read-only symbol/address contract, not an editor. The first parser scope is intentionally consumer-driven: module and byte order, scalar MEASUREMENT and CHARACTERISTIC, address/extension, record layout, bit mask and matrix size, plus IDENTICAL, LINEAR and RAT_FUNC conversion. Unknown balanced blocks are skipped; an unsupported layout or conversion is reported rather than guessed, especially before a write.

For multi-ECU files, symbols, COMPU_METHOD, RECORD_LAYOUT and inherited BYTE_ORDER remain scoped to their containing MODULE. Duplicate symbol names must be qualified with --module=<name>; BMCLI never chooses one ECU implicitly. A missing ECU_ADDRESS, READ_ONLY value, non-scalar characteristic, unsafe mask, or unsupported conversion remains visible for inspection but cannot be used for an XCP access.

Discover exact commands and options from:

Terminal window
bmcli help a2l --format=json
bmcli help xcp --format=json

The available XCP families cover endpoint configuration, connect/status/ disconnect, external security unlock, raw memory read/write/checksum, A2L-backed measurement and characteristic access, and bounded DAQ. XCP on CAN uses direct CTO/DTO frames and does not use ISO-TP. UDS uses BMCLI’s software ISO-TP transport. Both protocols can run on one analyzer channel when their CAN IDs are distinct; raw receive, logging and Web continue through independent RxBroker cursors.

Each CTO request is bounded by its own hardware-sequence-correlated transmit completion. A RES or ERR already queued at or before that boundary is not accepted as the current response; DTO, EV, and SERV traffic continues through the endpoint cursor on both sides of the boundary. Because XCP has no protocol transaction identifier, a syntactically valid response that a slave sends after the current request remains indistinguishable by content.

If a CTO write is accepted but its real completion cannot be observed, XCP is invalidated for that analyzer channel generation. Further XCP CTOs fail before leasing another completion sequence and instruct the caller to recover or reopen the channel. Other completion-dependent protocols keep using the shared pool; a trusted physical channel generation change clears only this XCP gate. After controlled recovery, BMCLI rebinds the preserved logical XCP endpoint to the replacement handle in a disconnected state; issue xcp connect again.

CAN NoACK mode does not publish transmit completions into BMAPI’s receive queue. XCP therefore returns the structured unsupported_in_noack_mode error before allocating a completion identity or calling BM_Write; the XCP generation guard remains unchanged. Reconfigure the channel to a completion- capable normal mode before issuing a CTO.

xcp memory write supports --dry-run to show the exact address, extension and bytes without transmitting, and --verify for exact readback after a write. CONNECT address granularity and live DAQ entry resolution are honored; byte lengths that cannot be represented by the negotiated granularity are rejected rather than rounded. UDS and XCP response routes are validated in both configuration orders.

The first DAQ implementation supports one list/ODT with at most 32 scalar symbols and a 256-sample host queue. xcp daq status reports queue and route drop counters. A full queue drops the oldest retained sample explicitly; a caller must not interpret that as a lossless acquisition. xcp daq create checks the CONNECT DAQ resource bit and all locally decidable event, prescaler, A2L symbol, scalar-layout, and MAX_DTO constraints before it sends GET_DAQ_RESOLUTION_INFO. Only entry granularity and maximum entry size depend on that slave reply, so local errors are not masked as slave timeouts. xcp daq receive returns one bounded JSON document with a samples array. Use --format=json; JSONL and CSV are rejected for this command. For a workflow that owns its XCP state, clean up in this order: DAQ stop, DAQ delete, disconnect, then database unload <resource> for only the A2L it loaded.

xcp disconnect also stops/frees an existing DAQ configuration before sending DISCONNECT. Its handshake permits other daemon commands, including a simulated slave’s message send, to run while waiting. A valid response (including a single-byte FF) completes the disconnect and clears connected, DAQ and queued DTO state. A genuine timeout still fails; the last connected state may remain because the slave has not confirmed the disconnect. Do not suppress that error or treat a later successful reply-send command as proof that the reply arrived before the timeout. Channel close cancels an outstanding exchange through the normal cooperative lifecycle.

OEM seed/key logic is always external. BMCLI loads a same-bitness shared library that exports:

int BMCLI_XcpComputeKey(
uint8_t resource,
const uint8_t *seed,
uint32_t seed_length,
uint8_t *key,
uint32_t *key_length);

Return zero on success. On entry *key_length is the key-buffer capacity (currently at most 62 bytes); on return it is the produced length. Resource bits are CAL/PAG 0x01, DAQ 0x04, STIM 0x08, and PGM 0x10. BMCLI never derives, records, or guesses an OEM algorithm.

The Web service exposes bounded XCP operations at GET/POST /api/v1/xcp. The POST body uses the same tokenized argv model documented by the live OpenAPI contract. A2L upload, durable time-series storage, users, reports, calibration approval and other general application concerns belong to the surrounding Web backend, not the BMCLI bus-domain service.


Source of truth: BMCLI 1.6.3 repository documentation. Run bmcli help <category> <action> --format=json for the exact contract of the installed version.