Login Register

Vida CEM swapping

A mid-size luxury crossover SUV, the Volvo XC90 made its debut in 2002 at the Detroit Motor Show. Recognized for its safety, practicality, and comfort, the XC90 is a popular vehicle around the world. The XC90 proved to be very popular, and very good for Volvo's sales numbers, since its introduction in model year 2003 (North America). P2 platform.
Post Reply
mikeak2001
Posts: 29
Joined: 30 March 2021
Year and Model: S70 1998 T5
Location: Wales
Has thanked: 3 times
Been thanked: 28 times

Re: Vida CEM swapping

Post by mikeak2001 »

oscilloscope wrote: 22 Oct 2023, 03:27 Furthering on from my investigation with this Siemens sid803a , I wanted to see if I could decode the flash. And see the config (if any) I took a dump of the flash and could see somthing which looked remarkably like a VIN number. I will note it down and see if its genuine. , I did some very basic searches for the ecu and suspected config data and I couldn't find anything of any substance. My search continues , any suggestions on what I can use to decode it into readable format I'm all ears.
VIN is stored in the ECM eeprom on SID803a

User avatar
TonyToronto
Posts: 13
Joined: 15 October 2023
Year and Model: 2007 XC90
Location: Toronto, Canada
Has thanked: 5 times
Been thanked: 1 time

Post by TonyToronto »

Got my Cracker done today, and works. Thank You guys for all hard work.
Attachments
PXL_20231024_214539717.MP.jpg
PXL_20231024_214539717.MP.jpg (432.77 KiB) Viewed 580 times
PXL_20231024_215202566.jpg
PXL_20231024_215202566.jpg (379.95 KiB) Viewed 580 times

vtl
Posts: 4724
Joined: 16 August 2012
Year and Model: 2005 XC70
Location: Boston
Has thanked: 114 times
Been thanked: 604 times

Post by vtl »

TonyToronto wrote: 24 Oct 2023, 17:47 Got my Cracker done today, and works. Thank You guys for all hard work.
TonyToronto, are you Antherzoll @ SS?

User avatar
TonyToronto
Posts: 13
Joined: 15 October 2023
Year and Model: 2007 XC90
Location: Toronto, Canada
Has thanked: 5 times
Been thanked: 1 time

Post by TonyToronto »

I hope not :-)

swappeds60r
Posts: 3
Joined: 16 August 2023
Year and Model: 2005 S60R
Location: Budapest

Post by swappeds60r »

Dear All!
I started to reconfigure my CEM. Please give me a feedback. My car is a 2005 S60R (FL, swapped AW51 to M66 AWD. Are these parameters are correct?
Manual:
Par.07 - 0x01 <VXMAN>
Par.08 - 0x18 <M66AWD>
Par.73 - 0x01 <U_GTRON>

Speed limit delete:
Par.05 - 0x00 — Not definied —

Are these correct?

matija0610
Posts: 50
Joined: 25 October 2021
Year and Model: 2003 S60 D5
Location: Croatia
Has thanked: 21 times
Been thanked: 13 times

Post by matija0610 »

swappeds60r wrote: 29 Oct 2023, 05:04
Manual:
Par.07 - 0x01 <VXMAN> OK !
Par.08 - 0x18 <M66AWD> OK!
Par.73 - 0x01 <U_GTRON> OK!

Speed limit delete:
Par.05 - 0x00 — Not definied — speed limit :
Screenshot_3.png
Screenshot_3.png (57.68 KiB) Viewed 514 times

swappeds60r
Posts: 3
Joined: 16 August 2023
Year and Model: 2005 S60R
Location: Budapest

Post by swappeds60r »

matija0610 wrote: 29 Oct 2023, 06:32
swappeds60r wrote: 29 Oct 2023, 05:04
Manual:
Par.07 - 0x01 <VXMAN> OK !
Par.08 - 0x18 <M66AWD> OK!
Par.73 - 0x01 <U_GTRON> OK!

Speed limit delete:
Par.05 - 0x00 — Not definied — speed limit :

Screenshot_3.png

Now i have 250 km/h limitaton, but i would like to delete!

LukeFlynn
Posts: 8
Joined: 22 September 2019
Year and Model: XC70, S40
Location: Knoxville, TN

Post by LukeFlynn »

T5Luke wrote: 09 Sep 2022, 17:26 This works on all CEMs to MY 2004, 10th place of VIN Y, 1, 2, 3 or 4. Read cem by arduino once, place it back into car and change how often you like by dice.

screenshot.2 CEM tool.jpg

Read CEM by arduino nano or UNO by this:

Code: Select all

#define BKPT 4
#define RESET 5
#define FREEZE 6
#define DSI 7
#define DSO 8

static word CMD_READ = 0x1940;
static word CMD_GO = 0x0C00;
static word CMD_WRITEM = 0x1840;

char command;
int n_line;

void setup() {
  // put your setup code here, to run once:
  pinMode(BKPT, OUTPUT);
  digitalWrite(BKPT, HIGH);
  pinMode(RESET, OUTPUT);
  digitalWrite(RESET, LOW);
  pinMode(FREEZE, INPUT);
  pinMode(DSI, OUTPUT);
  digitalWrite(DSI, LOW);
  pinMode(DSO, INPUT);
  Serial.begin(57600);
  while(!Serial){
  }
  Serial.println(F("Arduino CEM Reader, press:"));
  Serial.println();
  Serial.println(F("e: enter BDM Mode"));
  Serial.println(F("l: leave BDM (experimental)"));
  Serial.println(F("r: read complete memory"));
  Serial.println(F("b: read Boot 0-3FFF"));
  Serial.println(F("s: read security block 4000-7FFF"));
  Serial.println(F("d: read car data 8000-1FFFF"));
  Serial.println(F("f: read firmware 20000-7FFFF"));
  Serial.println(F("c: BD32 Command Mode")); 
  
  

}

void loop() {
  // put your main code here, to run repeatedly:
    if (Serial.available()) {
      command = Serial.read();
      switch (command)
      {
        case 'e':
        Serial.println("Enter BDM");
        digitalWrite(BKPT, LOW);
        delay(10);
        digitalWrite(RESET, HIGH);
        delay(100);
        Serial.println(digitalRead(FREEZE));
        break;

        case 'l':
        Serial.println("leave BDM");
        shift_BKPT_up();
        digitalWrite(RESET, LOW);
        delay(10);
        digitalWrite(RESET, HIGH);
        wait_openchannel();
        bdm_command(CMD_GO);
        digitalWrite(DSO, LOW);
        shift_BKPT_up();

        
        Serial.println(digitalRead(FREEZE));
        break;

        case 'r':
        Serial.println("Read FLASH");
       
        for (unsigned long offset = 0x0000; offset<=0x7FFFF; offset = offset + 0x02)
        {
           shiftRWord(offset);
        }
        break;

        case 'b':
        Serial.println(F("Read bootblock"));
       
        for (unsigned long offset = 0x0000; offset<=0x3FFF; offset = offset + 0x02)
        {
           shiftRWord(offset);
        }
        break;

        case 's':
        Serial.println(F("Read securityblock"));
       
        for (unsigned long offset = 0x4000; offset<=0x7FFF; offset = offset + 0x02)
        {
           shiftRWord(offset);
        }
        break;

        case 'd':
        Serial.println(F("Read cardata"));
       
        for (unsigned long offset = 0x8000; offset<=0x1FFFF; offset = offset + 0x02)
        {
           shiftRWord(offset);
        }
        break;

        case 'f':
        Serial.println(F("Read firmware"));
       
        for (unsigned long offset = 0x10000; offset<=0x7FFFF; offset = offset + 0x02)
        {
           shiftRWord(offset);
        }
        break;

        case 'c':
        Serial.println(F("BD32 Command Mode"));

        serialFlush();
        while(!Serial.available());
        {
        }
        break;

        default:
        break;

        case 'i':
        Serial.println("wipe");
        for (int i=0; i<=250; i++)
        {
          digitalWrite(BKPT, LOW);
          delay(1);
          digitalWrite(BKPT, HIGH);
          delay(1);
        }
        break;
      }
    }

}


void shiftRWord(unsigned long val)
{
    word i;
    word lowbyte = val;
    word hibyte = val >> 16;

    //Wait for DSO to get 0 => gets ready
   wait_openchannel();

    bdm_command(CMD_READ);
    shift_BKPT_up();
    shift_BKPT_up();
    


     for (i = 0; i < 16; i++)  {  //HighByte


        digitalWrite(DSI, !!(hibyte & (1 << (15 - i))));
        shift_BKPT_up();
    }
        digitalWrite(DSI, LOW);
        delayMicroseconds(1);
        shift_BKPT_up();



     for (i = 0; i < 16; i++)  {  //LowByte


        digitalWrite(DSI, !!(lowbyte & (1 << (15 - i))));
        shift_BKPT_up();
    }
    digitalWrite(DSI, LOW);
    delayMicroseconds(1);


    word W_Read;

    for (i= 0; i < 1; i++)   //Read Status Byte
    {
      //digitalWrite(BKPT, HIGH);
      //delayMicroseconds(1);
      digitalWrite(BKPT, LOW);
      delayMicroseconds(1);
      //Serial.print(digitalRead(DSO));
    }

    for (i= 0; i < 16; i++) //Read back
    {
      digitalWrite(BKPT, HIGH);
      delayMicroseconds(1);
      digitalWrite(BKPT, LOW);
      delayMicroseconds(1);
      //Serial.print(digitalRead(DSO));
       bitWrite(W_Read,(15-i),digitalRead(DSO));
    }

    check_lzero(W_Read);

    if (n_line <=6)
    {        
       Serial.print(W_Read,HEX);
       Serial. print(" ");
       n_line++;
    }else{
      Serial.println(W_Read,HEX);
      n_line = 0;
    }

   
    //return W_Read;
}


 void write_Register(word cmd, unsigned long addr)
 {
    word lowbyte = addr;
    word hibyte = addr >> 16;

    wait_openchannel(); //Wait for DSO to get 0 => gets ready
    bdm_command2(cmd);
    shift_BKPT_up();

    for (int i = 0; i < 16; i++)  {  //HighByte OFFSET
        digitalWrite(DSI, !!(hibyte & (1 << (15 - i))));
        shift_BKPT_up();
    }
    digitalWrite(DSI, LOW);
    delayMicroseconds(1);
    shift_BKPT_up();

    for (int i = 0; i < 16; i++)  {  //LowByte OFFSET
        digitalWrite(DSI, !!(lowbyte & (1 << (15 - i))));
        shift_BKPT_up();
    }
    digitalWrite(DSI, LOW);
    delayMicroseconds(1);
 }
 

 void check_lzero(word W_Read){
      if (W_Read < 0x10)
      {
        Serial.print("000");
        return;
      }
        
      if (W_Read < 0x100)
      {
        Serial.print("00");
        return;
      }
      if (W_Read < 0x1000)
      {
        Serial.print("0");
        return;
      }
     }

 void shift_BKPT_up()
 {
      digitalWrite(BKPT, LOW);
      delayMicroseconds(1);
      digitalWrite(BKPT, HIGH);
      delayMicroseconds(1);
 }

 void wait_openchannel()
 {
      while(digitalRead(DSO)!=0)
    {
      shift_BKPT_up();
    }
     while(digitalRead(DSO)!=1)
    {
      shift_BKPT_up();
    }
 }

 void bdm_command(word command)
 {
  for (int i = 0; i < 15; i++)  {  
        digitalWrite(DSI, !!(command & (1 << (15 - i))));
        shift_BKPT_up();
    }
  digitalWrite(DSI, LOW);
 }

  void bdm_command2(word command)
 {
  for (int i = 0; i < 16; i++)  {  
        digitalWrite(DSI, !!(command & (1 << (15 - i))));
        shift_BKPT_up();
    }
  digitalWrite(DSI, LOW);
 }

 void serialFlush(){
  while(Serial.available() > 0) {
    char t = Serial.read();
  }
}   
BKPT to D4
RESET to D5
FREEZE to D6
DSI to D7
DSO to D8

2 options, connect the 5V line at the capacitor, or connect the 12V at the CEMs main connector. Both connections 5V and +12V are not needed together...

Masse means GND
If you use 12V power supply connect GND from it also to arduios GND, so they should have common GND.

Copy content to HXD and save to BIN file.

Open bin file by this tool, make the changes you like and write this data back to cem by DICE-206751.
It would be nice to get paramter file fills up by the community if you need this tool...

As everything by me it is free, also free to analyze and build your own tools out of it...

Self i test this tools tomorrow, if it has bugs i will fix them... Have fun...
Finally got around to trying this, but I am only getting 0000s dumped as binary which is obviously nothing and it’s very sporadic. I have verified all of my connections, fortunately I did not kill CEM in the process. I wonder if trying 12 volts would be better vs 5v. The CEM only needs ground if using 12 volt source correct? I’m using probes and a frame and think maybe 5v off the arduino is a bit touchy through the probes

LukeFlynn
Posts: 8
Joined: 22 September 2019
Year and Model: XC70, S40
Location: Knoxville, TN

Post by LukeFlynn »

LukeFlynn wrote: 31 Oct 2023, 22:41
T5Luke wrote: 09 Sep 2022, 17:26 This works on all CEMs to MY 2004, 10th place of VIN Y, 1, 2, 3 or 4. Read cem by arduino once, place it back into car and change how often you like by dice.

screenshot.2 CEM tool.jpg

Read CEM by arduino nano or UNO by this:

Code: Select all

#define BKPT 4
#define RESET 5
#define FREEZE 6
#define DSI 7
#define DSO 8

static word CMD_READ = 0x1940;
static word CMD_GO = 0x0C00;
static word CMD_WRITEM = 0x1840;

char command;
int n_line;

void setup() {
  // put your setup code here, to run once:
  pinMode(BKPT, OUTPUT);
  digitalWrite(BKPT, HIGH);
  pinMode(RESET, OUTPUT);
  digitalWrite(RESET, LOW);
  pinMode(FREEZE, INPUT);
  pinMode(DSI, OUTPUT);
  digitalWrite(DSI, LOW);
  pinMode(DSO, INPUT);
  Serial.begin(57600);
  while(!Serial){
  }
  Serial.println(F("Arduino CEM Reader, press:"));
  Serial.println();
  Serial.println(F("e: enter BDM Mode"));
  Serial.println(F("l: leave BDM (experimental)"));
  Serial.println(F("r: read complete memory"));
  Serial.println(F("b: read Boot 0-3FFF"));
  Serial.println(F("s: read security block 4000-7FFF"));
  Serial.println(F("d: read car data 8000-1FFFF"));
  Serial.println(F("f: read firmware 20000-7FFFF"));
  Serial.println(F("c: BD32 Command Mode")); 
  
  

}

void loop() {
  // put your main code here, to run repeatedly:
    if (Serial.available()) {
      command = Serial.read();
      switch (command)
      {
        case 'e':
        Serial.println("Enter BDM");
        digitalWrite(BKPT, LOW);
        delay(10);
        digitalWrite(RESET, HIGH);
        delay(100);
        Serial.println(digitalRead(FREEZE));
        break;

        case 'l':
        Serial.println("leave BDM");
        shift_BKPT_up();
        digitalWrite(RESET, LOW);
        delay(10);
        digitalWrite(RESET, HIGH);
        wait_openchannel();
        bdm_command(CMD_GO);
        digitalWrite(DSO, LOW);
        shift_BKPT_up();

        
        Serial.println(digitalRead(FREEZE));
        break;

        case 'r':
        Serial.println("Read FLASH");
       
        for (unsigned long offset = 0x0000; offset<=0x7FFFF; offset = offset + 0x02)
        {
           shiftRWord(offset);
        }
        break;

        case 'b':
        Serial.println(F("Read bootblock"));
       
        for (unsigned long offset = 0x0000; offset<=0x3FFF; offset = offset + 0x02)
        {
           shiftRWord(offset);
        }
        break;

        case 's':
        Serial.println(F("Read securityblock"));
       
        for (unsigned long offset = 0x4000; offset<=0x7FFF; offset = offset + 0x02)
        {
           shiftRWord(offset);
        }
        break;

        case 'd':
        Serial.println(F("Read cardata"));
       
        for (unsigned long offset = 0x8000; offset<=0x1FFFF; offset = offset + 0x02)
        {
           shiftRWord(offset);
        }
        break;

        case 'f':
        Serial.println(F("Read firmware"));
       
        for (unsigned long offset = 0x10000; offset<=0x7FFFF; offset = offset + 0x02)
        {
           shiftRWord(offset);
        }
        break;

        case 'c':
        Serial.println(F("BD32 Command Mode"));

        serialFlush();
        while(!Serial.available());
        {
        }
        break;

        default:
        break;

        case 'i':
        Serial.println("wipe");
        for (int i=0; i<=250; i++)
        {
          digitalWrite(BKPT, LOW);
          delay(1);
          digitalWrite(BKPT, HIGH);
          delay(1);
        }
        break;
      }
    }

}


void shiftRWord(unsigned long val)
{
    word i;
    word lowbyte = val;
    word hibyte = val >> 16;

    //Wait for DSO to get 0 => gets ready
   wait_openchannel();

    bdm_command(CMD_READ);
    shift_BKPT_up();
    shift_BKPT_up();
    


     for (i = 0; i < 16; i++)  {  //HighByte


        digitalWrite(DSI, !!(hibyte & (1 << (15 - i))));
        shift_BKPT_up();
    }
        digitalWrite(DSI, LOW);
        delayMicroseconds(1);
        shift_BKPT_up();



     for (i = 0; i < 16; i++)  {  //LowByte


        digitalWrite(DSI, !!(lowbyte & (1 << (15 - i))));
        shift_BKPT_up();
    }
    digitalWrite(DSI, LOW);
    delayMicroseconds(1);


    word W_Read;

    for (i= 0; i < 1; i++)   //Read Status Byte
    {
      //digitalWrite(BKPT, HIGH);
      //delayMicroseconds(1);
      digitalWrite(BKPT, LOW);
      delayMicroseconds(1);
      //Serial.print(digitalRead(DSO));
    }

    for (i= 0; i < 16; i++) //Read back
    {
      digitalWrite(BKPT, HIGH);
      delayMicroseconds(1);
      digitalWrite(BKPT, LOW);
      delayMicroseconds(1);
      //Serial.print(digitalRead(DSO));
       bitWrite(W_Read,(15-i),digitalRead(DSO));
    }

    check_lzero(W_Read);

    if (n_line <=6)
    {        
       Serial.print(W_Read,HEX);
       Serial. print(" ");
       n_line++;
    }else{
      Serial.println(W_Read,HEX);
      n_line = 0;
    }

   
    //return W_Read;
}


 void write_Register(word cmd, unsigned long addr)
 {
    word lowbyte = addr;
    word hibyte = addr >> 16;

    wait_openchannel(); //Wait for DSO to get 0 => gets ready
    bdm_command2(cmd);
    shift_BKPT_up();

    for (int i = 0; i < 16; i++)  {  //HighByte OFFSET
        digitalWrite(DSI, !!(hibyte & (1 << (15 - i))));
        shift_BKPT_up();
    }
    digitalWrite(DSI, LOW);
    delayMicroseconds(1);
    shift_BKPT_up();

    for (int i = 0; i < 16; i++)  {  //LowByte OFFSET
        digitalWrite(DSI, !!(lowbyte & (1 << (15 - i))));
        shift_BKPT_up();
    }
    digitalWrite(DSI, LOW);
    delayMicroseconds(1);
 }
 

 void check_lzero(word W_Read){
      if (W_Read < 0x10)
      {
        Serial.print("000");
        return;
      }
        
      if (W_Read < 0x100)
      {
        Serial.print("00");
        return;
      }
      if (W_Read < 0x1000)
      {
        Serial.print("0");
        return;
      }
     }

 void shift_BKPT_up()
 {
      digitalWrite(BKPT, LOW);
      delayMicroseconds(1);
      digitalWrite(BKPT, HIGH);
      delayMicroseconds(1);
 }

 void wait_openchannel()
 {
      while(digitalRead(DSO)!=0)
    {
      shift_BKPT_up();
    }
     while(digitalRead(DSO)!=1)
    {
      shift_BKPT_up();
    }
 }

 void bdm_command(word command)
 {
  for (int i = 0; i < 15; i++)  {  
        digitalWrite(DSI, !!(command & (1 << (15 - i))));
        shift_BKPT_up();
    }
  digitalWrite(DSI, LOW);
 }

  void bdm_command2(word command)
 {
  for (int i = 0; i < 16; i++)  {  
        digitalWrite(DSI, !!(command & (1 << (15 - i))));
        shift_BKPT_up();
    }
  digitalWrite(DSI, LOW);
 }

 void serialFlush(){
  while(Serial.available() > 0) {
    char t = Serial.read();
  }
}   
BKPT to D4
RESET to D5
FREEZE to D6
DSI to D7
DSO to D8

2 options, connect the 5V line at the capacitor, or connect the 12V at the CEMs main connector. Both connections 5V and +12V are not needed together...

Masse means GND
If you use 12V power supply connect GND from it also to arduios GND, so they should have common GND.

Copy content to HXD and save to BIN file.

Open bin file by this tool, make the changes you like and write this data back to cem by DICE-206751.
It would be nice to get paramter file fills up by the community if you need this tool...

As everything by me it is free, also free to analyze and build your own tools out of it...

Self i test this tools tomorrow, if it has bugs i will fix them... Have fun...
Finally got around to trying this, but I am only getting 0000s dumped as binary which is obviously nothing and it’s very sporadic. I have verified all of my connections, fortunately I did not kill CEM in the process. I wonder if trying 12 volts would be better vs 5v. The CEM only needs ground if using 12 volt source correct? I’m using probes and a frame and think maybe 5v off the arduino is a bit touchy through the probes
Figured maybe probes on the pads had too much resistance, attempted to solder and lifted one… I knew I shouldn’t have attempted that with subpar equipment. CEM still functions, could probably save the pad with more skills but that CEM is almost done anyway. Freaks out every time it gets cold out. Is there any other way I can access the flash using T5Luke’s tool? Maybe from the other side? I’d like to take a dump of this. I can get the pin via can logging while doing a software download but do not have access to a tool to change the configuration, which is why his program seemed so useful

vtl
Posts: 4724
Joined: 16 August 2012
Year and Model: 2005 XC70
Location: Boston
Has thanked: 114 times
Been thanked: 604 times

Post by vtl »

LukeFlynn wrote: 01 Nov 2023, 20:00 Figured maybe probes on the pads had too much resistance, attempted to solder and lifted one… I knew I shouldn’t have attempted that with subpar equipment. CEM still functions, could probably save the pad with more skills but that CEM is almost done anyway. Freaks out every time it gets cold out. Is there any other way I can access the flash using T5Luke’s tool? Maybe from the other side? I’d like to take a dump of this. I can get the pin via can logging while doing a software download but do not have access to a tool to change the configuration, which is why his program seemed so useful
You can always use a hot air to blow the flash chip off and read it in a programmer like TL866a.

Post Reply
  • Similar Topics
    Replies
    Views
    Last post