APS Logo APS_TUNING [ ABOUT ] [ BLOG ]
[ VISSZA A LOGOKHOZ ]

Reverse Engineering Bosch EDC16: Kalibrációs Pointer Rendszer, MPC555 Direkt Címzés és Mapswitch Architektúra

TIMESTAMP: 2026.04.16 | TARGET: BOSCH EDC16 (MPC555, MPC562, MPC563) - BMW | AUTHOR: APS TUNING | UPDATED: 2026.09.10 | v9

A Bosch EDC16 az egyik legelterjedtebb dízel motorvezérlő platform. BMW, VW, Audi, Ford, gyakorlatilag bármelyik európai gyártó járművében találhatsz belőle valamilyen változatot. A szoftver-architektúra közös, de a visszafejtés korántsem egyszerű. A kalibrációs adatok, a térképek, a karakterisztikák és a konstansok többszintű indirekción át rejtőznek a kódban.

Egy pár BMW platformot vettem górcső alá (DDE5, DDE6.0, DDE6.2, két különböző ECU típuson: EDC16CP35 és EDC16C31), és a végén nagyjából ki lehet jelenteni, hogy a BMW EDC16 kalibrációs architektúrája az MPC562 és MPC563 alapú változatokban gyakorlatilag azonos. Ugyanaz a négyszintű pointer rendszer, ugyanaz a dual variant mechanizmus, ugyanaz a flash mirror. A platformok között csak a konkrét címek térnek el, maga a működés azonos. Egyetlen annotáló script, pár konfigurációs paraméter cseréjével, bármelyik MPC562-alapú BMW EDC16-on elboldogul.

Egy fontos kivétel akad: az EDC16C31 DDE5 (a korábbi E60/E61 530d, 525d motorokban), ami MPC555-re épül, és architektúrájában komoly eltéréseket mutat. Erről a bejegyzés végén lesz külön szó.

Bosch EDC16 MPC562-563 (DDE6.0 / DDE6.2)

Az EDC16 hardvere a Motorola/Freescale MPC562-563 processzorra épül. Ez egy 32 bites PowerPC mag, amit kifejezetten autóipari alkalmazásokra terveztek. A bináris két fő részből áll:

BlokkCímMéretTartalom
Külső Flash 0x000000 - 0x1FFFFF2 MBAlkalmazás kód + kalibrációs terület
Belső Flash 0x400000 - 0x480FFF~524 KBBosch Funktionsbibliothek (OS + standard rutinok)

A belső flash a Bosch standard könyvtára. Ez nagyjából minden EDC16-ban egyforma, és az összes alapvető rutint tartalmazza: interpolációt, matematikát, szűrőket, RTOS-t. Az applikációs kód a 2 MB-os flash-ben ezeket bl MPC:FUN_xxxxx utasításokkal hívogatja.

Hardver memória architektúra (A2L validációval)

Az MPC562-ben mindössze 32 KB belső CALRAM van (0x3F8000 - 0x3FFFFF), ebből a Bosch szoftver alkalmazásszinten 26 KB-ot használ (0x3F9800 - 0x3FFFFF). Ezt a területet az RTOS kernel és az időkritikus ISR rutinok foglalják. A tényleges alkalmazás a külső SRAM chipeken fut, amiket az MPC562 External Bus Interface (EBI) kezel.

Az alábbi felosztás egy 5660 változót tartalmazó A2L fájl elemzésén alapul. A változónevek és a prefixek elég egyértelműen kirajzolják, mire valók az egyes RAM területek.

RégióCímtartományMéretFunkció (A2L elemzés alapján)
INT_CALRAM (on-chip)0x3F9800 - 0x3FFFFF26 KBRTOS kernel, ISR stack, időkritikus változók, 0 wait-state hozzáférés
CS0 - External Flash0x000000 - 0x1FFFFF2 MBApplikációs kód + Kalibrációs terület
EXT_SRAM_A0x6F8000 - 0x6F87FF2 KBMérőpont puffer (kis, kiemelt): 99.2% _mp suffix (Messpunkt), ~128 db kritikus measurement point
EXT_SRAM_B0x7F8000 - 0x7FFFFF32 KBFő alkalmazói RAM (SDA, r13-relatív): 2469 futási változó, state machines, FrmMng, InjCrv, Lambda...
EXT_SRAM_C0x800000 - 0x807FFF32 KBStack + RTOS workspace, és az r13 pozitív offset tartománya (0x7FFFF0 + max 0x7FFF = 0x807FEF). Az A2L-ben nincs itt nevesített változó, de a futó kód használja: a 730d DDE626-on itt vannak például a CAL RAM cellák (0x802DBC - 0x802DC8) és init-idejű pointer cache-ek (0x801F14 - 0x801F24)
EXT_SRAM_D0x8FE000 - 0x8FFFFF8 KBNagy diagnosztikai mérőpont puffer: 3063 db measurement point, 98.2% _mp suffix

Kulcs felismerés: az _mp suffix a Messpunkt (mérőpont) rövidítése. Ezek nem a tényleges vezérlési változók, hanem shadow másolatok, amiket a BMW gyári diagnosztikai rendszer és például a Test-O olvasgat. A motor igazi vezérlése az EXT_SRAM_B régióban történik (r13-relatív címzéssel), és az eredmények másolatai kerülnek át az EXT_SRAM_A és EXT_SRAM_D pufferekbe, hogy kívülről is megfigyelhetők legyenek.

A CAN kommunikációhoz sok helyen egy dedikált dupla-portos SRAM (DPRAM) chip is található a boardon, ezt a CPU és a CAN-vezérlő közötti adatcserére használják. Ghidrában a memória blokkok beállításánál érdemes ezeket a tényleges méretnél egy kicsit nagyobbra definiálni.

A flash belső logikai felosztása

A 2 MB-os külső flash nem homogén, több, funkcionálisan elkülönített régióból áll. A felosztás szoftver-verziónként változhat, szóval minden új binárisnál érdemes a kód és a kalibráció határait ellenőrizni. A kalibrációs adatok jellemzően két különálló régióban laknak:

RégióTartalomHozzáférés
0x040000 - 0x052000Skalár kalibrációk, flag-ek, konfigurációr2/r14-relatív (SDA direct)
0x0C0000 - 0x0FFFFFMap-ek, táblák, karakterisztikákPointer table (r15)

A pontos határok szoftver-verziónként eltérnek, de a két régió közötti funkcionális elkülönítés (skalár vs térkép) minden BMW EDC16-ban ugyanaz. Ha a kalibrációs terület nem összefüggő, az annotáló scriptnek mindkét tartományt ismernie kell.

Az első lépés: Memory Map validáció

Az MPC562-nél a külső flash a CPU 0x000000 címére van mappolva. Ezt egy egyszerű teszttel lehet ellenőrizni: az MPC56x reset vector-a a 0x100 címen található. Ha ott értelmes utasítás van, akkor a WinOLS offsetek és a CPU címek egybeesnek.

Reset Vector @ 0x00000100
0x100:  48 00 01 82

ba      0x180                 ; Abszolút branch a startup kódra

A ba 0x180 utasítás a tényleges inicializáló kódra ugrik. Ez megerősíti, hogy WinOLS offset = CPU cím, nincs eltérés.

BTT DDE6 quickflash full backup betöltés: a full backup (internal és external flash egyetlen fájlban) az internal flash-t a 0x200000 file offsettől tárolja. Ez a processzor címterében 0x400000-nak felel meg. Ghidra betöltéskor az external flash-t 0x000000-ra, az internal flash-t 0x400000-ra kell mappolni.
Intel HEX betöltés: egyes intelhex dumpoknál a flash adat nem feltétlenül 0x000000-tól kezdődik. Az E60 535d HEX fájlban például az első adat 0x008000-nál indul, ami 0x8000 byte-os eltolást jelent a WinOLS nyers binárishoz képest. Ghidrában az Intel HEX loader automatikusan a helyes címekre rakja az adatokat, de WinOLS-ben WinOLS cím = CPU cím - 0x8000 korrekció kell.

A startup: Register poisoning és bázisregiszter inicializáció

A reset vector utáni kód először egy register poisoning mintát hajt végre: az összes általános célú regisztert 0x7F7F7F7F értékkel tölti fel:

Register Poisoning - Debug előinicializálás
lis     r1, 0x7f7f
addi    r1, r1, 0x7f7f
or      r2, r1, r1
...                              ; r3-r31 szintén 0x7F7F7F7F
or      r31, r1, r1

Ez egy debug jellegű előinicializálás: ha bármelyik regiszter használat előtt nem kap tényleges értéket, a 0x7F7F7F7F minta azonnal szemet szúr a memória dumpban. A tényleges bázisregiszter beállítás ezután következik a flash alkalmazáskódban:

CPU Init - Bázisregiszterek
lis     r11, 0x80
addi    r1, r11, 0x0         ; r1 = 0x00800000 - EXT_SRAM_C (stack, downward growing)

lis     r13, 0x80
subi    r13, r13, 0x10       ; r13 = 0x007FFFF0 - EXT_SRAM_B (SDA bázis, minden EDC16-ban azonos)

lis     r2, 0x5
subi    r2, r2, 0x7F10       ; r2 = 0x000480F0 - TOC/SDA2 Base (flash konstansok)

lis     r14, 0x4
addi    r14, r14, 0x6454     ; r14 = 0x00046454 - SDA Base (flash konstansok)

Dual Variant architektúra

Minden BMW EDC16 bináris tartalmazza a két szoftver-variáns kiválasztó mechanizmusát, és a boot során dől el, melyik fog futni. Az r2 és r14 regiszterek a variáns kiválasztásakor kapják meg a végleges értéküket, és a két lehetőség más-más kalibrációs adathalmazra mutat.

A Variant A és B r2/r14 értékei szoftver-verziónként minimálisan eltérnek, de a mechanizmus azonos. Ennek az architektúrának köszönhetően egyetlen firmware bináris több hardverkonfigurációt is ki tud szolgálni. Elég a variant flag-et módosítani, és az ECU máris teljesen más kalibrációs adatokkal dolgozik.

INFO: a mechanizmus mindig ott van, a B variáns adata viszont nem mindig. A 730d DDE626 szoftverben a kód mindkét r2/r14 párt ismeri (A: r2 = 0x480F0, r14 = 0x4653C, B: r2 = 0xF80F0, r14 = 0xF443C), de a B variáns r2-relatív struktúrái nem léteznek: a pointer tábla referencia helyén ([r2 + 0x7C48] = 0xFFD38) FF áll, a 0xF0000 - 0xF913F tartományt pedig az A variáns térkép blokkjai foglalják. A gyakorlatban tehát csak az A futhat. Az r2 értéke bitre megegyezik a fenti példával, az r14 szoftver-verziónként eltér.

Pointer relokáció a variánsváltáskor

A dual variant váltás nem merül ki az r2 és r14 regiszterek cseréjével. A boot szekvencia egy relokációs rendszert is lefuttat, ami 7 db RAM-ban tárolt pointert átszámol a régi és az új variáns kalibrációs báziscíme közötti különbség alapján:

Pointer relokáció - Számítási logika
r12 = 0x007FE100                ; fix referencia pont (RAM vége közelében)

; Variant A:
r11 = 0x3E98C                  ; fix offset

; Variant B:
r11 = lwz(r14 - 0x7740) + 0x3E98C  ; flash-ből olvasott delta + fix offset

delta = r12 - r11

; Irány 0 (undo):  new_ptr = delta + old_ptr
; Irány 1 (apply): new_ptr = old_ptr - delta

A négyszintű kalibráció-elérési modell

A BMW EDC16 firmware négyféleképpen fér hozzá a kalibrációs adatokhoz. Ezek a Bosch firmware-architektúra sajátosságai, és minden BMW EDC16-ban jelen vannak.

SzintMechanizmusPélda
1 - r15 Pointer táblalwz rXX, offset(r15) - pointer tábla entry, kalibrációs blokk base[r15 + 0x5CC] = 0x0F5078
2 - Közvetlen SDAlwz rXX, offset(r2) vagy (r14) - közvetlenül kalibrációs adat[r2 + 0x7034] = 0x04F124
3 - Propagációaddi / mr / or - bázisregiszter továbbvitel függvényen belüladdi r3, r31, 0x4FC = 0x0F5574
4 - Flash mirrorlis rXX, imm ; load rYY, offset(rXX) - 0x01000000+ tükörcímlis r11, 0x10c ; lhz r11, 0x3eea(r11) = 0x0C3EEA

A szintek nem hierarchikusak és nem zárják ki egymást: egy függvényen belül is vegyesen megjelenhet a pointer tábla elérés, a közvetlen SDA hozzáférés és a flash mirror minta. A firmware ezeket párhuzamosan, hibrid módon használja.

Szint 1: Az r15 pointer tábla

Az r15 regiszter instance pointerként viselkedik: a kalibrációs pointer tábla báziscímére mutat. A beállítás mechanizmusa minden BMW EDC16-ban azonos. Egy feltételes logika választ két lehetséges forrás közül (RAM working page vagy flash page), aztán az eredmény r15-be kerül:

r15 inicializáció - CAL_SetActiveDataset
; Kritikus szekció belépés (interrupt disable):
bl      FUN_0001f590          ; OSEK TaskEnter

; Instance selector ellenőrzés:
lbz     r12, CAL_PageSelect     ; CCP kalibrációs page (0 = flash, 1 = RAM)
cmpwi   r12, 0x1
bne     else
lbz     r12, CAL_RamCopyState   ; RAM working page állapot
cmpwi   r12, 0x4             ; 4 = RAM másolat kész, váltás engedélyezve
bne     else

; RAM working page (allokált RAM másolat):
lwz     r31, CAL_ActivePtr_Alt  ; RAM pointer tábla
b       done

else:
; Flash page (default, flash pointer tábla):
lwz     r31, CAL_ActivePtr_Default  ; flash tábla cím

done:
lwz     r12, PTR_TABLE_REF(r2) ; flash pointer tábla referencia cím
addi    r15, r31, 0x0       ; r15 = kiválasztott instance
subf    r12, r12, r31      ; offset = r15 - referencia cím
stw     r12, CAL_ActiveOffset  ; offset mentése

; Kritikus szekció kilépés:
b       FUN_0001f5b8          ; OSEK TaskExit (tail call)

A teljes r15 beállítás egy atomi művelet: interrupt disable/enable párossal van védve (OSEK kritikus szekció), hogy a pointer váltás közben ne történhessen félkész állapotú olvasás. A CAL_SetActiveDataset függvény neve, paraméterei és belső szerkezete minden BMW EDC16-ban azonos, csak a konkrét RAM címek térnek el.

A függvényt két helyről hívják: bootkor a CAL init, futás közben pedig a CCP SET_CAL_PAGE parancskezelő. A selector tehát nem map-választó, hanem a Bosch online kalibrációs page mechanizmusa: a 0 a flash referencia page, az 1 a RAM working page, a 4-es állapot pedig azt jelenti, hogy a RAM másolat elkészült. Éles ECU-n, kalibrációs hardver nélkül a RAM page nem aktiválódik, így r15 mindig a CAL_ActivePtr_Default értékét kapja.

A CAL init bootkor két flash tábla közül választ: az r2-relatív referencia táblát (éles eset), vagy egy második táblát, amely ugyanazokra a blokkokra a 0x01000000-s ablakon keresztül mutat (ETK/emulációs eset, lásd Szint 4). A választott címet a CAL_ActivePtr_Default-ba írja, majd page = 0 paraméterrel meghívja a settert.

Fontos tulajdonság: az r15 globális, dedikált regiszter. A setteren kívül semmi nem írja, és a taszkváltás sem menti, sem tölti vissza. Ha futás közben átállítjuk, attól a pillanattól minden taszk az új értéket látja.

Konkrét címek a 730d DDE626 (EDC16CP35) szoftverből:

ElemCím
CAL_SetActiveDataset (setter)0x11E918, r15 írás: 0x11E964
Kritikus szekció enter / exit0x1F488 / 0x1F4B0
CAL init0x11E994 (init lista 0x43614, 8. elem)
CCP SET_CAL_PAGE hívások0x124A38 / 0x124A44
CAL_PageSelect / CAL_RamCopyStater13 + 0x2DCD / r13 + 0x2DCC
CAL_ActivePtr_Default / Altr13 + 0x2DD0 / r13 + 0x2DD4
CAL_ActiveOffset (csak írva)r13 + 0x2DD8
Referencia tábla (éles)[r2 + 0x7C48] = 0x512F0
ETK tábla[r2 + 0x7C4C] = 0x50C10
Entry szám[r2 + 0x7C44] = 0x1B8 (440)

A Pointer Tábla

A pointer tábla egy sűrű, 4 bájtos bejegyzésekből álló tömb a flash-ben. Minden entry formátuma:

[ byte0: dataset ID | 24-bit: abszolút flash cím ]

A pointer tábla báziscíme és az entry-k száma szoftver-verziónként eltér (tipikusan 380-460 entry a 0x050000 - 0x060000 tartományban), de a formátum és a feloldási mechanizmus univerzális. A legmegbízhatóbb út a megtaláláshoz: azonosítsd a CAL_SetActiveDataset függvényt, és oldd fel az r2-relatív referenciát.

A tábla után egy sentinel szó áll, az utolsó blokk végcíme (a 730d-n 0x519D0 = 0xF9138). A Bosch címfordító rutin, amely a CCP memóriaelérésnél a referencia címet az aktív táblára fordítja, a blokk végét a referencia tábla következő entry-jéből veszi, a blokk kezdetét pedig az r15 táblából. Ebből következik, hogy egy klón táblának ugyanabban a sorrendben, ugyanannyi entry-vel kell követnie a referenciát.

Az A2L szimbólum-import után a pointer tábla valódi modulneveket kap. Minden entry egy-egy Bosch szoftver-modul kalibrációs blokkjára mutat, a Bosch prefix konvenció pedig elárulja, mire való: ExeMon a végrehajtás monitor, OvRMon a fordulatszám monitor, FrmMng a CAN frame manager, AirCtl a levegő szabályozás, CoEng a motor koordinátor, InjCrv a befecskendezés, CrCtl a tempomat. A kisebb modulok csak egy-két konstanst tartalmaznak, a nagyobbak (InjCrv, FrmMng, AirCtl) viszont több ezer byte-nyi térképet és karakterisztikát.

Pointer tábla A2L modul nevekkel Ghidrában

A pointer tábla Ghidrában, A2L szimbólum-import után: minden 4 byte-os entry egy Bosch kalibrációs modul nevét és flash címét tartalmazza.

Szint 2: Közvetlen SDA hozzáférés (r2/r14-relatív)

Az r2 és r14 regiszterek az SDA2 és SDA bázisként szolgálnak. Az SDA2 címzési tartomány (r2 plusz/mínusz 0x8000) tipikusan a 0x040000 - 0x052000 kalibrációs régiót fedi le, ahol a skalár konstansok, flag-ek és a pointer tábla bázisa is megtalálható:

Közvetlen SDA hozzáférés - r2-relatív
lwz     r12, 0x7034(r2)      ; r2 + 0x7034 = kalibrációs adat
lhz     r3, -0x1a6e(r2)      ; r2 - 0x1A6E = skalár konstans

A nagy kalibrációs térképek (0x0C0000 - 0x0FFFFF) kívül esnek az r2 címzési hatótávolságán. Ott a pointer tábla (Szint 1) az elsődleges út, míg az r2/r14-relatív hozzáférés inkább a skalár konfigurációkat szolgálja ki.

Szint 4: Flash mirror abszolút hozzáférés

A 2 MB-os külső flash nem csak a 0x000000 - 0x1FFFFF tartományban érhető el, hanem tükörképként a 0x01000000 - 0x011FFFFF címen is. Ez az MPC562 EBI chip select konfigurációjából adódik, és minden EDC16-ban jelen van. A létezésének oka a kalibrációs hardver: ETK vagy emulációs RAM esetén ez az ablak átirányítható, így a fejlesztő a flash helyett RAM-ból futtathatja a kalibrációt.

Flash mirror hozzáférés - lis + load minta
lis     r11, 0x10c            ; r11 = 0x010C0000
lhz     r11, 0x3eea(r11)     ; [0x010C3EEA] = flash tükörkép, valós cím: 0x0C3EEA
sth     r11, 0x77e(r13)      ; eredmény a RAM-ba

Ghidrában a 0x01000000 bázison egy 2MB-os overlay memory block létrehozásával a piros (unresolved) referenciák feloldódnak.

A 730d DDE626 szoftverben ez közvetlenül látszik. A CAL init előtt futó detektáló rutin (0x464F48) egy hardver bitet, két kalibrációs byte-ot, valamint a flash és a RAM oldali azonosítót veti össze. Ha emulációs hardvert talál, a referencia tábla helyett egy második pointer táblát (0x50C10) választ, amely ugyanazt a 440 blokkot a 0x010Cxxxx címeken éri el. Éles ECU-n ez az ág nem aktiválódik, a mirror ablak ilyenkor egyszerűen a flash-t tükrözi.

A Szint 4-es, fix lis 0x10C hozzáférések ebben a szoftverben a 0x0C03D0 - 0x0C3A37 tartományt olvassák. A motorvezérlési térképek blokkjai (0x0C3A38 felett) kizárólag r15-ön keresztül érhetők el, a kódban nincs rájuk beégetett cím.

A kalibrációs rendszer működés közben

Eddig azt néztük meg, hogyan van felhúzva maga az infrastruktúra: milyen úton-módon jut el a kód a kalibrációs adatokig. Most jöjjön két konkrét modul, amin keresztül látszik, hogy a firmware ténylegesen mihez kezd ezekkel az adatokkal, amikor a motort kell vezérelni.

Eset 1: Main Torque Limiter

A fő nyomaték limiter dolga egyszerű: a fordulatszám és a variant coding alapján megmondja, mennyi nyomatékot szabad kiadni. Egyetlen pointer tábla bejegyzésből dolgozik, semmi több.

Main TQ Limiter Ghidra listing

A Main Torque Limiter wrapper függvény Ghidrában, az annotátor által feloldott pointer referenciákkal.

Main Torque Limiter
lwz     r31, 0x268(r15)        ; PTR[0x268] = kalibrációs blokk (408 byte)
lha     r3, -0x6844(r13)       ; r3 = RPM (X tengely)
lbz     r4, -0x7793(r13)       ; r4 = Variant Coding (Y tengely)
addi    r5, r31, 0xa           ; r5 = map header
subi    r6, r13, 0x4216        ; r6 = interpolátor cache (RAM)
bl      FUN_004541cc             ; 2D INTERPOLÁCIÓ
Main TQ Limiter map WinOLS

A Main Torque Limiter 21x8 térkép a WinOLS-ben. X tengely: variant coding (0-7), Y tengely: RPM (600-5060), Z: nyomaték Nm-ben.

A 2D map struktúrája a flash-ben:

OffsetTípusTartalom
+0x00int16X_size = 21 (RPM tengelypont darabszám)
+0x02int16Y_size = 8 (variant coding tengelypont darabszám)
+0x04int16[21]RPM töréspontok: 600, 800, 1000, ... 5060
+0x2Eint16[8]Variant coding: 0, 1, 2, ... 7
+0x3Eint16[168]Nyomaték értékek (21 x 8, Nm)

A 2D interpolátor bilineáris interpolációt csinál 16.16 fixpontos aritmetikával, cached tengely pozícióval. A "cached" itt azt jelenti, hogy az interpolátor megjegyzi, hol járt legutóbb a tengelyen, és a következő híváskor onnan indul. Ha az RPM az előző hívás óta alig változott, ami motornál elég gyakori helyzet, a szegmens megkeresése szinte azonnal megvan.

2D interpolátor Ghidra listing

A 2D interpolátor függvény eleje: X_size és Y_size olvasás, majd az X tengely keresés indítása.

Az interpoláció után van még egy érdekes kis részlet, egy korrekciós ág:

Korrekciós ág - Enable byte ellenőrzés
lbz     r11, 0x1(r31)         ; korrekciós enable flag
cmpwi   r11, 0x0
beq     skip                  ; ha 0: nincs korrekció

; korrekciós szorzás (SOHA nem fut, mert az enable byte minden kalibrációban 0):
lha     r11, -0x687e(r13)    ; runtime szorzó
mullw   r3, r12, r11        ; result x factor
li      r4, 0x2000           ; 8192 = Q13 fixpont (1.0x)
bl      FUN_0045380c          ; r3 = (result x factor) / 8192, szaturált

skip:
sth     r3, -0x720e(r13)     ; output = Main TQ Limiter eredmény

Ez jól mutatja a Bosch fejlesztési filozófiáját: a kódban ott van egy runtime korrekciós szorzó, de a konkrét kalibrációban ki van kapcsolva. A Bosch modulárisan fejleszt, a funkciókat pedig kapcsolókkal engedi vagy tiltja. Ami az egyik OEM kalibrációban aktív, a másikban simán ki lehet kapcsolva, a kód viszont mindig ott marad, ha esetleg kell.

Eset 2: Boost Pressure Control - Töltőnyomás szabályozás

A boost modul egy tekintélyes méretű függvény, és egyetlen pointer tábla bejegyzésből szedi ki az összes adatát: PTR[0x558], ami egy 4492 bájtos kalibrációs blokkra mutat. Ezen a blokkon belül több mint 20 térkép és konstans van.

Boost module map selection Ghidra

A boost modul map-választó logikája: egy bit-teszt dönti el, hogy a base vagy az alternatív boost target map-et olvassa.

Base boost target kiválasztás
lwz     r31, 0x558(r15)        ; PTR[0x558] = boost kalibráció (4492 byte blokk)
lha     r3, -0x6844(r13)       ; r3 = RPM
lha     r4, -0x6df0(r13)       ; r4 = befecskendezési mennyiség (mg/cyc)

lbz     r12, runtime_flag      ; runtime flag byte
rlwinm. r12, r12, 0x1f, 0x1f, 0x1f  ; bit 1 teszt
beq     use_base              ; bit 1 = 0: base map

; bit 1 = 1: alternatív boost map
addi    r5, r31, 0x568        ; alt boost target
b       call_interp

use_base:
addi    r5, r31, 0x9fe        ; base boost target

call_interp:
bl      FUN_004541cc          ; 2D INTERPOLÁCIÓ, r3 = boost target [mbar]
Base boost target map WinOLS

A base boost target 16x16 térkép a WinOLS-ben. X tengely: befecskendezés (mg/cyc, 0.01 faktor), Y tengely: RPM, Z: kívánt töltőnyomás mbar-ban.

A base boost target után a kód gyors egymásutánban két DPF regenerációhoz kötődő boost map-et is beolvas:

DPF regen boost maps Ghidra

A DPF regeneráció phase 1 és phase 2 boost map hívások egymás után.

DPF Regen boost map-ek - ugyanazon pointer tábla bejegyzésből
; DPF Regen Phase 1 boost target:
addi    r5, r31, 0x572        ; regen phase 1 boost
bl      FUN_004541cc          ; 2D INTERPOLÁCIÓ

; DPF Regen Phase 2 boost target:
addi    r5, r31, 0x7b6        ; regen phase 2 boost
bl      FUN_004541cc          ; 2D INTERPOLÁCIÓ

Tehát három boost target fekszik párhuzamosan kiolvasva (base/alt, regen phase 1, regen phase 2), és a modul későbbi logikája dönti el, melyiket küldi tovább célértékként a szabályozóra.

A boost blokk barometrikus korrekciói

A boost blokkon belül négy olyan térkép is van, ami a légköri nyomást használja Y tengelyként (RPM x baro):

Boost limit vs atmospheric pressure WinOLS

A boost limit vs légköri nyomás térkép a WinOLS-ben: az egyetlen ténylegesen kalibrált barometrikus térkép ebben a szoftverben.

Négyből viszont csak egy aktív. Háromféle korrekciós mechanizmus van beépítve a kódba (additív, multiplikatív, és egy abszolút limit), de ebben a BMW kalibrációban a BMW kalibrátorok csak a limit táblát kapcsolták be. Szokásos Bosch mintázat, mindent beletesznek a szoftverbe, aztán az OEM kalibrátor eldönti, melyikkel akar dolgozni.

A boost blokk teljes térképe

Egyetlen pointer tábla entry mögött 22+ kalibrációs objektum rejtőzik:

OffsetFunkció
+0x3CBaro korrekció (additív, inaktív)
+0xE0Baro korrekció (multiplikatív, semleges)
+0x1841D karakterisztika
+0x19E2D map
+0x202, +0x224, +0x23E1D karakterisztikák
+0x25C, +0x3B0, +0x5042D map-ek (mg/cyc x RPM)
+0x568Alt boost target
+0x572DPF regen phase 1 boost
+0x7B6DPF regen phase 2 boost
+0x9FEBase boost target
+0xC42Baro korrekció (additív, inaktív)
+0xE86Boost limit vs légköri nyomás
+0x10CE2D map (RPM x mg/cyc)
+0x1134, +0x113832-bit kompárátorok
+0x1144Rate limiter / ramp
+0x1150, +0x1154Threshold konstans + 1D karakterisztika

Automatizáció: A Ghidra Annotáló Script

Miután a manuális nyomkövetéssel megértettük a rendszert, egy Ghidra Python script segítségével az egészet automatizálhatjuk. A script mind a négy szinten dolgozik egyszerre:

4 level script Ghidra

A Ghidra annotáló script eredménye.

SzintMit csinál
L1: r15 pointer táblaMinden lwz rX, offset(r15) mellé beírja a feloldott pointert és méretet
L2: r2/r14 SDA directMinden r2/r14-relatív load/store mellé kiírja a kalibrációs címet
L3: Regiszter propagációaddi, mr, or másolásokat követ, A2L symbol lookup
L4: lis + load mirrorlis rX, imm ; load rY, offset(rX) feloldja a mirror címet

A script egyetlen konfigurációs blokkból dolgozik, amelyben 5 paramétert kell az adott binárishoz beállítani: pointer tábla báziscím, r2 érték, r14 érték, és a két kalibrációs tartomány határai. Ez az összes. A négy szint felismerési logikája és maga az annotáció generálás teljesen univerzális, nem kell hozzányúlni.

A script háromféle módban tud futni, attól függően, hogy milyen kalibrációs információ van a kezünk ügyében:

Teljes hybrid konfigurációval futtatva a script ~17,800 annotációt szór szét a kódban, ~1,700 függvényben, egy ~3,870 függvényből álló binárisban. Ez a szám minden tesztelt BMW EDC16 binárison szinte hajszálpontosan ugyanaz - ami nem véletlen egybeesés, hanem az egységes architektúra egyik legjobb bizonyítéka.

A kódbázis regiszter-statisztikájából is szépen kilátszik a multi-regiszter architektúra:

RegiszterFunkciók számaMegjegyzés
r31190Leggyakoribb (hagyományos base regiszter)
r12178Scratch regiszter, közvetlen pointer felhasználás
r3085Második leggyakoribb dedikált base
r2948Pl. CoEng (DPF nyomatékkorlátozás) modul
r2829Pl. Rail Pressure Control modul
r27-r2438Ritkábban használt base regiszterek

DAMOS integráció

Ahol a DAMOS (a Bosch kalibrációs adatbázisa) rendelkezésre áll, ott a pointer címek helyére beírhatók az igazi funkcionális nevek:

DAMOS annotáció példa - Légmennyiségmérő diagnosztika
lwz     r12, 0x80(r15)       PTR[0x80], AFSCD_DebPlHiSetyDrftDef_C
addi    r4, r12, 0x27e      calib: AFSCD_swtSensInstVal_C
li      r3, 0x15
bl      FUN_0007df84

Térképstruktúra és testreszabás

Eddig arról volt szó, hogyan találjuk meg a kalibrációs adatokat. De mit kezdjünk velük, ha egyszer megvannak? A Bosch 2D interpolátor a térkép méretét dinamikusan olvassa a headerből, és ez elképesztően hasznos tulajdonság: azt jelenti, hogy a térképeket bővíthetjük anélkül, hogy a kódhoz hozzá kellene nyúlnunk.

A 2D térkép bináris felépítése

Minden 2D kalibrációs térkép pontosan ugyanúgy néz ki a flash-ben. A 2D interpolátor futásidőben olvassa ki a méreteket a header első két szavából, és ebből számolja ki, hol vannak a tengelyek és a Z adatok:

2D Map bináris struktúra (Bosch II header)
+0x00:  int16    ; X_size (pl. 0x0010 = 16 pont)
+0x02:  int16    ; Y_size (pl. 0x0010 = 16 pont)
+0x04:  int16[X] ; X tengely töréspontok (pl. RPM: 500, 750, 1000, ...)
+0x04+X*2: int16[Y] ; Y tengely töréspontok (pl. Nm: 0, 20, 40, ...)
+0x04+X*2+Y*2: int16[X*Y] ; Z értékek (interpolált kimeneti adat)

Egy térkép összmérete tehát: 4 + X*2 + Y*2 + X*Y*2 byte (a 4 byte-os header, plusz a két tengely, plusz a Z mátrix). A lényeg az, hogy a kód sehol nem tartalmaz beégetett méretet - mindent menet közben, a headerből olvas ki. Ez lesz a kulcsa annak, hogy a térképeket bővíteni is tudjuk, de erről mindjárt.

Az interpolátor működése

A 2D interpolátor (FUN_00457794 és társai) lépésről lépésre kb. ezt csinálja:

2D interpolátor - Működési elv
; 1. Header olvasás:
lhz     r11, 0x0(r5)          ; X_size = header[0]
lhz     r12, 0x2(r5)          ; Y_size = header[1]

; 2. X tengely keresés (cached):
;    Lineáris keresés a töréspontok között, az előző hívás
;    indexéből indulva (gyors, ha az RPM alig változott)

; 3. Y tengely keresés (cached):
;    Ugyanaz, a Y_size alapján számított offset-ről

; 4. Bilineáris interpoláció:
;    16.16 fixpontos szorzás a 4 szomszédos Z értékből
;    Eredmény: int16 a hívó regiszterbe (r3)

A cached tengely keresés lényege, hogy az interpolátor eltárolja az előző hívás X és Y szegmens indexét egy RAM-ban lévő cache struktúrában (amit r6-ban kap paraméterként). Ha a bemenet alig változott - márpedig motornál ez a tipikus, az RPM és a terhelés nem szokott ciklusról ciklusra ugrálni - a keresés 1-2 összehasonlítás után már meg is van.

Térképek bővítése

Mivel az interpolátor dinamikus, a térkép méretét simán megváltoztathatjuk a header átírásával. Mondjuk ha az eredeti térkép 16x16-os, és mi 32x16-ra akarjuk nyújtani:

16x16 (eredeti)32x16 (bővített)
Header4 byte4 byte
X tengely32 byte64 byte
Y tengely32 byte32 byte
Z adat512 byte1024 byte
Összesen580 byte1124 byte

A Bosch fejlesztési folyamatban a kalibrátorok menet közben hangolgatják a térképméreteket. Ehhez a kalibrációs blokkokban a térképek mögött sokszor padding (tartalék terület) van hagyva, ezekben az ecukban jellemzően 50-200 byte a számunkra releváns térképenként (NM-IQ konverzió vagy injektor kivezérlési idő). Ha a bővítés belefér ebbe a paddingbe, elég a headert és az adatokat átírni, a pointer offset-ek és a szomszédos térképek nyugodtan maradhatnak a helyükön.

Ha viszont a bővítés nem fér bele a paddingbe, akkor a megnövelt térképet szabad flash területre kell átköltöztetni, és a pointer/offset referenciát átírni az új címre. Ez assembly szintű patch-csel elméletileg megoldható: az eredeti addi r5, r31, offset utasítást kicseréljük egy lis r5, HI; ori r5, r5, LO abszolút címzésre, de a buktatók majd alább.

Gyakorlati példa: Nyomaték/Mennyiség átváltás bővítése

Az Nm/IQ (nyomaték/befecskendezési mennyiség) átváltó térkép az egyik legfontosabb kalibrációs objektum a motorvezérlőben. Az eredeti 16x16-os változatban 550 Nm-ig vannak töréspontok, ami egy gyári kalibrációhoz tökéletesen elég - de ha Stage 2+ tuningot csinálunk, ennyi már kevés.

32x16 Nm-IQ conversion map

A kibővített 32x16 Nm-IQ átváltó térkép: az X tengely 0-tól 1400 Nm-ig, 32 töréspont. Az eredeti 16 pontos tengely dupla felbontásra bővítve, a 650 Nm feletti tartomány extrapolált értékekkel feltöltve.

A bővítés menete:

LépésMit csinálunk
1. Padding ellenőrzésMegnézzük, mennyi szabad hely van a térkép vége és a következő objektum headere között
2. Maximum méret kalkulációA szabad hely alapján: (hely - 2 - Y) / (1 + Y) = max X_size, ahol a hely a térkép jelenlegi mérete plusz a padding, 16 bites értékekben
3. Header átírásX_size módosítása 16-ról 32-re (egyetlen szó a flash-ben)
4. X tengely bővítésÚj töréspontok hozzáadása (pl. 650, 700, 750, ... 1400 Nm)
5. Z adat kitöltésA meglévő adatokból lineáris extrapoláció az új tartományra

A következő induláskor az interpolátor a 32-es X_size-t olvassa ki a headerből, és 32 töréspontot keres az X tengelyen. A kód nem változott, csak az adat.

INFO: A maximális bővítés mértéke mindig a padding méretétől függ. Egy 624 értéknyi (16 bites) teljes hely mellett, 16 pontos Y tengellyel, a max X méret 35. A 32x16 a gyakorlatban ideális kompromisszum: van elég felbontás a kiterjesztett nyomatéktartományhoz, és még marad is tartalék a paddingben.

Kivétel: EDC16C31 DDE5 - Az MPC5xx világ

Az eddig tárgyalt EDC16 platformok (CP35, DDE6) mind MPC562/MPC563 processzorra épülnek, 2 MB külső flash-sel és az r15 pointer táblás kalibrációs címzéssel. A korábbi generációs EDC16C31 DDE5 (BMW E46/E60/E61 20d, 25d, 30d első szériák) viszont teljesen más hardveren fut: a Motorola MPC555 processzoron.

MPC555: Más hardver, más világ

Az MPC555 az MPC500 családba tartozik, és az MPC562-höz képest komolyan eltér a memória-architektúrája:

JellemzőEDC16 MPC562/563 (DDE6.0/DDE6.2)EDC16C31 MPC555 (DDE5)
ProcesszorMPC562/MPC563MPC555
Internal Flash0x400000 - 0x480FFF (~512 KB)0x000000 - 0x06FFFF (448 KB)
External Flash0x000000 - 0x1FFFFF (2 MB)0x800000 - 0x8FFFFF (1 MB)
Internal SRAM0x3F8000 - 0x3FFFFF (32 KB CALRAM)SRAM A: 0x3F9800 - 0x3FBFFF (10 KB)
SRAM B: 0x3FC000 - 0x3FFFFF (16 KB)
External SRAM0x6F8000 - 0x8FFFFF (több chip)0x400000 - 0x401FFF (~8 KB)
r130x007FFFF0 (EXT_SRAM_B)0x004017F0 (EXT_SRAM)
Kalibráció címzésr15 pointer táblaKözvetlen (direkt) címzés

Direkt kalibrációs címzés - r15 pointer tábla nélkül

A legfontosabb architekturális különbség: az MPC555 alapú EDC16C31-ben nincs r15 pointer tábla. A kód közvetlenül, abszolút címzéssel hivatkozik a flash kalibrációs területre:

MPC563 (r15 pointer tábla) vs MPC555 (direkt címzés)
; MPC563 EDC16CP35 DDE6 
; Két lépcsős indirekcó:
lwz     r31, 0x268(r15)      ; 1. pointer tábla - blokk cím
addi    r5, r31, 0xa         ; 2. blokkon belüli offset
bl      interpolate_2D

; MPC555 EDC16C31 DDE5
; Közvetlen flash hivatkozás:
lis     r5, 0x8C              ; r5 = 0x008C0000 (ext flash kalibrációs terület)
addi    r5, r5, 0x3FE4       ; r5 = 0x008C3FE4 (konkrét térkép cím)
bl      interpolate_2D

Az MPC555 DDE5-ben a kalibrációs címek egyenesen bele vannak égetve az applikációs kódba. Nincs pointer tábla, nincs indirekcó, nincs CAL_SetActiveDataset. Minden térkép, karakterisztika és konstans egy fix lis + addi (vagy lis + ori) abszolút címmel elérhető.

Ez az egyszerűbb felépítés a statikus elemzésnek kifejezetten kedvez (Ghidrában azonnal látszik, hova mutat egy hivatkozás), viszont a kalibrációs terület módosítását nehezíti: ha áthelyezünk egy térképet, az összes kódreferenciát meg kell keresni és átírni. Az MPC562 r15 pointer táblás megoldásánál ehhez képest egyetlen pointer entry módosítása elég.

INFO: Az MPC555 DDE5 bináris két részből áll a flash fájlban: az internal flash (0x000000 - 0x06FFFF, 448 KB) és az external flash (file offset 0x070000-tól, CPU cím 0x800000 - 0x8FFFFF, 1 MB). Ghidrába külön memory block-ként kell betölteni őket, az external flash-t 0x800000 báziscímre mappolva.

Ghidra r13 konfigurálás MPC555-höz

Az MPC555-nél az r13 = 0x004017F0, és a signed 16-bit offset tartomány (+-0x8000) mindkét SRAM tartományt lefedi: a belső SRAM-ot negatív offset-tel (pl. r13 - 0x4D08 = 0x3FCAE8, ez SRAM B-be esik), a külső SRAM-ot meg pozitív offset-tel. Ghidrában a regiszter beállításnál erre kell figyelni: az assume r13 = 0x4017F0 a helyes érték, nem a 0x7FFFF0, amit az MPC562-nél használunk.

Mapswitch: Miért nehéz?

A tuning közösségben a "mapswitch" (futásidőben több kalibrációs térkép közötti váltás) az egyik legkeresettebb funkció. Elméletben egyszerűnek hangzik: ha az ECU a pointer táblán vagy közvetlen címzésen át éri el a kalibrációt, irányítsuk át a pointert vagy a címet egy másik térképre, és kész. A gyakorlatban viszont ez jóval bonyolultabb mint gondolnánk.

A Bosch nyomaték-pipeline és a konzisztencia probléma

A modern Bosch EDC16 firmware nem egy egyszerű "térkép be - output ki" rendszer. A nyomatékvezérlés egy többszintű pipeline: több párhuzamos alrendszer számol nyomatéklimiteket (füst limiter, boost limiter, váltóvédelem, motorvédelem), és ezeket egy arbiter MIN-eli össze. Ráadásul a Bosch egy belső konzisztencia-ellenőrzőt is üzemeltet, ami figyeli, hogy a különböző alrendszerek számolt értékei összhangban vannak-e.

Ha egy mapswitch patch csak egyetlen alrendszert piszkál meg (pl. a fő nyomaték limitert), miközben a többi szépen a stock kalibrációból számolgat tovább, a konzisztencia-ellenőrzés eltérést fog észlelni. Az eredmény nem szép: ECU leállás, derate mód, vagy CAN kommunikáció korrupció.

Az r15 base swap: mikor csapda, és mikor nem

Az egyik kézenfekvőnek tűnő ötlet: az r15 pointer tábla báziscímét futásidőben átírjuk egy klón pointer tábla címére, ahol a kívánt térképek más adatokra mutatnak. Ez elméletben az összes r15-felhasználót egyszerre irányítja át. A korábbi tesztjeimben ez hibára futott: CAN frame korrupció, a gázpedál nem reagált, és hamis riasztás jelent meg motor túlmelegedés miatt.

A cikk korábbi verziója ezt a Bosch callback dispatch-nek tulajdonította, mondván, hogy a base pointer mellé tartozó derived értékek nem frissülnek. A 730d DDE626 szoftver részletes elemzése után ezt a magyarázatot pontosítanom kell. A dispatch létezik, de mást csinál:

Callback dispatch (730d DDE626, 0x470A8C)
lbz     r29, 0x7c74(r2)      ; entry szám (730d: 3)
addi    r31, r2, 0x7c50      ; tábla, 12 byte/entry: {arg0, arg1, fn}
loop:
lwz     r30, 0x8(r31)        ; fn (0 esetén nincs hívás)
lwz     r3, 0x0(r31)         ; arg0
lwz     r4, 0x4(r31)         ; arg1
mtlr    r30
blrl                         ; r3 = fn(arg0, arg1)
stwu    r3, 0x4(r28)         ; eredmény két RAM tömbbe
stwu    r3, 0x4(r27)
addi    r31, r31, 0xc
addic.  r29, r29, -1
bne     loop

A 730d-n három entry van, és mindhárom RAM terület allokáció a kalibrációs RAM working page számára. Az egyik például a 0x8C0000 - 0x8FD800 tartomány, ami pontosan a flash kalibrációs szegmens RAM tükre. A dispatch a CAL init során egyszer fut le, a setter nem hívja. Vagyis nem kalibrációból számolt értékeket frissít, és az r15 átírása nem hagy maga után stale dispatch állapotot.

A valódi ok: az init-idejű cache

A stale állapot forrása az init lista. A Bosch OS indításkor egy hosszú függvénylistát futtat le (a 730d-n 486 elem), és ezek közül sok egyszer kiolvassa a saját kalibrációs blokkját, majd az eredményt RAM-ban tartja. A 730d-n 159 init függvény olvas r15-ön keresztül, összesen 148 entry-t a 440-ből. Van, amelyik magát a blokk pointert menti el (például PTR[0xC0], PTR[0x4DC]), és van, amelyik egy abból kiolvasott értéket (például PTR[0x12C], PTR[0x440], PTR[0x558]).

Init-idejű érték cache (730d DDE626, 0x404C54)
lwz     r3, 0x50(r15)        ; PTR[0x050] blokk
lha     r11, 0xa6(r3)
sth     r11, -0x7506(r13)    ; RAM másolat, reboot-ig nem frissül
lha     r10, 0xa4(r3)
sth     r10, -0x7508(r13)
blr

Ha futás közben átírjuk az r15-öt, a periodikus taszkok azonnal az új blokkokat olvassák, az init-időben cache-elt pointerek és értékek viszont stock állapotban maradnak. Ugyanaz a modul így félig az új, félig a régi kalibrációból dolgozik. A tapasztalt tünetekre ez a jobb magyarázat: ha például a CAN frame manager init-időben cache-el, a kereteket már részben inkonzisztens adatból építi fel. Nem minden cache veszélyes: amelyik függvény periodikus taszkban fut (a 730d-n például a 0x52408), az minden ciklusban újratölti a pointereit.

Két biztonságos út az r15 váltáshoz

Runtime tábla váltás a Bosch setteren keresztül
cal_select:                        ; r3 = map index
stwu    r1, -0x10(r1)
mflr    r0
stw     r0, 0x14(r1)
lis     r12, TBL_LIST_HI
ori     r12, r12, TBL_LIST_LO      ; {stock ref, klón 1, klón 2, ...}
slwi    r3, r3, 2
lwzx    r4, r12, r3
stw     r4, CAL_ActivePtr_Default(r13)
li      r3, 0xFF                   ; page változatlan
bl      CAL_SetActiveDataset       ; kritikus szekció + r15 írás
lwz     r0, 0x14(r1)
mtlr    r0
addi    r1, r1, 0x10
blr

A klón táblát a referencia tábla mintájára kell felépíteni: minden entry a saját blokkjának klón címére mutat (stock cím + slot delta), a sentinel is relokálva. A referencia táblához (r2-relatív) nem nyúlunk, így a Bosch címfordító automatikusan a klón blokkokat olvassa. A 730d-n a 0x140000 - 0x1FFFFF terület (768 KB) üres, és egyetlen checksum szegmens sem fedi le, így több teljes klón is elfér benne. Ennek az ára, hogy a klónokat az ECU saját integritás-ellenőrzése nem védi.

Alternatíva: végső output cella felülírás

Ha csak egyetlen kimenetet akarunk befolyásolni, a legkevésbé invazív megközelítés nem a pointer-szintű átirányítás, hanem a nyomaték-pipeline végső kimeneti cellájának felülírása. A Bosch torque pipeline végén van egyetlen RAM cella, ami az interpolált nyomaték limiter értéket tartalmazza. Ezt egyetlen downstream modul olvassa, és ami a lényeg: nincs rajta konzisztencia-ellenőrzés.

Ha a mapswitch patch az összes Bosch számolást békén hagyja (stock pointer tábla, stock base, stock variant switch), és csak ezt a végső output cellát írja felül egy kívánt értékkel, semmilyen belső ellenőrzés nem sérül. A többi alrendszer (füst limiter, boost limit, váltóvédelem) változatlanul működik, a motor védelme biztosított marad.

Végső output cella felülírás (SOI-stílusú RAM override)
; Hook: közvetlenül a stock nyomaték-kimenet írása UTÁN
lbz     r12, map_counter(r13)   ; aktív térkép index (0/1/2)
cmpwi   r12, 0x0
beq     skip                    ; map 0 = stock, ne módosíts

; Kalibráció-vezérelt felülírás:
lis     r11, CAL_TQ_HI
ori     r11, r11, CAL_TQ_LO
lha     r3, 0x0(r11)           ; r3 = TQ override érték (kalibrációból)
sth     r3, TQ_output(r13)     ; felülír a kívánt értékkel

skip:
; Stolen instrukciók (a hook által kiszedett eredeti kód):
addi    r1, r1, 0x10           ; stack frame felszabadítás
blr                              ; visszatérés

Az override érték a flash kalibrációs területén van tárolva, WinOLS-ben map definícióként kalibrálható, és maga a kód soha nem módosul. Ez a "data driven patch" filozófia: a logika a cave-ben van, az értékek meg a kalibrációs területen. Ha változtatni akarunk, csak az adatot piszkáljuk, a patch-hez nem kell hozzányúlni.

Záró gondolat

Négy BMW platform, két ECU típus (CP35, C31), négy szoftver-verzió, egy végeredmény: a BMW EDC16 kalibrációs architektúra az MPC562/563-alapú változatokban egységes. Ugyanaz a pointer tábla, ugyanaz a dual variant, ugyanaz a flash mirror, ugyanaz a script - csak más paraméterekkel. Az utólagos 730d DDE626 elemzés ugyanezt a szerkezetet adta vissza, a CAL_SetActiveDataset utasításról utasításra megegyezik. Az MPC555-ös DDE5 egy korábbi generáció, ami direkt címzéssel dolgozik: egyszerűbb statikus elemzés, de nehezebb testreszabás.

A mapswitch fejezet megmutatta, miért nem triviális a többtérképes konfiguráció: a Bosch firmware nem tűri a félkész módosítást. A félkész állapot viszont nem magából az r15 váltásból fakad, hanem abból, hogy mit érint. Ha a klón csak olyan blokkokat módosít, amelyeket az init nem cache-el, vagy ha a váltás bootkor történik, az r15 swap tiszta megoldás, és egyetlen lépésben az összes térképet átkapcsolja. Ahol csak egyetlen kimenet a cél, ott a pipeline végső output cellájának kontrollált felülírása a legkevésbé invazív út.

A tanulság: ha egy megközelítés több platformon is ugyanazt az eredményt adja, az nem véletlen, hanem rendszerszintű igazolás. Az annotáló script bármelyik MPC562-alapú BMW EDC16-on működik, a konfigurációs paraméterek cseréjével. A gépezet ugyanaz, csak a címek mások. Az MPC555-höz a direkt címzési mód felismerése kell, de az annotálási logika ott is adaptálható.

< VISSZA A LOGOKHOZ