You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Some notes on working with a used C300 (2011) cluster that I obtained recently, which may be helpful to someone else.
Connectivity
The instrument cluster is connected to the vehicle from a single cable assembly with a 19-pin connector. Faint pin numbers (1, 9, 10, 18) should be visible in the socket itself.
The pin pitch is 2.54mm (0.1") and readily accepts hobbyist jumper cables. This socket design is commonly used across MB vehicles of its generation, and its pin definition can be obtained from Elektrischer Schaltplan Steuergerät Kombiinstrument (KI).
CAN-E ("Fahrwerk-CAN" / "Chassis-CAN")
This bus operates at 500KBaud over UDS. This is the preferred interface as the command set and communication parameters are well defined in the IC_204.cbf diagnostics file.
CAN-B ("Innenraum-CAN" / "Interior-CAN")
Most properties and contents in this bus is unknown (to me) as the data is not specified in the CBF diagnostics file, and I do not have the environment to capture traces.
OBD-II pinout to J2534 hardware
For convenience, the above diagram shows a suggested pinout to communicate with the cluster. 12V to the J2534 device is optional.
Termination resistors
CAN networks require two 120Ω termination resistors on both ends of the network to operate properly. In this case, a 60Ω to 120Ω resistor should be inserted between CAN+ and CAN- anywhere on the connection.
Interaction
For use in simulators or general purpose displays, the cluster has to be able to:
Wake up and receive commands ✅
Control the pointers/gauges ✅
Control the display ✅
Control the indicator LEDs ❌
So far, the cluster is "usable" as a simulation display, but the inability to control any of the LEDs (especially the turn signals) is a major impediment.
Waking the device
Normally, the cluster remains in a low-power sleep state when 12V power is applied. The device should fully wake when requested by the EIS i.e when the key is inserted and turned.
In my case, I do not have access to an EIS. This is a workaround that I found:
Enter a diagnostic session
(Subsequently also requires regular TesterPresent messages 3E 00 at 2000ms intervals)
10 03
Enter the pointer control mode and set the engine temperature gauge position to 0, to keep the cluster awake
31 01 00 10 03 00 00
The cluster should be online at this point. However, in my case, the mileage value was not visible.
To view the mileage on the display, exit the pointer control mode, and the mileage should be displayed briefly before the cluster enters its sleep mode.
31 02 00 10
Note: The cluster appears to run a stepper homing routine on power up (12V) and sometimes upon detection of any CAN-E signal.
Pointer control
The cluster that I am using has gauges for the speedometer, tachometer, fuel level and temperature. The gauges can be individually controlled with:
PP PP : Pointer position percentage in big-endian. (0: 0%, 1000: 100%)
Example: To set the speedometer pointer (spanning from 0 to 160mph) on 80mph:
Selected gauge = 0 (speedometer), Pointer position = 500 (80/160*1000)
The command will therefore be 31 01 00 10 00 01 F4
To exit the pointer control mode and release all the pointers, send 31 02 00 10.
Note: The floating pointer for the speedometer has some latency when responding to rapid speed changes.
Display control
The cluster's display measures 200px wide and 150px high, and includes a set of primitive draw commands.
The useful routines to look out for are RT_Displaytest_Set_Pixel_Start , RT_Displaytest_Set_Rectangle_Start and RT_Displaytest_Set_Text_Start. Screen coordinates and pixel widths are 16-bit big-endian integers, and color is represented by a single byte (01 = white, 00 = black).
A font has to be specified for the text draw routine, and each font has its own character set, encoding and constraints. For example, numeric fonts such as 1, 2 do not have support for alphabetic characters. Strings are null terminated, and the draw coordinates define the center of the drawn text.
Notes:
A small portion on the top of the display seems to have physical pixels, but is not addressable.
To clear the screen, draw a rectangle with a color of 0 at 0,0 with a size of 200x150.
To exit the display-test mode, send 31 02 00 06.
ART Segment Display
The 204 cluster has a fascinating segmented display feature that is activated during cruise control, indicating the speed setpoint. The 64 segments are not bound to the pixel grid, and seems to behave more like a second, independent LCD that is stacked over the standard display.
To activate it, send a value between 31 01 00 0D 00 00 00 00 00 00 00 00 and 31 01 00 0D FF FF FF FF FF FF FF FF , where the bits control individual segments.
Others:
Chime (seatbelt warning?) : 31 01 00 04
Full lamp test : 31 01 00 09
RT_Beleuchtung_dimmen_Start appears to have some sort of backlight control. The values are mapped across bit boundaries which is currently unsupported in Caesar.
EEPROM
While the uC is capable of storing non-volatile data, its memory is fully reserved for its firmware. User settings are stored on an external 16KB 24LC128 EEPROM which is accessible over I2C. The EEPROM is found on the opposite layer, directly under the uC, and exposing it requires a few minutes of disassembly.
Backing up the EEPROM is strongly recommended before doing anything with the cluster.
The EEPROM is 5V-tolerant, and can be easily accessed from most microcontrollers. I used an ESP32 to dump the its contents:
When the EEPROM is read externally, remember to add pullup resistors as I2C is an open-drain bus, and pull the write protect pin to VCC (or GND only if writing).
The EEPROM can be (probably) be read while in-circuit as well: conveniently, several test points are exposed. The uC must be held in reset during this process, else the data will be corrupted if a spurious request was inserted in the middle of an operation. The reset pin is routed under the uC, and it may be easier to short the primary crystal to stop the processor.
Hardware
The heart of this cluster is a NEC (now Renesas) µPD70F3426GJ, with a RISC-ish V850E architecture.
The processor is intended for automotive use, and comes with 2048 kbytes of internal flash, 84kbytes of internal RAM, and a bunch of helpful peripherals such as I2C, CAN, stepper drivers and LCD interfaces. Fortunately, the datasheet can be found online on unofficial sources (search for "UPD70F3426GJ", peripherals/registers: "RNCCS17265-1").
The uC's embedded flash is capable of self-reprogramming. User-facing portions of the memory (SW1, SW2) can be found in the flash CFF files. However, the bootloader memory does not seem to be publicly available since the bootloader was not intended to be updated.
The uC can be reprogrammed, however the entire memory has to be erased, which would be an issue as I will not be able to restore its original functionality without the bootloader.
At this point, I have tried:
UDS: Request upload (0x35), unimplemented in both bootmode (at access level 5) and extended session (default access level)
UDS: Read Memory By Address (0x23), unimplemented in bootmode, rejected in extended session (default access level), though this command probably reads from the I2C EEPROM instead of the flash memory, which is undesirable in this situation.
I did not try:
External ISP read : the uC has protection mechanisms that I am pretty sure that I can't circumvent.
External ISP erase : the protection mechanism specifically prevents partial erases if the protection bits are set.
Bootmode erase : Unlike VW, there does not seem to be a granular block erase function. It is implemented as a single routine 31 01 FF and has no configurable parameters. Later revisions accept erasing of individual logical blocks.
There are two major hindrances when trying to load the firmware in Ghidra:
The architecture has a special callt instruction. If I understand correctly, function pointers are stored in a table (similar to interrupts), and callt is an easier way to call a function by specifying its table index. Ghidra does not follow these calls.
I have no idea where the application entrypoint is, since the original entrypoint starts at the bootloader. The bootloader first verifies the firmware against a signature and checksum block ("software interlock" aka "SWIL"), before jumping into the application entrypoint. Ghidra's "Aggressive instruction finder" yields some results, but generates a lot of false positives that requires a lot of sifting.
Uncategorized
In this specific firmware, the string 10156593AF seems to mark out several memory regions, and might be related to the SWIL process.
Visualization of the firmware using binvis.io: a small section of the start of the memory map is blank, and the tail end of the memory appears to have a block named "DUMMY".
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Some notes on working with a used C300 (2011) cluster that I obtained recently, which may be helpful to someone else.
Connectivity
The instrument cluster is connected to the vehicle from a single cable assembly with a 19-pin connector. Faint pin numbers (1, 9, 10, 18) should be visible in the socket itself.
The pin pitch is 2.54mm (0.1") and readily accepts hobbyist jumper cables. This socket design is commonly used across MB vehicles of its generation, and its pin definition can be obtained from Elektrischer Schaltplan Steuergerät Kombiinstrument (KI).
CAN-E ("Fahrwerk-CAN" / "Chassis-CAN")
This bus operates at 500KBaud over UDS. This is the preferred interface as the command set and communication parameters are well defined in the
IC_204.cbf
diagnostics file.CAN-B ("Innenraum-CAN" / "Interior-CAN")
Most properties and contents in this bus is unknown (to me) as the data is not specified in the CBF diagnostics file, and I do not have the environment to capture traces.
OBD-II pinout to J2534 hardware
For convenience, the above diagram shows a suggested pinout to communicate with the cluster. 12V to the J2534 device is optional.
Termination resistors
CAN networks require two 120Ω termination resistors on both ends of the network to operate properly. In this case, a 60Ω to 120Ω resistor should be inserted between CAN+ and CAN- anywhere on the connection.
Interaction
For use in simulators or general purpose displays, the cluster has to be able to:
So far, the cluster is "usable" as a simulation display, but the inability to control any of the LEDs (especially the turn signals) is a major impediment.
Waking the device
Normally, the cluster remains in a low-power sleep state when 12V power is applied. The device should fully wake when requested by the EIS i.e when the key is inserted and turned.
In my case, I do not have access to an EIS. This is a workaround that I found:
Enter a diagnostic session
(Subsequently also requires regular TesterPresent messages
3E 00
at 2000ms intervals)10 03
Enter the pointer control mode and set the engine temperature gauge position to 0, to keep the cluster awake
31 01 00 10 03 00 00
The cluster should be online at this point. However, in my case, the mileage value was not visible.
To view the mileage on the display, exit the pointer control mode, and the mileage should be displayed briefly before the cluster enters its sleep mode.
31 02 00 10
Note: The cluster appears to run a stepper homing routine on power up (12V) and sometimes upon detection of any CAN-E signal.
Pointer control
The cluster that I am using has gauges for the speedometer, tachometer, fuel level and temperature. The gauges can be individually controlled with:
31 01 00 10 GG PP PP
GG
: Selected gauge (0: speed, 1: fuel level, 2: RPM, 3: temperature)PP PP
: Pointer position percentage in big-endian. (0: 0%, 1000: 100%)Example: To set the speedometer pointer (spanning from 0 to 160mph) on 80mph:
Selected gauge = 0 (speedometer), Pointer position = 500 (80/160*1000)
The command will therefore be
31 01 00 10 00 01 F4
To exit the pointer control mode and release all the pointers, send
31 02 00 10
.Note: The floating pointer for the speedometer has some latency when responding to rapid speed changes.
Display control
The cluster's display measures 200px wide and 150px high, and includes a set of primitive draw commands.
The useful routines to look out for are
RT_Displaytest_Set_Pixel_Start
,RT_Displaytest_Set_Rectangle_Start
andRT_Displaytest_Set_Text_Start
. Screen coordinates and pixel widths are 16-bit big-endian integers, and color is represented by a single byte (01 = white, 00 = black).A font has to be specified for the text draw routine, and each font has its own character set, encoding and constraints. For example, numeric fonts such as 1, 2 do not have support for alphabetic characters. Strings are null terminated, and the draw coordinates define the center of the drawn text.
Notes:
To exit the display-test mode, send
31 02 00 06
.ART Segment Display
The 204 cluster has a fascinating segmented display feature that is activated during cruise control, indicating the speed setpoint. The 64 segments are not bound to the pixel grid, and seems to behave more like a second, independent LCD that is stacked over the standard display.
To activate it, send a value between
31 01 00 0D 00 00 00 00 00 00 00 00
and31 01 00 0D FF FF FF FF FF FF FF FF
, where the bits control individual segments.Others:
31 01 00 04
31 01 00 09
RT_Beleuchtung_dimmen_Start
appears to have some sort of backlight control. The values are mapped across bit boundaries which is currently unsupported in Caesar.EEPROM
While the uC is capable of storing non-volatile data, its memory is fully reserved for its firmware. User settings are stored on an external 16KB 24LC128 EEPROM which is accessible over I2C. The EEPROM is found on the opposite layer, directly under the uC, and exposing it requires a few minutes of disassembly.
Backing up the EEPROM is strongly recommended before doing anything with the cluster.
The EEPROM is 5V-tolerant, and can be easily accessed from most microcontrollers. I used an ESP32 to dump the its contents:
When the EEPROM is read externally, remember to add pullup resistors as I2C is an open-drain bus, and pull the write protect pin to VCC (or GND only if writing).
The EEPROM can be (probably) be read while in-circuit as well: conveniently, several test points are exposed. The uC must be held in reset during this process, else the data will be corrupted if a spurious request was inserted in the middle of an operation. The reset pin is routed under the uC, and it may be easier to short the primary crystal to stop the processor.
Hardware
The heart of this cluster is a NEC (now Renesas) µPD70F3426GJ, with a RISC-ish V850E architecture.
The processor is intended for automotive use, and comes with 2048 kbytes of internal flash, 84kbytes of internal RAM, and a bunch of helpful peripherals such as I2C, CAN, stepper drivers and LCD interfaces. Fortunately, the datasheet can be found online on unofficial sources (search for "UPD70F3426GJ", peripherals/registers: "RNCCS17265-1").
The uC's embedded flash is capable of self-reprogramming. User-facing portions of the memory (SW1, SW2) can be found in the flash CFF files. However, the bootloader memory does not seem to be publicly available since the bootloader was not intended to be updated.
The uC can be reprogrammed, however the entire memory has to be erased, which would be an issue as I will not be able to restore its original functionality without the bootloader.
At this point, I have tried:
I did not try:
31 01 FF
and has no configurable parameters. Later revisions accept erasing of individual logical blocks.Firmware
A disassembler for Ghidra is available at https://github.com/esaulenka/ghidra_v850 , and it does a very respectable job of generating valid, readable results.
There are two major hindrances when trying to load the firmware in Ghidra:
callt
instruction. If I understand correctly, function pointers are stored in a table (similar to interrupts), andcallt
is an easier way to call a function by specifying its table index. Ghidra does not follow these calls.Uncategorized
10156593AF
seems to mark out several memory regions, and might be related to the SWIL process.Beta Was this translation helpful? Give feedback.
All reactions