3P's TCCS Disassembly/Analysis

Oct 11, 2005
3,814
13
38
Thousand Oaks, CA
It's remarkable that after nearly 20 years the Toyota Computer Control System (TCCS) engine management computer used for the 7M remains a mystery as far as the public domain is concerned. Partly, this is because it uses a proprietary Denso microprocessor with zero official documentation available outside of Toyota, and also because the 12kB of ROM code is burned into the microprocessor itself making extraction a major effort, and also preventing any code changes without adding a complex daughter board to allow the processor to run with external memory.

Although several commercial companies cracked it (Techtom, Mines) they kept everything secret and in the case of Techtom even went as far as to encrypt their own code to discourage reverse engineering.

One Japanese site run by H. Kashima has published significant information on the microprocessor architecture, including schematic and layout of a nice board to read the code burned into the microprocessor. He also developed a disassembler for the processor, and has put together a datasheet for the chip pinout, register and memory structure, and so on. Probably because it is written in Japanese, and also because Kashi decided to sell his disassembler and processor datasheet rather than make them public domain, not too many have taken advantage of his hard work in this area.

Recently, Jeremy Ross a guy who hangs out on the UK MR2 forum IMOCUK, has developed a very nice daughter board and software to allow real time data logging and updating of the code tables in the MR2 Gen 1 and 2 ECUs, which are essentially identical to the 7M ECUs of the same vintage. However, Jeremy keeps most of his info to himself, and obviously has plans to sell his ECU kits, so once again nothing gets disclosed publicly.

Against this backdrop of secrecy, there is one glimmer of hope, which is a Canadian based Toyota ECU Wiki. Although not exactly a hotbed of activity, it does have some of Kashi’s stuff translated to English, and also a public domain disassembler for the micro written in Perl.

So, the purpose of this thread will be to read out and analyze the code embedded in these ECUs, and to analyze and publish the various fuel/ignition maps and algorithms used by the 7M ECU.

Acknowledgements:
A couple of people on the forums have helped me out by donating ECUs, and or getting them to me at way below market value.

S383mmber1 (William) gave me a 7MGE M/T ECU. This is an early ECU with only a single circuit board inside. As such, it is probably the best place to start as it is the simplest to analyze.

Supraholics (Miguel) sent me two ECUs including a grey plug 7MGTE M/T ECU for shipping only. This is going to be my first mule for testing things out.
 
Last edited:
Oct 11, 2005
3,814
13
38
Thousand Oaks, CA
Okay, we start with Williams 7M-GE M/T ECU. First step was to build the ECU reader, which closely follows the one published by Kashi.

I swapped a few components that I couldn't find here in the U.S., but otherwise it is the same. The schematic is attached as a thumbnail to this post. I had about 6 reader printed circuit boards fabricated, so anyone interested can buy one from me.

The reader board uses its own code burned into the 28C256 EEPROM on the board to run the microprocessor. It works by running the micro in a hybrid mode, where it can access both internal and external memory at the same time. A simple serial port interface connects to hyperterminal on a windows PC, and the code is dumped out on the terminal where it can be saved to a file. Kashi supplies a crippled demo copy of the assembly code he used to extract the ECU ROM. With an evening's work tracing his code, it turns out a simple change to one line of demo code is all that is needed to allow the extraction of the entire 12kB stored in the ROM.

Once the code is out, you can run a disassembler to convert it to assembler. Then comes the real challenge, interpreting the assembler to understand how the code controls the engine, discovering and analyzing the built-in maps, and learning how the various engine sensors and controls interface to the micro.

By the way, Jeremy Ross has discovered a high-speed data-logging feature hidden in the code that Toyota used during development. Every variable in the system can be read out up to 200 times a second with 16 bit accuracy. Explaining how to access this datalogger will be one of the first things tackled in this thread.

Below find a photo of the ECU reader board assembled and loaded with the target ECU, a D151801-3920 from William's ECU. Also, a schematic of the reader board, and hopefully the extracted binary code if I can figure out how to attach it to this post.

img4429fr9.jpg



 

Attachments

  • D151801-3920.zip
    9.6 KB · Views: 49
Oct 11, 2005
3,814
13
38
Thousand Oaks, CA
It's a good question, and ultimately depends on how much time I can spend doing this.

First priority is to disseminate info on how these ECUs calculate engine operating parameters, and to publish the 7M ignition/fuel maps.

I already have a daughter board fabricated that will allow me to run the processor from code in an external EEPROM. This allows things like fuel-cut, AFM scaling, ignition maps and so on to be modified. But the process is clunky, you need to FLASH and swap the memory chip to make any changes. Its basically what Mines and Techtom offered back in the day.

Ultimately, I would like to go down the path of Jeremy Ross and work out a way to do real time changes to the maps. That will take some effort as you need to run the code in RAM, and write the software to do datalogging and map tweaking from a laptop. It's my goal, but it's a ways off right now.

I have little interest in making a business out of any of this. I have a real job so I see this as more of a hobby. Some things I may decide to sell if there is interest, such as pcb boards as they can be expensive and time consuming to have fabricated and I have a bunch of extras sitting around.
 

Brutus

New Member
Jun 16, 2008
32
0
0
Vosgian mountains, France
Hello,

First of all 3p141592654, thanks a lot for releasing this binary file.
This is a great job you've done extracting it! :bigthumb:

The file is 12Ko and doesn't cover the whole 64Ko address space.
If I read the address map on the Toyota wiki (thanks to Greg Kunyavsky for this), it tells us about the D151801 memory map that there's 12ko of ROM memory.

I dissasembled the file using the Perl program (written by Greg Kunyavsky again).
Seeing the addresses started at 0x0000, I decided to make it start at 0xE000, which is the starting address of the ROM inside the CPU.
This file is attached to this post.

If we take a look at the memory map again, we can see that the reset vector is stored at 0xFFFE.
The reset vector is used when the chip is powered on or reset to lead the CPU to the beginning of the program.
This 16bit address leads us to 0xF053

I have to get used to this processor mnemonics but if read the first instructions at 0xF053 while looking at the memory map at the same time:

ld #0x7, $0x1F // Sets the five least significant bit of the SMR register to 1
di // Disable interrupts
ld #0xD, $0x20 // inits the timer comparison LSB with the port A data (?)
ld #0xF, $0x0 // inits the timer comparison #3 with the port A direction status (?)
ld #0x40, $0x22// Sets the first byte of the RAM with the port B data
ld #0xFF, $0x1 // Sets the last byte of the RAM with the port B direction status


I still don't know the exact purpose of these inits, but looking at this, we can see that these instructions are matching correctly and that this looks like what the begining of a program in assembly often looks like.
By the way, if we try to take a look at the instructions before 0xF053, we see no logic at all from one instruction to another, which leads me into thinking this is some data space that is used for ignition, fuel map or whatever.

3p141592654, if you still have one of these TCCS reader PCB, I would be glad to buy one (or even better, two of them since my soldering skills are average, to say the least).
 

Attachments

  • D151801-3920asm.zip
    52.6 KB · Views: 21
Last edited:
Oct 11, 2005
3,814
13
38
Thousand Oaks, CA
Good work Brutus, nice to know I'm not the only one with some disassembler skills. A much delayed tapeout for a IC amplifier project I am working on plus last week spent in Atlanta at the IEEE microwave symposium is keeping me from pursuing this project lately, but I will pick it back up in a few weeks.

I have slightly different interpretation of the start code, using some of the data I know about the lower bytes of the CPU (my addressing is off, as you noted, but easily fixed-up).

Note that #0x07 means load immediate, so for the first instruction $_OMODE=0x07 rather than a memory reference i.e. it is not $_OMODE=[0x07]

Also note, that for no good reason the operands are swapped for immediate loads. All other "load" instructions are op.1=op.2, so that is probably why you got confused. This inconsistency is a quirk carried over from the Motorola 6800 assembler, proving bad ideas never die I guess!

; reset vector
002053 33071f ld #0x07, $_OMODE ; run internal mode
002056 05 di ; disable interrupts
002057 330d20 ld #0x0d, $_PORTA ; set port A o/p bits
00205a 330f00 ld #0x0f, $_DDRA ; configure i/p bits Port A
00205d 334022 ld #0x40, $_PORTB ; set port B o/p bits
002060 33ff01 ld #0xff, $_DDRB ; configure i/p bits Port B


I'm still struggling to get IDA running right, but that will help alot compared to trying to do this with a simple disassembler. I also need to better understand the mapping of the ports, timers, edge sensors, and so on to the actual engine sensors/actuators. That takes a lot of circuit tracing on the ECU board, and is very painful.

I have extra boards, and I think I have extra parts as well if you want to buy a kit.
 
Last edited:
Oct 11, 2005
3,814
13
38
Thousand Oaks, CA
Ian, as it stands we are just pulling apart the code and learning how things work. We need to isolate the maps and figure out the algorithms they use before we can move to the next step of plotting the maps and deciding what to change.

I have a very simple board made that can be used to run new code stored in an EEPROM, and bypass the stuff burned into the factory ECU. That would allow changes to be made, but its not very practical to tune this way since you have to physically swap the EEPROM each time. I also want to get access to the ECU real time data so that we can start doing logging. The logging software is all still there, just need to add the interface to a laptop like others have done fro the MR2.

Longer term I want to be able to run the code in RAM so that changes to the maps can be done via lap top interface. That's still way off in the future for now.

Shaeff, thanks for the offer. Right now I'm more time limited than $ limited, but I appreciate your offer and those from a few others as well. This is a great community.
 

Brutus

New Member
Jun 16, 2008
32
0
0
Vosgian mountains, France
3p141592654;1057497 said:
Note that #0x07 means load immediate, so for the first instruction $_OMODE=0x07 rather than a memory reference i.e. it is not $_OMODE=[0x07]

Also note, that for no good reason the operands are swapped for immediate loads. All other "load" instructions are op.1=op.2, so that is probably why you got confused. This inconsistency is a quirk carried over from the Motorola 6800 assembler, proving bad ideas never die I guess!

Thanks for correcting about this opcode (I think you meant #0x33), the code looks muuuuuuuuuuch more logic now! :icon_bigg

3p141592654;1057497 said:
I'm still struggling to get IDA running right, but that will help alot compared to trying to do this with a simple disassembler.

I've never used IDA before. I will try to use it if understanding the program gets too tough.

3p141592654;1057497 said:
I also need to better understand the mapping of the ports, timers, edge sensors, and so on to the actual engine sensors/actuators. That takes a lot of circuit tracing on the ECU board, and is very painful.

I've done a lot of work on 42pins D151801 ECUs regarding circuit tracing, including the decoding of the AD converter signals that are sent to the main processor. I have also had run these ECUs running out of the car.
I confirm circuit tracing is a painful job, almost impossible without removing all the components of the ECU.
I'm sure I can be of good help regarding this, since I can now recognize some components and figure out their use in many old style Toyota ECUs quite fast.

All analog sensors go to the ADC, and are sent to the CPU via two lines.
Digital sensors go to the CPU via a voltage converter/protecting (vertical) IC.
The actuators (all digital), are sent from the CPU to an amplifying IC (set of Darlington Transistors).
The injectors have their own triggering IC, which is fed by the CPU via less lines than injectors.

I don't know really for the ignition, as the ECU I worked on used only one ignition coil.

I will bring home a 7MGTE ECU next week-end to look at this.

3p141592654;1057497 said:
I have extra boards, and I think I have extra parts as well if you want to buy a kit.

Great!
If you get the hand on those parts, this will save me the time to buy them.
Just PM me your paypal account if you have one and the price you want for this, keeping in mind the postage price to France.

I will post my findings when I get some.
 
Last edited:
Oct 11, 2005
3,814
13
38
Thousand Oaks, CA
JJ: Intel Microcomputer Development System?

Brutus: Check your PM.

We are some ways out from a tunable factory ECU, but there is precedent over in the MR2 world. The stock ECU is pretty impressive for something that was developed about the same time as the IBM AT personal computer. More to come, stay tuned.
 

jetjock

creepy-ass cracka
Jul 11, 2005
9,439
0
0
Redacted per Title 18 USC Section 798
3P: Yes but the only Intel MDS I worked with back in those hey-days of MPU development was the Series II that ran ISIS. It's emulation capabilities didn't support this device. There were others that did however. A logic anaylzer was also used.
 

Brutus

New Member
Jun 16, 2008
32
0
0
Vosgian mountains, France
Hello everybody,

I'm working on the code at the moment (Identifying interrupt vectors, locate the main part of the program...).

Of course, as 3P said this is going to be far easier to decrypt the code after having located the sensors and actuators pins.

I will bring back a 7MGTE ECU with me this week-end, but I will also bring back a Celica ST165 ECU, since I believe its closer to the 7MGE ECU (single board, 64 pins CPU, only one ignition transistor) we will work with at first.

Unfortunately, I can't destroy it tearing appart all the components as I only have one of these.

If anybody has a unused 7MGE ECU for sale, I would be interested to get it.

It would also be of great help if anyone can post very high resolution pictures (both sides) of a 7MGE ECU for comparison.

I will post the disassembled file in the beginning of next week, as I will hopefully find interesting stuffs in the code by then.
 

Brutus

New Member
Jun 16, 2008
32
0
0
Vosgian mountains, France
st165-3sgte-ECU.jpg

OK, found this picture of a ST165 ECU. Please let me know if it's close to the 7MGE ECU or not, because I will work on it until I get a 7MGE ECU.
I believe the 7MGE must have only 4 transistors (at the bottom of picture, attached to the frame of the ECU) instead of five because injectors opening are grouped by two injectors, instead of being independant from one another on the ST165.

Here's what I know about the chips at the moment:

D151801-6430: CPU, what's interesting us.
TC40508P: Injector driver, should be linked with the CPU by four lines.
D151801-6470: Knock sensor CPU
D949577-2100: Analog Digital Converter, communicates using a PWM protocol with the Main CPU through pin 3 of this IC. I think it's linked to some ASR pin of the CPU.
HC150: Voltage converter (12V/5V, digital sensors go through this)
MF168 ?
SE022: Not sure about that one, but seems to be some kind of timer.

Please let me know about the 7MGE ECU
 
Oct 11, 2005
3,814
13
38
Thousand Oaks, CA
Henri, it's very close, but from memory looks a little different. I'll post up a picture of the 7MGE board that I pulled the CPU out of for the assembly code posted above.

Your ECU reader stuff is boxed up, need to get it mailed out today.
 

Brutus

New Member
Jun 16, 2008
32
0
0
Vosgian mountains, France
3p141592654;1063426 said:
Henri, it's very close, but from memory looks a little different. I'll post up a picture of the 7MGE board that I pulled the CPU out of for the assembly code posted above.

Your ECU reader stuff is boxed up, need to get it mailed out today.

Thank you for your time Jon,

I'm trying to find the same ECU as yours on ebay. In fact, the most difficult is to find somebody accepting to send something to Europe (These ECUs are hardly ever found here). I will let you know as soon as I can put a hand on one.

Here's the little I have found now (more to come this week).
The main ADC output (pin 3) goes to ASR0 (This can be checked with a multimeter. Resistance should be close to 0 Ohms).
Injector driver is linked to C3.
PB3 and PB2 goes to the knock detection IC.

I'm struggling with the instruction set now, I have googled everywhere to find some litterature about unusual instructions like TBBS, TBBC, BGEA, BLTA... etc to check their effect on the processor, but couldn't find anything except this decrypted version of Kashi's Datasheet:
http://members.shaw.ca/tibiivan/mk2/Toshiba_8x - Decrypted.pdf

As you can see, the instruction set is described, but with some japanese inside. Does anybody read japanese or knows someone who could translate this?
 
Oct 11, 2005
3,814
13
38
Thousand Oaks, CA
TBBS and TBBC are a bit confusing to me too. Here is what I know.

TBBS: Branch if bit set ( bit.(op.1) of M[op.2]) = 1 then PC=PC+op.3

opcode: 0x35
operand 1: first 3 bits specify bit to test (0 through 7), remaining 5 bits specify memory location (limited to first 32 bytes of RAM)
operand 2: 8 bit relative shift like the other branch functions

TBBC: Branch if bit clear ( bit.(op.1) of M[op.2]) = 0 then PC=PC+op.3

BGEA: Branch if arithmetic >= (N ∀ V = 0)
Branches if the result of an arithmetic compare was greater than or equal to
operand 1: 8 bit relative shift (all branch instructions use 8 bit relative for the branch so can only access +/- 127 bytes from the instruction location)

Here N (negative) and V (overflow) are two bits in the ECU CCR register

BLTA: Branch if arithmetic < (N &#8704; V = 1)
Branches if the result of an arithmetic compare was less than

and so on for the other branches. These closely follow the instructions you can find in the MOT 65xx and MOS6502 processors.

I have decoded the Kashi document. Will need to figure out where to post it.
 

GrimJack

Administrator
Dec 31, 1969
12,377
3
38
56
Richmond, BC, Canada
idriders.com
Good work, folks. This was on my list of things to do for years, but it keeps getting pushed off by real life (tm) concerns.

I've got high res pics of the GTE ecu floating around somewhere from the HAC sensor mod for the MAFT Pro setup, if you get to the point that you need them, let me know. I wouldn't be much use on the code end of things without some serious reading, I haven't done any machine code for nearly 20 years! All my EEPROM gear has been in storage nearly that long, too.
 

Brutus

New Member
Jun 16, 2008
32
0
0
Vosgian mountains, France
3p141592654;1065963 said:
TBBS and TBBC are a bit confusing to me too. Here is what I know.

TBBS: Branch if bit set ( bit.(op.1) of M[op.2]) = 1 then PC=PC+op.3

opcode: 0x35
operand 1: first 3 bits specify bit to test (0 through 7), remaining 5 bits specify memory location (limited to first 32 bytes of RAM)
operand 2: 8 bit relative shift like the other branch functions

TBBC: Branch if bit clear ( bit.(op.1) of M[op.2]) = 0 then PC=PC+op.3

BGEA: Branch if arithmetic >= (N &#8704; V = 0)
Branches if the result of an arithmetic compare was greater than or equal to
operand 1: 8 bit relative shift (all branch instructions use 8 bit relative for the branch so can only access +/- 127 bytes from the instruction location)

Here N (negative) and V (overflow) are two bits in the ECU CCR register

BLTA: Branch if arithmetic < (N &#8704; V = 1)
Branches if the result of an arithmetic compare was less than

and so on for the other branches. These closely follow the instructions you can find in the MOT 65xx and MOS6502 processors.

I have decoded the Kashi document. Will need to figure out where to post it.

Thanks for the help again. :drink1:
I need to re-read some Motorola litterature. :)

I've started working on putting absolute adresses on the relative branch instructions since yesterday to make the code clearer.
When branch offset is less than 128 this is a forward branch, and when it's equal or greater, this is a 256-Offset reverse branch, if I remember well.
This is a pretty long job to do (I don't feel like modifying the disassembler now), so this will require two or three days (not a lot of spare time).

I should be able to get a 7MGE ECU next week, hopefully.
I will then be able to send voltage to the digital sensors inputs on the ECU plug to see which pin of the processor is concerned.
The same way, I will be able to apply 5 volts or ground to the pins of the processor (I/O pins, of course) to check which actuator is concerned on the ECU plug pin.
This won't work for the injectors, but this will be faster than route tracing at the beginning.
 
Last edited: