AWD: diff the 2022 AWD vs RWD DIR, and work out the DIF/PMF front drive unit #25
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Follow-on from PR #24 (2026 sim variants), which found two front-drive frames on the 2026 AWD DIR —
0x1D5 PMF_state4and0x2E5 DIF_power— and deliberately left them unsimulated as AWD-only.Goal: get an AWD rear DU working on the bench, starting at 2022.45.15 (the rev that already spins RWD).
Detail lives in
docs/private/PLAN-awd-front-drive-unit.md(gitignored — local only).Variant coding, established while scoping this
Images are
<DIR|DIF>_<gen>-<assembly>-<usage>. The usage digit is the drivetrain role:0= AWD rear — named..._Master_VDC1= front DU —DIF_*/PMF_*2= RWD rear — named..._Single_VDC"Single" vs "Master" is semantic: a RWD rear is the only DU, an AWD rear is master of a master/front pair.
The front DU is its own node,
pmf:, and likepmr:(which owns PMR CPU1 + DIR CPU2) it owns bothpm/<build>/PMF_*.bhxanddi/<build>/DIF_*.bhx. There is nodif/pmfdirectory underseed_artifacts_v2— front and rear ship from the samedi/pmtrees, separated only by build number and node id.Step 1 — controlled AWD/RWD diff at 2022
Pair differing only in the usage digit, so no fw-year or hardware confound:
di/12803DIR_28-65-2_M3_Single_VDCdi/12804DIR_28-65-0_M3_Master_VDCReuse the
checkRxDlcrx enumerator + gate/seed sweep built for PR #24. Two cautions: don't assume the checksum seeds carry over (0x3A1 and 0x25B already deviate fromid_lo + id_hi), and diff the TX side too — the rear commands the front, so the interesting traffic is rear→front and an rx-only enumeration won't see it.Step 2 — DIF firmware
2026 is already imported:
dif_33-83-1_bayberry(pmf:559087617,di/13313). For 2022 the front builds areDIF_23-64-1…DIF_33-83-1; note the front assembly never matches the rear's, so a gen-28 AWD car pairs rear28-65-0with a front from a different assembly (66/69/71/76/80/81/84). Pairing is by car-config conditions, not assembly number — verify before staging rather than matching on 65.Step 3 — sim support
Only after 1 and 2, in a rev-keyed
fw_variantsentry, sending every MIA-supervised frame.Main open risk
A
Masterimage may hard-require a front DU on the bus, in which case the sim has to impersonate the front and Step 1's TX diff becomes the critical piece rather than the rx diff. The bench has one DU, so testing may need a second unit or a simulated front.Steps 1 and 2 are done; step 3 is implemented and pushed as
feat/sim-dif-front-unit. Full write-up indocs/private/awd-dir-dif-can-interface.md.First, a correction that widens the scope
A DIR has two rx CAN buses, not one. There are two
checkRxDlchelpers per image and the earlier sweep indir-pmr-can-delta-2022-to-2026.mdfound only the vehicle-bus one. So the "42 frames" figure there was one bus — the real 2022 RWD set is 60, with 18 more on the chassis/partybus (RCM / ESP / DAS / IBST / EPAS / SCS). Helpers have to be discovered by shape; ranking callees by call-site volume picks one and hides the other.The 2026 numbers in that doc were short the same way. Re-swept: the 2026 AWD DIR rx's 72, and three chassis-bus frames were never recorded anywhere —
0x209,0x20A,0x20E.Step 1 — the AWD delta is exactly 4 frames
Same-rev, same-gen, same-assembly pair (
di/1280328-65-2 vsdi/1280428-65-0, both 2022.45.15), both on the post-09-10 SLEIGH. AWD 64 = RWD 60 + 4, nothing removed, no DLC changes on shared frames, and no reseeds — seeds are byte-identical across the pair.All four are front-inverter frames. Every seed follows
id_lo + id_hi; the only image-wide exception is the already-known0x3A1 = 0x12A.Two traps worth naming:
0x2D5is DLC 7 in firmware and 8 in every DBC. DLC is an exact match, so a DBC-length frame is rejected and the frame goes MIA looking perfectly healthy on the wire. It is 8 again on 2026.8.3.ESP_status 0x145andIBST_status 0x39Dalready use that layout in the sim, which is a nice independent check on the extractor.)0x2E5 DIF_poweris now confirmed AWD-only rather than inferred — that open question is closed. Separately,0x1D5 PMF_state4is absent from the 2022 AWD DIR entirely, so on the DIR it is a 2026 addition and AWD-gated; the two weren't alternatives.Step 2 — the front DU
The TX-table diff turned out to be unnecessary. The front's rx set names what the rear sends, and it's a clean symmetric pair:
0x108 DIR_torque,0x118 DI_systemStatus,0x148 DI_chassisControl,0x257 DI_speed,0x3B6 DI_odometerStatusThe DIF is not a rear-fed slave — 25 of its 33 rx frames are rest-of-car (BMS, VCFRONT, UI, GTW, ESP), so it needs its own liveness.
On the "does a Master image require a front" risk: yes, but it's cheap to satisfy. All four frames are MIA-supervised, and the rear carries
DIR_a040 difMIA,DI_a138 frontUnitDisabled, plus VDC cross-checksDI_a207 vdcPowertrainTorque_dif/DI_a211 vdcMotorSpeed_dif. Faking a front is 4 frames with known DLC, seed and placement — no second physical unit needed to get the rear out of difMIA. (Whether those specific alerts fire on this build is unproven; the catalog is a shared namespace.)Correction to the plan's step 2: it proposed
DIF_28-81-1as "the likely M3 gen-28 counterpart".version_map2.tsvgives no basis for that — all 15pmf:node ids carry identical conditions (chassisType=2,drivetrainType=1), so nothing distinguishes one gen-28 M3 front from another. Pairing is by the front unit's own part number. I imported 12875 as a representative; any gen-28 M3 front would do. Also decoded:drivetrainType1=AWD / 0=RWD,chassisType2=M3 / 3=MY,vdcTypeorthogonal to the usage digit.Step 3 —
feat/sim-dif-front-unitNew
DIFnode sending exactly those four frames, with2022.45.15(DLC 7) and2026.8.3(DLC 8) variants. 3205 tests pass, ruff clean. A RWD bench drops it via the existingreal/simselection.Caveat to flag: a 2024.8.9 target resolves to the 2022 entry and so sends DLC 7, which is unverified — no 2024 AWD DIR is imported, and the DBC isn't evidence here since it says 8 for 2022 too.
Loose ends
0x318 GTW_carState's counter is at bits 49-52, not 52-55.feat/sim-2026-fw-variantsends it at @52 per the old note, which would make the fw see 0/8/0/8 and reject every frame after the first (the first-frame bypass is one-shot). Worth checking before that branch lands.pm/12804) is still not imported, so the PMR AWD delta is untouched.Corrections to my previous comment, plus the sim scenarios.
0x318 GTW_carState — confirmed a bug, and not a firmware-version delta
I flagged this as a "possible" bug. Checked it properly, and it holds.
The counter is at bits 49-52 (
uVar1 >> 1 & 0xfon word 3), not 52-55. Three images agree, across two firmware years and both drivetrain variants:13294>> 1 & 0xf12804>> 1 & 0xf13292>> 1 & 0xfSo there is no revision at which
@52was right. And no ETH DBC defines a counter or checksum signal for 0x318 at any revision — meaning@52was never read off anything, it was the default byte6/byte7 assumption carried over from the frames that do use that layout.Consequence for
feat/sim-2026-fw-variant: a counter written at @52 is read by the firmware as 0 / 8 / 0 / 8…, which never satisfies(prev + 1) & 0xf. The first-frame bypass is one-shot (the validator clears the bypass bit on the first success), so every 0x318 after the first is dropped and 0x318 never clears its MIA. Worth fixing before that branch lands.Three more corrections, from the same 2024.8.9 sweep
0x238,0x318and0x3FDare not 2026 additions. All three are already in the 2024.8.9 DIR (13294).dir-pmr-can-delta-2022-to-2026.mdlists them as 2026-new; they arrived at or before 2024.8.9, and only the 2022→2024 boundary is untested.0x3A1is reseeded at every revision, not twice: 0xA4 (2020) → 0x12A (2022) → 0xE2 (2024.8.9) → 0xC0 (2026). The 2024 value is new. Re-read the seed per target revision rather than assuming it only moved twice.0x25C→0x25Brenumber and0x132DLC 8 → 6 — 2024 still has 0x25C and still has DLC 8.Front vs rear: the sets are not the same, and the asymmetry is structural
Worth recording since it came up. Rear rx's 64 frames, front 33, 25 shared. The rear is the master (vehicle-level DI aggregate, gear FSM, VDC, brake vote) so it subscribes to most of the car; the front is a follower. The 8 the front takes that the rear doesn't:
0x108 DIR_torque,0x118 DI_systemStatus,0x148 DI_chassisControl,0x257 DI_speed,0x3B6 DI_odometerStatus0x1D5 PMF_state4, which is symmetric: the rear takes0x1D8 PMR_state4instead0x142 VCLEFT_liftgateStatus,0x136(in no DBC)The larger asymmetry runs the other way: 39 frames the rear takes that the front does not.
Sim scenarios (pushed to
feat/sim-dif-front-unit)scenarios/drive-awd.toml— bench an AWD rear with the front simulated:drivetrainType=AWDand DIF deliberately out ofreal.scenarios/drive.tomlgains the matching explicit RWD car config (already the defaults, so no behaviour change — it just puts the one difference between the profiles in the same visible place). Verified against the real DBC:3206 tests pass, ruff clean.
Two judgement calls, both reversible:
drive.tomllistsDIFinreal, which is a semantic stretch — a RWD car has no front unit at all, butrealis the only lever that drops a node from the broadcast set. A dedicatedabsentkey would be the honest fix if the pattern recurs.number_hvil_nodesleft unset on the AWD profile. A two-DU car does have more HVIL nodes, but the 2022 images are not gated on it and it only feedsa144 configMismatch, so I matched the working RWD bench rather than guess. Revisit if a144 appears.On running a real AWD pair on the bench
At the CAN layer the two halves close the loop themselves — each transmits what the other waits on. Caveats if you go that route:
0x108/0x118/0x257on the party bus.scripts/dir/dir.pystill calls its own bus assignment provisional; this pins those three.0x136,0x142(party),0x500.DI_a207 vdcPowertrainTorque_difandDI_a211 vdcMotorSpeed_difmean the rear cross-checks the front's torque and speed against its own, which two units on separate stands are exactly positioned to fail.