Skocz do zawartości

Tajemnice ECU - część I


tomiwroc6

Rekomendowane odpowiedzi

W nawiązaniu do wstępu tym razem przejdziemy do sposobu w jaki można zacząć analizę kodu. Poniżej znajduje się ciąg instrukcji procesora, jest to wycinek zawartości zewnętrznego eeproma.

Quote:

5D 26 03 4F 20 2D A1 00

22 04 4F 5F 20 25 5A 3A

A1 00 25 04 17 5F 20 1B

5A 09 A1 00 25 FA 26 04

17 5F 20 0F 37 A0 00 E6

01 E0 00 CE 00 00 3A 5F

02 8F 32 39


Co tu dużo mówić, w ten sposób nie jesteśmy w stanie dopatrzeć się czegokolwiek odnośnie przeznaczenia tego fragmentu. A tym bardziej tego, że przedstawia on funkcje wyliczającą indeks w zadanej tablicy na podstawie podanej wartości....

Aby uzyskać bardziej przyjazny kod asemblerowy, można użyć programu DHC11. Oto efekt konwersji :

Code:



tstb ; Test for negative or zero

bne loc_C4D0 ; Branch if not equal

clra ; Clear

bra locret_C4FD ; Branch always

loc_C4D0: ; Compare accumulator with memory

cmpa 0,x

bhi loc_C4D8 ; Branch if > (unsigned)

clra ; Clear

clrb ; Clear

bra locret_C4FD ; Branch always

loc_C4D8: ; Decrement

decb

abx ; Add b to index register

cmpa 0,x ; Compare accumulator with memory

bcs loc_C4E2 ; Branch if carry bit set

tba ; Transfer B to A

clrb ; Clear

bra locret_C4FD ; Branch always

loc_C4E2: ; Decrement

decb

dex ; Decrement index register

cmpa 0,x ; Compare accumulator with memory

bcs loc_C4E2 ; Branch if carry bit set

bne loc_C4EE ; Branch if not equal

tba ; Transfer B to A

clrb ; Clear

bra locret_C4FD ; Branch always

loc_C4EE: ; Push accumulator B into stack

pshb

suba 0,x ; Subtract

ldab 1,x ; Load accumulator from memory

subb 0,x ; Subtract

ldx #0 ; Load index register from memory

abx ; Add b to index register

clrb ; Clear

idiv ; Integer divide 16 by 16

xgdx ; Exchange D with index register

pula ; Pull accumulator A from stack

locret_C4FD: ; Return from subroutine

rts


Teraz przynajmniej cokolwiek można odczytać jednak analiza kolejnych wykonywanych instrukcji może sprawiać problemy - więc zastosujemy kolejne ułatwienie - graficzny deasembler, który w odróżnieniu od DHC11, oprócz prezentacji samego kodu, tworzy również bardziej zrozumiałe wykresy ( ala schematy blokowe ).

Tak wygląda screen z przykładowego program IDA.

280074465-Image3.jpg

Taka postać prezentacji kodu już jest w miarę czytelna.

W takim razie przejdźmy do tematu dzisiejszego odcinka - analizy fragmentu tym razem konkretnego kodu, który wylicza indeksy dla zadanych wartości z map.

Dane wejściowe dla tej funkcji znajdują się w rejestrach :

X - wskaźnik do adresu początku tablicy z wartościami,

A - wartość dla której należy określić indeks

B - długość tablicy ( ilość komórek )

Zawartość przykładowej tablicy, przyjmujemy numeracje komórek od 0 :

Quote:

00 0A 14 1E 28 32 3C 46 50 5A 64 6E 78 82 8C 96


Załóżmy że szukamy A=39 dla X=adres podanej wyżej tablicy , długości B=16

A teraz analiza kodu :

Sprawdzamy zawartość B czy zawiera wartość 0, jeżeli tak to A=0 i kończymy funkcje.

Jeżeli B > 0 to porównujemy szukaną wartość do 0 komórki tablicy, jeżeli A <= X[0] to A,B=0 i kończymy funkcje.

Zmniejszamy B o 1 i przesuwamy się na koniec tablicy X=X+15.

Sprawdzamy czy w komórce wartość jest A >= X[X+15].

Jeżeli tak to A = B , B= 0 i kończymy funkcje.

Jeżeli znajdujemy się w punkcie loc_C4E2 to znaczy że szukana wartość jest większa od 0 komórki tablicy i większa od ostatniej, oraz znajdujemy się w ostatniej komórce tablicy X = [X+(B-1)].

Następnie tak długo przesuwamy się do 0 komórki aż szukana wartość będzie >= od wartości w komórce. ( B -- , X -- )

Jak już znajdziemy taką komórkę A >= X[0], to sprawdzamy czy wartości są równe. Jeżeli tak to A = B , B = 0, i koniec.

Jeżeli A > X[0] to wykonujemy następujące czynności :

zapamiętujemy wartość aktualną B ( znaleziony indeks w tablicy ).

Code:



A = A - X[0]

X = X[1] - X[0]

B = 0

X = D div X

D = D mod X

D <=> X


Do A ściągamy zapamiętaną wcześniej wartość znalezionego indeksu i kończymy funkcje.

I tutaj mała zagadka co praktycznie wykonuje zaznaczony fragment kodu. I z których rejestrów można odczytać wynik.

post-42871-1435248963213_thumb.jpg

Odnośnik do komentarza
Udostępnij na innych stronach

  • 2 tygodnie później...

Code:



A = A - X[0]

X = X[1] - X[0]

B = 0

X = D div X

D = D mod X

D <=> X


No więc sprawa wygląda następująco dla przykładu :

szukamy wartości 92 i znaleźliśmy komórki z wartościami :

X[0] = 84

X[1] = 100

z obliczeń wynika że :

D = 92 - 84 = 800

X = 100 - 84 = 16

X = D / X = 50

Czyli praktycznie oznacza to że wartość 92 znajduje się 50% pomiędzy 100 a 84. Czyli wartość zwrócona przez funkcję to indeks 0 , i procent 50.

W przeliczeniu na wartości HEX, w rejestrze

A = 0x00

B = 0x80

D = 0x0080 i taka wartość zostaje zapamiętana do dalszych wyliczeń.

A teraz przykład zastosowania, myślę że bardzo ciekawy ponieważ w kwestii chip-tuningu bardzo ważny. W uproszczeniu jedna z ważniejszych map, które głównie podlegają modyfikacji wygląda tak ( jest to mapa wyprzedzenia zapłonu dla zamkniętej przepustnicy ) :

280115702-ign.jpg

Na osi Y mamy wartość wyprzedzenia zapłonu, natomiast na osi X obroty.

I tutaj najważniejsza sprawa, jak widać wartości są od 0 do 255 ( 1 bajt), tylko że te wartości oznaczają konkretne obroty, jednak żeby to jakoś można przeliczyć musi być znana wartość na końcu skali dla 255. Wtedy z proporcji można sobie wyliczyć obroty dla dowolnej wartośći.

To jest dość ciekawy i myślę że ważny problem, którego rozwiązanie wydaje mi się że jest znane wielu osobom, liczę więc na jakieś konkretne podpowiedzi które pomogą ustalić tą tajemniczą wartość. Czekam również na propozycje co może tam się znajdować. Dla mnie wydaje się najodpowiedniejsza wartość obrotów przy odcięciu zapłonu, wtedy mamy do wykorzystania cały zakres skali.

Prawdopodobna jest też wartość praktycznie nieosiągalna np. 8000 , tylko wtedy tracimy część skali gdy mamy odcinke przy np. 6700.

Jak napisałem czekam na Wasze opinie jak myślicie jaka wartość może się tam znajdować, i liczę również na pomoc fachowców z tego forum. wink.gif

To jest ciekawostka numer 1. Dosyć ciekawe jest też kolejne rozwiązanie właśnie tego problemu, czyli być może niedostatecznej rozdzielczości ( a w efekcie możliwości precyzyjnego strojenia ) mapy.

Jak widać na poprzednim wykresie, wartość obrotów jest zamieniana na indeks 0...16 za pomocą opisanej na początku metody. Jednak nie jest to przeliczenie liniowe ( co w sumie byłoby najprostsze ). Czyli wartość 0xFF to indeks 15, 0xEE 14 itd... tylko została użyta kolejna "mapa", za pomocą której możemy "sterować" charakterystyką przeliczenia :

280115702-rpm.jpg

Jaki widać im wykres bardziej stromy tym mniejsza rozdzielczość ( a zarazem dokładność ) przeliczenia i na odwrót. Dzięki temu jeżeli w całym zakresie obrotów występuje pewny przedział gdzie potrzebna jest regulacja co mniejsza ilość obrotów, możemy sobie zwiększyć rozdzielczość oczywiście kosztem innego przedziału gdzie ją stracimy.

W końcu w przyrodzie nic nie ginie wink.gif.

Jak widać na tym wykresie, przeliczenie również tutaj nie jest liniowe czyli mamy większą dokładność na początku skali czyli "dla wolnych obrotów".

Czyli w trakcie zmiany wszystkich map gdzie na którejś z osi mamy obroty zamienione na indeks za pomocą takiej charakterystyki musi brać to pod uwagę - co widać wyraźnie na wcześniejszym wykresie zapłonu. Górny rząd wartości osi X , jest to przeliczenie liniowe , a poniżej z uwzględnieniem mapy charakterystyki. Jak widać miejscami różnice są znaczące, jeżeli chcemy zmienić kąt dla np. 3000 obrotów widać że być może trzeba by zmieniać różne komórki w zależności od charakterystyki.

To chyba na razie tyle, jak pisałem liczę na pomoc w rozwiązaniu ostatniej zagadki, bo wtedy cały odcinek można by uznać za zamknięty.

Dziękuję za uwagę. wink.gif

post-42871-14352489818657_thumb.jpg

Odnośnik do komentarza
Udostępnij na innych stronach

> i owo, a ewidentnie sa rozne. Czy dobrze kombinuje, ze sa dwie

> rozne skale do indeksowania predkosci obrotowej?

0xF0A3 16bit => 0x10A

0xF0B3 16bit => 0x10C

Po zastanowieniu się nad tą częścią kodu, można wyciągnąć jeszcze kilka ciekawych informacji. Do tej mapy brana jest wartość o której pisałem jakie obroty są jednoznaczne z 0xFF, jakby udało się znaleźć skąd się bierze wartość która jest przeliczana tymi mapami może dałoby się i znalęźć odpowiedź na to pytanie....

Właśnie dlatego proponowałem przesiadke na mój wsad, bo z innym nie będę wstanie pomóc.

>No ja walcze z tym celem remapu mojego CCS-a, takze wole wiedziec >co w moim piszczy.

Naprawdę niechce się narzucać ale widzę po tych szybkich postępach że może jakąś współprace można by nawiązać, jednak do tego jest potrzebny jednakowy wsad.

A to że komputery od strony hardware-u są identyczne, powinno być istotną informacją waytogo.gif

>Drugim zadaniem bedzie zezwolenie na inne wartosci min max MAP sensora, zeby np. przy turbo komp nie wywalal bledow.

Niestety to chyba nie tędy droga bo napięcie na czujniku jest sprawdzane tylko dla wartości granicznych, tak jak w podanym przykładzie, więc zakresu zbytnio zwiększyć już nie można.

Trzeba zastosować mapsensor o innym zakresie działania.

Odnośnik do komentarza
Udostępnij na innych stronach

> 0xF0A3 16bit =0xF0B3 16bit =

> Po zastanowieniu się nad tą częścią kodu, można wyciągnąć jeszcze

> kilka ciekawych informacji. Do tej mapy brana jest wartość o

> której pisałem jakie obroty są jednoznaczne z 0xFF,

Zmeczony jestem, takze bierz na to poprawke wink.gif W obu tych skalach ostatnia wartosc jest taka sama - $F0. Znaczy sie obie te skale dzialaja do tego samego zakresu obrotow. Odpowiedzia na twoje pytanie moze byc analiza interfejsu diagnostycznego. Tak sie sklada, ze do niego akurat mam dokumentacje (znalazlem linka na fiatforum.com, nie chce mi sie teraz szperac). Interfejs diagnostyczny zwraca dla predkosci obrotowej 2 bajty, ktore sie przelicza na rpm tak: 15x10^6/$byte1$byte2. "Wystarczy" teraz tylko znalezc skad kod diagnostyczny bierze ta wartosc i zobaczyc co sie z nia dzieje zanim jest wyliczona wartosci 1 bajtowa do mapy,..

> Właśnie dlatego proponowałem przesiadke na mój wsad, bo z innym nie

> będę wstanie pomóc.

Na razie ugrzezlem w swoim 270751858-jezyk.gif Ale mam juz zidentyfikowane prawie wszyskie tablice powyzej f000 (w sensie wiem gdzie sie zaczynaja, gdzie koncza i jak niektore z nich zaleza od siebie na wzajem).

> Naprawdę niechce się narzucać ale widzę po tych szybkich postępach

> że może jakąś współprace można by nawiązać,

Mozna, problem w tym, ze (1) za malo wiem o silnikach i czujnikach, (2) na razie jestem na wakacjach, to mam czas, potem bedzie gorzej.

> Niestety to chyba nie tędy droga bo napięcie na czujniku jest

> sprawdzane tylko dla wartości granicznych, tak jak w podanym

> przykładzie, więc zakresu zbytnio zwiększyć już nie można.

> Trzeba zastosować mapsensor o innym zakresie działania.

To juz wykoncypowalem. Mimo wszystko, inny czujnik, niezaleznie od swojego zakresu cisnien min i max, bedzie inaczej wyskalowany, znaczy sie napiecia min i max beda tez inne (chyba ze sie myle). Krotko mowiac maly burdel, trzeba go jakos w programie wyskalowac - (1) tablica skalujaca, (2) wartosci graniczne, ktore sprawdza procedura testujaca. Tak to widze.

Odnośnik do komentarza
Udostępnij na innych stronach

> To juz wykoncypowalem. Mimo wszystko, inny czujnik, niezaleznie od

> swojego zakresu cisnien min i max, bedzie inaczej wyskalowany.

Wszystkie czujniki działają tak samo - maja charakterystykę liniową, od 0V do 5V. Różnią się tylko wartością maksymalną przy 5V. Seryjny ma przy 5V 0bar(cisnienie atmosferyczne), a sa takie co maja i 1.5bara.

> "Wystarczy" teraz tylko znalezc skad kod diagnostyczny bierze ta wartosc i zobaczyc co sie z nia dzieje zanim jest wyliczona wartosci 1 bajtowa do mapy,..

No i proszę wywiązała się ciekawa dyskusja, jeszcze tylko małe sprostowanie - jeżeli już znamy komórkę w której zapisywane jest to przeskalowanie z obrotów na 0xFF, wystarczy poszukać fragment gdzie zapisywana jest ta wartość do komórki z rejestrów. A zapis musi być poprzedzony jakimiś tajemniczymi obliczeniami... wink.gif

No i jeszcze jedna zagadka, skoro konwersja wartości aktualnych obrotów zapisana w ramie, musi zostać przeliczona za pomocą takiej formuły 15*10^6 / wartość.

To co w takim razie oznacza wartość oryginalna ?

I jeszcze jeden wniosek do poprzedniej zagadki, analizując praktyczne zastosowanie mapy przeskalowania obrotów na indeks, już na podanym przykładzie pokazuje że problemem wcale nie musi być za duża wartość maksymalna (0xFF), jak wcześniej pisałem która ograniczyła bym nam rozdzielczość mapy, ponieważ można przeskalować obroty tak żeby już dość mała wartość, dawała końcowy indeks. Dobrze myśle ? wink.gif

Odnośnik do komentarza
Udostępnij na innych stronach

> Wszystkie czujniki działają tak samo

No to upraszcza troche sprawe.

> No i proszę wywiązała się ciekawa dyskusja, jeszcze tylko małe

> sprostowanie - jeżeli już znamy komórkę w której zapisywane jest

> to przeskalowanie z obrotów na 0xFF, wystarczy poszukać fragment

> gdzie zapisywana jest ta wartość do komórki z rejestrów. A zapis

> musi być poprzedzony jakimiś tajemniczymi obliczeniami...

Dokladnie to mialem na mysli, zrobilem tylko skrot myslowy

> No i jeszcze jedna zagadka, skoro konwersja wartości aktualnych

> obrotów zapisana w ramie, musi zostać przeliczona za pomocą

> takiej formuły 15*10^6 / wartość.

> To co w takim razie oznacza wartość oryginalna ?

> I jeszcze jeden wniosek do poprzedniej zagadki, analizując praktyczne

> zastosowanie mapy przeskalowania obrotów na indeks, już na

> podanym przykładzie pokazuje że problemem wcale nie musi być za

> duża wartość maksymalna (0xFF), jak wcześniej pisałem która

> ograniczyła bym nam rozdzielczość mapy, ponieważ można

> przeskalować obroty tak żeby już dość mała wartość, dawała

> końcowy indeks. Dobrze myśle ?

Patrze wlasnie na kod i te mapy, i powiem szczerze, ze powoli zaczynam dochodzic do wniosku (nie mam jeszcze potwierdzenia), ze te skale sa odwrocone - $FF oznacza obroty 0, $00 oznacza obroty maksymalne. Dlaczego tam mysle: miedzy innymi dlatego, ze katy wyprzedzenia powinny malec wraz z predkoscia obrotowa silnika, a w kazdym razie jeden malo trzezwy inzynier mi tak wczoraj powiedzal. Ale jeszcze niczego nie jestem pewien

Odnośnik do komentarza
Udostępnij na innych stronach

> ze te skale sa odwrocone - $FF oznacza obroty 0, $00 oznacza

> obroty maksymalne.

Nie wiem jak z tym katem wyprzedzenia, ale obroty sa od 0 do FF

To jeszcze zapytam tak, z jakiej komórki brana jest wartość do wyliczenia indeksu ?

I może wycinek kodu gdzie zapisywana jest wartość do tej komórki ( prawdopodobnie ten kod to przeskalowanie z obrotów ) waytogo.gif

Odnośnik do komentarza
Udostępnij na innych stronach

Z obrotami masz racje. Co do kodu, to takie cos znalazlem:

65BB ldD L00E1

65BD lsrD

65BE lsrD

65BF lsrD

65C0 lsrD

65C1 xgDX

65C2 ldD #$9278

65C5 idiv

65C6 xgDX

65C7 tstA

65C8 beq L65CC

65CA ldaB #$FF

65CC L65CC staB engine_speed_value

65CE ldX engine_speed_scale1

65D1 ldaA engine_speed_value

65D3 ldaB #$10

65D5 call LBEB5

65D8 stD L010A

65DB ldX engine_speed_scale2

65DE ldaA engine_speed_value

...

Zakladajac, ze odcyfrowalem dobrze etykiety, to wzor na przeliczenie dwu bajtowej wartosci obrotow na jeden bajt jest taki:

$9278 / ($rot1$rot2 / 16)

Problem w tym, ze zakladajac wzor z wczesniejszego posta, wartosc rpm 1000 daje $28 (calkiem rozsadnie), rpm 8000 daje $140 (czyli poza zasiegiem), rpm dla $ff byloby circa 6500 (6400 dokladnie rzecz biorac, tu mi cos nie styka).

Odnośnik do komentarza
Udostępnij na innych stronach

Co tu dużo mówić, jestem naprawdę pod wrażeniem waytogo.gif.

Chyba została odkryta jedna z ważniejszych "ciekawostek".

Pozwolę sobie troszkę szczegółowiej wytłumaczyć.

Code:


  

xX = CZAS / 16

xD = #$9278

xD = xD / xX

Jeżeli (xD > 0xFF) to xD = 0xFF ( obcięcie skali )


Teraz trochę obliczeń ( zgodnie z formułą przeliczeniową )

[ Po przeanalizowaniu formuły okazuje się że wartość trzyma w komórce z prędkością obrotową to czas obrotu wału w us*2]

Dla zoobrazowania ( RPM )

1000 = $3A98

2000 = $1D4C

3000 = $1388

4000 = $0EA6

5000 = $0BB8

6000 = $09C4

7000 = $085E

Teraz podstawmy do wzoru dla 7000 ( 85E )

$85E / $10 = $85

$9278 / $85 = 119 , za dużo zostanie obcięte, weźmy 6000

$9278 / $9C = F0 , za mało można więcej

sprawdźmy ile

$9278 / $FF = $93 , jakie to są obroty :

15000000 / $930 = 6377

Czyli mamy już to co znajduje się na końcu skali.

Jak dla mnie to było duże zdziwienie ponieważ uniemożliwia to strojenie auto powyżej takich obrotów - nawet dla 8000 brane są parametry jak dla 6377. Dla samochodu seryjnego to jeszcze nic dziwnego ale już po modach może to być przeszkodą.

No i mamy wyskalowane jak trzeba obroty :

280127838-Image2.jpg

post-42871-14352489857944_thumb.jpg

Odnośnik do komentarza
Udostępnij na innych stronach

  • 1 rok później...

> Pięknie. To teraz ja mam zagadkę. Poniżej trzy mapy. "Wiersze" to

> obroty, "Kolumny" to obciążenie. Co te mapy przedstawiają? Jedna

> to czasy wtrysków, potem musimy mieć jeszcze kąty wyprzedzenia,

> i jest coś jeszcze. Ale która jest która?

> mapa1

Czas wtrysku

> mapa2

Kąt wyprzedzenia zapłonu

> mapa3

Tu jest jakiś binarny parametr...

Na początku myślałem że tu jest zapisany warunek pracy w pętli zamkniętej/otwartej, ale trochę nie pasuje.

Może to być też np. sterowanie zaworem pochłaniacza par paliwa.

Odnośnik do komentarza
Udostępnij na innych stronach

Temat został przeniesiony do archiwum

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...

Powiadomienie o plikach cookie

Używając tego serwisu, wyrażasz zgodnę na naszą Polityka prywatności oraz Warunki użytkowania.