ECU Reverse Engineering

MSB map switching

Wednesday, April 17, 2019 - 07:00

I was having a look at the MSB diagnostics a couple of days ago and came across the request for switching between maps.
Some MSB ECU's - most often the Auto versions - come with tunes former than one market and the switching function provides a method for selecting the correct tune.


The NOSELECT tune is default on a new spare ECU. The tune provides just enough functionality to start an engine.
The duration maps are 2 x 2 tables that have rows for 0 and 750 rpm, so should allow the engine to idle.

The remaining tunes are full market specific fuel maps.
In this case the ECU is an MSB1011191 and has tunes for European and Japanese Auto D2s.

European Auto Tune

Japanese Auto Tune

With some minor modifications to the .bin this ECU should support at least one additional fuel map.
The NOSELECT "tune" seems to be referenced in several places during startup so possibly needs to be retained as is.

Even so this opens up the possibility of software switching between two or three maps without resorting to additional hardware to perform address line switching hacks.


Monday, March 18, 2019 - 18:45

I've been working on a disassembly of a K-Series engine map that runs on an NNN petrol MEMS ECU for last day or so.

While there is a basic level of commonality with the Td5 this is very much restricted to low level drivers and some utility functions, like map lookup and interpolation, basic kline drivers, CANBUS drivers, etc, etc.

It's this type of functionality that accounts for the similar appearance of the ECU fuel maps. The lookup for sensor scaling is pretty much identical, even though the actual processing has significant differences, for example.

Once you move beyond this "housekeeping" code, you are firmly into the realm of engine specifics.

So yes, MEMS are similar up to a point - but this also hides a lot of difference in the actual engine code.

In other words "MEMS ain't MEMS"

Wastegate Modulator: Operation

Thursday, May 4, 2017 - 09:00

This is a bit of background on how the physical waste gate modulator unit operates.

It has only been in the last few weeks that it finally dawned on me that I'd been uncritically accepting the "Active to Limit" theory as correct. While it doesn't seem that important on the surface, it's difficult to make sense of code when the behaviour seems to be at odds with how you believe the hardwares should be operating.

Let's start by looking the Active to Limit Boost theory of operation:

  • power off, the valve is in an open position and boost flows from turbo outlet pipe to the Wastegate Actuator;
  • power on and no PWM signal from the ECU, the valve is in a closed position and boost is prevented from reaching the Wastegate Actuator;
  • power on and PWM signal from the ECU, the valve opens and allows boost to reach the Wastegate Actuator, opening the waste gate.

Active to Limit Boost is the most commonly expressed explanation of how the WGM operates, even if it's not explicitly stated.

This example is from Urban Panzer's excellent website...

"trying to the rev the engine over 2500 RPM the waste gate modulator info that Nanocom shows under "read fuelling" went to zero occasionally, so it basically was not controlling turbo charger boost / waste at certain times and was very "hit and miss" at best. That all seems to make sense and description in RAVE would appear to confirm that view. And the Nanocom logs seem to suggest this is what happens in practice.

You can clearly see the WGM active = controlling boost, WGM inactive = boost uncontrolled aspects of the Active to Limit Boost theory.

You'll see this theory of operation informing most forum posts relating to over boosting and WGM diagnosis. It's difficult not to fall into this way of thinking due to it's prevalence - that's my excuse anyway.

So lets look at this in detail...

Hardware first

After a bit of digging I found a couple Pierburg service information sheets for electric switch over valves. These were for parts identical in appearance to the D2's waste gate modulator, but with different part numbers. The test methodology given in the service information required a hand vacuum pump, so I decided put the site donations fund to use and purchased a Mityvac kit. Thanks again to those who have contributed!

The test procedure is fairly straight forward, but the main question I had was whether the valve on the D2 behaved in the same way as described.

WGM testing
WGM diagrams

Testing the modulator on my D2 suggests that the flow through the modulator does match that outlined in the test procedures.

  • power off, boost flows from turbo outlet pipe into port 1 for the modulator and out of port 3 to the waste gate actuator;
  • power on, engine running, and no pwm, boost flows in from turbo outlet pipe into port 1 for the modulator and out of port 3 to the waste gate actuator;

In the course of doing these tests I discovered that while the WGM seemed to be OK, it wasn't passing the Tightness test 1.3.
It was possible to pull down to 0.5 bar vacuum but this dropped to 0 within roughly 10-15 seconds. Similarly, applying pressure to port 1 with port 3 capped resulted in a loss of pressure over 10-15 seconds.

To confirm normal operation I ordered a Pierburg OEM modulator and bench tested.
Out of the box the modulator would hold 0.5bar vacuum on port 2 for 20 minutes with no visible loss of vacuum.
Testing with port 3 capped and 2.0 bar applied to port 1, there was no visible loss of pressure after 20 minutes.

The pin to pin resistance of the new WGM was 29.3ohm, which is within the 28.4ohm +/-1.5ohm specification.

Powered Benchtests

Rather than leave the testing hanging I decided to perform tests 1.1 and 1.2 from the Pierburg service information. This was done with a bench power supply and confirmed the new WGM behaved as described.

For test 1.1 Electrical Function there was distinct click as the solenoid activated, as you'd expect
For test 1.2 Internal Fouling the air flow matched the required values:

  • no power: air flowed from port 1 -> port 3.
  • power: air flowed from port 3 -> port 2.

The thing to note here is that port three is the common outlet. The solenoid is switching between port 1 and port 2.

Next step was to connect the WGM to my tester ECU. Power to the + pin on the WGM was taken from the "master relay" on the interface board. The - pin was connected to A21 on the ECU.

I also hooked up the Bitscope Micro with the scope probe connected to the - pin and the earth clip hooked up to the power supply earth. Add in the Mityvac and Nanocom and it all starts getting a bit messy!

WGM Testing

The main difference between unpowered (ignition off) and powered (ignition on) without a PWM signal is the voltage level.
Unpowered and no PWM gives 0V on both +ve and -ve pins.
Powered and no PWM gives supply voltage on both +ve and -ve pins.

Because there is no voltage differential between +ve and -ve no current flows and no "work" is done.

In the case of power applied to +ve pin and PWM operation, the +ve pin is at supply voltage and -ve pin at earth reference when the PWM completes the earth path. Because there is a voltage differential of around 13.5V and the solenoid coil has resistance around 29ohms the WGM will draw 0.46 amps and dissipated about 6.28 Watts when it is activated.

I can attest that leaving the WGM hooked up to a 12V supply for 5 minutes results in the WGM becoming hot to the touch. oops!

The Bitscope capture below shows the Nanocom Wastegate Modulator Test in action.

Nanocom WGM test

You can see the effect of the PWM completing the earth path resulting in the voltage at the - pin of the WGM dropping by just under 12V.

The pulse width is 100ms or 10Hz, and the duty cycle is roughly 50%, which corresponds with frequency and duty cycle requested by the Nanocom test routine.

I couldn't work out how to capture on video but with the port 3 capped and port 1 pressurised to 2 bar, there was a distinct "puff" as pressure was released through port 2 each time the WGM activated.

As can been seen from the video the WGM is directing pressure to the capped port 3 when it's not receiving a PWM signal.
When PWM is active the pressure in the capped waste gate actuator outlet is released via port 2.
The small drop in pressure seen on the gauge with each activation is due to the small internal volume of the cap I've used.

Revised Theory of Operation

At this point it should be apparent the theory of operation outlined at the start of the post was a bit back-to-front.

Updating the theory to reflect real world behaviour we get:

  • power/ignition off, air pressure flows from port 1 (turbo outlet) -> port 3 (waste gate actuator) - wastegate receives full boost
  • power/ignition on, and no PWM signal, air pressure flows from port 1 (turbo outlet) -> port 3 (wastegate actuator) - wastegate receives full boost.
    In these cases the WGM is de-energised.

WGM de-energised

  • power/ignition on and PWM signal, air pressure flows from port 3 (waste gate actuator) -> port 2 (turbo intake pipe) - wastegate isolated from full boost.

In this case the WGM is energised.

WGM energised

This means when the WGM is recieving a PWM signal it is operating to reduce pressure at the Wastegate Actuator. Rather than "Activate to Limit Boost" the system is "Activate to Increase Boost".

But RAVE says...

So what does RAVE actually say to support the "activate to limit boost" theory?
The following sentence is often pointed to as evidence:
When full boost is reached a control signal is sent to the wastegate modulator, and a vacuum is applied to the wastegate valve.

Interestingly this sentence incorrectly states that vacuum rather than boost operates the waste gate valve. This is often excused as a typo but there is clearly an error in the statement.

Nothing else in RAVE indicates a specific method of operating, just that the system controls boost pressure to prevent overboost.

What about the Nanocom logs....

The Nanocom samples engine data once every 1.2 seconds in the current EVO guise - Nanocom 1 was a bit quicker at 1 second.
The WGM control code samples boost pressure and engine load once every 10ms and updates the PWM amount at that speed.

This means the WGM PWM has potentially been updated 120 times for each data point the Nanocom logs show. Transitions between PWM on and off to control limit boost occur quite quickly. 500ms is not uncommon, and the actual switch off occurs faster than the 70ms sample time of the logs.

In conclusion...

Looking back at the opening quote it's pretty obvious what is occurring.

... the waste gate modulator info that Nanocom shows under "read fuelling" went to zero occasionally, so it basically was not controlling turbo charger boost / waste at certain times and was very "hit and miss" at best.

The waste gate modulator PWM drops to 0% because the ECU is trying to direct full boost pressure to the waste gate actuator. And from the diagnostic information you can surmise the failure mode is either loss of spring tension in the valve or internal fouling of the modulator.

The next post in the Wastegate Modulator series will look at the WGM control maps.

AAP/AAT sensor swapping

Friday, April 7, 2017 - 12:15

This is a fairly niche modification.

EU2 and EU3 engines are fitted with significantly different airbox sensors.

The EU2 uses a three wire Ambient Air Pressure sensor, while the EU3 uses a four wire Ambient Air Pressure/Ambient Air Temp sensor.

The curve of the AAP portions of the two sensors are different and require different parameters to give the correct reading.

Without adjusting the parameters there is a misread of around 10kPa. You'll get an over-read ( -700 m altitude) with EU2 AAP + EU3 tune, and under read (+700m altitude) with EU3 AAP + EU2 tune.

The problem is not so bad with EU2 AAP + EU3 tune as the engine assumes higher air density in some correction maps and will INCREASE injected fuel and give a 0.1 bar increase in the boost limit. The boost level is MAP - AAP so reducing AAP by 0.1 results in boost levels 0.1 higher than the would be with correct setup. I suspect this is why you often hear the comment that an EU3 tune drives better that the correct EU2 tune.

If you've addressed the issue by installing a 4-wire sensor - replace airbox lid, sensor and run an extra wire back to the ECU - the problem occurs when you want to run an EU2 map on the motor. The under-read means the ECU uses corrections which reduce the fuelling plus the boost limit is reduced by 0.1 bar. It guarantees bad performance.

The fix is in

The way to fix this problem is to use the correct parameters for the AAP you have installed. Search for the values for the base map and replace with values for the sensor you are using.

EU3 - 4 wire sensor
multiplier: 13171 ( 0x3373 )
offset: 267 ( 0x010B )

EU2 - 3 wire sensor
multiplier: 10410 ( 0x28AA )
offset: 1227 ( 0x04CB )

It's not too hard to find these values with a hex editor as I think they are fairly unique. As a rough guide they are somewhere around an offset of 0x6A0 from the start of the fuel map. In a Nanocom .map the fuel map always begins at 0x19010.

The donor-ware XDF's now have a patch that swaps the values. It's a bit rough as it shows a stock EU3 tune as being patched, so installing the EU2 parameters requires "reversing" the patch.

Td5 NNN ECU "Base" Code

Sunday, March 5, 2017 - 14:15

One of the very early posts one this site shows a diagram of the firmware layout used on the Td5 NNN ECU's.

The portion of memory located between addresses 0x0000 - 0xFFFF was cryptically called "ECU Base Code", with the note that this is not touched during Nanocom .map uploads.

The "Base" code is possibly better described as management or boot loader code. In normal usage the main function it performs is basic setup of the ECU hardware, verifying that certain check points are present in the Variant and Fuel maps, then running the variant map code if everything correct.

The secondary function of the management code is to provide support for factory programming of the ECU. Without a variant or fuel map installed the ECU will boot into a special diagnostic mode that provides access to the functions need to upload .map files, program injector codes, synchronise with the BCU immobiliser, and set the throttle pedal type. I assume this mode would have been used on the production line to program new ECU after installation into a vehicle.

The management code is identical across all the NNN ECU's with two minor differences.

The first difference is the code identifier. Like engine maps each variant management has a unique identifier. The second difference is the ECU hardware code, which reflects the well know NNN numbering. So the thbtp001 ecu code has the indentifer NNN000120, whereas the thbtp005 has the identifier NNN500250.

The complete list is:

NNN000120: thbtp001
NNN000130: thbtp002
NNN500020: thbtp003
NNN500030: thbtp004
NNN500250: thbtp005

If you are simply uploading .map files using a diagnostic tool you don't need to worry about this as the management code is not touched even if you brick the ECU.

Where you can run into problems is if you upload a complete .bin file from a different ECU type.

One of the differences between the NNN000xxx and NNN500xxx ECU's is that the power driver chips used to control the injectors were changed from Intersil HIP0060 to Infineon TLE6220GP parts. While both types of chips use Serial Peripheral Interface bus to communicate with the MCU the format of the messages and the representation of faults differs.

The ECU code uses the identifier from the management code to determine which driver chip is present.

So if you fit a .bin from a NNN000120 to a NNN500020 or NNN500250 for example the Variant code will read the NNN000120 identifier and use the code for the HIP0060 driver chip, rather than the TLE6220GP.

What makes this problematic is that one chip arranges it's fault codes:

A_OverTemp, B_OverTemp, C_OverTemp, D_OverTemp,  A_OpenLoad, B_OpenLoad, C_OpenLoad, D_OpenLoad

with a value of 1 signalling a fault.

The other uses:

A_bit1, A_bit2, B_bit1, B_bit2, C_bit1, C_bit2, D_bit1, B_bit2

If both bit1 and bit2 are set to value of 1 the channel is operating normally, and if both are set to zero there is a "short to ground" fault present.

This means if you send the diagnostic bits from a HIP0600 showing no faults (all zeros) to an ECU configured for a TLE6220GP the best you can hope for is "short to ground" faults on all channels.

The injector fault check is called in the main loop of the ECU code and it's potentially updated every 10 milliseconds or so. I haven't been able to confirm how this impacts general running, but I've been speaking to someone who has had ongoing issues with poor starting who appears to be running NNN000120 management code on an NNN500250 so it seems fairly likely this is related.

Anyway, it's something to be aware of...

Saleae Logic

Saturday, December 21, 2013 - 18:00

I've been having a bit of trouble getting my head around what is happenning of the SPI bus of the Td5 ECU, so I've given in and ordered a Saleae Logic 8 channel logic analyser as a solstice present to myself.

First up on the hit list when the parcel arrives is working out the read and write protocols to the EEPROM that is used to store things like injector codes, logged fault codes and immobliser codes. Ultimately it should be possible to use this information to write a script to dump the EEPROM contents, modify the injector codes, disable the immobilser, etc.

The other task that I have lined up is sorting out the canbus communications with the Autobox. I have identified the routines which process canbus communications, but need to see what data is transmitted over the bus in normal operation. There appears to be a significant amount of configuration information related to the canbus and I'm intrested to see if any of this is sent to the Autobox ECU. 


I've had a quick play with the Logic 8 and it seem to do what it says on the box. I hooked up to the signal lines to the eeprom and triggered off the first rising edge of the clock and captured a big block of reads from the EEPROM. The the first lot of read requests tallied with what I'd worked through on paper so looks good. I'll have to wade through and verify the responses are being decoded correctly.


Capture of eeprom read command


Td5 ECU Tools: scripts for the USBBDM NT

I've been using the USBBDM NT interface to recover bricked Td5 ECU's and modify VIN information. As supplied the USBBDM NT lacks the required configuration to work with the Td5 ECU, so I have written a package of config files and a script that largely automates the recovery process.

I made a short tutorial video a couple of weeks ago that demonstrates how the "Td5 ECU Tools" config/script package can be used for recovering a "bricked" ECU or loading unencrypted map files.

The main menu of the revised script now looks like this:

The interface and scripts can be used for loading any unencrypted .map file or binary image. This means the system can be used for uploading remaps from vendors who supply maps in the standard Nanocom format.

For a working setup you'll need:

  •'s USBBDM NT available here
  • USBJTAG software license (needed for Mac or Linux only) available here
  • DC Power supply (in the range of 12-16V - 13.8V is perfect. I use one of these) or plugged into the vehicle harness for "ghetto style" operations
  • 10 pin dual in line header (for soldering a permanent header to the ECU board) or
    • 2 x IDC 10pin dual inline headers
    • 15cm of 10 wire ribbon cable
    • 10 pogo pins

The script package is available for $50.00USD, which helps to support further work on reverse engineering the Td5 ECU firmware.
Site donors can get the scripts for $25.00USD.

The package has been updated to include an archive of all the .map files available in the Nanocom Map Wizard. These have been spilt into Variant and Map .bin files. I've also put together a reference pdf listing all known factory variant and fuel maps.

Please use this  contact form if you are interested in purchasing.

Please do not order unless you have the interface in your possession. A few people have had trouble ordering from so you need to make sure the interface arrives before buying the scripts. I can get the scripts sent out within 12 hours of receiving payment.

Reverse engineering the Td5 ECU

I've spent a bit of time over the past few months trying to get my head around the firmware for the TD5 ECU. It's been a long tedious process but things are slowly falling into place.

I'd been puzzling over how the fuel map table were looked up and finally found the routine used to look up the tables. The key point is there is an index of tables addresses near the end of the fuel map. The variant map looks up the address of the required table using the index and then calls the table lookup with the address of the table and the values for the x and y variables. The subroutine returns a value based on this information which is then processed as required.

By referring to "known" tables listed in the Td5MapEditor application, I've been able to make some inroads into the way the tables are used, but it is still far from straight forward. The descriptors of the variables in Td5MapEditor don't really capture the complexity of the process.

As an example the fuel maps are described as a function of the RPM and throttle position. I've traced the "throttle position" input back through three levels of subroutines and still haven't hit a direct reference to the throttle position. The subroutine preceding the fuel map lookup modifies the "throttle position" variable based on two maps, one of which is applied if the revs are below 1000rpm, the other if the revs are above 4200rpm. If the revs are between 1000 and 4200 the values from both maps are extrapolated from the 1000rpm and 4200rpm values.

ECU Clock Frequency

Update: After doing further work on ECU I've discovered that the none of the speculation originally reported in this post is accurate and should be ignored. After locating the code that handles clock setup for the OBD-II communications I've been able to determine the crystal is actually 4.0768Mhz and the system clock runs at 16.3072Mhz.

Old content begins here:

I'd come across a comment on a European forum that the ECU uses a 16.77Mhz crystal, so had been keeping that in the back of my mind while working with the code. I decided to have another look at this as it would be very handy to know for sure.

The crystal on the NNN500030 ECU I've been working with is soldered to the board at both ends, and the only visible marking is 23A18. I'd pondered the possibility that this is a hex representation of the frequency but it would have to a very unusual, although not entirely implausible result.

Checking back on the SIM documentation the CPU will accept a clock up to 20Mhz from an external source, but this requires that the clock signal be supplied on a single pin (EXTAL) and the second pin (XTAL) be left floating. This does not reflect the Td5 CPU layout, which appears to have a crystal attached as a reference for the internal Phase-Lock Loop. The allowable frequency range for the crystal in this case is 4.194 - 5.234Mhz.

Assuming the crystal is the 4.194Mhz used as a default value in the manual, then fsys is configured to 16.776Mhz.

It looks like I'll need to actually measure the crystal to see what frequency is being used, but at least it should be within the range that my multimeter can handle.

Progress on BDM programming the Td5 ECU

Sunday, February 17, 2013 - 07:45

I'd initally intended to use a cheap parallel port BDM interface which used a free dos based software to do BDM programming but I decided that it was just too inconvienient to be practical. The PC I had setup usually lives in storage so it required a trip to retrieve every time I wanted to hook up the ECU. Needless to say it wasn't really conducive to being productive.

A few weeks back I came across a reasonably priced USB BDM interface that had Mac version of the programming software available so I bit the bullet.

There is no out of the box support for the flash memory chip used in the NNN ECU's, nor the Td5 ECU, however there was documentation on the USB BDM forum to on how to write the flash configuration from the datasheet, so that was fairly straight forward. The software came with a configuration for the GM ECU based on the MC68332 which proved to be a good basis for a Td5 ECU configuration.

The following need to be added to the end of flash.xml file in the config directory:

            <name>AMD AM29F200BT</name>

This allows the software to recognise the stock AMD AM29F200 EEPROM. It would be fairly straight forward to add support for the AM29F400 but you'll loose the ability to erase/write individual code blocks.

I'll post up the ECU config once I have it sorted out a little better. At present it is fully functional and has named tabs for the main blocks of code in the firmware.

The named tabs make it simple to do things like modify the VIN stored in the ECU for example. Instead of rewriting the entire firmware you can erase and then program the memory sector containing the VIN.
The named tabs act as a shortcut to the address and length of the memory sector so you can issue the following commands:

erase VIN
sprogram VIN
rather than
erase 0x3A000 0x2000
sprogram 0x3A000 0x2000

Changing the programmed VIN becomes a 2 minute exercise once the ECU is hooked up.

I'd been thinking about updating the VIN for a while but this had meant unsoldering the eeprom and then reprogramming before soldering back in place. This is much easier to do.

As a failed .map upload will only corrupt the Variant or Fuel map sections of the firmware, it is apparent that you can deBrick simply by rewriting these memory sectors, rather than reflashing the entire chip. This has the benefit of preserving the existing VIN and supervisor code for the ECU.

With a small amount of manipulation it's possible to convert a .map file into the required format to be uploaded via BDM. I'll post on how this can be done in the future.