PDA

View Full Version : How to disassemble MSS52 DME dump? help needed please



Katvis
29th March, 2010, 03:50 PM
Hi guys
Here is a screen shot of my DME for the E39 M5, does anybody know which processor I need to choose in IDA to get a good disassembly? Any advise on how to disassemble this code will be greatly appreciated.

http://i895.photobucket.com/albums/ac152/coenraadg/DME/DME.jpg

Cheers
C

pepi
29th March, 2010, 06:59 PM
Data on 2 flash memories 29F

Katvis
29th March, 2010, 07:05 PM
I have the complete dump of the code, my problem is that if I use IDA to disassemble I need to chose the Processor type.

For the Bosch motronics it is easy as Andy Whitaker made nice tutorial videos that explain exactly how to disassemble the code.

I am looking for similar help to disassemble the MSS52 code.

Cheers
C

oldford
29th March, 2010, 07:13 PM
Can you post (attach) the dump?

Katvis
29th March, 2010, 07:21 PM
Here is the complete program dump from the MSS52 E39 M5

Cheers
C

Katvis
24th April, 2010, 06:28 AM
anyone? any help would be appreciated..;)
Cheers

alexics
24th April, 2010, 01:32 PM
You will need the datasheet and also a reference for the assembly language opcodes. I used to write disassemblers for hc05, hc11 and tms370. Not very complicated, about two screenfuls of code.

easytech
24th April, 2010, 02:24 PM
as far as I knows they are 68332 or 68336 processors

alexics
24th April, 2010, 02:40 PM
as far as I knows they are 68332 or 68336 processors

Pinouts would be useful and data on peripherals attached to the processor. Without knowing the exact aims of the exercise that is as much as I can say.

Katvis
18th May, 2010, 04:47 PM
Hi Guys
A quick update, I was away for work and was waiting for more information before I reply here. I have bought a spare DME and am awaiting delivery. I do not want to mess up my car's own DME for obvious reasons but as soon as I have the spare DME I can trace a few tracks and confirm 100% that the CPU is a 68376 Motorola chip. I will post the tracks that I trace for your information.

Can somebody please give me some more advise on how to disassemble the CPU32 code with IDA. I do have IDA pro but apart from the 68k Processor type I can not see the CPU32 instruction set. Somebody advised me to use the 68330 processor type but I find that in both instances there is some instructions that does not get disassembled. Is there a version of IDA that list CPU32 as a processor type?


as far as I knows they are 68332 or 68336 processors
Thank you very much for this info, I had a look earlier at the 68332 but the pin count did not match. The 68336/68376 CPU's pin count does match.


Pinouts would be useful and data on peripherals attached to the processor. Without knowing the exact aims of the exercise that is as much as I can say.
Thank you very much for your help, I really appreciate it. Will post the tracks and pin outs of the CPU as soon as I receive the DME.

Thanks again for all the input
Regards
C

alexics
18th May, 2010, 05:35 PM
I can't remember from the docs you sent but does the MCU have background debug mode? It may be better to source an emulator. Check out the Freescale site. They may be giving the old stuff away now.

alexics
18th May, 2010, 05:39 PM
Try here to start with

MC68336 Product Summary Page (http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MC68336&fpsp=1&tab=Design_Tools_Tab)

Katvis
18th May, 2010, 05:46 PM
Hi there
Yes the 683xx series CPU does have a BDM mode. I have ordered a wiggler interface cable for the BDM port from macraigor. This only works with a free debugger and I am sure it wont be as powerful as a full blown emulator. I am going to give this BDM with debugger a go and hopefully I can make sense of the code I read. If this does not work I will look further to try and source a emulator, you will be surprised to find that even though this CPU chip is very old that each and every emulator I could find was very expensive. A normal USB BDM cable plus custom debugger was offered at $1500..! So I did not even ask for the price for the full blown emulator with trace functions.

The DME I have does not have the BDM port soldered on the pc board so I have to solder the wires on the chip pins, but it should not be a problem as this is my test DME, I will post pics of my setup as soon as I receive my DME.

Cheers
C

Katvis
7th July, 2010, 12:51 PM
Hi guys
I need some help to identify some chips please. I have searched the internet and can find the model numbers but I can not find any data sheets for the chips.

Interesting as well is the BDM connector tracks that is on the board, below is the detail picture, I have ordered two plugs that will fit on this tracks and are still waiting for the hardware, will post pictures once I receive the plugs, on the picture below the tracks can be seen next to the memory chips:

http://i895.photobucket.com/albums/ac152/coenraadg/DME/BDM-connector-tracks.jpg

Here are pics of the Ignition drivers as well as the driver chip for the driver ic's, one driver chip is on the front of the pc board and the other on the back:

http://i895.photobucket.com/albums/ac152/coenraadg/DME/IGN2-3-5-8-drivers.jpg

http://i895.photobucket.com/albums/ac152/coenraadg/DME/IGN1-4-6-7-drivers-plusdriver-chip.jpg



Below are three pictures of driver IC's that I would like to have data sheets for please if any of you can help I will appreciate it very much.

http://i895.photobucket.com/albums/ac152/coenraadg/DME/TY94086FB.jpg

http://i895.photobucket.com/albums/ac152/coenraadg/DME/STT128E-1.jpg

http://i895.photobucket.com/albums/ac152/coenraadg/DME/DPS326718-R7014A.jpg

Cheers

alexics
7th July, 2010, 10:56 PM
Do you have another module the same? If so try desoldering the chips. Sometimes the manufacturer mumbers are on the underside. I would assume that these are driver chips for whatever transmission protocol the unit uses. K-line, can bus etc.

alexics
7th July, 2010, 11:19 PM
STT128E- Selling Leads,STT128E- Datasheet ,STT128E- PDF -TheICStock (http://www.theicstock.com/stock-STT/STT128E-.html)

Scroll all the way down to the bottom of the page past all the blank bit for a brief description of the chip. This site may also allow you to get this 'hidden' data on your other chips.

alexics
7th July, 2010, 11:38 PM
DPS326718 R7014A Selling Leads,DPS326718 R7014A Datasheet ,DPS326718 R7014A PDF -TheICStock (http://www.theicstock.com/stock-DPS/DPS326718%20R7014A.html)

ATM38-2 Selling Leads,ATM38-2 Datasheet ,ATM38-2 PDF -TheICStock (http://www.theicstock.com/stock-ATM/ATM38-2.html)

:thrasher:

Katvis
12th July, 2010, 08:05 PM
First we correct the bytes on a 16bit boundry to get the BIGENDIAN format for the Motorolla protocol.
We disassemble with Motorolla 68330 as CPU choice.
ROM:00000000 ; Processor: 68330
ROM:00000000 ; Target Assembler: 680x0 Assembler in MRI compatible mode
ROM:00000000 ; This file should be compiled with "as -M"
ROM:00000000
ROM:00000000 ; ================================================== =======================
ROM:00000000
ROM:00000000 ; Segment type: Pure code
ROM:00000000 ; segment "ROM"

Table 6-1 Exception Vector Assignments
Vector
Number
Vector Offset Assignment
Dec Hex Space
0 0 000 SP Reset: Initial Stack Pointer
1 4 004 SP Reset: Initial Program Counter
2 8 008 SD Bus Error
3 12 00C SD Address Error
etc etc

From the above documentation we can see that the Initial Stack Pointer is set to zero and that the Initial Program Counter shows to dc.l loc_200

ROM:00000000 dword_0: dc.l 0 ; CODE XREF: sub_362C+6j
ROM:00000000 ; sub_3E10E:loc_3E2AEj ...
ROM:00000000 ; INITIAL STACK POINTER
ROM:00000004 off_4: dc.l RESET_INITIAL_PROGRAM_COUNTER
ROM:00000004 off_4: dc.l loc_200 ; DATA XREF: sub_1056+90o
ROM:00000004 ; ROM:loc_172Co ...
ROM:00000004 ; START of program address
ROM:00000008 off_8: dc.l sub_5B0 ; DATA XREF: sub_966+88o
ROM:00000008 ; sub_CD6+68o ...
etc
etc

ROM:00000200 RESET_INITIAL_PROGRAM_COUNTER: ; CODE XREF: sub_5B0+10j
ROM:00000200 ; sub_3072+5Cj ...
ROM:00000200 StackPointer = sp ; store Adres registers on stack
ROM:00000200 StatusRegister = sr ;
ROM:00000200 VectorBaseRegister = vbr
ROM:00000200 movem.l a2-a3,-(StackPointer)
ROM:00000204 movea.l #$3FE0,a3
ROM:0000020A clr.l d0
ROM:0000020C movec d0,VectorBaseRegister ; clear vector base register
ROM:00000210 movea.l d0,StackPointer
ROM:00000212 movea.l #$4800,a2
ROM:00000218 tst.w (a2)
ROM:0000021A bne.w loc_24A
ROM:0000021E
ROM:0000021E loc_21E: ; CODE XREF: sub_3072-2E50j
ROM:0000021E addq.l #2,a2
ROM:00000220 tst.w (a2)
ROM:00000222 beq.s loc_21E
ROM:00000224 cmpi.w #$FFFF,(a2)
ROM:00000228 bne.s loc_230
ROM:0000022A jsr MAIN_LOOP? ;do some stuff and then jump to MAIN_LOOP
ROM:00000230
ROM:00000230 loc_230: ; CODE XREF: sub_3072-2E4Aj
ROM:00000230 cmpi.w #$F500,(a2)
ROM:00000234 beq.s loc_23E
ROM:00000236 cmpi.w #$F5,(a2) ; ')'
ROM:0000023A bne.w loc_24A
ROM:0000023E
ROM:0000023E loc_23E: ; CODE XREF: sub_3072-2E3Ej
ROM:0000023E lea ($4880).l,a0
ROM:00000244 movea.l dword_4884-dword_4880(a0),a0
ROM:00000248 jmp (a0)
ROM:0000024A ; ---------------------------------------------------------------------------
ROM:0000024A
ROM:0000024A loc_24A: ; CODE XREF: sub_3072-2E58j
ROM:0000024A ; sub_3072-2E38j
ROM:0000024A cmpi.l #$5AA556C9,(dword_FFFC).l
ROM:00000254 bne.s loc_25C
ROM:00000256 jsr (sub_1B78).l
ROM:0000025C
ROM:0000025C loc_25C: ; CODE XREF: sub_3072-2E1Ej
ROM:0000025C lea ($FFE500).l,a0
ROM:00000262 movea.l a0,StackPointer
ROM:00000264 move a0,usp
ROM:00000266 move.w #$C046,($FFFA00).l
ROM:0000026E move.w #$D200,($FFFA04).l
ROM:00000276 move.b #$BD,($FFFA21).l
ROM:0000027E move.b #$55,($FFFA27).l ; 'U'
ROM:00000286 move.b #$AA,($FFFA27).l
ROM:0000028E move.l #$FFE000,($FFFB44).l
ROM:00000298 clr.w ($FFFB40).l
ROM:0000029E move.w #$FFC1,($FFFA50).l
ROM:000002A6 move.w #$3830,($FFFA52).l
ROM:000002AE move.w #$FFC1,($FFFA54).l
ROM:000002B6 move.w #$5830,($FFFA56).l
ROM:000002BE jsr (sub_478).l
ROM:000002C4 jsr (sub_3CA).l
ROM:000002CA
ROM:000002CA loc_2CA: ; DATA XREF: sub_339AE+24o
ROM:000002CA ; sub_33AB0+5Co
ROM:000002CA btst #0,($FFE50C).l
ROM:000002D2 beq.s loc_2F8
ROM:000002D4 move.w #6,($FFFA48).l
ROM:000002DC clr.w ($FFFA5A).l
ROM:000002E2 clr.w ($FFFA5E).l
ROM:000002E8 move.w #$FFD0,($FFFB04).l
ROM:000002F0 move.w #$1000,($FFFB00).l
ROM:000002F8
ROM:000002F8 loc_2F8: ; CODE XREF: sub_3072-2DA0j
ROM:000002F8 cmpi.b #$4D,(a3) ; 'M'
ROM:000002FC bne.s loc_304
ROM:000002FE jsr (sub_55E).l
ROM:00000304
ROM:00000304 loc_304: ; CODE XREF: sub_3072-2D76j
ROM:00000304 jsr (sub_33A).l
ROM:0000030A
ROM:0000030A loc_30A: ; CODE XREF: sub_3072-2D56j
ROM:0000030A ; sub_3072-2D4Cj
ROM:0000030A jsr (sub_EB6).l
ROM:00000310 move.b #$55,($FFFA27).l ; 'U'
ROM:00000318 cmpi.b #$4D,(a3) ; 'M'
ROM:0000031C bne.s loc_30A
ROM:0000031E btst #5,($FFD15A).l
ROM:00000326 bne.s loc_30A
ROM:00000328 ori.b #1,($FFFA19).l
ROM:00000330
ROM:00000330 loc_330: ; CODE XREF: sub_3072-2D40j
ROM:00000330 nop
ROM:00000332 bra.s loc_330
ROM:00000332 ; END OF FUNCTION CHUNK FOR sub_3072
ROM:00000334 ; ---------------------------------------------------------------------------
ROM:00000334 movem.l (sp)+,a2-a3
ROM:00000338 rts


Then we land here:
In the start of this routine we can see that VBR gets loaded with loc 10000

ROM:00010C08 ; =============== S U B R O U T I N E ================
ROM:00010C08
ROM:00010C08
ROM:00010C08 MAIN_LOOP?: ; CODE XREF: sub_3072-2E48p
ROM:00010C08 ; sub_11068+40j
ROM:00010C08 lea (dword_10000).l,a0
ROM:00010C0E movec a0,vbr


If we go to 10000 we find another vector table shown below:

ROM:00010000 dword_10000: dc.l 0 ; DATA XREF: ROM:00002058o
ROM:00010000 ; ROM:00002658o ...
ROM:00010004 dc.l RESET_INITIAL_PROGRAM_COUNTER
; SAME AS FIRST VECTOR TABLE loc 200
ROM:00010004 ;
ROM:00010008 dc.l $11068
ROM:0001000C dc.l $11068
ROM:00010010 dc.l $11068
ROM:00010014 dc.l $11068
ROM:00010018 dc.l $11068
ROM:0001001C dc.l $11068
ROM:00010020 dc.l $11068
ROM:00010024 dc.l $11068
ROM:00010028 dc.l $11068
ROM:0001002C dc.l $11068
ROM:00010030 dc.l $11068
ROM:00010034 dc.l $11068
ROM:00010038 dc.l $11068
ROM:0001003C dc.l $11068
ROM:00010040 dc.l $11068
ROM:00010044 dc.l sub_1161C
ROM:00010048 dc.l sub_1196E
ROM:0001004C dc.l sub_11940
ROM:00010050 dc.l $11068
ROM:00010054 dc.l $11068
ROM:00010058 dc.l $11068
ROM:0001005C dc.l $11068
ROM:00010060 dc.l SPURIOUS_INTERRUPT
;interesting interrupts from CPU32 and 68376documentation
ROM:00010064 dc.l LEVEL1_INTERRUPT
ROM:00010068 dc.l LEVEL2_INTERRUPT
ROM:0001006C dc.l $11068
ROM:00010070 dc.l $11068
ROM:00010074 dc.l LEVEL5_INTERRUPT
ROM:00010078 dc.l $11068
ROM:0001007C dc.l LEVEL7_INTERRUPT
ROM:00010080 dc.l $11068
ROM:00010084 dc.l $11068
ROM:00010088 dc.l $11068
ROM:0001008C dc.l $11068
ROM:00010090 dc.l $11068
ROM:00010094 dc.l $11068
ROM:00010098 dc.l $11068
ROM:0001009C dc.l $11068
ROM:000100A0 dc.l $11068
ROM:000100A4 dc.l $11068
ROM:000100A8 dc.l $11068
ROM:000100AC dc.l $11068
ROM:000100B0 dc.l $11068
ROM:000100B4 dc.l $11068
ROM:000100B8 dc.l $11068
ROM:000100BC dc.l $11068
ROM:000100C0 dc.l sub_11690
ROM:000100C4 dc.l sub_11662
ROM:000100C8 dc.l sub_116BE
ROM:000100CC dc.l sub_116EC
ROM:000100D0 dc.l sub_1171A
ROM:000100D4 dc.l sub_11748
ROM:000100D8 dc.l sub_11776
ROM:000100DC dc.l sub_117A4
ROM:000100E0 dc.l sub_117D2
ROM:000100E4 dc.l sub_11800
ROM:000100E8 dc.l $11068
ROM:000100EC dc.l $11068
ROM:000100F0 dc.l sub_1182E
ROM:000100F4 dc.l $11068
ROM:000100F8 dc.l loc_118E4
ROM:000100FC dc.l loc_11912
ROM:00010100 dc.l $11068
ROM:00010104 dc.l $11068
ROM:00010108 dc.l $11068
ROM:0001010C dc.l $11068
ROM:00010110 dc.l $11068
ROM:00010114 dc.l sub_1185C
ROM:00010118 dc.l sub_1187E ; DATA XREF: ROMff_2FD7Co
ROM:0001011C dc.l sub_118A0
ROM:00010120 dc.l sub_118C2
ROM:00010124 dc.l $11068
ROM:00010128 dc.l $11068
ROM:0001012C dc.l $11068 ; DATA XREF: ROMff_2FD52o
ROM:00010130 dc.l $11068
ROM:00010134 dc.l $11068
ROM:00010138 dc.l $11068
ROM:0001013C dc.l $11068
ROM:00010140 dc.l $11068
ROM:00010144 dc.l $11068
ROM:00010148 dc.l $11068
ROM:0001014C dc.l $11068
ROM:00010150 dc.l $11068
ROM:00010154 dc.l $11068
ROM:00010158 dc.l $11068
ROM:0001015C dc.l $11068
ROM:00010160 dc.l $11068
ROM:00010164 dc.l $11068
ROM:00010168 dc.l $11068
ROM:0001016C dc.l $11068
ROM:00010170 dc.l $11068
ROM:00010174 dc.l $11068
ROM:00010178 dc.l $11068
ROM:0001017C dc.l $11068
ROM:00010180 dc.l $11068
ROM:00010184 dc.l $11068
ROM:00010188 dc.l $11068
ROM:0001018C dc.l $11068
ROM:00010190 dc.l $11068
ROM:00010194 dc.l $11068
ROM:00010198 dc.l $11068
ROM:0001019C dc.l $11068
ROM:000101A0 dc.l $11068
ROM:000101A4 dc.l $11068
ROM:000101A8 dc.l $11068
ROM:000101AC dc.l $11068
ROM:000101B0 dc.l $11068
ROM:000101B4 dc.l $11068
ROM:000101B8 dc.l $11068
ROM:000101BC dc.l $11068
ROM:000101C0 dc.l $11068
ROM:000101C4 dc.l $11068
ROM:000101C8 dc.l $11068
ROM:000101CC dc.l $11068
ROM:000101D0 dc.l $11068
ROM:000101D4 dc.l $11068
ROM:000101D8 dc.l $11068
ROM:000101DC dc.l $11068
ROM:000101E0 dc.l $11068
ROM:000101E4 dc.l $11068
ROM:000101E8 dc.l $11068
ROM:000101EC dc.l $11068
ROM:000101F0 dc.l $11068
ROM:000101F4 dc.l $11068
ROM:000101F8 dc.l $11068
ROM:000101FC dc.l $11068

Now if you are curious like me you will count the vector addresses and get 128, exactly halve of what it should be? I do not know why yet because the documentation clearly state we should have 256 vector addresses?

Rest of main loop:

ROM:00010C12 move.w #$4046,($FFFA00).l
ROM:00010C1A move.w #$D200,($FFFA04).l
ROM:00010C22 move.b #$BD,($FFFA21).l
ROM:00010C2A move.b #$55,($FFFA27).l ; 'U'
ROM:00010C32 move.b #$AA,($FFFA27).l
ROM:00010C3A jsr sub_10ECA
ROM:00010C40 lea ($FFE400).l,a0
ROM:00010C46 movea.l a0,sp
ROM:00010C48 move a0,usp
ROM:00010C4A move.b #$40,($FFFA41).l ; '@'
ROM:00010C52 move.w #$2FFF,($FFFA44).l
ROM:00010C5A move.w #$20A,($FFFA46).l
ROM:00010C62 move.w #$FFC1,($FFFA50).l
ROM:00010C6A move.w #$3830,($FFFA52).l
ROM:00010C72 move.w #$FFC1,($FFFA54).l
ROM:00010C7A move.w #$5830,($FFFA56).l
ROM:00010C82 jsr sub_120B4
ROM:00010C88 jsr sub_10CFA
ROM:00010C8E btst #1,($FFE50C).l
ROM:00010C96 beq.s loc_10CA4
ROM:00010C98 jsr sub_3E000
ROM:00010C9E jsr sub_3E0DA
ROM:00010CA4
ROM:00010CA4 loc_10CA4: ; CODE XREF: MAIN_LOOP?+8Ej
ROM:00010CA4 jsr sub_10F6C
ROM:00010CAA jsr sub_10FD2
ROM:00010CB0 jsr sub_11EAE
ROM:00010CB6 jsr sub_10FF6
ROM:00010CBC jsr sub_11FD6
ROM:00010CC2 jsr sub_11FAA
ROM:00010CC8 jsr sub_11F78
ROM:00010CCE moveq #$FFFFFFFF,d0
ROM:00010CD0 move.l d0,d1
ROM:00010CD2 move.l d0,d2
ROM:00010CD4 move.l d0,d3
ROM:00010CD6 move.l d0,d4
ROM:00010CD8 move.l d0,d5
ROM:00010CDA move.l d0,d6
ROM:00010CDC move.l d0,d7
ROM:00010CDE movea.l d0,a0
ROM:00010CE0 movea.l d0,a1
ROM:00010CE2 movea.l d0,a2
ROM:00010CE4 movea.l d0,a3
ROM:00010CE6 movea.l d0,a4
ROM:00010CE8 movea.l d0,a5
ROM:00010CEA movea.l d0,a6
ROM:00010CEC jsr sub_1332C
ROM:00010CF2 jsr sub_135DA
ROM:00010CF8 rts
ROM:00010CF8 ; End of function MAIN_LOOP?

Katvis
12th July, 2010, 08:06 PM
thank you again Alexics for your time and advise, I really appreciate it. The information is not enough and I think I will try and get a second DME and remove the components and see if I can find more data on the underside of the chips. I really need the pin outs that I can trace it back to the CPU and know which pin does what pin for pin

An update of where I am at the moment..;)

I have connected the Wiggler BDM interface to the ECU and at first I used the for free OCD commander supplied on Macraigor site. The debugger works perfectly but I found that I needed more information, I guess I am still spoiled by the windows debuggers..;) Next I searched for software that could work with the wiggler interface, it seems like there are not many options, the one I chose to use at the moment is the ICD32Z debugger program. This program shows all the registers, one can monitor the memory area and single step or step till a given address. The program lacks a few functions which would be nice to have but for the price I am happy for now, again, if I need more I have to pay more.

http://i895.photobucket.com/albums/ac152/coenraadg/DME/Debugger.jpg

The code seen in the debugger is exactly what I expected to see because this is the code that IDA showed as well. This code in the debugger also ties in with my explanations of the vector tables and entry point in the program posted earlier in this thread.

I have bought a digital oscilloscope to monitor the sensors on the engine. My ultimate goal still is to simulate the sensors to have a bench setup of a "running engine". Here are two pics of the crankshaft sensor and the exhaust camshaft position sensor. One can see on the crankshaft that the pulse train is 60 pulses per rotation with a position pulse missing at 60 to indicate TDC.

http://i895.photobucket.com/albums/ac152/coenraadg/DME/RevCam3.jpg

http://i895.photobucket.com/albums/ac152/coenraadg/DME/RevCam2.jpg

Where I am at the moment is as follows. I have setup the DME on the bench with a power supply connected and also a switch to simulate the ignition switch. I also have connected a LED to show the fuel pump request. I have done this as I know the fuel pump comes on briefly when you switch the ignition on and this is a good starting point for me to trace code and get familiar with the code and debugging. At the moment when I switch the power on to the DME my fuel pump LED lit for two seconds and then switch off. If I switch the ignition switch to start the fuel pump LED lit as well but as soon as I switch the ignition "start" off the fuel pump LED goes off. This is because the fuel pump does not operate if the engine is not running. When I looked at the crankshaft signal I saw that the frequency matched the revolutions of the engine, that is 800 RPM = 800Hz, 2000RPM = 2kHz etc etc. I then bought a cheap signal generator kit and tried to simulate the engine speed to the DME. With the signal generator switched on with a frequency of for example 800Hz and the "ignition start switch in the off position" the fuel pump LED stays lit. This was a positive sign for me but when I tried to see the RPM with INPA it did not show any RPM's? I think this is because the blank pulse is not present in my signal generators pulse train?

Last night I traced the code and tried to establish where the fuel pump LED get its signal and tried to see how the output of the CPU works. This proofed to be not as easy as I though even when I studied the trace code when the LED lit up. This led me back to the 68376CPU documentation and found the part where it gets described how the CPU manipulates the outputs of in this case the TPU outputs. This is a very steep learning curve and I am still trying to get my head around the exact method but I will study the papers tonight and try my luck again tomorrow..;)

I am still waiting for my small package BDM connectors and will post pics as soon as the connectors are soldered on the pc board.

Cheers
C

alexics
12th July, 2010, 08:39 PM
You said

I think this is because the blank pulse is not present in my signal generators pulse train?


I think you are right there and a proper simulation is going to be difficult. I am very interested in how you get on with this so keep me posted. If I can help further let me know.

Katvis
24th July, 2010, 08:15 PM
Hi guys
I have used the CrankWheelPulser utility to create the pulse train and boosted the voltage level through a normal desktop speaker system to 9Volts. I still cannot see the RPM values in INPA. I have connected a temperature sensor on the bench DME and can see the ambient temperature in INPA. I do not know yet why the RPM does not show in INPA. I have tried to modify the pulse signal as follows but still no luck.

Zero pulse as created by crankwheelpulser:

http://i895.photobucket.com/albums/ac152/coenraadg/DME/Pulsebeforemodify.jpg

Pulse modified with audacity:

http://i895.photobucket.com/albums/ac152/coenraadg/DME/ZEROpulse.jpg

The DME does see the pulse train because as soon as I switch the pulse train on the fuel pump switch on and stays on until I switch the pulse train off.



I have also received my BDM connector and soldered it on CPU1 side.

http://i895.photobucket.com/albums/ac152/coenraadg/DME/BDMconnector.jpg



I have traced the code until I found the place where the fuel pump gets switched on.


000276F0 RTS
000276EC MOVEM.L (A7)+,A2-A5
000276E6 MOVE.W (A3),(0FFE7D6).L
000276E2 LEA (24,A7),A7
00012F1A RTS
00012F18 MOVE.L (A7)+,D2
00012F12 MOVE.L D0,(0FFFE1C).L ;When this line executes the fuel pump switch on
00012F10 OR.L D2,D0
00012F0A AND.L (0FFFE1C).L,D0
00011660 RTE
0001165C MOVEM.L (A7)+,D0-D1/A0-A1
00011654 BNE.B 1165C
0001164E SUBQ.B #1,(0FFE50A).L
0001164A MOVE.W #2700,SR


In the above code I have commented where the fuel pump switch on. The problem I had when tracing the code was that while tracing the code there were exceptions happening. At first I thought this exceptions had something to do with the fuel pump code but when I traced the code for the exceptions I realized that it was exceptions from the CTM4 circuit. The fact that exceptions occur when one trace the code does make life more difficult as one has to trace through a lot of unnecessary code.

I do not know yet how the exceptions are raised. When I read the documentation there are descriptions and one can see the vector table entries addresses but I do not know yet exactly how and if I can read and trace the disassembled code and see the event that trigger an exception or if the exception is purely raised by timer events, or external requests. I would really appreciate if somebody with embedded CPU32 programming experience can give me some advise?

I really find that the software that I use has its limitations for tracing through code but the next level of software are really expensive, might be an option if I feel I can not manage with the current software.

Furthermore I have bought software that can read the software of the memory chip through the BDM interface. This helps a lot as I have the software that is on the DME that I play with now and it makes it much easier to follow the code addresses. Only problem was that the software was read as a S19 file, fortunately IDA recognise S19 files and the disassembly was perfect.

The next week or so I will spend studying some more reference manuals and try and get a clearer understanding of exactly how for instance the PWM pins are controlled. I have found the place in the software where for instance one of the Vanos solenoids are controlled but I need to trace through the code and see exactly how and where the values for Pulse width and period are created and set:


seg000:00028000 PWM5_load_registers: ; CODE XREF: sub_277B4+1ACp
seg000:00028000 ; sub_277B4+1C4p ...
seg000:00028000
seg000:00028000 arg_2 = 6
seg000:00028000 arg_6 = $A
seg000:00028000
seg000:00028000 move.w arg_2(sp),($FFF42C).l ; PWM Pulse width register
seg000:00028000 ;
seg000:00028008 move.w arg_6(sp),($FFF42A).l ; PWM Pulse Period register
seg000:00028008 ;
seg000:00028010 btst #3,($FFEBAE).l
seg000:00028018 bne.s locret_28036
seg000:0002801A btst #6,($FF81D5).l
seg000:00028022 bne.s locret_28036
seg000:00028024 btst #6,($FF81D7).l
seg000:0002802C bne.s locret_28036
seg000:0002802E ori.w #%100000,($FFF428).l ; enable load of pulse width and period registors in PWM output wave

seg000:00028036 rts
seg000:00028036 ; End of function PWM5_load_registers


Not suprisingly thought this subroutine gets traced back to a exception that gets raised to get here.

Thats it for now, as always, any advise and help will be appreciated..;)
Cheers

alexics
24th July, 2010, 10:55 PM
Have you identified the main program loop. I would start from that point. I would guess that there would be subroutine tables and flags to switch execution of handler routines on dependant upon certain conditions. Flags set in these routines will trigger the exceptions. Usually if external signals are missing you will get an exception. If you can't simulate all the inputs the system expects then repeated exceptions will occur. These may be caused also by the fuel pump activation when some other critical engine specific input is missing.

Can you trace through and document the exception vectors? Are they system or user defined?

Katvis
24th July, 2010, 11:35 PM
Hi Alexics
As always you give good advise..;)
I have found the main routine, there are a lot of JSR routines and from which I can follow there are a few subroutines for setting up the different modules of the 68376 CPU.

I have commented a few lines as follows:

ROM:00010C08 MAIN_LOOP: ; CODE XREF: sub_3072-2E48p
ROM:00010C08 ; sub_11068+40j
ROM:00010C08 lea (dword_10000).l,a0
ROM:00010C0E movec a0,vbr
ROM:00010C12 move.w #$4046,($FFFA00).l ; If bit no 6 in SIMCR - Module Configuration Register = 1,
; Internal modules are addressed from $FFF000 to $FFFFFF
; 0100 0000 0100 0110
ROM:00010C1A move.w #$D200,($FFFA04).l ; The SYNCR determines system clock operating frequency
; SYNCR - Clock Synthesizer Control Register
; page 51 SIMRM
; 1101 0010 0000 0000
; == 11534kHz
ROM:00010C22 move.b #$BD,($FFFA21).l
ROM:00010C2A move.b #$55,($FFFA27).l ; 'U'
ROM:00010C32 move.b #$AA,($FFFA27).l
ROM:00010C3A jsr sub_10ECA
ROM:00010C40 lea ($FFE400).l,a0
ROM:00010C46 movea.l a0,sp ; set supervisor stack pointer and
; user stack pointer to FFE400
ROM:00010C48 move a0,usp
ROM:00010C4A move.b #$40,($FFFA41).l ; '@'
ROM:00010C52 move.w #$2FFF,($FFFA44).l ; 10 11 11 11 11 11 11
ROM:00010C5A move.w #$20A,($FFFA46).l ; 10 0000 1010
ROM:00010C62 move.w #$FFC1,($FFFA50).l
ROM:00010C6A move.w #$3830,($FFFA52).l
ROM:00010C72 move.w #$FFC1,($FFFA54).l
ROM:00010C7A move.w #$5830,($FFFA56).l
ROM:00010C82 jsr sub_120B4
ROM:00010C88 jsr sub_10CFA ; SIM....
ROM:00010C8E btst #1,($FFE50C).l
ROM:00010C96 beq.s loc_10CA4
ROM:00010C98 jsr sub_3E000
ROM:00010C9E jsr sub_3E0DA
ROM:00010CA4
ROM:00010CA4 loc_10CA4: ; CODE XREF: MAIN_LOOP+8Ej
ROM:00010CA4 jsr sub_10F6C
ROM:00010CAA jsr sub_10FD2
ROM:00010CB0 jsr sub_11EAE ; QADC...
ROM:00010CB6 jsr TPU_INIT ; TPU init?
ROM:00010CBC jsr CTM4_Init ; CTM (PWM) init
ROM:00010CC2 jsr sub_11FAA ; QSM....
ROM:00010CC8 jsr sub_11F78 ; QSM.....


The fuel pump is switched on/off by the TPU module, I know this because the output pin used for the fuel pump is in the TPU module. The TPU configuration register shows to address 100C0 as the first vector for the TPU, I have assumed that the next 15 vectors are for the TPU as well? This I do not know for sure, the reason why I doubt is that three of the vectors shows to the reset routine...? Unless that three vector addresses never get used in the code. The thing about the vector address is that it only shows twice in the IDA disassembly, once in the vector table and once in the routine that shows to the vector table entry. So I guess what I am asking is how and where does the exception for a specific address gets raised if the vector number never gets addressed anywhere in the code?

On page 68 of the 68376 Reference Manual it shows the vector table used by the CPU, so I guess it is system generated but addressed through code?

Below is the vector address that gets pointed to by the TPU control register:

seg000:000100C0 dc.l loc_11690 ; TPU 0 Interupt Vector
seg000:000100C4 dc.l sub_11662
seg000:000100C8 dc.l sub_116BE
seg000:000100CC dc.l sub_116EC
seg000:000100D0 dc.l sub_1171A
seg000:000100D4 dc.l sub_11748
seg000:000100D8 dc.l sub_11776
seg000:000100DC dc.l sub_117A4
seg000:000100E0 dc.l sub_117D2
seg000:000100E4 dc.l sub_11800
seg000:000100E8 dc.l $11068 ;reset?
seg000:000100EC dc.l $11068 ;reset?
seg000:000100F0 dc.l sub_1182E
seg000:000100F4 dc.l $11068 ;reset?
seg000:000100F8 dc.l loc_118E4 ; possible PWM vector routine...?
seg000:000100FC dc.l loc_11912 ; TPU 15 Interupt Vector


I can definitely see some flags that gets used throughout all the sub routines, my next quest will be to try and identify the flags and try and see how they get used. I guess if I can identify some of the flags the code will read easier as well...;)

I have ordered a few books on CPU32 programming but they have not arrived yet, I hope to find some more information in the books.

Cheers

alexics
25th July, 2010, 12:02 AM
Have you got a listing of 11690? Also have you a full assembly listing with your comments so far? I may be able to put together a quick search and replace with comments so you could map port names and give meaningful names to flag setting values.

For instance if a register or port is ored with 01 you may want to change these to say start_fuel_pump instead of just 01. Only for reference to that port. Then add an associated comment to document that start_fuel_pump value is 01. This could allow entry of port value to search for, flag value to replace, name of value and comment to append. One operation could replace all instances and save an awful lot of time.

You will make mistakes but this function can also be used to correct them later.

alexics
25th July, 2010, 12:16 AM
Just so I am clear which way round are source and destination in the listing?

I see immediate values so source first, destination second?

alexics
25th July, 2010, 12:26 AM
On page 68 of the 68376 Reference Manual it shows the vector table used by the CPU, so I guess it is system generated but addressed through code?

It depends, for illegal instruction exception it will be microcode in the processor. Watchdog timers trigger on timeout. Other exceptions may depend upon data being present or absent on a port. Some exceptions will be the result of problems and be used to set fault codes that diagnostics will pick up.

What protocol does the unit use? Canbus, k-line or other?

MMichael
9th August, 2010, 12:23 AM
The ecu is connected by canbus to the ABS/DSC unit and some other units. Afaik the engine wont start or operate in safe mode if the is no canbus present. It uses k-line for external diagnosis tools.

Katvis
9th August, 2010, 05:06 AM
very interesting, thank you for this, I will unplug my cars canbus and see if the engine still starts, thanks for the tip
cheers
k

MMichael
9th August, 2010, 07:04 PM
I would like to help. I have some experience with assembler but only with microchip asm so far. After reading some of the mc68337 doc i slowly know whats going on.


ROM:00010C2A move.b #$55,($FFFA27).l ; 'U'
ROM:00010C32 move.b #$AA,($FFFA27).This resets the watchdog timer , right ?

Are there subroutine(s) witch addresses the can interface ($FFF080-$FFF0A6)? Can you post the disassembled listing of that?

alexics
9th August, 2010, 08:18 PM
I would like to help. I have some experience with assembler but only with microchip asm so far. After reading some of the mc68337 doc i slowly know whats going on.

This resets the watchdog timer , right ?

Are there subroutine(s) witch addresses the can interface ($FFF080-$FFF0A6)? Can you post the disassembled listing of that?

To simulate the canbus you will need a can interface. I have a contact for these. Also is it 11 bit or 29 bit ids. I think volvo are 29 bit others 11 bit.

The k-line will either have a slow or fast init but not both IIRC. Could be either 5 baud or 200 baud for slow and 10400 for fast so find the baud rate registers first for this. You should find k-line interface schematics through a search on DK. The l-line is not normally used but may be in this case be check for both.

alexics
9th August, 2010, 08:28 PM
Just a though. Look for the format of the keep alive packet on the k-line. After several seconds of no comms the ECU will assume no connection and drop back to slow baud.

Of you need any pointers on packet structure and response codes let me know.

BTW The theoretical buffer length for k-line transmission is 255 but in practice may be much less.

MYTO8
10th August, 2010, 02:44 PM
JimStim MegaSquirt Stimulator with Wheel Simulator - Assembled DIYAutoTune.com (http://www.diyautotune.com/catalog/jimstim-megasquirt-stimulator-with-wheel-simulator-assembled-p-178.html)
This device may be of interest its cheap simple and effective

I use one of these on my test bench to help with disassembly can simulate crank trigger patterns iac coolant sensors etc.

Good luck

Katvis
13th August, 2010, 12:00 AM
I would like to help. I have some experience with assembler but only with microchip asm so far. After reading some of the mc68337 doc i slowly know whats going on.

This resets the watchdog timer , right ?

Are there subroutine(s) witch addresses the can interface ($FFF080-$FFF0A6)? Can you post the disassembled listing of that?

Hi guys
Thank you very much for all the advise...;)
I do not think the CAN will influence the working of a test bench at all. For me the purpose of reverse engineering is exactly this, to disable the CAN if it will prevent the test bench setup to start...

I must admit this project is way more difficult than what I thought. When I saw the initial 256k code I thought this could not be diffilcult, get a successful disassembly and read through the code, remember I am used to windows reverse engineering.

Then I started to read the CPU32 instruction set, I started to study the MC68376 documentation and the more I read and study the more I realize how much study it will take to read the code like a book. I still belive it should be easy enough for an experienced embedded programmer to read the code and get to the relevant pieces of code quite easy. For me that knew absloutely nothing about CPU32 before I started this project it is a steep study curve, but everyday that past I know more than the day before so all in all I see progress...;)

So no, I have not commented a lot of code yet, I started to comment all the initial setup code of the various modules of the CPU chip but have not finished it yet.

I am not at a stage yet where I can comment a piece of code, for instance, look for CAN, do not see CAN and fail to start engine. Of course this will be first price eventually, not disabling the CAN but understanding the code to such a degree.

At the moment it is "priority" to understand the interupt sequence and the way interupts work. I do not think it will make the code read easier as such, for me it is a challenge to understand how the engine gets controlled apart from understanding exactly how the CPU works.

So yes, I saw the sequence of the bytes to reset the watchdog but I do not even know what the watchdog does..;( I have ordered a few books explaining the CPU32 and the 68k family of processors and I hope to learn more from it.

At the same time we are busy to design and build a bench simulator to simulate various functions of the engine. I had a look at the engine simulator but the problem with the one given above is that it is not adequate enough to simulate the S62 engine. Keep in mind the S62 engine use four vanos valves, four CPS sensors, two water temperature sensor, etc etc and various engine components to monitor the working of the engine and if any of this components give a false reading the DME will revert to some or the other safe mapping mode or one of three or is it four limp home modes. Now the challenge is to build a simulator to fool the MSS52 to think it is attached to a fully working engine.

In the mean time work keeps me too busy lately and my progress is slower than what I would like, but like a good friend of mine say, slow and steady wins the race, so onwards I go.

Thanks for all the input, I really appreciate it
Cheers

Katvis
14th August, 2010, 01:17 AM
Here is the BIN file that I work with at the moment, please note this is only one CPU file, the other CPU has its own file and controls different parts of the engine.

Use IDA with the Motorolla 68k selected as processor to disassemble.

Cheers

oldford
15th August, 2010, 09:02 AM
A watchdog is a device/chip that checks if the software is working correctly - at least that it has not run-away, crashed or hangs in a indefinite loop. The way it works is you have to kick the watchdog (write the sequence) periodically or it will kick you (perform a hard reset).

BMW has a different approach to communications on the K-line. There's no timeout. Also there's no initialization.
You just ask what you want to know without bothering with initialization or timing.
Also, BMW has 2 versions of the KW2000 protocol. One with 8 bits no parity and 10K4 baud.
The other (older) version has 8-bits WITH parity (I think even, have to check) and 9600 baud.

ipejasinovic
15th August, 2010, 11:14 AM
Also, for BMW's is characteristic XOR check-sum.

easytech
15th August, 2010, 03:11 PM
As an CKP and/or Cam signal generator I use a simple funktion generator
feeding an adress counter connected to an Eprom (I use a 2816). Then you can use the 8 data lines as output.
You fill the Eprom with some data to use one of the data lines you want.
In case of the MSS50-54 ecu only the CKP is enough to let it work, but you first have to disable the EWS.
This is in the code where also the fuel data is.

alexics
15th August, 2010, 05:26 PM
A watchdog is a device/chip that checks if the software is working correctly - at least that it has not run-away, crashed or hangs in a indefinite loop. The way it works is you have to kick the watchdog (write the sequence) periodically or it will kick you (perform a hard reset).

BMW has a different approach to communications on the K-line. There's no timeout. Also there's no initialization.
You just ask what you want to know without bothering with initialization or timing.
Also, BMW has 2 versions of the KW2000 protocol. One with 8 bits no parity and 10K4 baud.
The other (older) version has 8-bits WITH parity (I think even, have to check) and 9600 baud.

Well that's just sneaky and way off the ISO standard.

oldford
15th August, 2010, 06:04 PM
Who says you have to comply to ISO standards before 2001? And where does it say a factory protocol has to comply?
And say you have to comply. Who will check that? In Europe they don't even check whether or not a car complies to EOBD.
Look at 2004 and younger diesels. MIL is on, you restart the car, and the code is "forgotten".
And no manufacturer has been fined or sanctioned for infringements like these.

And BMW is not the only one that doesn't comply.
ISO 9141 clearly states how the initialization should be done. It also specifies how many key bytes an ecu is allowed to send back. 2, 4, 6, 8, etc. just along as it's an even number. Why is Fiat using 5 key bytes?
Or a bit more modern - VAG's can protocol. That doesn't match anything published by the ISO or SAE.

Katvis
16th August, 2010, 02:43 AM
As an CKP and/or Cam signal generator I use a simple funktion generator
feeding an adress counter connected to an Eprom (I use a 2816). Then you can use the 8 data lines as output.
You fill the Eprom with some data to use one of the data lines you want.
In case of the MSS50-54 ecu only the CKP is enough to let it work, but you first have to disable the EWS.
This is in the code where also the fuel data is.

Is it at all possible to explain in more detail how we can do this please?

I have bought a 8 way signal generator but found the functionality was not enough to simulate a RPM which can varies and also change four CPS sensors where they should be.

I have read a article where somebody used a C167 to program a simulator but to be honest it will take me another year to learn how to program a simulaotr before I can continue with disassemblig the MSS52 and that is not my idea, hence the reason why we decided to use hardware at the moment.

If you can perhaps help us with the software version of the crankshaft sensor, let us control the RPM and position the four CPS sensors as well via a software signal generator that will be first price..:)


The DME that I have does have its matching EWS and key so I do not yet have to play with disabling the EWS, that is a project for much later.

Thanks again for all the advise
Cheers

oldford
16th August, 2010, 10:18 AM
How about this idea?
Get a trigger wheel like you have on the car. Connect it to an electric motor of which the rpm can be controlled.
Attach the camshaft trigger wheel with a 50% reduction of the rpm and use the standard sensors?

Katvis
16th August, 2010, 11:11 AM
How about this idea?
Get a trigger wheel like you have on the car. Connect it to an electric motor of which the rpm can be controlled.
Attach the camshaft trigger wheel with a 50% reduction of the rpm and use the standard sensors?


That is exactly what we are doing at this stage, but if an electronic simulator is available it would be nice to test.

Katvis
10th September, 2010, 06:35 PM
Some pictures from the test bench in construction:

"Vanos" solenoid arrangement

http://i895.photobucket.com/albums/ac152/coenraadg/Toetsbank/Vanossolenoids.jpg


Crankshaft sensor wheel

http://i895.photobucket.com/albums/ac152/coenraadg/Toetsbank/SensorwheelCPS.jpg


Modified idle control valve with needles for indication:

http://i895.photobucket.com/albums/ac152/coenraadg/Toetsbank/ICV2.jpg


Faceplate, still await missing items in mail:

http://i895.photobucket.com/albums/ac152/coenraadg/Toetsbank/Faceplate.jpg


Rear view of two boxes, sensor wheel runs horizontal in bottom box:

http://i895.photobucket.com/albums/ac152/coenraadg/Toetsbank/Backview.jpg



I am still waiting for some spares from the engineering shop and will post more pics once I receive them.

Cheers

Katvis
18th September, 2010, 03:32 PM
Here are some more pics and update on the working of the simulator:

Picture showing the assembled solenoids with camshaft sensor disc as well as CPS sensor:

http://i895.photobucket.com/albums/ac152/coenraadg/Toetsbank/SolenoidsplusCPS.jpg


Updated picture of the control panel, just a few bits left to go in:

http://i895.photobucket.com/albums/ac152/coenraadg/Toetsbank/Controlpanel.jpg


Throttle position sensor, throttle valve actuator plus idle control valve in place:

http://i895.photobucket.com/albums/ac152/coenraadg/Toetsbank/ICV_TPS_TVA.jpg


Power supply plus motor speed controller:

http://i895.photobucket.com/albums/ac152/coenraadg/Toetsbank/Powersupplyspeedcontrolller.jpg


Most of the spares are fitted now, I am still waiting for the three throttle position potentiometers to arrive which will complete the hardware and then I can test the complete workings.

At the moment I can not "start" the "engine" without hot wire. If I hot wire the circuit the motor runs and I can check running parameters. With the propper sensor wheel in place INPA does indicate the correct RPM through the OBD II diagnostic port.

I have setup up the timing of the camshaft discs as well by using DIS display of the camshaft positions, if I manually control the solenoids I can even simulate a successful vanos test..;)

There are still a few error codes at the moment, mostly the CAN bus errors and then the oil level sensor. I have a oil level sensor connected but the WDS explanation is that the oil level is just looped through the DME but the main feed is to the IKE.

My main concern at the moment is that I thought I will go into the code and trace the CAN bus routines and try and make the CAN believe that it saw the missing modules. First problem is that there are no CAN setup in the code...

I have both CPU chips BIN files and not in one of the BIN files is there any setup routines for the CAN bus. Next I traced the pins for CAN back to the PC board. I could get the CAN chip plus a second "82527 SERIAL COMMUNICATIONS CONTROLLER, :dontknow:CONTROLLER AREA NETWORK PROTOCOL" chip. This chip is connected to the CPU via address lines but there are no connections to the CAN TX and RX lines on the CPU chip.

Next I tried to trace the TX and RX lines of the two CAN lines from the CPU. I could not find any place that they connected to. The pins does have pc tracks on them but they appear not to connect to any components on the PC board? This is a bit confusing for me unless all the CAN bus routines are done through the above two chips?

Next I will try and trace the code where the CS lines are connected to the CPU and see when the chip is selected and try and figure out how the CAN is controlled.

Cheers

alexics
18th September, 2010, 10:29 PM
Is it a multi layered circuit board?

Katvis
19th September, 2010, 06:38 AM
Hi Alexics

Yes indeed it is a multi layered board. I have followed the tracks and tried to find the exit of the track on one of the surface components but could not find it anywhere yet... Like I said, the CAN lines from the DME connection goes to the CAN controller chip and from there it goes to the other CAN chip which is connected by address lines...

Do you know if it is possible to place components in between layers, like small capacitors? I tried to look at the board against a strong light but can not see any evidence of anything between layers?

What do you make out that there are no setup routines for the CAN bus in the BIN files anyway?

Cheers

MMichael
20th September, 2010, 12:32 AM
Katavis,

tumbs up for you ecu sim box !

I couldnt find any setup routines for the can interface aswell.

You found two CAN chips. So it sould be clear the one which is connected to the DME connection is the CAN transceiver. Usally a small SO8 device which converts from logic levels to can voltage levels.

The other CAN chip which is connected to the CPU is either a stand alone CAN bus controller or another Microcontroller with CAN controller. Do you have a datasheet for this chip ?

Components between layers: Have a look here. (http://www.izm.fraunhofer.de/Images/mls_tcm358-91220.pdf)
But i dont think its a issue here.

Did you try to sniff some can data from the dme? If you have a CAN inteface you might want to try if your interface is supported by Canhacker. (http://www.canhack.de/download/CANHackerV2.00.01.zip)

Katvis
20th September, 2010, 06:05 AM
Hi MMichael
Thanks you very much for the two links.

I think I made my mistake because all the time I believed that the CPU chip was a variant of the MC68376. This appears not to be true as I can not find any setup routines for the mask rom module as well. I still have a lot to learn and mistakes is part of the learning curve...;)

And you are correct, the small 8pin chip, PCA82C250 CAN controller interface, is the one connected to the DME pins and the input for this chip comes from a 44pin 82527 SERIAL COMMUNICATIONS CONTROLLER, CONTROLLER AREA NETWORK PROTOCOL. I do have the data sheets for both chips and will do some more tracing today.

I have downloaded the CANHacker and will give it a try as well, thanks for this..;)

Cheers

schland86
20th September, 2010, 07:47 AM
Are you interested in original BMW Datafiles?

Which are used with original BMW WinKFP Software to update complete DME Data.

In folder of MSS52 there are 2 kinds of files. *.0PA which i think is Program. *.0DA which i think is just the data field (Kennfeld)

Programming of DME chips work in ASCII Mode, i did not find out exactly, but a lot, file looks like this:


$REFERENZ 211321001601 N
:020000020000FC
:0200000400D02A
:1000000000000000000002000001106800011068FC
:1000100000011068000110680001106800011068FC
:1000200000011068000110680001106800011068EC
:1000300000011068000110680001106800011068DC
:10004000000110680001161C0001196E0001194022
:1000500000011068000110680001106800011068BC
.....
.....
:10FFA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61
:10FFB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51
:10FFC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41
:10FFD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31
:10FFE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21
:10FFF010FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01
:020000020000FC
:020000040000FA
:001D501083
$CHECKSUMME 3E88 A
;$CARB_MODE_9_CVN 069A3FA4 X
:00000001FF


lets take a data line like:

:1000000000000000000002000001106800011068FC

:1000000000000000000002000001106800011068FC

The first 8 chars are the address, and the last 2 are XOR Checksum of the Blue data line, each lines has 16 bytes.
It seems WinKFP konverts the text HexDump into real data when updating a DME software

Maybe you find out something, i extracted all the blue data, but i couldn't do anythin with it :( WinOLS did not helped, maybe they are encoded with a checksum or something...

Here is original Dataset from WinKFP:
RapidShare: 1-CLICK Web hosting - Easy Filehosting (http://rapidshare.com/files/420089976/BMW_MSS52.rar)

one Number is on ZSB (Zusammenbaunummer) and means different version (with cat support, without cat support etc)...
you can look in the oem catalog to see whicht fits

alexics
20th September, 2010, 07:33 PM
Hi Alexics

Yes indeed it is a multi layered board. I have followed the tracks and tried to find the exit of the track on one of the surface components but could not find it anywhere yet... Like I said, the CAN lines from the DME connection goes to the CAN controller chip and from there it goes to the other CAN chip which is connected by address lines...

Do you know if it is possible to place components in between layers, like small capacitors? I tried to look at the board against a strong light but can not see any evidence of anything between layers?

What do you make out that there are no setup routines for the CAN bus in the BIN files anyway?

Cheers

What you need to find are port routines in general. Usually code will and or xor values to the ports. For an 8 bit i/o port each output can control different things. If you can identify a bank of addresses that always seem to use ands or xors to set or clear individual bits then it is likely to be i/o related.

MMichael
21st September, 2010, 06:58 PM
Katvis,

Did you found the exact type of cpu? According to this list (http://www.cpu-world.com/info/Motorola/Custom-parts.html) its a custom Motorola CPU.

See the attached .pdf for some CAN basics, particularly pay attention to the can bus termination. Check if your DME has CAN bus resistors integrated. If you want to sniff from can bus you have to make sure the can bus is terminated right.


Alexis,

now i now what the chip select pins are for. I found some setup routines which setup the EBI(external bus interface), some are 8bit wide some are 16bit. They have base adresses and blocksize.

alexics
21st September, 2010, 08:37 PM
Katvis,

Did you found the exact type of cpu? According to this list (http://www.cpu-world.com/info/Motorola/Custom-parts.html) its a custom Motorola CPU.

See the attached .pdf for some CAN basics, particularly pay attention to the can bus termination. Check if your DME has CAN bus resistors integrated. If you want to sniff from can bus you have to make sure the can bus is terminated right.


Alexis,

now i now what the chip select pins are for. I found some setup routines which setup the EBI(external bus interface), some are 8bit wide some are 16bit. They have base adresses and blocksize.

In this definition the busses use source, length then target which would throw most people. Usually it is length first 8x source target. Have you any example code for the setup routines? Do any other i/o port show up there?

MMichael
23rd September, 2010, 08:08 PM
loc_25C:
lea ($FFE500).l,a0
movea.l a0,sp
move a0,usp
move.w #$C046,($FFFA00).l ;SIM CONFIGURATION REGISTER (SIMCR)
move.w #$D200,($FFFA04).l ;SYNTHESIZER CONTROL REGISTER (SYNCR)
move.b #$BD,($FFFA21).l ;SYSTEM PROTECTION CONTROL (SYPCR)
move.b #$55,($FFFA27).l ; 'U' ;Software Watchdog Service Register(SWSR)
move.b #$AA,($FFFA27).l ;reset wachdog, write $55 $AA to SWSR
move.l #$FFE000,($FFFB44).l ;RAM Array Base Address Register High (RAMBAH)
clr.w ($FFFB40).l ;RAM Module Configuration Register (RAMMCR)
move.w #$FFC1,($FFFA50).l ;CHIP-SELECT BASE ADDRESS REGISTER 1 (CSBAR1)
move.w #$3830,($FFFA52).l ;CHIP-SELECT OPTION REGISTER 1 (CSOR1)
move.w #$FFC1,($FFFA54).l ;CHIP-SELECT BASE ADDRESS REGISTER 2 (CSBAR2)
move.w #$5830,($FFFA56).l ;CHIP-SELECT OPTION REGISTER 2 (CSOR2)
jsr (sub_478).l
jsr (sub_3CA).l



sub_3CA:
move.w #$411,($FFFA22).l ;PERIODIC INTERRUPT CONTROL REGISTER (PICR)
move.w #$2FFF,($FFFA44).l ;CHIP-SELECT PIN ASSIGNMENT REGISTER (CSPAR0)
move.w #$20A,($FFFA46).l ;CHIP-SELECT PIN ASSIGNMENT REGISTER (CSPAR1)
move.w #5,($FFFA48).l ;CHIP-SELECT BASE ADDRESS REGISTER BOOT (CSBARBT)
move.w #$7830,($FFFA4A).l ;CHIP-SELECT OPTION REGISTER BOOT (CSORBT)
move.w #5,($FFFA4C).l ;CHIP-SELECT BASE ADDRESS REGISTER 0 (CSBAR0)
move.w #$6030,($FFFA4E).l ;CHIP-SELECT OPTION REGISTER 0 (CSOR0)
move.w #$482,($FFFA58).l ;CHIP-SELECT BASE ADDRESS REGISTER 3 (CSBAR3)
move.w #$3830,($FFFA5A).l ;CHIP-SELECT OPTION REGISTER 3 (CSOR3)
move.w #$482,($FFFA5C).l ;CHIP-SELECT BASE ADDRESS REGISTER 4 (CSBAR4)
move.w #$5830,($FFFA5E).l ;CHIP-SELECT OPTION REGISTER 4 (CSOR4)
move.w #$FF80,($FFFA60).l ;CHIP-SELECT BASE ADDRESS REGISTER 5 (CSBAR5)
move.w #$7830,($FFFA62).l ;CHIP-SELECT OPTION REGISTER 5 (CSOR5)
move.w #$FF00,($FFFA64).l ;CHIP-SELECT BASE ADDRESS REGISTER 6 (CSBAR6)
move.w #$7AF0,($FFFA66).l ;CHIP-SELECT OPTION REGISTER 6 (CSOR6)
move.b #$40,($FFFA41).l ; '@' ;PORT C DATA (PORTC)
move.b #$C4,($FFFA11).l ;PORT E DATA (PORTE0)
move.b #$C4,($FFFA15).l ;PORT E DATA DIRECTION (DDRE)
clr.b ($FFFA17).l ;PORT E PIN ASSIGNMENT (PEPAR)
move.b #$19,($FFFA19).l ;PORT F DATA (PORTF0)
move.b #$11,($FFFA1D).l ;PORT F DATA DIRECTION (DDRF)
clr.b ($FFFA1F).l ;PORT F PIN ASSIGNMENT (PFPAR)
rts
; End of function sub_3CAChip select pin configuration (CSPAR1:CSPAR0)

CS4,CS3,CS2,CS1,CS0 : 16bit port select pin
CS10,CS7,CS6,CS5 : 8bit port select pin
CS8,CS9 : discrete output pin

So there are 5 16bit buses and 4 8bit buses.
One of the CS Pins should lead to the CAN chip.

WHY do some CS pins 'share' the same base adress ?!?!

BASE ADDRESS REGISTER BOOT & BASE ADDRESS REGISTER 0 :
$0 256 kbytes

BASE ADDRESS REGISTER 1 & BASE ADDRESS REGISTER 2 :
$FFC000 8 kbytes

BASE ADDRESS REGISTER 3 & BASE ADDRESS REGISTER 4 :
$48000 16 kbytes

BASE ADDRESS REGISTER 5:
$FF8000 2 kbytes

BASE ADDRESS REGISTER 6:
$FF0000 2 kbytes

Katvis
24th September, 2010, 02:34 PM
hi MMichael
Now this is very interesting, I spend most of yesterday to put all this in an excel file that I can view the relationship better. The way you put it makes a lot of things clearer, but why and how did you decide to place the three extra zero to the base address? for instance how did you get from FFC1h to FFC000h, I know the 1 indicates the block size but then you placed three more 000 at the end?

My way of thinking at the moment is to find out exactly how the code gets read from the eeprom memory chip. I have asked help elsewhere but I need more direction, call me a slow learner..;)

For instance, we know that at location BFFCh is a checksum result stored. So how does the value gets extracted or even placed at that exact address?

I have traced the AM29F200BB tracks and two CS's from the CPU are connected, CS0 which connects to the WE# pin43, and CSBOOT form the CPU is connected to OE# on the memory chip.

I have searched in IDA for the value of BFFCh and only one comes up in the code and then it is 4BFFCh.

This is advise that another guru has given me:


As far as addressing goes, the Flash is an external device. All
addresses will show up as double-word, which tells the MCU that the
address is external.

Lets take that checksum. The following command will load the
checksum from the flash, and place it into data register 0 (D0). In the
code, this will show up as:


MOVE.L $0000BFFC.L,D0.L

or something to that effect. At no time will you see:


MOVE.L $BFFC.W,D0.L

during a flash read, as this implies that the address is local in the
MCUs own memory map. $BFFC.W is actually $FFFFBFFC, which
would point to a RAM address, and not the flash. All reads from the
MCUs RAM are given as word length addresses. All external reads are
double word length addresses.


At the hardware level, the flash has its chip enable and output enable
tied to the MCUs address lines. In the MCU itself, you can configure
what parts of the memory map will be mapped to the flash chip, and
which lines are then set to the appropriate state during a flash chip
read. When the MCU accesses the flash, it will enable the chip, and
then read in the data thru the common 16-bit address bus shared by
the MCU, flash, DLC, and other chips. By default, there are certain
lines enabled when the MCU powers up, and these are tied to the CE
and OE of the flash chip. You can find out more by looking at the
datasheet for the MCU and flash chip, but from a coding standpoint, its
not necessary to understand all the details. What your mainly
concerned with is what hardware is mapped to what address.



The CPU chip is most likely a varient of the MC68336 chip, I go by this because most of the pins I traced was consistant with the 68336 pin out. I had a look at some other 160pin varients but none matched the pin out. I also had a look at the 68338 cpu as was suggested on the site you linked but the 68338 only has 144 pins. Like I said, at first I thought it was the 68376 varient but because of the lacking CAN setup routines and also no setup routine for mask rom module I am leaning more towards the MC68336 chip now.


I am not home anymore so the CAN routines have to wait a bit. I have ordered the CAN interface and will play with it when I get home in another four weeks time, thank you for the documentation, I will study it in the mean time.

Cheers

Katvis
24th September, 2010, 02:38 PM
What you need to find are port routines in general. Usually code will and or xor values to the ports. For an 8 bit i/o port each output can control different things. If you can identify a bank of addresses that always seem to use ands or xors to set or clear individual bits then it is likely to be i/o related.

still hunting for the code..;)

btw I found encouragement when I read your signature:)

MMichael
24th September, 2010, 09:53 PM
but why and how did you decide to place the three extra zero to the base address? for instance how did you get from FFC1h to FFC000h, I know the 1 indicates the block size but then you placed three more 000 at the end? The base address register holds 13bit msb of a 24 bit address (addr23:11), address bits 10:0 cant be defined !?

alexics
25th September, 2010, 07:49 PM
The base address register holds 13bit msb of a 24 bit address (addr23:11), address bits 10:0 cant be defined !?

Like selectors in an Intel Pentium. Base + offset, where the base is implied. In IDA can these bases be entered to ensure an accurate disassembly? I ask this because I have been out of the loop on this type of hacking for a while now. I really need to get IDA Pro. I keep saying it but never get round to it.

alexics
25th September, 2010, 07:53 PM
still hunting for the code..;)

btw I found encouragement when I read your signature:)

One thing to clarify. Often the port value will be read out into a register, then the bit masked before being written back. This happens mostly with control registers, Interrupt enable, port direction etc.

Katvis
26th September, 2010, 06:59 PM
I have done some more studying of the code. A while ago Alexics gave me advise regarding the sector values that the eeprom spec sheet give:



Sector A16 A15 A14 A13 A12
SA3 0 0 1 X X 32/16 08000h?0FFFFh
SA4 0 1 X X X 64/32 10000h?1FFFFh
Now if I understand correctly if the CPU wants to read from the eeprom it needs to address the eeprom sector and then the position in the sector, for instance, position 8000h which is the start of the MAPS, CURVES and CONSTANTS section will be addressed as $48000

I have commented a piece of code as follows:



seg000:000332AC moveq #0,d0
seg000:000332AE move.w ($4BFFC).l,d0 ; checksum number
seg000:000332B4 asr.l #8,d0
seg000:000332B6 move.b d0,(a2)+ ; move high order byte in (a2)
seg000:000332B8 move.b ($4BFFD).l,(a2)+ ; low order byte of checksum in (a2)
seg000:000332B8 ;
seg000:000332BE move.b ($48001).l,(a2)+ ; second byte in data section
seg000:000332BE ;
seg000:000332C4 move.b (byte_3A6E6).l,(a2)+ ; 3A6E6 = 1
seg000:000332CA clr.b (a2)+
seg000:000332CC move.b ($FFE540).l,(a2)+
seg000:000332D2 clr.b d2
seg000:000332D4
seg000:000332D4 loc_332D4: ; CODE XREF: sub_3323A+A2j
seg000:000332D4 clr.b (a2)+ ; clear 15 bytes, increase (a2) with every byte clear
seg000:000332D6 addq.b #1,d2
seg000:000332D8 cmpi.b #$E,d2
seg000:000332DC bcs.s loc_332D4
seg000:000332DE movea.l #$48006,a3 ; a3 == 48006
seg000:000332E4 clr.b d2
seg000:000332E6
seg000:000332E6 loc_332E6: ; CODE XREF: sub_3323A+B4j
seg000:000332E6 move.b (a3)+,(a2)+ ; write 15 bytes from location 48006 in memory, increase a3 and a2 after every instruction
seg000:000332E6 ; this according to my list is the series, engine type, etc etc bytes
seg000:000332E8 addq.b #1,d2
seg000:000332EA cmpi.b #$E,d2
seg000:000332EE bcs.s loc_332E6
seg000:000332F0 bra.w loc_333A4
Now that I know how the data is read from the eeprom I can do some more searching.

Some of the instructions can be very intimidating..;)
take for instance...?

Jmp (32570,PC,54*1) ;with PC = 3256C

and the result is jump to 325C4

Cheers

Katvis
5th October, 2010, 08:09 PM
hi again
I am trying to understand how the interrupts gets used. Reading from the reference manual it says that every module must have its own IABR value. If I write down all the IABR values and multiply it by 4 and add it to the VBR I get it as follows:


seg000:00010004 dc.l loc_200 ;reset ProgramCounter value
seg000:00010008 dc.l Reset_Routine
seg000:0001000C dc.l Reset_Routine
seg000:00010010 dc.l Reset_Routine
seg000:00010014 dc.l Reset_Routine
seg000:00010018 dc.l Reset_Routine ;SIM vector (6*4) FFFA00
seg000:0001001C dc.l Reset_Routine
seg000:00010020 dc.l Reset_Routine ;QSMR vector (8*4) FFFC00
seg000:00010024 dc.l Reset_Routine
seg000:00010028 dc.l Reset_Routine ;TPU vector (A*4) FFFE00
seg000:0001002C dc.l Reset_Routine
seg000:00010030 dc.l Reset_Routine
seg000:00010034 dc.l Reset_Routine
seg000:00010038 dc.l Reset_Routine ;QADC vector (E*4) FFF200
seg000:0001003C dc.l Reset_Routine
seg000:00010040 dc.l Reset_Routine
seg000:00010044 dc.l sub_118CA ;periodic interupt timer...? FFFA22
seg000:00010048 dc.l sub_11932
seg000:0001004C dc.l sub_11910 ;QSM vector FFFC04
seg000:00010050 dc.l Reset_Routine
seg000:00010054 dc.l Reset_Routine
seg000:00010058 dc.l Reset_Routine
seg000:0001005C dc.l Reset_Routine
seg000:00010060 dc.l sub_10FA6
seg000:00010064 dc.l sub_11976
seg000:00010068 dc.l sub_11954
seg000:0001006C dc.l Reset_Routine
seg000:00010070 dc.l Reset_Routine
seg000:00010074 dc.l sub_119A4
seg000:00010078 dc.l Reset_Routine
seg000:0001007C dc.l sub_119C6


now obvioulsy this is not right, anybody with advise?

alexics
7th October, 2010, 03:08 AM
hi again
I am trying to understand how the interrupts gets used. Reading from the reference manual it says that every module must have its own IABR value. If I write down all the IABR values and multiply it by 4 and add it to the VBR I get it as follows:


seg000:00010004 dc.l loc_200 ;reset ProgramCounter value
seg000:00010008 dc.l Reset_Routine
seg000:0001000C dc.l Reset_Routine
seg000:00010010 dc.l Reset_Routine
seg000:00010014 dc.l Reset_Routine
seg000:00010018 dc.l Reset_Routine ;SIM vector (6*4) FFFA00
seg000:0001001C dc.l Reset_Routine
seg000:00010020 dc.l Reset_Routine ;QSMR vector (8*4) FFFC00
seg000:00010024 dc.l Reset_Routine
seg000:00010028 dc.l Reset_Routine ;TPU vector (A*4) FFFE00
seg000:0001002C dc.l Reset_Routine
seg000:00010030 dc.l Reset_Routine
seg000:00010034 dc.l Reset_Routine
seg000:00010038 dc.l Reset_Routine ;QADC vector (E*4) FFF200
seg000:0001003C dc.l Reset_Routine
seg000:00010040 dc.l Reset_Routine
seg000:00010044 dc.l sub_118CA ;periodic interupt timer...? FFFA22
seg000:00010048 dc.l sub_11932
seg000:0001004C dc.l sub_11910 ;QSM vector FFFC04
seg000:00010050 dc.l Reset_Routine
seg000:00010054 dc.l Reset_Routine
seg000:00010058 dc.l Reset_Routine
seg000:0001005C dc.l Reset_Routine
seg000:00010060 dc.l sub_10FA6
seg000:00010064 dc.l sub_11976
seg000:00010068 dc.l sub_11954
seg000:0001006C dc.l Reset_Routine
seg000:00010070 dc.l Reset_Routine
seg000:00010074 dc.l sub_119A4
seg000:00010078 dc.l Reset_Routine
seg000:0001007C dc.l sub_119C6
now obvioulsy this is not right, anybody with advise?

I would do this differently. Each interrupt would end with a return from interrupt instruction. IRET or similar. From these points in the code it should be fairly easy to work backwards to find the start of the interrupt code. Noting all the entry addresses should give you a list that will correspond with the vector table, or at least with a jump table linked back to the vectors. This should be a better way to confirm that you have found the right position for the vectors on memory.

Katvis
7th October, 2010, 08:37 PM
I would do this differently. Each interrupt would end with a return from interrupt instruction. IRET or similar. From these points in the code it should be fairly easy to work backwards to find the start of the interrupt code. Noting all the entry addresses should give you a list that will correspond with the vector table, or at least with a jump table linked back to the vectors. This should be a better way to confirm that you have found the right position for the vectors on memory.

Hi Alexics
You are right, fortunately IDA does a very good job with the disassembly, I can easily see where the vectors start and where they end with a RTE (return from exception) command. IDA does list the entry points of all the exceptions as well as per my above extract from the code. The reason why I am trying to figure out how the exception table get generated is that most of the times when I trace a variable then I end up in a exception routine.

I have done a bit more reading and will try and figure it out again. I still believe the entry table gets generated by the values specified in the control registers of the various modules. Will give feedback once I know what is up.

Thanks
C

alexics
8th October, 2010, 10:12 AM
Hi Alexics
You are right, fortunately IDA does a very good job with the disassembly, I can easily see where the vectors start and where they end with a RTE (return from exception) command. IDA does list the entry points of all the exceptions as well as per my above extract from the code. The reason why I am trying to figure out how the exception table get generated is that most of the times when I trace a variable then I end up in a exception routine.

I have done a bit more reading and will try and figure it out again. I still believe the entry table gets generated by the values specified in the control registers of the various modules. Will give feedback once I know what is up.

Thanks
C

Sometimes for the purposes of code obfuscation an exception will be generated on purpose to frustrate debugging attempts. I am not saying this has been used here but through the use of timeouts an exception can be generated if a piece of code takes longer to execute than is expected. As breakpoints cause huge gaps in the execution cycle these timeouts would always occur. In which case careful placement of breakpoints would be the answer. I would check the various timer interrupts to see what flags are being set then identify if any are checked near to the points where exceptions are generated.

Katvis
4th November, 2010, 05:57 PM
update on the quest..;)

I have learned a lot the past few months but not without the help of some people who shared their time and effort with me, a big thank you to all of you..!

at the moment I have a disassembly which have all the major registers commented and some minor addresses as well. Already the code read easier but my big draw back is that I need a detail explanation of all the constants in the DATA section..;(

With a lot of effort one can find the major MAPS and CURVES in the data section but when it get to one byte constants it is not easy if possible at all. Unfortunately the code relies heavily on all the constants to check parameters etc etc

The test bench helps a lot to find memory locations of for instance the MAF values, the oxygen sensor inputs, the temperature sensor inputs etc.

One thing that I have learned is that one has to rely on the documentation if one wants to figure out for instance where the data for example the temperature sensors are stored and used.

One such module the QADC module has a memory map where all the results for the analogue to digital values are stored. So if one know that for example the MAFS use a 0-5V signal one would expect to find the conversion value in this memory space which indeed is true.

I have spend a lot of time to trace the pc tracks of the MSS52 but it is a very difficult task..;) I have made a basic excel file which is by no means complete with some of the output driver IC's named so that I can see which pin control which output function.

Once I have success to comment a piece of code which will make sense to read I will post again. At the moment I have only fragments of comments which does not say a lot yet..;)

Cheers

Katvis
20th November, 2010, 08:32 AM
I have done some work on the oxygen routines the past two days. I had a hard time understanding one of the subroutines so I went the way to program the routine in Easy68K. This way I could change the two input values and in the end I could see what the routine did..;) Great success for me..;)

Stack:000125BE arg_0 = 4
Stack:000125BE arg_4 = 8
Stack:000125BE arg_8 = $C
Stack:000125BE
Stack:000125BE movem.l d2-d5,-(sp)
Stack:000125C2 move.l $10+arg_0(sp),d2 ; calculated value of present Oxy reading
Stack:000125C6 move.l $10+arg_8(sp),d4 ; value of 8
Stack:000125CA move.l $10+arg_4(sp),d5 ; previous value of Pre_Oxy which was stored
Stack:000125CE tst.w d4 ; Compares the operand with zero
Stack:000125D0 beq.s loc_125F8 ; branch if D4 is zero
Stack:000125D2 move.w d2,d0 ; calculated value of Pre_Oxy1_reading
Stack:000125D2 ; Oxygen reading was multiplied by $45C and then the
result devided by 2^A ($400)
Stack:000125D4 ext.l d0
Stack:000125D6 move.w d5,d1 ; previous stored value of the Pre_Oxy reading
Stack:000125D8 ext.l d1
Stack:000125DA sub.l d1,d0 ; deduct stored value form current value
Stack:000125DC move.l d0,d3
Stack:000125DE moveq #0,d1
Stack:000125E0 move.w d4,d1 ; move the value which is 8 in D1
Stack:000125E2 divs.l d1,d0 ; devide the result of the difference between stored value
and newly calculated value by 8
Stack:000125E6 move.l d0,d2
Stack:000125E8 bne.s loc_125F6
Stack:000125EA tst.l d3 ; test D3 value against zero
Stack:000125EC ble.s loc_125F0 ; if value is negative, branch
Stack:000125EE moveq #1,d2 ; else move 1 in D2
Stack:000125F0 tst.l d3
Stack:000125F2 bge.s loc_125F6
Stack:000125F4 moveq #$FFFFFFFF,d2
Stack:000125F6 add.w d5,d2 ; if difference between the stored value and the
calculated value was negative then add FF to stored value
Stack:000125F6 ; else if difference was postive add 1 to stored value
Stack:000125F8 move.w d2,d0
Stack:000125FA ext.l d0
Stack:000125FC movem.l (sp)+,d2-d5
Stack:00012600 rts





Sometimes I think I try and understand too much but that is the way I am, I want to have the complete picture. I can quite easy decode the assembler once I know what to look for, what I still find hard is to understand the complete process...;)

At the moment I am still trying to figure out the FF8xxx memory space. The way I think this through is that once the CPU starts executing the assembler code it must follow a set path to get to all the values written in the memory space. So if in one routine the memory is cleared and in the next routine a value is called for from the same memory space SOMETHING must have put the new values there?

If I look at the pc tracks I can see that the data lines are all interconnected to all five memory devices. So basically what I am trying to understand is how to know which variable is stored in the FF8xxx memory space. I can see where the memory space gets cleared but not where the values get written back in the memory space.

What I suspect is that the memory space of FF8xxx gets access to values in the other memory spaces and this is where the values get read from.

So basically what I am trying to say is that every time the CPU starts up memory space FF81AC MUST know where to get its update from?

This code initialize the value to #$80, but in the next routine the value change all the time.
move.b #$80,(unk_FF81AC).l


So I guess what I am asking is how does for example memory space FF81AC KNOWS where to get its updated value from? There must be a way to figure this out because every time the CPU starts to execute the code FF81AC is a value for the same variable... It is my hope and understanding that if one can figure this out one can name most of the variables and read the code much easier.

Katvis
24th November, 2010, 01:55 AM
one of the subroutines that one will find a lot in the code is the call to retrieve a value from the MAPS or CURVES.

I have used 68000 Integrated Development Environment Homepage (http://home.kpn.nl/pj.fondse/ide68k/index.html) to test the code below and single step through the routine to see what is happening and to comment the code. This code was cut and paste from IDA and I just did a few tweaks to work with IDE68k.

The values in the CURVE below was taken directly from the real CURVE data form the MSS52 BIN file.



*Define CURVE values at memory location $2000
org $2000
Curve dc.w $0500 MAP or CURVE size, because this is a CURVE only we get 5 X 1 CURVE
dc.w $03E8 1000 RPM
dc.w $07D0 2000 RPM
dc.w $0BB8 3000 RPM
dc.w $0FA0 4000 RPM
dc.w $1194 4500 RPM
dc.w $012C
dc.w $01F4
dc.w $01F4
dc.w $01F4
dc.w $0000

RPM_Value dc.w $101D 4125 RPM
;RPM_Value dc.w $109A 4250 RPM
;RPM_Value dc.w $1117 4375 RPM


org $400 start of program (>= $400)

clr.l d0
move.w (RPM_Value),d0
move.l d0,-(sp)
pea Curve move the address location of the CURVE on the stack
jsr Get_value_from_curve_unsigned


Get_value_from_curve_unsigned ;TBLU

move.w #1,-(sp) offset stack with one word length
; placing a 1 here indicates we want a unsigned value from the Curve
bra loc_11138

Get_value_from_curve_signed ;TBLS

move.w #0,-(sp) if we enter the subroutine here we place a 0 on the stack which test later for
; signed or unsigned retrieval of value from Curve


loc_11138:

movem.l d2/a2,-(sp)
clr.l d0
movea.l $E(sp),a0 move CURVE address in A0
move.w $14(sp),d0 move RPM_value in D0
clr.l d1
move.b (a0),d1 how many values in axis, ie 5
lea 2(a0,d1.w*2),a2 load beginning address of look_up axis in A2
cmp.w 2(a0),d0 compare RPM value with first value in RPM axis
bhi loc_1115C branch if higher
move.w (a2),d0 ELSE move lowest RPM_value in table into RPM_value
bra loc_11198 and branch


loc_1115C:
cmp.w (a0,d1.w*2),d0 compare RPM_value to last value in RPM axis
bcs loc_1116C branch if less or the same
move.w -2(a2,d1.w*2),d0 ELSE move highest value in axis in RPM_value
bra loc_11198


loc_1116C:

cmp.w -(a2),d0 compare RPM_value to the value in A2 address
bcs loc_1116C branch if less or the same
; decrease A2 value by word size with every branch till match is found
; A2 now contains the lower boundry value where the RPM_value was found
clr.l d2
move.w 2(a2),d2 move next (upper) boundry value of RPM axis in D2
sub.w (a2),d2 get the difference between the two boundry axis values,
; RPM_value lies between this two addresses
sub.w (a2),d0 subtract lower boundry axis value from RPM_value
lsl.l #8,d0 multiply with $100 (256)
divu.l d2,d0 (RPM_value - lower boundry axis value)*256/difference between two axis values
;
tst.w $8(sp) test for signed or unsigned lookup
bne loc_11192 branch if not equal to zero
tbls.w (a2,d1.w*2),d0 place signed interpolated value in D0
bra loc_11198

loc_11192:
tblu.w (a2,d1.w*2),d0 place unsigned interpolated value in D0

loc_11198:

movem.l (sp)+,d2/a2 restore the stack
addq.l #2,sp get rid of the word size that we used for signed or unsigned test
rts return to subroutine with value in D0
; End of function get_value_from_curve_b2

I used different RPM values to test the value retrieved from the CURVE and every time it checked out good..;)

I have attach the ASM file if you guys want to play around with this routine.

Cheers

Katvis
25th November, 2010, 08:48 AM
Find below a routine to retrieve a value from a MAP:


*Define MAP values at memory location $2000
*This is real MAP values from KF_LA_NEG in MSS52 bin file:

org $2000
Map dc.w $0505 x axis and y axis size, ie 5 for X axis (columns) and 5 for Y axis (rows)

dc.w $02BC Column start address, ie 5 word values
dc.w $03E8
dc.w $07D0
dc.w $09C4
dc.w $0FA0

dc.w $003C Row start address, ie 5 word values
dc.w $00B2
dc.w $00D6
dc.w $012F
dc.w $01BD

dc.w $0400 lookup table start here, ie 25 byte values
dc.w $0202
dc.w $0004
dc.w $0707
dc.w $0E1A
dc.w $0408
dc.w $090B
dc.w $1D04
dc.w $0C0B
dc.w $111F
dc.w $050E
dc.w $0F15
dc.w $2300




RPM_Value dc.w $8CA ;2250 RPM
Table_lookup_value dc.w $D5 ;Value to lookup in MAP lookup table area



org $400 start of program at line 400


move.w (Table_lookup_value),d0
move.l d0,-(sp)
move.w (RPM_Value),d0
move.l d0,-(sp)
pea Map move the address location of the MAP on the stack
jsr Get_value_from_maps

clr.l d6
nop


Get_value_from_maps

move.w #1,-(sp) move 1 on stack for TBLU (unsigned) interpolation
bra loc_11388

move.w #0,-(sp) move 0 on stack for TBLS (signed) interpolation

loc_11388:

movem.l d2-d5/a2-a3,-(sp) this is not necessary but I want to keep the code
clr.l d0 as close as possible to the dissasembly
clr.l d1 1A Stack offset is calculated like this
;1 WORD value pushed on stack
;6 LONG values pushed on stack
;that is 6*4 + 2
;26 which is 1Ah
movea.l $1E(sp),a0 1A+4 to get passed the return address on the stack
;that is A0 now contains the MAP start location
;ie the first AXIS entries count
move.w $24(sp),d1 1A+A to get stored RPM_value
move.w $28(sp),d0 1A+E to get position to search for
clr.l d2
clr.l d3

;The next three instructions get the AXIS entry values amount. Each MAP starts with two BYTES
which indicate the AXIS entries count, both for X(first) and Y(second) axis.
move.b (a0),d2 how many values in first AXIS
move.l d2,d5 store first axis count
move.b 1(a0),d3 how many values in second AXIS
lea (a0,d2.w*2),a2 address of last value of FIRST axis into A2
cmp.w 2(a0),d1 compare RPM_value with first value in RPM AXIS
bcc loc_113BC branch if RPM_value is => than first entry value
move.w 2(a0),d1 ELSE if RPM_value is < than first entry in AXIS then set
RPM_value to first entry value
bra loc_113C4


loc_113BC:
cmp.w (a2),d1 compare RPM_value with last value in AXIS
bls loc_113C4 branch if lower and the same and continue
move.w (a2),d1 ELSE limit RPM_value to highest number in AXIS


loc_113C4:
cmp.w 2(a2),d0 compares table_lookup_value to search for with FIRST entry in
second AXIS
bcc loc_113D4 branch if greater and equal to
move.w 2(a2),d0 if table_lookup_value to search for is lower than first entry in
AXIS then set search value to first entry value, we dont want to search outside the MAP frame
bra loc_113E0


loc_113D4:
cmp.w (a2,d3.w*2),d0 compares table_lookup_value to search for with last entry in
ROW AXIS
bls loc_113E0 if lower or the same branch and continue
move.w (a2,d3.w*2),d0 ELSE limit value to search for equal to last entry in ROW AXIS


loc_113E0:
addq.l #2,a2 A2 points to first value in second AXIS
lea (a2,d3.w*2),a3 A3 points to first BYTE value in MAP results (Z) area
movea.l a3,a0


loc_113E8:
cmp.w -(a2),d1 A2 is pointed to the last value in the first AXIS
;step a WORD at a time back and try and find a match for
PRM_value
dbcc d5,loc_113E8 loop 5 times, D5 contains number of entries values in first AXIS
;if value is found A2 will contain the address of the match

loc_113EE:
cmp.w -(a3),d0 A3 points to last value in second AXIS
dbcc d3,loc_113EE loop 5 times, D3 contains number of entries values in second AXIS


subi.l #1,d5 subtract 1 from D5 value which contains the column count of
DBCC loop
subi.l #1,d3 subtract 1 from D3 value which contains the row DBCC count loop[/COLOR]
clr.l d4
move.w 2(a2),d4 move the address of the next word entry in the column where the
RPM_value was found in D4

sub.w (a2),d4 get the difference between the two boundry entries in the column
AXIS
;this is used for the scaling for the value retrieval

bne loc_11410 branch if not equal to zero
moveq #1,d4 ELSE if there was no difference move 1 into D4


loc_11410:
sub.w (a2),d1 get difference between RPM_value and lower boundry axis value
lsl.l #8,d1 multiply difference with $100 (#256)
divu d4,d1 devide result by difference between AXIS values where in between
RPM_value was found,


mulu.w d2,d3 multiply first AXIS column entry amount by second axis row
position where table_lookup_value was found

add.l d5,d3 add column value where RPM_value was found
move.l d1,d5 save the column scaling factor result in D5[/COLOR]


tst.w $18(sp) we have moved a 1 on the stack which indicated we want to
retrieve an unsigned value from the map
bne loc_11438 branch if not equal to zero
tbls.b (a0,d3.w),d1
add.l d2,d3
tbls.b (a0,d3.w),d5
bra loc_11446


loc_11438:
tblu.b (a0,d3.w),d1 A0 = start address of lookup table
;D3 = lower COLUMN boundary value in lookup table
;D1 = "scaling value" result for lookup table
;result in D1 = retrieved COLUMN interpolated value
;retrieved from between two lower COLUMN boundaries

add.l d2,d3 ;add lookup table width to lower ROW boundry where RPM value
was found in lookup table

tblu.b (a0,d3.w),d5 A0 = start address of lookup table
;D3 = higher boundry of ROW value in lookup table ;D5 = scaling factor
;result in D5 = retrieved COLUMN interpolated value
;retrieved from between two UPPER COLUMN

;Basically what we do is to get two column values from the MAP,
;then we find the ROW inerpolated value between that two COLUMN values


2BC 3E8 7D0 9C4 FA0
___________________________________________
3C 04 00 02 02 00
B2 04 07 07 0E 1A
D6 04 08 09 0F 1D
12F 04 0C 0B 11 1F
1BD 05 0E 0F 15 23

The value we are looking for lies in between the four green values



loc_11446:
clr.l d4
move.w 2(a3),d4 A3 upper boundry of ROW lookup value
D4 = ROW upper boundry value
sub.w (a3),d4 get difference between two ROW axis values
bne loc_11456
moveq #1,d4 if difference between ROW lookup axis values is zero, make it 1

loc_11456:
sub.w (a3),d0 subtract ROW lower boundry value from ROW lookup value
lsl.l #8,d0 multiply with $100 (#256)
divu d4,d0 devide by difference between two ROW axis values, (scaling)

tst.w $18(sp) do we want signed or unsigned result?
bne loc_1146E
tbls.b d1:d5,d0 D1: first position in ROW where value was found
D5: second position in ROW where value was found
bra loc_11472


loc_1146E:
tblu.b d1:d5,d0 D1: first position in ROW where value was found
D5: second position in ROW where value was found

loc_11472:
movem.l (sp)+,d2-d5/a2-a3 Restore the stack
addq.l #2,sp remove word value used for signed/unsigned indication
rts[/code]

Hotbmwm3
22nd March, 2011, 02:11 PM
This thread has amazing information, congratulations to all those involved. Has there been any more progress this year?

Katvis
22nd March, 2011, 02:23 PM
hahaha progress in which direction? yes I have worked a lot on the code, still do not know everything but enough to help myself

Deja5
29th April, 2012, 11:58 PM
You will need the datasheet and also a reference for the assembly language opcodes. I used to write disassemblers for hc05, hc11 and tms370. Not very complicated, about two screenfuls of code.

Hi Alexics

I'm trying to disassemble 9S12Hz128 with Ida Pro 6.1 and I use a usb multilink, but not get comunication with mcu(unsecured).
Please, could you help me how configure ida to connect with this mcu or some tutorial about.

Thank's
Dejair

alexics
8th May, 2012, 05:46 PM
What are you using to read the processor?

pako001
13th June, 2012, 01:41 PM
HI all,
I am also working on disassemble M5 E39 MSS52. I can attach winols map-pack for the data version 7837954 Is not complete but pretty well I think. May help

Katvis
14th June, 2012, 10:17 AM
Can you please attached the map pack, would help a lot of us, thanx

Katvis
27th June, 2012, 09:58 PM
One of the things which can take up a lot of time when working with BIN files is to manually work through the disassembly and tell IDA what is code or not. I have tried to write a small script to help, this is by no means complete and it does not work 100% as well but it will save you a lot of time.

The second modified and third script was written by a friend and I hope he wont mind me posting it here as well. So first run the "format data" script, it will take quite a while to complete, just imagine doing this by hand..! Wait until you see the message "END OF SCRIPT REACHED" in the output window.

Then run the "intvectors" and finally the "find jump tables" script.

What I have tried to do here is to convert known opcodes to code, for some or other reason the script still miss some of the opcodes but it should not take too much time to convert the missed ones, unless somebody can improve on the script code and post it here as well please:

Format data.idc

// Make good opcode CODE
#include <idc.idc>


static main()
{
auto ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en, eo, ep, eq, er, es, et, eu, ev ;
auto addr;
auto SegStart;
auto SegEnd;
auto count;


addr = 0;
ea = 0;
SegEnd = SegEnd(SegByName("ROM"));

for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

ea = (FindBinary(addr, 0x23, "48 E7")) ;
addr = ea;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

eb = (FindBinary(addr, 0x23, "4c DF")) ;
addr = eb;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

ec = (FindBinary(addr, 0x23, "20 6F")) ;
addr = ec;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

ed = (FindBinary(addr, 0x23, "2F 0A")) ;
addr = ed;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

ee = (FindBinary(addr, 0x23, "22 7C")) ;
addr = ee;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

ef = (FindBinary(addr, 0x23, "48 78")) ;
addr = ef;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

eg = (FindBinary(addr, 0x23, "4E 56")) ;
addr = eg;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

eh = (FindBinary(addr, 0x23, "20 7C")) ;
addr = eh;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

ei = (FindBinary(addr, 0x23, "4C 3C")) ;
addr = ei;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

ej = (FindBinary(addr, 0x23, "30 39")) ;
addr = ej;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

ek = (FindBinary(addr, 0x23, "4C DF")) ;
addr = ek;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

el = (FindBinary(addr, 0x23, "20 6F")) ;
addr = el;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

em = (FindBinary(addr, 0x23, "22 7C")) ;
addr = em;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

en = (FindBinary(addr, 0x23, "2F 0A")) ;
Message("%08lx en\n", en); //where BINARY were found
Message("%08lx 2f 0A REACHED\n", addr);
addr = en;
}
return;
addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

eo = (FindBinary(addr, 0x23, "4E 56")) ;
addr = eo;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

ep = (FindBinary(addr, 0x23, "48 78")) ;
addr = ep;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

eq = (FindBinary(addr, 0x23, "20 79")) ;
addr = eq;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

er = (FindBinary(addr, 0x23, "20 7C")) ;
addr = er;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

es = (FindBinary(addr, 0x23, "E3 46")) ;
addr = es;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

et = (FindBinary(addr, 0x23, "E3 40")) ;
addr = et;
}

addr = 0;
for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2)
{
MakeCode(ea);

eu = (FindBinary(addr, 0x23, "4A 39")) ;
addr = eu;
}
//ek = (FindBinary(addr, 0x23, "48 E7")) ;



Message("END OF SCRIPT REACHED\n", addr);
}


IntVectors.IDC

#include <idc.idc>


static Int_Reg(addr,comment)
{
MakeComm(addr,comment);
}

static main()
{
auto a;
auto b;
auto addr;
{
for (addr=SegStart(SegByName("ROM"));addr<=0x1ff;addr=addr+4)

MakeDword(addr);

Message("END OF BOOT REACHED\n", addr);
} //end Main


{
for (addr=(0x10000);addr<=(0x101ff);addr=addr+4)

MakeDword(addr);
}
Message("END OF CODE REACHED\n", addr);



Int_Reg(0x000, "Reset: initial stack pointer");
Int_Reg(0x004, "Reset: initial program counter");
Int_Reg(0x008, "Bus error");
Int_Reg(0x00C, "Address error");
Int_Reg(0x010, "Illegal instruction");
Int_Reg(0x014, "Zero division");
Int_Reg(0x018, "CHK, CHK2 instructions");
Int_Reg(0x01C, "TRAPcc, TRAPV instructions");
Int_Reg(0x020, "Privilege violation");
Int_Reg(0x024, "Trace");
Int_Reg(0x028, "Line 1010 emulator");
Int_Reg(0x02C, "Line 1111 emulator");
Int_Reg(0x030, "Hardware breakpoint");
Int_Reg(0x034, "(Reserved, coprocessor protocol violation)");
Int_Reg(0x038, "Format error and uninitialized interrupt");
Int_Reg(0x03C, "Format error and uninitialized interrupt");

b=0;
for (a=0x040;a<=0x05C;a=a+4)
{
Int_Reg(a, "(Unassigned, reserved)"+ltoa(b,10));
b=b+1;
}

Int_Reg(0x060, "Spurious interrupt");
Int_Reg(0x064, "Level 1 interrupt autovector");
Int_Reg(0x068, "Level 2 interrupt autovector");
Int_Reg(0x06C, "Level 3 interrupt autovector");
Int_Reg(0x070, "Level 4 interrupt autovector");
Int_Reg(0x074, "Level 5 interrupt autovector");
Int_Reg(0x078, "Level 6 interrupt autovector");
Int_Reg(0x07C, "Level 7 interrupt autovector");

b=0;
for (a=0x080;a<=0x0BC;a=a+4)
{
Int_Reg(a, "Trap vector "+ltoa(b,10));
b=b+1;
}
b=0;
for (a=0x0C0;a<=0x0E8;a=a+4)
{
Int_Reg(a, "Reserved coprocessor "+ltoa(b,10));
b=b+1;
}
b=8;
for (a=0x0EC;a<=0x0FC;a=a+4)
{
Int_Reg(a, "Unassigned reserved "+ltoa(b,10));
b=b+1;
}
b=0;
for (a=0x100;a<=0x1FC;a=a+4) // onyl 64?
{
Int_Reg(a, "User defined vector "+ltoa(b,10));
b=b+1;
}

/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////

Int_Reg(0x10000, "Reset: initial stack pointer");
Int_Reg(0x10004, "Reset: initial program counter");
Int_Reg(0x10008, "Bus error");
Int_Reg(0x1000C, "Address error");
Int_Reg(0x10010, "Illegal instruction");
Int_Reg(0x10014, "Zero division");
Int_Reg(0x10018, "CHK, CHK2 instructions");
Int_Reg(0x1001C, "TRAPcc, TRAPV instructions");
Int_Reg(0x10020, "Privilege violation");
Int_Reg(0x10024, "Trace");
Int_Reg(0x10028, "Line 1010 emulator");
Int_Reg(0x1002C, "Line 1111 emulator");
Int_Reg(0x10030, "Hardware breakpoint");
Int_Reg(0x10034, "(Reserved, coprocessor protocol violation)");
Int_Reg(0x10038, "Format error and uninitialized interrupt");
Int_Reg(0x1003C, "Format error and uninitialized interrupt");

b=0;
for (a=0x10040;a<=0x1005C;a=a+4)
{
Int_Reg(a, "(Unassigned, reserved)"+ltoa(b,10));
b=b+1;
}

Int_Reg(0x10060, "Spurious interrupt");
Int_Reg(0x10064, "Level 1 interrupt autovector");
Int_Reg(0x10068, "Level 2 interrupt autovector");
Int_Reg(0x1006C, "Level 3 interrupt autovector");
Int_Reg(0x10070, "Level 4 interrupt autovector");
Int_Reg(0x10074, "Level 5 interrupt autovector");
Int_Reg(0x10078, "Level 6 interrupt autovector");
Int_Reg(0x1007C, "Level 7 interrupt autovector");

b=0;
for (a=0x10080;a<=0x100BC;a=a+4)
{
Int_Reg(a, "Trap vector "+ltoa(b,10));
b=b+1;
}
b=0;
for (a=0x100C0;a<=0x100E8;a=a+4)
{
Int_Reg(a, "Reserved coprocessor "+ltoa(b,10));
b=b+1;
}
b=8;
for (a=0x100EC;a<=0x100FC;a=a+4)
{
Int_Reg(a, "Unassigned reserved "+ltoa(b,10));
b=b+1;
}
b=0;
for (a=0x10100;a<=0x101FC;a=a+4) // onyl //64?
{
Int_Reg(a, "User defined vector "+ltoa(b,10));
b=b+1;
}

} //end Main


There are two kind of jump tables in the code, this script will convert for both but if I remember correctly it only works 100% with one kind of jump table, again if somebody improve on the script code please post it here as well.
FindJumpTables.IDC

#include <idc.idc>


static main()
{
auto addr;
auto b;
auto pTable; //pointer tablestart
auto offset; //offset
auto pCode; //pointer to code

for (addr=SegStart(SegByName("ROM"));addr<=SegEnd(SegByName("ROM"));addr=addr+2) {

if ((GetMnem(addr)=="jmp")&&(strstr(GetOpnd(addr,0),"(pc,d0.w)")!=-1)) {

Message("\n\nJumptable found\n");
MakeComm(addr,"Jump table");



b=0; //set case counter to 0
pTable=GetOperandValue(addr,0);
offset=pTable;


pCode=Word(offset)+pTable;

while ((MakeCode(pCode))&&(MakeWord(offset))) {

Message("Converted %x to Word\n",offset);
Message("Made Code at:%x\n",pCode);
MakeComm(offset,"case"+ltoa(b,16));
MakeComm(pCode,"case"+ltoa(b,16));
offset=offset+2; //next table entry
pCode=Word(offset)+pTable; //new pointer to code
b=b+1;
Wait();
}
}
}
}


Cheers
K

alexics
29th June, 2012, 04:03 AM
How much commecnted code have you done by hand so far? BTW is this an 8051 based instructions set?

HybridNz
3rd August, 2012, 05:54 AM
Hi Katvis,

I stumbled across your thread while looking for WDS PDF files for a S62B50 into e46 M3 conversion Im working on at the moment.

A friend and myself have successfully transplanted a s50b32 into an e30 thought we will give the e46 m3 a go :)

I have been working on a few projects which are starting to get down into the protocol and MCU layers and all I can say keep it up!

The same friend of mine who I worked with on the s50/e30 conversion has his own project. And has been working on his Mitsi EVO3 and disassembling his ECU/MCU to add features such as antilag and flat shifting. He successfully reprogrammed the MCU to do this using modified pins from the ECU and creating a new clutch switch into the ECU and writting code to deal with this.
I learnt a lot of what hes done and have been looking at ways to apply it to MSS5X ECUs .. Obviously understanding that the MSS5X ECU class uses more than one CPU which helps complicate things a little.

Im keen to get up and running and maybe assist you in your battle with a colabrative effort.

Ultimately it would be nice to create a Nice XDF file for tuner pro with easy to use scalers etc to add some motorsport features to our ECU's like the JDM market enjoys.

keep it up

Cheers
Josh

Katvis
14th August, 2012, 07:01 PM
Some more info for those interested:
Checksums, the quick and dirty way..;)

For boot loader, there is an address just after the start of the code
at 200h which show where the BOOT section end, this address is in word
format. Highlight the BOOT section up to the word address, calculate
the CRC16 and you will see it match the checksum directly at the end
of that section.

For the CODE section you do as follows, go to address 3DBEh, here you
will find a address in the start of the CODE section, goes to this
address and again here you will find the END OF CODE address,
highlight the code from 10000h up to this address and calculate the
CRC16 and you will see the check sum match directly after the code end
word.


I have not successfully decode the DATA section, for some or other reason this does not work for the data, any ideas?

Meat-Head
14th August, 2012, 08:34 PM
Sorry, *WHY* are you doing this.

Apart from the cool test rig, why?

HybridNz
14th August, 2012, 10:22 PM
Sorry, *WHY* are you doing this.

Apart from the cool test rig, why?

When you disassemble an ECU you can do more than just fiddling with the maps. You can work out the true inner workings of HOW and WHY the ECU does what it does.

EG you can replace a pin funtion on the ECU to install a clutch switch and program in flatshifting or other motorsport style functions.

Effectively turning your stock ECU into same capability as a an aftermarket ECU but you get to retain all of the great stateful functionality such as warm up programs etc.
You can also use spare ROM space to store higher resolution maps that stock, which benefit boosted applications.

It would be awesome to get it to a state where a XDF overlay can be made for each BIN and people can work their own cars with out having to disassemble and edit raw data.

the other reason is its a bloody cool hack if nothing else.

malva
17th August, 2012, 07:07 PM
WOW,

Sounds like you could build a spaceship mate, why not do something really awesome like hack into Barclays and transfer ?1,000,000 to me!

0to60Motorsports
10th December, 2012, 09:04 AM
Wow loads of info here. Most of it is beyond me but great work guys :)

paffy
27th December, 2012, 05:53 AM
Any progress on this ?

I just started on MSS54 and the software seems pretty much the same.

P.

SliM3
7th January, 2013, 09:21 PM
This is an extremely resourceful thread. I am working on a pretty LARGE (translated) xdf with maps, curves, and scalars (actually more than what is needed for tuning). Hardest thing is guesstimating what the hell some of these functions control.

My next step is to learn what you are doing here. GREAT WORK!! And we also have a lot of great info over at Comprehensive MSS54/MSS54HP DME Information - BMW M3 Forum.com (E30 M3 | E36 M3 | E46 M3 | E92 M3 | F80/X) (http://www.m3forum.net/m3forum/showthread.php?t=423771&highlight=IDA+pro) M3Forum.

thehsm
7th January, 2013, 09:26 PM
Could they be PowerPC processors?

Katvis
21st February, 2013, 11:14 PM
Some more info for those interested:
Checksums, the quick and dirty way..;)

For boot loader, there is an address just after the start of the code
at 200h which show where the BOOT section end, this address is in word
format. Highlight the BOOT section up to the word address, calculate
the CRC16 and you will see it match the checksum directly at the end
of that section.

For the CODE section you do as follows, go to address 3DBEh, here you
will find a address in the start of the CODE section, goes to this
address and again here you will find the END OF CODE address,
highlight the code from 10000h up to this address and calculate the
CRC16 and you will see the check sum match directly after the code end
word.


I have not successfully decode the DATA section, for some or other reason this does not work for the data, any ideas?

I am very glad the guys on the BMW M3 forum figured out how to calculate the DATA section check sums, have to test it sometime on my data...;)

It is well worth while to read and join the BMW M3 forum if you need more information on the MSS52 MSS54 DME

bmwMcrzy
27th February, 2013, 04:28 AM
Katvis, how many of the MSS52's maps do you have defined?
Are you using winOLS ?

Katvis
27th February, 2013, 05:40 AM
Katvis, how many of the MSS52's maps do you have defined?
Are you using winOLS ?

I have not defined a lot of MAPS or CURVES as it was never my goal to tune the DME. If you send me a private message with your email address I can forward the excel spreadsheet that I have and this should give you a good idea which MAPS/CURVES/CONSTANTS are available.

I would strongly suggest to join the conversation on the M3Forum because to do this work on your own is a very hard route to go :)

tap46
2nd April, 2013, 10:05 PM
tap here crossing over from M3Forum.

Trying to learn more about the MSS52/4!

I should be able to supply a more complete list of maps and curves to support the disassembly if needed!

SKYTON
18th September, 2016, 05:20 PM
I have the complete dump of the code, my problem is that if I use IDA to disassemble I need to chose the Processor type.

For the Bosch motronics it is easy as Andy Whitaker made nice tutorial videos that explain exactly how to disassemble the code.

I am looking for similar help to disassemble the MSS52 code.

Cheers
C
can you shre link to tuto Andy Whitaker

Katvis
19th September, 2016, 12:02 PM
can you shre link to tuto Andy Whitaker

Good day
I have tried to find the post but cannot see it now, which ECu are you working on?

Cheers
K