alertLog decode (DU + PCS) + DIR 2022 CAN support #13
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/odin-support"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Integrates the alertLog decode work + DIR 2022 CAN support that accumulated on
feat/odin-supportsince PR #11 (16 commits, 33 files).Highlights
.sofiles (so_alerts,so_candata), feeding a new alerts/faults layer.alert_log.py): decodes<NODE>_alertLogCANframes from firmware-recovered bit layouts. Drive-unit (DI/DIR) coverage +
PCS 0x424 decode, 63/84 alerts (PR #12). Rationality decoder matches the
offending-id / errorType / badValues by field name (order varies across ECUs).
is 0x210 (not 0x25D) across revs.
docs/private/alerts/,rev-tagged); extractor tooling stays local/gitignored.
Tests
Sim golden inventory refreshed; ODJ shape tests made dump-agnostic; alert_log
tests (24) pass.
Private-only: carries
docs/private/RE material — this branch does not convergewith the sanitized public
origin.The infotainment stack ships the full per-build catalogs as exported relocated data, richer than anything else in the dump: - so_candata: libQtCarCANData.so holds the 446-message ETH signal catalog (names, units, value tables) vs 140 messages in a per-revision compact.json. No bit layout -- pair with candata_to_dbc to overlay a compact.json donor. - so_alerts: libQtCarAlerts.so holds 6308 alerts with names, descriptions, cause / clear / effect, and the signals each one logs -- in the clear, where bus-alerts-map.json stores only salted hashes (dump_alerts). - tesla_alertlog: decodes <NODE>_alertLog frames (38 ids). byte0 = alert code mux -> NODE_aNNN. CAN-rationality alerts resolve the offending message and error type on the reversed DU and PCS layouts. One field decodes for ANY alert: a094 pins the payload's first log signal to bit 16, so masking to its value table's maximum bit width reads it correctly without knowing the field's true width -- every defined value fits. That field is the alert's reason on the 507 alerts that lead with an enum: 0x527 A2 80 04 00 00 01 22 7C -> DI_a162_shiftDenied, shiftDeniedReason = SYS_STATE_NOT_ENABLED The remaining per-alert field widths exist in no shipped artifact (the .so catalog has no bit layout; neither compact.json nor the year DBCs carry an alertLog message), so they are reported by name as undecoded rather than guessed at -- brute force over a real a162 frame left 61 self-consistent packings, so a single frame cannot pin them. can_decoder overlays the decode onto alertLog frames, lazily and best-effort, so a viewer without a firmware root is unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>The shipped artifacts name an alert's log signals but never place them (the .so catalog has no bit layout; compact.json and the year DBCs carry no alertLog message at all), so until now everything past the leading enum was reported as undecoded. Statically extracting each alert's snapshot packer from the drive-unit firmware supplies the missing bit positions. alertlog_layouts.json holds them as node -> aNNN -> field -> [bit, width, signed], over the log-payload area (frame bytes 2-7, little-endian, bit 0 == byte2 bit0). 33 alerts across DI and DIR. Field counts are verified against the catalog's log_signals, packings are gated on non-overlap and <= 48 bits, and a162 cross-checks against an independent hand reverse-engineering. decode() is now three tiers: a reversed layout decodes every field, else the CAN-rationality packing, else the leading-enum reason alone. Enum and unit labelling still comes from the per-revision catalog at decode time, so one layout serves every revision that keeps the fields, and a field the catalog drops is skipped. A missing or unreadable layouts file degrades to the reason-only tier rather than failing. 0x527 A2 80 04 00 00 01 46 7C -> DI_a162_shiftDenied, reason SYS_STATE_NOT_ENABLED, currentGear N, requestedGear D (a refused N->D shift) WIP: the extractor output is checked in as data, but the extraction itself still needs a pass to make it scalable -- coverage is 33 of ~3000 alerts with log signals, and the signedness heuristic (unsigned unless wide torque/speed/accel telemetry) is not yet derived from the firmware. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>RC 0x0201 (checkModuleProgrammedCorrectly) is a verify, not just a CRC check: on legacy bootloaders it recomputes the image CRC, but on secure bootloaders (e.g. 2026+ PMR) the same routine also enforces an ECC signature and SVN rollback check, so a non-zero status can mean an unsigned/wrongly-signed/ rolled-back image rather than a CRC mismatch. Rename step_verify_crc -> step_verify and _RC_VERIFY_CRC -> _RC_VERIFY, and reword the progress/error output ("CRC check"/"MISMATCH" -> "Verify"/"Verify FAILED (CRC mismatch, or signature/rollback rejection on secure bootloaders)"). Also renames the CLI named routine verify-crc -> verify and updates the docs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>Reverse-engineered the PCS (variant-411, F28377D dual-core) alertLog packing and recovered per-alert log-field bit layouts, the PCS analog of the drive-unit work. Each PCS alert builds a 4-word record = the 0x424 frame (word0 code/state, words 1-3 = the 48-bit payload over bytes 2-7, same little-endian view the framework already decodes) then calls the setter with the alert id as an explicit immediate. A dataflow interpreter over the mask/shift/OR + FPU-clamp packing idiom (local tooling in docs/private/alertlog-extractor) recovers each field; field counts are checked against libQtCarAlerts log_signals, non-overlap/<=48b gated, and anchored on a030 = {canRxErrorType:[0,3], canID:[8,16]} (matches Damien Maguire's handle424) plus a029. 60/84 alerts emitted into the shared, rev-tagged layouts file under a "PCS" node (cross-rev names borrowed from 2024/2026 where the 2022 catalog is silent; tail flag groups split into 1-bit fields). The remaining alerts either have no published field names, are MIA source-bit markers, or are register-built packers left to the reason-only fallback. Also fixes a latent drive-unit bug: the CAN-rationality decoder paired the offending-id / errorType / badValues positionally, but their catalog order varies (DIR a094 = [canID, errorType, ...] vs a066 = [badValue1, badValue2, canID, errorType]); now matched by field name, which fixes PCS a030 and the DU a066 family. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Pull request closed