Pages: [1] 2 3
Author Topic: MED9 journey to multi-map switching (likely a slow one)  (Read 38472 times)
oldcarguy85
Full Member
***

Karma: +15/-1
Offline Offline

Posts: 247


« on: March 09, 2014, 10:51:16 AM »

Hey all,
So i figured i'd start this thread to document my journey to building multi-map switching in the MED9.

For anyone reading, I don't have this working -- not even remotely close!

This will likely seem really basic to most of you, but for me, getting to this point was a bit trying and i learned a lot getting here...

So i started by loading my flash into IDA.  This was the first hurdle.  I followed the info in the "MED9.1 Dissasembly" thread and got started.  Loaded file at 0x400000, ram at 0x700000.

I used the AutoIT script commonly used for ME7 to assist me with basically marking the whole file (up to 1c9ff0) as code.  This was a HUGE time saver.

I have a number of maps already defined, so I found LDRXN in IDA, then found references to it. There was one reference to the first LDRXN.  I actually have 6 LDRXNs defined, but it looks like only the first one is used (so that's pretty cool info to know!).

The reference to LDRXN was at 5D01C0.  This location was referenced in a function, so i found that reference.  There were two instructions pertaining to this.  One loaded high part of LDRXN reference and the second loaded low part. 

So my next goal was just a proof of concept to change these two instructions to branch instructions to point to a new function that loaded references to a different LDRXN.  since there were already 6 LDRXN maps, i decided just to load the second one instead of the first one.  I defined two functions.  One simply loaded the High part of my new LDRXN reference and the other loaded the Low part of my new LDRXN reference.  I slapped these functions in some unused space in the flash.  It took a bit of reading a messing around to formulate branch instructions using offsets, but it worked!

Anyway, i know this is really basic, but maybe it will help someone get started.

My next goal is to learn how the EEPROM is read/written.  Does anyone know what offset i should load this at?  I've tried loading it simply at 0x0, and there are a few references to data in it, but not enough that it seems right. I also tried 0x80000, but that doesn't seem right either.  Any help is greatly appreciated.

Also, it seems cruise control stalk input will likely come from CAN bus.  I think it's going to be fairly difficult to track down code for this in IDA, but i'm going to give it a shot.  I guess i first need to figure out what the CAN bus messages actually are from the cruise control stalk.  Anyone have any ideas on how to debug this?  I have a FTDI can-bus cable as well as VCDS can cable, but IDK if there's anyone to monitor the can-bus with these. 

I guess i also might need to trace the can pins from teh ECU to the processor itself -- sounds like a PITA!

So attached is my IDA file.  The functions i added (2 liners) are called JRC_LOAD_LDRXN_HIGH and JRC_LOAD_LDRXN_LOW.  I've defined a few other things with meaningful names as well.  I've also attached teh idb file from before i made any changes so you can see what i edited.

Thanks for any help/insight!

-Jordan
Logged
oldcarguy85
Full Member
***

Karma: +15/-1
Offline Offline

Posts: 247


« Reply #1 on: March 09, 2014, 11:07:01 AM »

Just one more note ...

So i lowered the values in my newly referenced LDRXN VERY low, and sure enough, the car ran very low boost, so it worked!!
Logged
phila_dot
Hero Member
*****

Karma: +171/-11
Offline Offline

Posts: 1709


« Reply #2 on: March 09, 2014, 01:58:15 PM »

You don't need to worry about CAN messages.

The messages get processed into variables or condition bits and then utilized as needed. Find and identify them by how they are used.
Logged
Sven77
Newbie
*

Karma: +0/-0
Offline Offline

Posts: 20


« Reply #3 on: April 29, 2014, 10:20:11 AM »

This is going to be interesting, im still a novice at this but i will see what input i can provide after having a look at your file, I can also assist with any trial test down the road ..
Logged
Basano
Full Member
***

Karma: +90/-3
Offline Offline

Posts: 192


« Reply #4 on: June 09, 2014, 12:03:55 PM »

Hi guys,

Here is my Map Switching project for MED9.1

Since there are numerous versions of the MED9.1 binary, each with its own map locations, ram variables and free space, it’s never going to be as easy as just copying and pasting the examples. Rather, the best way is to work through the example and then apply that to your own bin Smiley This post is best read in conjunction with these other posts on storing data in the eeprom and interacting with the cluster.

Pulling it all together, we need a few things:

1)   A way for the ecu to ‘remember’ what maps are currently selected. It would be no use if we had to re-select our maps every time we switched the car off and on again! Fortunately we can store a variable representing our selection in the e2p.
2)   A way of interacting with the driver so you can select a map and get feedback about what you have chosen. I have a manual car without cruise control, so I decided to use clutch and brake pedals for choosing my maps and the rev counter to show the selection.
3)   Some maps to select between. In this example, I have just used maps that already have multiple copies. For example in my bin I have three copies of LDRXN of which only the first seems to be in use (at least, only the first has a reference to it in IDA).

The code to select which map is current is in fact the most straightforward of this whole example. All the hard work is already done and described in my other posts about the ram mirror and cluster interaction. My work on the cluster interaction meant that I had a handy variable that I could check against and jump to a specific location based thereupon. You’ll need the information in those posts to make sense of this post.

Just like in the other posts, in order to patch in my changes I needed an entry point into the code. In this case, just before the code reads the location of LDRXN, I insert a jump to my new routine. The new routine then compares what my map count variable is set to and jumps back again with a suitable location for LDRXN. This is all there is to it – depending on the value of byte_7FABF7 I jump to one of three places. In each of those places I load up an address and then jump back to the main program. The code below corresponds to LDRXN. If you wanted additional maps (e.g. LAMFA), then simply repeat the code below for the extra maps you require.

Code:

ROM:0047C850 loc_47C850:                             # CODE XREF: ROM:00519790j
ROM:0047C850                 lbz       r10, byte_7FABF7 (my non-volatile map count variable. Check it against 0, 1 & 2)
ROM:0047C854                 cmpwi     r10, 0
ROM:0047C858                 beq       loc_47C86C
ROM:0047C85C                 cmpwi     r10, 1
ROM:0047C860                 beq       loc_47C878
ROM:0047C864                 cmpwi     r10, 2
ROM:0047C868                 bge       loc_47C884
ROM:0047C86C
ROM:0047C86C loc_47C86C:                             # CODE XREF: ROM:0047C858j
ROM:0047C86C                 lis       r10, ((off_5CEF48+0x10000)@h)  (load an appropriate address pointing at the address of LDRXN 0, 1 or 2)
ROM:0047C870                 addi      r10, r10, -0x10B8 # off_5CEF48
ROM:0047C874                 b         loc_519798 (jump back to the main program)
ROM:0047C878 # ---------------------------------------------------------------------------
ROM:0047C878
ROM:0047C878 loc_47C878:                             # CODE XREF: ROM:0047C860j
ROM:0047C878                 lis       r10, ((off_5CEF4C+0x10000)@h)
ROM:0047C87C                 addi      r10, r10, -0x10B4 # off_5CEF4C
ROM:0047C880                 b         loc_519798
ROM:0047C884 # ---------------------------------------------------------------------------
ROM:0047C884
ROM:0047C884 loc_47C884:                             # CODE XREF: ROM:0047C868j
ROM:0047C884                 lis       r10, ((off_5CEF50+0x10000)@h)
ROM:0047C888                 addi      r10, r10, -0x10B0 # off_5CEF50
ROM:0047C88C                 b         loc_519798


Worth noting here is that the address I load up (e.g. off_5CEF48) is not the direct address of the LDRXN map. In fact it’s an address that in turn contains the address of the LDRXN map. So 5CEF48 actually points at 5CED28 which is the first LDRXN map. Why it’s like that, I don’t know. Fortunately IDA sorts it all out.

Code:

ROM:005CEF48 off_5CEF48:     .long unk_5CED28        # DATA XREF: ROM:loc_47C86Co
ROM:005CEF4C off_5CEF4C:     .long word_5CED6A       # DATA XREF: ROM:loc_47C878o
ROM:005CEF50 off_5CEF50:     .long dword_5CEDAC      # DATA XREF: ROM:loc_47C884o


Q&A

What bin is all this based upon?
MED9.1
Audi S3 8P MY2007 UK spec
8P0907115H
0261S02342
387951

How do I change maps?
The maps are changed like this. Without starting the car, switch on the ignition. Press the brake pedal and keep it pressed. Now press and release the clutch pedal. Every time you press the clutch pedal, the rev counter needle will flick 1000 rpm -> 2000 rpm -> 3000 rpm -> 4000 rpm -> 1000 rpm. That represents what you’ve chosen (1 to 4).

What map am I currently on?
I was running out of pedals here, so you can’t really just view your active selection. View and change are combined. Every time you press that clutch pedal, you move to the next map and the rpm needle shows you what’s active. Pressing the pedal will change you to the next selection, but since there are only four selections at the moment you’ll be fine Wink

I get an oil pressure alarm?
Don’t be alarmed if you get an oil pressure alarm whilst the engine is off. The cluster thinks the engine is running since it sees rpm, but it isn’t getting a corresponding oil pressure signal. Once you’ve chosen your map, you can switch the ignition off and back on again to clear any false alarms that popped up. Any genuine alarms will be persistent and should be investigated!

My variable counts from 1 to 4 but there are only three LDRXN maps?
That’s right. Right now 3 and 4 both select the third LDRXN map. Code it how you want e.g. 4 might choose the same LDRXN as 3 but have a different LAMFA map instead. It’s your map switching routine Smiley

How do I get the RAM dumps to figure out the RAM locations?
Hmm, that’s a good one. I used a ram logger based on an Arduino, but you need some hardware and software for that (which I made myself). The best suggestion I’ve got is disassemble my bin that I’ve posted plus the internal and external RAM dumps I’ve posted and line up the cross references against your own bin. Also, if there is a popular bin that a lot of people use, I could load that into my bench ecu and dump the ram contents on your behalf.

How do you know what general purpose registers are free?
Read a bit ahead in the code. If you see something like this
ROM:0047C878                 lis       r10, ((off_5CEF4C+0x10000)@h)
It means that the contents of r10 are being loaded with a new value. Therefore it’s safe enough to use r10 since the original code is going to load a new value into r10 anyway. Just make sure the original code doesn’t check r10 between you using it and the original code loading a new value in it!

What ram is free?
Check in IDA for cross references. I picked a value towards the end of the external ram that had no references to it in IDA.

Could you do this with the CCS buttons instead?
Of course! To find the variables that contain the CCS buttons, try this. CCS buttons are Measuring Block 67-2. Work through this post on Measuring Blocks and you’ll end up with the memory and ram locations.

What should I look for/at in IDA?
I’ve attached my IDA project containing all these patches. I’ve also included my bin (both stock and patched). This is where I’ve patched:

004F 7B60 - jump from original code to new cluster interaction code at 0047 C750
0047 C750 - new cluster interaction code
0051 9790 - jump from original code to new LDRXN address code at 0047 C850
0047 C850 - new LDRXN address code

What else is in the bin?
There are a few other patches in there as well at 0047 C650. They relate to measuring blocks though and aren’t necessary here. Some of the maps have been changed as well in my attempts at a mild stage 1 tune. I really suggest you don’t copy them though, since I’m better at the software than I am at the tuning!!

I hope it helps and motivates you to create your own map switching routine Smiley 

Post up how you get on and I’ll help as best I can.
Logged
technic
Full Member
***

Karma: +17/-5
Offline Offline

Posts: 227


« Reply #5 on: June 09, 2014, 12:12:18 PM »

Let me be the first to say that this is EPIC...
Logged
technic
Full Member
***

Karma: +17/-5
Offline Offline

Posts: 227


« Reply #6 on: June 09, 2014, 12:35:48 PM »

We could fake an canbus oilpressure message in the same part of the code changing nmot_c ?
Logged
terminator
Sr. Member
****

Karma: +15/-4
Offline Offline

Posts: 425


« Reply #7 on: June 09, 2014, 03:26:50 PM »

Thank you very much! I cant believe my eyes, so rare and useful info!

I would like to add that if anybody want to use CC bit into RAM (lets say the 1 bit), you need recheck the byte, cause VCDS shows smth like 00000011 (looks like the 1 bit = 1), but actually this is 0000001100 (1 bit = 0).
Logged
oldcarguy85
Full Member
***

Karma: +15/-1
Offline Offline

Posts: 247


« Reply #8 on: June 09, 2014, 03:57:34 PM »

Well you beat me to it... By a lot!! I figured this was where you were going with your last couple posts. Really excellent work. This is likely one of the most valuable things in this forum. Someone should sticky this or something.
Logged
Basano
Full Member
***

Karma: +90/-3
Offline Offline

Posts: 192


« Reply #9 on: June 10, 2014, 12:57:30 AM »

ram dump from 386852

E2P starts around (0x7F8000+0x2B90) = 0x7FAB90
CANBUS buffers start around (0x7F8000 + 0xC4EC = 0x8044EC

Enjoy Smiley

Logged
ddillenger
Hero Member
*****

Karma: +637/-21
Offline Offline

Posts: 5640


« Reply #10 on: June 10, 2014, 12:59:58 AM »

ram dump from 386852

E2P starts around (0x7F8000+0x2B90) = 0x7FAB90
CANBUS buffers start around (0x7F8000 + 0xC4EC = 0x8044EC

Enjoy Smiley



It's like watching the golden age of ME7 unfold all over again!

Smiley
Logged

Please, ask all questions on the forums! Doing so will ensure the next person with the same issue gets the opportunity to learn from your experience!

Email/Google chat:
DDillenger84(at)gmail(dot)com

Email>PM
Basano
Full Member
***

Karma: +90/-3
Offline Offline

Posts: 192


« Reply #11 on: June 10, 2014, 01:52:51 AM »

ram dump from 523981

E2P starts around (0x7F8000+0x2960) = 0x7FA960
CANBUS buffers start around (0x7F8000 + 0xCC70) = 0x804C70
Logged
Basano
Full Member
***

Karma: +90/-3
Offline Offline

Posts: 192


« Reply #12 on: June 10, 2014, 02:08:15 AM »

We could fake an canbus oilpressure message in the same part of the code changing nmot_c ?

I had a quick look but I think the oil pressure swiitch is wired directly to the cluster. Thus the message is not generated in the egine ecu and so we can't overide it there. Need to check my wiring diagrams. A nicety to tidy up later Wink

Thank you very much! I cant believe my eyes, so rare and useful info!

I would like to add that if anybody want to use CC bit into RAM (lets say the 1 bit), you need recheck the byte, cause VCDS shows smth like 00000011 (looks like the 1 bit = 1), but actually this is 0000001100 (1 bit = 0).

Ah, understood. I'd like to have a go with CCS myself. Been meaning to retrofit it so this might spur me on.
Well you beat me to it... By a lot!! I figured this was where you were going with your last couple posts. Really excellent work. This is likely one of the most valuable things in this forum. Someone should sticky this or something.

Thanks Jordan  Grin

I've dumped the ram from your bin and posted it in the thread. Now get cracking and start coding!

lol

It's like watching the golden age of ME7 unfold all over again!

Smiley

Thanks Daz! The forum has helped me so much and I wanted to help as well.
Logged
Basano
Full Member
***

Karma: +90/-3
Offline Offline

Posts: 192


« Reply #13 on: June 12, 2014, 12:44:28 AM »

ram dump from 510588

E2P starts around (0x7F8000+0x2B9C) = 0x7FAB9C
CANBUS buffers start around (0x7F8000 + 0xC9A0) = 0x8049A0
Logged
Basano
Full Member
***

Karma: +90/-3
Offline Offline

Posts: 192


« Reply #14 on: June 12, 2014, 12:45:37 AM »

ram dump from 387951

E2P starts around (0x7F8000+0x2ADC) = 0x7FAADC
CANBUS buffers start around (0x7F8000 + 0xC404) = 0x804404

Logged
Pages: [1] 2 3
  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Page created in 0.034 seconds with 17 queries. (Pretty URLs adds 0s, 0q)