Notices
ECU Flash

MUT/RAM logging

Thread Tools
 
Search this Thread
 
Old Aug 15, 2021 | 07:23 PM
  #1  
orion4096's Avatar
Thread Starter
Newbie
iTrader: (1)
 
Joined: Dec 2014
Posts: 83
Likes: 27
From: -
MUT/RAM logging

I was looking for code to watch RAM contents on an evo9 to help with understanding the disassembly. I found this post which talks about a DMA logging feature built into the stock ROM: https://www.evolutionm.net/forums/ec...live-tune.html

After looking through the dissambly I was able to find the DMA code. Looks like there are a few state machines watching for either a 5 baud init (0x00, 0x33, 0x10?, 0x89?) or a DMA logging command to decide how to use the k-line. For DMA logging you just connect at full speed and write a 0x33 byte (for 24x logging) control message. The ECU then continuously dumps data on the serial port with the current values using a 0x33 byte response. There are commands from 0x81 to 0x89. I've only tried the 24x2B format which uses command 0x81. Other commands are for 24x1B, 5x2B, 6x1B + 2x2B, and also support for special RAM accesses. The lower address values map directly to MUT. For example, 0x17 reads the TPS value. It's also possible to read RAM in the 0x6000-0xDFFF address range. I hacked together a c# app to try it out which you can see in the gif below. There's a counter value incrementing in RAM and I also pressed the throttle so the TPS (0x17) value changes. Ignore the slow updates - I think that's due to the widgets the c# app uses and the speed of the animated gif.

I haven't figured out the right way to disconnect which doesn't require power cycling the ECU and openport. EvoScan can usually reset the port by connecting and trying a 5 baud init, but a 5baud init PassThru command hangs for me. I also set a bit in the ROM header which I think enables some of the DMA modes and need to verify if it's necessary.

This post is mainly to illustrate how the stock ECU logging feature works. I doubt I'll make a logging app, but maybe someone else may find this info useful.

24x2B Request 0x33 Bytes: <CMD 0x81> <2B address in little endian> ... <0x30 Bytes of address> <1B CheckSum> <Trailer=0x0D>
24x2B Responses 0x33 Bytes: <CMD 0x01> <2B data in little endian> ... <0x30 Bytes of data> <1B CheckSum> <Trailer=0x0D>





Code:
NOTE: Sorry for the c# syntax. I don't have a lot of experience coding.

PassThruOpen(IntPtr.Zero, ref mDeviceId);
PassThruReadVersion(apiVersion, dllVersion, firmwareVersion, mDeviceId);
PassThruConnect(mDeviceId, 3, 0x1200, 62500, ref mChannelId);
// watch for everything
PassThruStartMsgFilter(mChannelId, 0x1, pMsg, pMsg, IntPtr.Zero, ref msgId);
// write DMA
PassThruWriteMsgs(mChannelId, pMsg, ref numMsgs, mTimeout);
// read frame start
PassThruReadMsgs(mChannelId, pMsg, ref numMsgs, mTimeout);

<loop>
PassThruReadMsgs(mChannelId, rpMsg, ref rnumMsgs, mTimeout);
The following users liked this post:
Construct (Aug 18, 2021)
Old Aug 18, 2021 | 02:29 PM
  #2  
orion4096's Avatar
Thread Starter
Newbie
iTrader: (1)
 
Joined: Dec 2014
Posts: 83
Likes: 27
From: -
The low sample rate was caused by dropped samples. Looks like it combines responses into a single message if multiple are waiting and the code was only looking at the first. I decoupled the processing of the data and reading the port in separate threads and increased the sample rate. It's still dropping some samples, though. Also haven't figured out how to reset the DMA engine properly without causing the openport to hang which makes testing harder.

In the animated gif below you can see the throttle varying. The other graphs aren't very interesting with the engine off: ECT, RPM, battery voltage, spark advance.


The following 2 users liked this post by orion4096:
Construct (Aug 18, 2021), Segfault (Aug 19, 2021)
Old Aug 23, 2021 | 09:39 AM
  #3  
orion4096's Avatar
Thread Starter
Newbie
iTrader: (1)
 
Joined: Dec 2014
Posts: 83
Likes: 27
From: -
I added some stuff to test out data logging. The first pic is cold start. The second is after it idled for a few minutes and I tap the throttle. The car is pretty much stock and I don't have the tephra 1B Load value in the ROM to log, but the load is low enough to show what's happening. The highlighted cells are a bit off from the actual RPM and Load due to a bug.

Disconnects are still broken which I need to figure out next. There's also too much c# code running now and it can't process the samples fast enough so the logging is a bit delayed. That also needs to be fixed.


Old Aug 23, 2021 | 09:53 AM
  #4  
orion4096's Avatar
Thread Starter
Newbie
iTrader: (1)
 
Joined: Dec 2014
Posts: 83
Likes: 27
From: -
I also looked through the commands more:
81: 24x2B logging
82: 24x1B? logging
83: 5x2B logging
84: 24x2B + live tuning using last 4B?
85: 2x6B 6x1B + live tuning using last 4B?
86: 5x2B + live tuning using last 4B?
87: copy to/from 0x400 scratch in RAM. can't see any use of this scratch in the unmodified ROM, though
89: some live tuning options controlled by f33, f34, f39 in the header?

The disconnect is some problem I'm having with sending a write through the openport2. If I send the message with a timeout it hangs. Without a timeout (=0) it succeeds but then hangs on the disconnect.
Old Aug 24, 2021 | 11:10 AM
  #5  
Construct's Avatar
EvoM Guru
iTrader: (4)
 
Joined: Nov 2009
Posts: 1,688
Likes: 146
From: Utah
Great stuff. You have an Evo IX ECU, right?

I patched my ROM with @jcsbanks 's DMA logging code long ago ( https://www.evolutionm.net/forums/ec...ode-works.html ) but I'll have to go back and look for this built-in DMA code again. I'm surprised none of the original ECU disassemblers found this (or at least no one mentioned it publicly).
Old Aug 24, 2021 | 12:26 PM
  #6  
orion4096's Avatar
Thread Starter
Newbie
iTrader: (1)
 
Joined: Dec 2014
Posts: 83
Likes: 27
From: -
Ya, I have a 9 with the 1860A465 ECU. Would love to get a cheap spare for a bench setup, but they are hard to find. I've been looking through the 88590015 ROM. There's a lot of code and indirection (table lookups for function call pointers, etc) associated with the feature. I'll share my source and a binary as soon as I figure out how to keep the OP2 from hanging on the DMA logging cancel write message. Also accidentally deleted the source last night so it's going to take a few days to rewrite

Here are a few of the function calls associated with DMA logging (88590015):

0x00026468 - Setup and handle DMA operations on timer (CAS?) interrupt. Handles subset of DMA operations
0x00026104 - Handle DMA operations in main loop. Handles other set of DMA operations
0x00009206 - RX (input) buffer message checks and decode. This is run on the RX buffer once for the logging command types.
0x000096BC - 24x2B and 24x1B (and 5x2B?) TX buffer fill code based on ADEC table

0xADD8 has 5 function pointers for RX DMA setup, TX DMA setup, error/DMA cancel checks, idle checks, etc
0xADEC is a table of of 6B structures that <2B resp rate ctr compare?> <1B resp msg header> <1B params per resp> <1B size of each param> <FF?>
Think 0xF30 has to be changed from 2 to 3 to enable some of the logging functionality. The two lower bits of that byte have something to do with two independent buffers and DMA logging setups. I haven't tried it without that change. That whole block of addresses (F30 up to the ROM ID) seems to be a bit vector to enable various debug features.

Here's an example where RX (input) buffer is decoded. The online disassembler treats the values as signed but you can see the 0x81 (#-127), 0x82, ... comparison logic.


Code:
.data:00009306 ea 81 mov #-127,r10
.data:00009308 6a ac extu.b r10,r10
.data:0000930a 3d a0 cmp/eq r10,r13
.data:0000930c 8b 04 bf 0x00009318
.data:0000930e 85 e8 mov.w @(16,r14),r0
.data:00009310 cb 02 or #2,r0
.data:00009312 81 e8 mov.w r0,@(16,r14)
.data:00009314 a0 76 bra 0x00009404
.data:00009316 00 09 nop
.data:00009318 6d dc extu.b r13,r13
.data:0000931a ea 82 mov #-126,r10
.data:0000931c 6a ac extu.b r10,r10
.data:0000931e 3d a0 cmp/eq r10,r13
.data:00009320 8b 04 bf 0x0000932c
.data:00009322 85 e8 mov.w @(16,r14),r0
.data:00009324 cb 04 or #4,r0
.data:00009326 81 e8 mov.w r0,@(16,r14)
.data:00009328 a0 6c bra 0x00009404
.data:0000932a 00 09 nop
.data:0000932c 6d dc extu.b r13,r13
.data:0000932e ea 83 mov #-125,r10
.data:00009330 6a ac extu.b r10,r10
.data:00009332 3d a0 cmp/eq r10,r13
.data:00009334 8b 04 bf 0x00009340
.data:00009336 85 e8 mov.w @(16,r14),r0
.data:00009338 cb 08 or #8,r0
.data:0000933a 81 e8 mov.w r0,@(16,r14)
.data:0000933c a0 62 bra 0x00009404
.data:0000933e 00 09 nop
.data:00009340 6d dc extu.b r13,r13
.data:00009342 ea 84 mov #-124,r10
.data:00009344 6a ac extu.b r10,r10
.data:00009346 3d a0 cmp/eq r10,r13
.data:00009348 8b 07 bf 0x0000935a
.data:0000934a 85 e8 mov.w @(16,r14),r0
.data:0000934c 6a 0d extu.w r0,r10
.data:0000934e 9b 20 mov.w 0x00009392,r11 ! 2002
.data:00009350 2a bb or r11,r10
.data:00009352 60 a3 mov r10,r0
.data:00009354 81 e8 mov.w r0,@(16,r14)
.data:00009356 a0 55 bra 0x00009404
.data:00009358 00 09 nop
.data:0000935a 6d dc extu.b r13,r13
.data:0000935c ea 85 mov #-123,r10
.data:0000935e 6a ac extu.b r10,r10
.data:00009360 3d a0 cmp/eq r10,r13
.data:00009362 8b 07 bf 0x00009374
.data:00009364 85 e8 mov.w @(16,r14),r0
.data:00009366 6a 0d extu.w r0,r10
.data:00009368 9b 14 mov.w 0x00009394,r11 ! 2010
.data:0000936a 2a bb or r11,r10
.data:0000936c 60 a3 mov r10,r0
.data:0000936e 81 e8 mov.w r0,@(16,r14)
.data:00009370 a0 48 bra 0x00009404
.data:00009372 00 09 nop
.data:00009374 6d dc extu.b r13,r13
.data:00009376 ea 86 mov #-122,r10
.data:00009378 6a ac extu.b r10,r10
.data:0000937a 3d a0 cmp/eq r10,r13
.data:0000937c 8b 2c bf 0x000093d8
.data:0000937e 85 e8 mov.w @(16,r14),r0
.data:00009380 6a 0d extu.w r0,r10
.data:00009382 9b 08 mov.w 0x00009396,r11 ! 2020
.data:00009384 2a bb or r11,r10
.data:00009386 60 a3 mov r10,r0
.data:00009388 81 e8 mov.w r0,@(16,r14)
.data:0000938a a0 3b bra 0x00009404
.data:0000938c 00 09 nop

Last edited by orion4096; Aug 24, 2021 at 06:05 PM.
The following users liked this post:
Construct (Aug 24, 2021)
Old Aug 29, 2021 | 08:34 PM
  #7  
orion4096's Avatar
Thread Starter
Newbie
iTrader: (1)
 
Joined: Dec 2014
Posts: 83
Likes: 27
From: -
Found a fix for the disconnect issue. It takes ~10s but works most of the time. I didn't understand the bus timing parameters before and the logging mode doesn't work with the default values when trying to disconnect. It also seems to require a 5baud init to kick the DMA logging out of its state machine after the "stop" write message is sent and remaining log data is drained.

The source is here: https://github.com/nanner55/mscan
The latest binary is here: https://github.com/nanner55/mscan/re...t_build_v1.zip

If you want to give it a try download the zip and copy your ROM into the unzipped directory. Maybe in the future parts of the ROM can be read over OBD rather than requiring a local copy.

Keep in mind that the program isn't very tested and can (will) crash. The ECU will continue to log until power is cut by the relay. From what I've seen, the car still functions fine while logging, but I've only idled it and haven't had a chance to drive, yet.

You will need to modify your evo8/evo9 ROM to set bit 0 in 0xF30 (2->3) and flash it. This enables support for the type of DMA logging used by default. Before connecting, load an EvoScan style parameter file with the LoadParam button. It must have a EFI section with MUT (or RAM address) request IDs. A sample one that works with an evo IX is included and named param.xml. If you want to view tables, copy your ROM into the same directory as the binary press the LoadROM button. Some temporary XML files are included from EcuFlash. If the XML files don't support your ROM ID it will throw an exception and show a message. You can try copying your EcuFlash XML into the metadata subdirectory. The ROM/XML parsing is a hack so don't be surprised if it doesn't work.

It's had some basic testing on an evo IX using a tactrix openport 2.0. The tactrix will glow red when the logging is enabled signifying lots of message data waiting in its receive buffer. If you try to disconnect and it remains red the logging is still enabled and the disconnect was unsuccessful. Typically the mscan program hangs when this happens. You will need to cycle the ECU power (Ignition -> ACC) for a few seconds until you hear the relay click and the tactrix stops glowing red. You can also try reloading mscan and doing a connect and then disconnect. Sometimes that works, too.
Old Sep 6, 2021 | 02:27 PM
  #8  
orion4096's Avatar
Thread Starter
Newbie
iTrader: (1)
 
Joined: Dec 2014
Posts: 83
Likes: 27
From: -
I looked through the 0x87 DMA command that supports read (1) and write (0) of 0xFFFF9C00-0xFFFF9FFF. I couldn't find any use of that memory region anywhere else so 2 new commands were added to support reading any memory location (5) and writing anything in the FFFFxxxx range (4). The additions fit within the existing code without branching out. The ROM Id can now be read out of flash over serial and used to calculate table addresses to read. It's really slow, though, since it seems like the ECU will only buffer 1 command at a time and the data size is fixed at 0x2C. I'll check if it's easy to take a length and have the ECU push all the data at once.

The weird CTR param incrementing pattern in the previous versions was caused by the thread timers only going down to ~15ms of precision. It's using a different set of timers now with more precision.

Hoping Tactrix can help me figure out a way to keep the OP2 from buffering 0xFE0 worth of data before responding back with a message. That adds ~1s of latency. Would be nice if that was closer to 100ms-200ms.

Picked up a 2006 Lancer AT bench ECU so no more debugging inside the car. It doesn't have any sensors hooked up so I just connected the 5V supply pin to TPS a few times.


Last edited by orion4096; Sep 7, 2021 at 12:11 PM.
Old Sep 9, 2021 | 12:12 AM
  #9  
Dow Jhob's Avatar
Newbie
 
Joined: Jun 2016
Posts: 93
Likes: 7
From: siberia
nice, look my code.. https://github.com/DowJhob/Evo-live-map
Old Sep 9, 2021 | 05:27 PM
  #10  
orion4096's Avatar
Thread Starter
Newbie
iTrader: (1)
 
Joined: Dec 2014
Posts: 83
Likes: 27
From: -
Thanks for the link. It looks like it uses the E1-E4 MUT changes to do the reads and writes? I haven't read through those ASM changes. If I decide to add live maps I may take a look at your code to see how it works. Right now the existing Mitsubishi DMA code is interesting to look through and change.

I fixed performance of the new DMA read and write by adding a count field to the existing packet. For reads it's in terms of 0x2C byte data packets for up to 0x2C00 worth of data and for writes its in terms of bytes. Reads are significantly faster now and writes don't require a read-modify-write which isn't atomic.
Old Sep 9, 2021 | 06:41 PM
  #11  
Dow Jhob's Avatar
Newbie
 
Joined: Jun 2016
Posts: 93
Likes: 7
From: siberia
in my opinion, you are working incorrectly with reading, you do not need two timers and even super-accurate ones, look at the example in the tactrix driver, reading in an infinite loop in a separate thread, and all your problems with timeouts will disappear. I gave a link to show that pure c is much faster than c#, but if you really want c# then look at the tephra livemap client for evo10
and of course use unsafe code for native work with j2534 messages, ideally you need to write a module that will work with unsafe inside

this man --> https://github.com/RcusStackwalker at one time found a stock DMA and was going to write a client, but then he abandoned it here it was discussed http://airtrek-turbo.ru/viewtopic.php?f=17&t=26

Last edited by Dow Jhob; Sep 9, 2021 at 07:25 PM.
Old Sep 10, 2021 | 07:47 AM
  #12  
Dow Jhob's Avatar
Newbie
 
Joined: Jun 2016
Posts: 93
Likes: 7
From: siberia
imho you wrong interpret SCONFIG parameter

http://embeddedsystem.ru/index.php?p...standarta-obd2

see fig.5

this parameters control by ECU you must set adequte parameter in your j2534 adapter, its not timeout
Old Sep 13, 2021 | 09:13 AM
  #13  
Dow Jhob's Avatar
Newbie
 
Joined: Jun 2016
Posts: 93
Likes: 7
From: siberia
class enum direction:WORD
{
write,
read,
info, //wtf???
addedWrite,
addedRead
}
struct _0x87mode
{
byte modeId = 0x87;
direction directionId;
WORD offset;
byte data[0x2C] // 44 bytes.
byte checkSumm;
byte endOfStruct = 0x0D;
}

you change to

class enum direction:byte
{
write,
read,
info, //wtf???
addedWrite,
addedRead
}
struct _0x87mode
{
byte modeId = 0x87;
direction directionId;
byte packetCount;
DWORD addr;
byte data[0x2A] // 42 bytes!.
byte checkSumm;
byte endOfStruct = 0x0D;
}

while maintaining the total length of the packet right?
but your LOG_DAT_SIZE = 0x2C, for example line 591..


what's the point in this packet counter?

Last edited by Dow Jhob; Sep 13, 2021 at 09:37 AM.
Old Sep 13, 2021 | 01:46 PM
  #14  
orion4096's Avatar
Thread Starter
Newbie
iTrader: (1)
 
Joined: Dec 2014
Posts: 83
Likes: 27
From: -
Post

The read and write packets have 2 new formats. This was done to make only a small amount of inline changes to the ECU code to support the new formats and still keep the existing functions. The packetCount field in the read allows multiple 0x2C responses to be sent by the ECU which is much faster than reading 0x2C at a time. The byteCount was added to the write so someone isn't forced to write 0x2C bytes all the time. If you only want to write 1 byte it doesn't require a read of the other 0x2B bytes of data that may be changed by the ECU.

EDIT: I should clarify that these are request packet formats. The read response format is still the same with read mode 1 and 5: <0x05> <0x00> <0x01> <offset2B/upperAddr2B> <0x2C of Data> <CSUM1B> <0x0D>

Code:
class enum direction:byte
{
    write = 0x00, // write 0x2C bytes to scratch space using 2B addr/offset field. truncate on overflow
    read = 0x01, // read 0x2C bytes from scratch space using 2B addr/offset field. truncate on overflow
    info = 0x02, // returns scratch? space info for ECU: addr4B=0xFFFF9C00, srcAddr4B=0x0003FB40, size2B=0x400 on 88590015
    addedWrite = 0x04, // write 0x00-0x2C bytes to FFFF<addr> address
    addedRead = 0x05 // read 0x01-0xFF or 0x100 packets of size 0x2C from any 4B addr
}
struct _0x87mode_read
{
    byte modeId = 0x87;
    byte packetCount = 0x00-0xFF; // 0x00 represents 0x100.
    (byte)direction directionId = 0x05;
    DWORD addr; // increased to 4B to support reading full address space
    byte data[0x2A]; // 42 bytes!. // data is don't care for read
    byte checkSumm;
    byte endOfStruct = 0x0D;
}

struct _0x87mode_write
{
    byte modeId = 0x87;
    byte byteCount = 0x00-0x2C; // represents bytes to write from starting address <addr>
    (byte)direction directionId = 0x04;
    WORD addr; // prepended with 0xFFFF in ECU to avoid increasing addr size in packet
    byte data[0x2C];
    byte checkSumm;
    byte endOfStruct = 0x0D;
}
I started with just a single thread to read the ECU, but I couldn't get the OP2 to return anything other than buffered 0xFE0 worth of data. It isn't very interesting to present 79.7 packets on the screen all at once since the ECU is sending them every 10ms. That's why I added the first timer on the display side. Then I thought maybe adding a timer to the PassThruReadMsgs call with no timeout might allow the OP2 to give less packets, but it just returns nothing most of the time. I agree the code is very complex but that's because I haven't figured out how to get OP2 to give me the data without excessive buffering. I also tried changing the MIN/MAX values for some of the timings hoping that would affect how much data it buffered. That also didn't work. I agree that I need to figure out the actual timings for the bidirectional communication to always work correctly. I have not done that, yet.

Last edited by orion4096; Sep 13, 2021 at 07:15 PM.
Old Sep 13, 2021 | 07:33 PM
  #15  
Dow Jhob's Avatar
Newbie
 
Joined: Jun 2016
Posts: 93
Likes: 7
From: siberia
that is, for each request with packetCount = 0x00, I will receive a response from six messages

struct _0x87response
{
byte typeId;
WORD sudType;
WORD offset;
byte data[0x2C];
byte chckSmm;
byte endOFstruct;
}
?


Quick Reply: MUT/RAM logging



All times are GMT -7. The time now is 10:24 PM.