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:
bmcli help a2l --format=jsonbmcli help xcp --format=jsonThe 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.