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
dikidera
Posts: 1304
Joined: 15 August 2022
Year and Model: S60 2005
Location: Galaxy far far away
Has thanked: 67 times
Been thanked: 175 times

Re: Vida CEM swapping

Post by dikidera »

The features are small, but the biggest deterrent is the jelly. I wish to avoid removing it as it has useful properties, and the bonding wires probably need between 0.5 to 1.5 newtons of force to break as they are between 12-25 microns in width, which isn't very much.

As such I figured this was the only way, and my hunches were correct. I just need more weight and less movement of the "probes".

I have high confidence I will succeed.

scaro
Posts: 47
Joined: 22 April 2021
Year and Model: Volvo&Audi
Location: Sweden
Has thanked: 14 times
Been thanked: 1 time

Post by scaro »

Yes, same as when trying repair ABS or other that use "jelly". The very very small goldwires are hard to fix. The bigger ones is possible sometimes. Using good flux and clean well.
It would be nice to have a bounding machine but i think its not "just" have one that is hard.

The pogopin probes i have is sharp as a needle (there is alot of different ones) and stays in place but could be hard to get to right place when using many close togheter.

Of course you will succeed... its fun reading about how it goes anyway
244 Turbo (86K miles) 1983
242 B230FK, Rollcage, LSD 1984
244 B21A with R-Sport Turbo-kit 1980
A5 2.0TFSI Quattro Conv. 2012
A4 1.9TDI 1997 BV43, 11mm vp37, 0.26 nozzels, 6speed, A8 brakes front, S4 discs/calibers rear
A4 1.9TDI 1998 Daily

Treur
Posts: 126
Joined: 16 November 2024
Year and Model: 2007 V70
Location: Estonia
Has thanked: 3 times
Been thanked: 6 times

Post by Treur »

scaro wrote: 14 Jan 2025, 11:53 Is it 2020 ETM? Havent take any of them apart. Have a couple old MMs but havnt taken them apart yet. I was just thinking that the chips you talked about is "old". Is these inside really? :)

I now that i should have files for "upgraded" ETM (Magnetti Marelli) for the Brick P2 somewhere. Upgraded them with SDA long time ago.
Not that it will help you in this case.
Do you have SDA files for Marelli? I need SBL. Want to try for reflash.

dwappertam
Posts: 9
Joined: 2 January 2025
Year and Model: 2001 S60 P2
Location: On this planet
Has thanked: 3 times

Post by dwappertam »

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...


Will this work for a 2001 Cem-B
Thanks for placing this shit learning allot from all of u. While i stil got lost and lots to learn i am figuring it out on the go . .

Dudde
Posts: 64
Joined: 22 January 2020
Year and Model: 2005 V70 and more
Location: Finland
Has thanked: 14 times
Been thanked: 17 times

Post by Dudde »

Hi, i have CEM L with serial number 00004xxxxxx, is it possible to swap it for newer 00005xxxxxx SN CEM?

Or if anyone have a way of decrypting 93LC86C eeprom? I have lost sync and do not have tools for decrypting eeprom from cem?

dwappertam
Posts: 9
Joined: 2 January 2025
Year and Model: 2001 S60 P2
Location: On this planet
Has thanked: 3 times

Post by dwappertam »

Anybody can give me some advice about going after the BDM way for my 2001 cem-b for a s60.
Sorry for my bad english ,yes i am trying. So hang on.
I see that there are a couple of way's for arduino,... The Nano version from T5Luke, or the Atmega2560 Pro mini from CKeav https://www.drive2.ru/l/580486615202272050/
Both using the bdm ways, whats the difrence ?.

I looked at the OBD cracking Way's and that also confuses me a bit, there is the teensy code from vtl, and the code from ALEXPUX https://gitee.com/mirrors_Alexpux/volvo-cem-cracker, ..
What is the diffrence beside just the code.
My 2001 s60 { 9452596, CAN_250KBPS, 0 }, is listed in vtl's code but is it usable to crack the pin . if so how can i make it work, what do i have to put in the code and where .?

For the BDM part i got,
Arduino Nano v3 clone
Mega2560 pro Mini clone
For the Teensy way i got the 4.0 and the 4.1.
And a mcp2515 , even got the A82C50 one's and also the MCZ33661 witch what i think is the k-line chip from inside a 28f400 CEMB that has been ruined by morons. Yeah thanks for that, i have the transceivers and the flash and the rest of the chips . are those usable for the teensy way ?
Hopefully anybody can help with either the BDM proces to get a copy from my cem from start to finish , or the cracking proces.

Thank u all for posting your knowledge, i am learning alot .
Greetz

dikidera
Posts: 1304
Joined: 15 August 2022
Year and Model: S60 2005
Location: Galaxy far far away
Has thanked: 67 times
Been thanked: 175 times

Post by dikidera »

Considering I am also working on an MC683XX chip, I used this Arduino library https://github.com/psobot/arduino-coldfire-bdm

It won't work out of the box as it uses Python 3.6 features which have been disabled in Python 3.7 and onwards, specifically nullcontext from contextlib package. However the code itself is useable.

The 28f400 is a standard memory chip, has nothing to do with K-line or whatever. The only caveat with the 28X, 29X chips is that they do not use any sort of serial communication but each data and address pin needs to be connected for a total of 32(maybe 33) pins, which is why BDM helps here. I have been crazy enough to solder 32 pins however and successfully read a 29LV200BC chip off a Denso board with an Arduino.

You are lucky to have such easy access to those chips.

I on the other hand have to be creative

Image

Image

dikidera
Posts: 1304
Joined: 15 August 2022
Year and Model: S60 2005
Location: Galaxy far far away
Has thanked: 67 times
Been thanked: 175 times

Post by dikidera »

As I suspected. I've erased the initial stack + PC pointers at top(bottom?) of boot block.

Oh yeah. I did it. I BDM'ed the ETM using T5Luke's code.

EDIT: I wish to announce with a lot of work, I have managed to revive my ETM. It no longer needs BDM.

Patches for T5Luke's Arduino code to allow probing of system control registers

Code: Select all

void ReadSysReg(word addr)
{
    word i;
    word lowbyte = 0x0;
    word hibyte = 0x0;

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

    bdm_command2(addr);
    //bdm_command2(0x0);
    shift_BKPT_up();
    shift_BKPT_up();


    delayMicroseconds(1);


    long W_Read = 0;

    for (i= 0; i < 32; i++) //Read back
    {
        digitalWrite(BKPT, HIGH);
        delayMicroseconds(1);
        digitalWrite(BKPT, LOW);
        delayMicroseconds(1);
        //Serial.print(digitalRead(DSO));
        if (digitalRead(DSO)) {
          W_Read |= (1UL << (31 - i));  // Set bit at position (31 - i)
        } else {
          W_Read &= ~(1UL << (31 - i)); // Clear bit at position (31 - i)
        }

    }

  long upper_16 = (W_Read & 0xFFFF0000) >> 1;  
  long lower_16 = W_Read & 0x0000FFFF;         
  W_Read = upper_16 | lower_16; 
  if (W_Read < 0x10) 
  {
    Serial.print("0");  // Add leading zero if necessary
  }
  if (W_Read < 0x1000) 
  {
    Serial.print("00");  // Add leading zero if necessary
  }
    if (n_line <=6)
    {        
       Serial.print(W_Read,HEX);
       Serial. print("");
       n_line++;
    }else{
      Serial.println(W_Read,HEX);
      n_line = 0;
    }

    Serial.println();
   
    //return W_Read;
}

Code: Select all

 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);
 }
Used

write_Register(0x2480, 0x16000); // Set RPC system control register
write_Register(0x248C, 0x41E00);
write_Register(0x248D, 0x41E00);
ReadSysReg(0x2580);
ReadSysReg(0x2589);
ReadSysReg(0x258D);
write_Register(0x0800, 0x16000); // CALL command for special redundant PBL I created

duzi
Posts: 21
Joined: 16 September 2021
Year and Model: S60
Location: Lithuania
Has thanked: 18 times
Been thanked: 5 times

Post by duzi »

Dudde wrote: 17 Jan 2025, 09:07 Hi, i have CEM L with serial number 00004xxxxxx, is it possible to swap it for newer 00005xxxxxx SN CEM?

Or if anyone have a way of decrypting 93LC86C eeprom? I have lost sync and do not have tools for decrypting eeprom from cem?
yes, it can be done

mikeak2001
Posts: 29
Joined: 30 March 2021
Year and Model: S70 1998 T5
Location: Wales
Has thanked: 3 times
Been thanked: 28 times

Post by mikeak2001 »

Is it possible for any of you programmers in this thread to help me out?
I promise at the end of my project there will be a sweet surprise for end users but I need help or some pointers on the following:

Using Visual Studio 2022 C++, I want to use dice J2534 commands, can anyone point me in the direction of how to do this?
What do I need to import etc?
I know SDA has a sample project but it doesn't explain much.
If I do a driver function extraction on known apps that work with dice I don't see the dice drivers getting loaded.

I know some of you have made apps for dice reading and flashing, you don't have to give me a step by step but some good pointers would do the trick.

Thank you all

Post Reply
  • Similar Topics
    Replies
    Views
    Last post