RMAC OBD commands

They go by many names, P01, P59, VPW, '0411 etc. Also covering E38 and newer here.
Post Reply
tkelly2784
Posts: 9
Joined: Sat Apr 11, 2020 1:54 pm
cars: Too many BMW's.

RMAC OBD commands

Post by tkelly2784 »

Hello, I'm looking through the list of OBD options in the 2088 annotated disassembly and I found this


DC.B $22 ;Request diag. data (2 byte PIDs)
DC.B $23 ;Request memory addr. contents (3 byte address)

Is there a way to make an OBDLinkMX BT work with $23 and request the contents of the ram?

Does anyone know how big the ram is and how much is in use?
User avatar
antus
Site Admin
Posts: 8250
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: RMAC OBD commands

Post by antus »

Yes, I have implemented it. It was a long time ago but I think it was hard coded in the OS to only send the calibration area ROM, rather than RAM. The version I wrote you had to load a bin with the matching OS, then it used mode 23 to pull back the calibration segment and replace it in the bin. It was incredibly slow, and since you needed to have the OS yourself already it didnt seem better than reading it the normal ways. It _may have_ been possible to do it on a standard elm, but with broken elms in the wild and incompatibilities between elm hardware and software I didnt want to release it, I predicted it wouldnt work for a lot of people. People are better of with one of the other low cost options and pcmhammer so they can write back changes.

For the ram I believe its 16kb, from FF8000 up. Different parts of it have special purposes at run time. FF8000 is a copy of the data in the bin at the paramater block either at 4000 or 6000. The OS writes changes to RAM at runtime (if any) then at key off it compares to flash and writes a copy back to flash to persist the changes.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
tkelly2784
Posts: 9
Joined: Sat Apr 11, 2020 1:54 pm
cars: Too many BMW's.

Re: RMAC OBD commands

Post by tkelly2784 »

That's so cool! If you feel comfortable sharing your code it would be fascinating to look at. Or even where you were tweaking the bin.

Do you have any clue where the OS limits the ability to read the ram?

I didn't really want to use it to change the calibration, but now that we know that is possible it would be fun to use it for that! As you've mentioned using it for a full table re-write is not super useful, but if we're dealing with a P59 that has 300k or so free space we could, for example, have 4 different fuel tables with a lookup table with the address to each of them. The only thing we would need to change in the ram (or the rom) is the lookup value. Then a single 16bit write could have a huge change. You would still need to commit to a tune by flashing it.

We could also make a PE/BE type table(s) for real-ish time tuning.

My goal was to use it to read the RAM addresses for debugging purposes. I have changed the OS to allow a MAP value higher than 105kPa. The OBD PID is a U_8 and corresponds to kPa. When I log it I get values up to 255kPa then it wraps around and goes back up to 135kPa. It would also be nice to have the higher resolution of the full 16bit value in the ram and it would help track down unknown values in the disassembly.

What is $A0 and $A1 high speed mode?

the $23 routine is at 0x3BE0A and not annotated :(

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MOVEM.L D0-D1/A0,-(A7) ;3BE0A: 48E7C080
JSR EXT_0F13 ;3BE0E: 4EB90003D6EE
MOVE.L A0,EXT_1A1A.W ;3BE14: 21C89C20
CMPI.B #$08,(A0) ;3BE18: 0C100008
BNE.S LAB_16B0 ;3BE1C: 6648
CMPI.B #$01,(8,A0) ;3BE1E: 0C2800010008
BNE.S LAB_16B0 ;3BE24: 6640
CLR.L D0 ;3BE26: 4280
MOVE.B (6,A0),D0 ;3BE28: 10280006
ASL #8,D0 ;3BE2C: E140
ANDI.L #$0000FFFF,D0 ;3BE2E: 02800000FFFF
CLR.L D1 ;3BE34: 4281
MOVE.B (5,A0),D1 ;3BE36: 12280005
ASL.L #8,D1 ;3BE3A: E181
ASL.L #8,D1 ;3BE3C: E181
ADD.L D0,D1 ;3BE3E: D280
CLR.L D0 ;3BE40: 4280
MOVE.B (7,A0),D0 ;3BE42: 10280007
ADD.L D0,D1 ;3BE46: D280
MOVE.L D1,D0 ;3BE48: 2001
JSR EXT_0F0B ;3BE4A: 4EB90003BD8C
TST.B D0 ;3BE50: 4A00
BEQ.S LAB_16AF ;3BE52: 670E
MOVE.L D1,EXT_189D.W ;3BE54: 21C19870
MOVEQ #107,D0 ;3BE58: 706B
JSR EXT_0F30 ;3BE5A: 4EB900040BFC
BRA.S LAB_16B2 ;3BE60: 600C
LAB_16AF:
MOVEQ #49,D0 ;3BE62: 7031
BRA.S LAB_16B1 ;3BE64: 6002
LAB_16B0:
MOVEQ #18,D0 ;3BE66: 7012
LAB_16B1:
JSR EXT_0F03 ;3BE68: 4EB90003B414
LAB_16B2:
MOVEM.L (A7)+,D0-D1/A0 ;3BE6E: 4CDF0103
RTS ;3BE72: 4E75
LINK A6,#-4 ;3BE74: 4E56FFFC
MOVEM.L D1/A0,-(A7) ;3BE78: 48E74080
MOVEA.L EXT_189D.W,A0 ;3BE7C: 20789870
MOVE.L A0,(-4,A6) ;3BE80: 2D48FFFC
MOVE.L A0,D0 ;3BE84: 2008
LSR #8,D0 ;3BE86: E048
JSR EXT_003D ;3BE88: 4EB9000006A6
MOVE.L A0,D0 ;3BE8E: 2008
JSR EXT_003D ;3BE90: 4EB9000006A6
MOVE.B (A0),D0 ;3BE96: 1010
JSR EXT_003D ;3BE98: 4EB9000006A6
MOVEQ #1,D1 ;3BE9E: 7201
LAB_16B3:
MOVEA.L (-4,A6),A0 ;3BEA0: 206EFFFC
ADDQ.L #1,A0 ;3BEA4: 5288
MOVE.L A0,(-4,A6) ;3BEA6: 2D48FFFC
MOVE.L A0,D0 ;3BEAA: 2008
JSR EXT_0F0B ;3BEAC: 4EB90003BD8C
TST.B D0 ;3BEB2: 4A00
BEQ.S LAB_16B4 ;3BEB4: 6704
MOVE.B (A0),D0 ;3BEB6: 1010
BRA.S LAB_16B5 ;3BEB8: 6002
LAB_16B4:
CLR.B D0 ;3BEBA: 4200
LAB_16B5:
JSR EXT_003D ;3BEBC: 4EB9000006A6
ADDQ.B #1,D1 ;3BEC2: 5201
CMPI.B #$03,D1 ;3BEC4: 0C010003
BLS.S LAB_16B3 ;3BEC8: 63D6
MOVEQ #1,D0 ;3BECA: 7001
MOVEM.L (A7)+,D1/A0 ;3BECC: 4CDF0102
UNLK A6 ;3BED0: 4E5E
RTS ;3BED2: 4E75
User avatar
antus
Site Admin
Posts: 8250
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: RMAC OBD commands

Post by antus »

Heres a couple of fragments. The app doesnt seem to work anymore, but you can probably re-implement from this.

I'll see if I can find the code your looking for and post back later.

Code: Select all

        #if MODE23
        private byte[] mode23_read(uint address, uint length)
        {

            byte[] request = { 0x6D, 0x10, toolid, 0x23, (byte)(address>>16), (byte)((address>>8)&0xFF), (byte)(address&0xFF), 01 };
            byte[] failure = { 0x6C, 0xF0, 0x10, 0x7F };
            byte[] rx;
            byte[] empty = {};

            if (length != 4) log("warning: request for " + length + " bytes via mode 23");
            log("request for " + length + " bytes from " +address);

            rx = avt_vpw(request);

            if (tools.ByteArrayCompare(rx, failure, failure.Length)) return empty;
            
            return rx;
        }
        #endif

Code: Select all

            if (fast)
            {
                addr = PCM.data.imagestart;
                end = PCM.data.imagestart + PCM.data.imagesize;
                size = PCM.data.imagesize;
            }
            else {
                #if MODE23
                log("Using mode 23 (slow method)");
                len = 4;
                addr = PCM.data.calstart;
                end = PCM.data.calend;
                size = PCM.data.calend-PCM.data.calstart;

                log("Loading bin template");
                // populate a buffer with OS data
                openFileDialog_bin4calread.Title = "Select a template bin with OSID " + PCMOSID.Text;
                openFileDialog_bin4calread.FileName = PCMOSID.Text + ".bin";
                if (openFileDialog_bin4calread.ShowDialog() == DialogResult.OK)
                {
                    using (BinaryReader br = new BinaryReader(File.Open(openFileDialog_bin4calread.FileName, FileMode.Open)))
                    {
                        PCM.data.image=br.ReadBytes((int)PCM.data.imagesize);
                    }
                }
                else
                {
                    log("User abort");
                }
                #else
                // were not doing mode 23 so abort the read
                reading = 0;
                #endif
            }
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
User avatar
antus
Site Admin
Posts: 8250
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: RMAC OBD commands

Post by antus »

Here is your function. Its called from "JSR EXT_0F0B ;3BE4A: 4EB90003BD8C" and its return code is tested.

It looks like there are 5 ranges where it'll allow you to read. 4 of RAM, and the calibration segment in flash. The addresses are looked up, I named the variables after the addresses in the bin so you can see the areas this code is referencing at a glace.

FF8000 -> FF8FFF
FF9000 -> FF9FFF
FFA000 -> FFBFFF
FFC000 -> FFCDFF
008000 -> 01EF9F

So in practice, thats FF8000 -> FFCDFF (RAM) and 8000->1EF9F (Calibration)

Code: Select all

ROM:0003BD8C                                         ; =============== S U B R O U T I N E =======================================
ROM:0003BD8C
ROM:0003BD8C
ROM:0003BD8C                                         test_valid_address:                     ; CODE XREF: mode_23_handler+40↓p
ROM:0003BD8C 2800                                                    move.l  d0,d4
ROM:0003BD8E 2604                                                    move.l  d4,d3
ROM:0003BD90 B6B9 0000 1BE2                                   cmp.l   (addr_FF8FFF).l,d3
ROM:0003BD96 6208                                                    bhi.s   loc_3BDA0
ROM:0003BD98 B6B9 0000 1BDE                                   cmp.l   (addr_FF8000).l,d3
ROM:0003BD9E 6440                                                    bcc.s   loc_3BDE0
ROM:0003BDA0
ROM:0003BDA0                                         loc_3BDA0:                              ; CODE XREF: test_valid_address+A↑j
ROM:0003BDA0 B6B9 0000 1BFA                                   cmp.l   (addr_FF9FFF).l,d3
ROM:0003BDA6 6208                                                    bhi.s   loc_3BDB0
ROM:0003BDA8 B6B9 0000 1BF6                                   cmp.l   (addr_FF9000).l,d3
ROM:0003BDAE 6430                                                    bcc.s   loc_3BDE0
ROM:0003BDB0
ROM:0003BDB0                                         loc_3BDB0:                              ; CODE XREF: test_valid_address+1A↑j
ROM:0003BDB0 B6B9 0000 1C06                                   cmp.l   (addr_FFBFFF).l,d3
ROM:0003BDB6 6208                                                    bhi.s   loc_3BDC0
ROM:0003BDB8 B6B9 0000 1C02                                   cmp.l   (addr_FFA000).l,d3
ROM:0003BDBE 6420                                                    bcc.s   loc_3BDE0
ROM:0003BDC0
ROM:0003BDC0                                         loc_3BDC0:                              ; CODE XREF: test_valid_address+2A↑j
ROM:0003BDC0 B6B9 0000 1C1E                                   cmp.l   (addr_1EF9F).l,d3
ROM:0003BDC6 6208                                                    bhi.s   loc_3BDD0
ROM:0003BDC8 B6B9 0000 1C1A                                   cmp.l   (addr_8000).l,d3
ROM:0003BDCE 6410                                                    bcc.s   loc_3BDE0
ROM:0003BDD0
ROM:0003BDD0                                         loc_3BDD0:                              ; CODE XREF: test_valid_address+3A↑j
ROM:0003BDD0 B6B9 0000 1BEE                                   cmp.l   (addr_FFCDFF).l,d3
ROM:0003BDD6 622E                                                    bhi.s   loc_3BE06
ROM:0003BDD8 B6B9 0000 1BEA                                   cmp.l   (addr_FFC000).l,d3
ROM:0003BDDE 6526                                                    bcs.s   loc_3BE06
ROM:0003BDE0
ROM:0003BDE0                                         loc_3BDE0:                              ; CODE XREF: test_valid_address+12↑j
ROM:0003BDE0                                                                                        ; test_valid_address+22↑j ...
ROM:0003BDE0 263C 00FF 8000                                    move.l  #unk_FF8000,d3
ROM:0003BDE6 B883                                                    cmp.l   d3,d4
ROM:0003BDE8 6508                                                    bcs.s   loc_3BDF2
ROM:0003BDEA 2A03                                                    move.l  d3,d5
ROM:0003BDEC 5685                                                    addq.l  #3,d5
ROM:0003BDEE BA84                                                    cmp.l   d4,d5
ROM:0003BDF0 6414                                                    bcc.s   loc_3BE06
ROM:0003BDF2
ROM:0003BDF2                                         loc_3BDF2:                              ; CODE XREF: test_valid_address+5C↑j
ROM:0003BDF2 7032                                                    moveq   #$32,d0 ; '2'
ROM:0003BDF4 D083                                                    add.l   d3,d0
ROM:0003BDF6 B084                                                    cmp.l   d4,d0
ROM:0003BDF8 670C                                                    beq.s   loc_3BE06
ROM:0003BDFA 7033                                                    moveq   #$33,d0 ; '3'
ROM:0003BDFC D083                                                    add.l   d3,d0
ROM:0003BDFE B084                                                    cmp.l   d4,d0
ROM:0003BE00 6704                                                    beq.s   loc_3BE06
ROM:0003BE02 7001                                                    moveq   #1,d0
ROM:0003BE04 6002                                                    bra.s   locret_3BE08
ROM:0003BE06                                         ; ---------------------------------------------------------------------------
ROM:0003BE06
ROM:0003BE06                                         loc_3BE06:                              ; CODE XREF: test_valid_address+4A↑j
ROM:0003BE06                                                                                 ; test_valid_address+52↑j ...
ROM:0003BE06 4200                                                    clr.b   d0
ROM:0003BE08
ROM:0003BE08                                         locret_3BE08:                           ; CODE XREF: test_valid_address+78↑j
ROM:0003BE08 4E75                                                    rts
ROM:0003BE08                                         ; End of function test_valid_address
High speed mode is VPW 4x, its a faster bus speed normally used for flashing the computer. But if your ok with your dash showing errors because your only doing a dyno pull and you want higher resolution data you can put the PCM in to 4x mode and get data out of the PCM more quickly than normal.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
User avatar
antus
Site Admin
Posts: 8250
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: RMAC OBD commands

Post by antus »

I think these are broken up like this for a reason... as far as i can tell:

FF8000 -> FF8FFF is a copy of the parameter block

FF9000 -> FF9FFF general purpose RAM
FFA000 -> FFBFFF general purpose RAM

FFC000 -> FFCDFF used by the timers

008000 -> 01EF9F calibration
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
tkelly2784
Posts: 9
Joined: Sat Apr 11, 2020 1:54 pm
cars: Too many BMW's.

Re: RMAC OBD commands

Post by tkelly2784 »

I'm sorry it's taken me a couple days to process all of this information and to find out how to use my OBD device. I am now able to type and send 010B through the BT serial port and see the 1 byte return value while changing the voltage of the map sensor, even when it wraps around from too much boost.

I can see where the PCM determines where it is and is not allowed to read and write. Someone with a BDM tool could try unlocking the rest of the ram and ROM by changing that code. The 5 areas that we're given by GM is so much to play with already. I wonder if any of that area is unused.

I have seen this part of the code you shared and it is confusing to me how to implement it.

byte[] request = { 0x6D, 0x10, toolid, 0x23, (byte)(address>>16), (byte)((address>>8)&0xFF), (byte)(address&0xFF), 01 };


I have found this

This parameter is a one
byte value with each
nibble encoded separately:
bit 3 - 0: Length
(number of bytes) of the Memory
Address parameter
bit 7 - 4: Length
(number of bytes) of the
Memory Size parameter

from here

http://unifieddiagnosticservices.blogspot.com/

I'm trying to do this by hand for now with BTSerial and a MX+.

23 A1 FF 90 00 01

would read one byte of the ram at FF9000?

Our PCM doesn't do $3D which is the write mem address UDS code, so how did you put data in using $23? All I'm concerned about at this point is sending a write code through $23 and making a brick.
User avatar
antus
Site Admin
Posts: 8250
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: RMAC OBD commands

Post by antus »

The request would be:
6D 10 F0 23 FF 90 00 01

Once you've set the headers, you'd type

23 FF 90 00 01

to read FF 90 00

I cant remember if you need to unlock the PCM to do this or not. But you should get the data in mode + 40 response packet (eg starting with 63) or an error, starting with 7F
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
Post Reply