Welcome to Tesla Motors Club
Discuss Tesla's Model S, Model 3, Model X, Model Y, Cybertruck, Roadster and More.
Register

Tesla Wall Connector load sharing protocol

This site may earn commission on affiliate links.
Two breakthroughs to report...

One is that after a lot of sleuthing through log files and comparing messages I sent to values found in corrupt OTP memory, I'm now 99% sure I understand what RS485 commands broke my TWCs.

Tesla segments OTP memory into blocks of 16 values where each value is a 16-bit number like 0xFFFF. Normally, block 1 holds the TWC model number in ascii values: EVWTS80HL
Block 2-5 are unused and remain set to all FFFF values.

Block 6 contains what I think might be a date and place of manufacture code and TWCID (9393 in this case): A17I0039393
Block 7 and higher are unused and remain set to all FFFF values.

It appears that during boot, the firmware looks at Block 4 first. If it finds non-FFFF values, it uses that as the model number. If not, it looks at Block 3, then Block 2, etc. Normally it must scan down to Block 1 to find a valid model number. With my corrupt OTP, it finds all 0000 values in Block 4 and uses that as the model number. This puts it in an odd state where it's stuck in Master mode and won't charge a car.

The firmware also looks at Block 16 for TWCID. If it finds all FFFF, it checks Block 15, 14, etc, and normally finds the TWCID in Block 6. If it finds all 0000 data it actually doesn't break - it somehow interprets the 0000 values as TWCID EB30, at least in protocol 1.

The RS485 command FC19xxxx looks at OTP Block 6, then 7, then 8, etc. When it finds a block that does not contain all FFFF values, it writes the data contained in xxxx to that block (expanding 8-bit values to 16-bit). The TWC then either freezes, or responds with an FD 19 01 00 00 00 00 00 00 00 00 00 00 message. I don't know why it freezes sometimes. So basically, FC19 lets you permanently write a new TWCID and date of manufacture. The new TWCID is not loaded until TWC is reset or power cycled. If the TWC reads up to Block 16 and finds none have all FFFF values, FC19 does nothing. Oddly, it still returns FD 19 01 ... as if the write were successful.

The RS485 command FC1Axxxx looks at OTP Block 1, then 2, then 3, then 4. If it finds a block that does not contain all FFFF values, it writes the data contained in xxxx to that block (expanding 8-bit values to 16-bit). The TWC responds with an FD 1A 01 00 00 00 00 00 00 00 00 00 00 message if it found a block to write to, otherwise it responds with FD 1A 00 .... Basically, FC1A lets you permanently write a new model number. Unfortunately, if you don't write a valid model number, next time the TWC is reset it enters that broken state where it won't charge a car. Once you've called FC1A 3 times and blocks 1-4 are filled, you're screwed if block 4 doesn't contain a valid model number. This is the state I'm in on two TWCs. OTP memory can not be altered once a value is written because each bit set to 0 basically blows up a tiny capacitor that creates a permanent short that represents a value of 0 instead of 1. I tried manually burning a model number into Block 5 using the JTAG interface but it did not fix the problem, so apparently the firmware doesn't look at Block 5.

I think the only reason I didn't break my TWC early on in testing sequential undocumented messages is that I always tested FC19 before FC1A, and FC19 happened to freeze it in those cases, which prevented FC1A from doing anything.

The second thing I have to report is I was able to burn the firmware from my broken protocol 1 TWC to a working protocol 2 TWC. This turned my working TWC into a protocol 1 TWC which lets me stop the car from charging by simply setting the amps to 0. It also changed the TWC's ID from 9399 to 018F. I tried the same with my broken protocol 2 TWC and its ID changed from 9393 to 0189. Notice that 9399 - 9393 = 6 and 018F - 0189 = 6. This lends credence to the theory that protocol 1 and 2 firmware get the TWCID from the same place in OTP memory but each interprets it differently. I suspect the fact protocol 1 firmware doesn't read 9393 correctly is actually a bug, but not one that necessarily breaks anything.

It would be great if everyone could put protocol 1 on their TWC and solve the problem of stopping cars from charging, but unfortunately it requires buying at least $50 of equipment and some software setup that isn't trivial. I'm also worried that Tesla will eventually update the TWC firmware to protocol 2 through the connection to the car. I might be able to block firmware updates with a hack to the firmware version number.
 
Last edited:
Wow, great work!
I do have a C2000 launchpad dev bord from TI, i might be able to use the build in JTAG programmer to connect to one of my TWC's
Will give it a try.
Sadly my copy of IDA (standard) does not support the TMS320, IDA pro does seem to support it though...
 
Sadly my copy of IDA (standard) does not support the TMS320, IDA pro does seem to support it though...

I don't think IDA does support it. Their list of supported processors does not include TMS320F28034 or anything that begins with "TMS320F". This discussion from 2012 also says the chip isn't supported.

"TMS320" has become rather generic at this point because it refers to a huge family of processors. From Wikipedia: Texas Instruments TMS320 is a blanket name for a series of digital signal processors (DSPs) from Texas Instruments. It was introduced on April 8, 1983 through the TMS32010 processor, which was then the fastest DSP on the market.

TMS320F28034 in particular uses a "C28x Piccolo" processor and is part of a large "C2000" family of MCUs:
C2000 microcontroller family consists of 32-bit microcontrollers with performance integrated peripherals designed for real-time control applications. C2000 consists of 5 sub-families: the newer C28x + ARM Cortex M3 series, C28x Delfino floating-point series, C28x Piccolo series, C28x fixed-point series, and C240x, an older 16-bit line that is no longer recommended for new development.
The C2000 series is notable for its high performance set of on-chip control peripherals including PWM, ADC, quadrature encoder modules, and capture modules. The series also contains support for I²C, SPI, serial (SCI), CAN, watchdog, McBSP, external memory interface and GPIO. Due to features like PWM waveform synchronization with the ADC unit, the C2000 line is well suited to many real-time control applications.
The C2000 family is used for applications like motor drive and control, industrial automation, solar and other renewable energy, server farms, digital power, power line communications, and lighting. A line of low cost kits are available for key applications including motor control, digital power, solar, and LED lighting.

I think the only way to disassemble the machine code in the firmware may be to run it in the debugger of Code Composer Studio. It looks like hex2000.exe -b in CCS is responsible for converting the .obj file to .bin for C2000 family MCUs. The .bin is then burned directly to the MCU FLASH. I haven't been able to find any tools to decompile .bin to .obj for the C2000 line or the C28x Piccolo.

I do notice that IDA supports TI "TMS320C27x/TMS320C28x" and this TI guide on "Programming TMS320x28xx and 28xxx Peripherals in C/C++" says "If you have assembly instruction-related questions, see the TMS320C28x CPU and Instruction Set Reference Guide ( SPRU430 )". That could mean IDA Pro's support of TMS320C28x would work.
 
Last edited:
I think the only way to disassemble the machine code in the firmware may be to run it in the debugger of Code Composer Studio. It looks like hex2000.exe -b in CCS is responsible for converting the .obj file to .bin which gets burned to the MCU FLASH, but I haven't been able to find any tools to decompile .bin to .obj.
GNU objcopy? It's a shot in the dark, but...
 
...so the attached code is Python. I'll probably move the official github project to Python as well. If anyone would like to port changes back to Perl so we can maintain both languages, let me know.
...


Hey thank you man!
This is just perfect and a very VERY clear documentation! superb!

I just got my pi and am actually installing it by the letter of your pdf guide.
I guess I have to switch to this here attached python code right? (at least until you moved it to the github project...)

What do you actually prefer to use now?
 
What do you actually prefer to use now?

Ok, never mind. It seems clear now, that you will need the python version for a Gen 2 TWC to be able to stop charging.
I finished it now, and it works flawlessly so far!
I put the pie in my heating room, connected with a twisted pair cable to the TWC. Did not want to mess with the TWC power supply and internal cable tapping.
 
What do you actually prefer to use now?

I'm going to stick with Python code in the future. I'll update github with the car API version if necessary, but I'm currently weeding through the firmware to see if there is a way to stop charging with protocol 2. I figured out how to read it as assembly language instructions in the CCS debugger but it's pretty slow to decipher.

I deciphered the section that handles reading OTP memory and got both my broken TWCs to boot normally using the CCS debugger. When I tried to modify a couple bytes in the firmware to fix them permanently, the TWC won't boot (no lights). There is some sort of firmware checksum algorithm embedded in the firmware that I have to decipher to actually modify the firmware.
 
Happy to chip in 50euro to buy this for cdragon (if he’s interested)

Thanks for the offer, but if I understand correctly, Maxem's equipment requires a monthly subscription fee to operate and even if it was possible to sign up for a month and then cancel, I don't believe they serve U.S. customers. Not to mention I don't want to get into any legal trouble by reverse engineering their equipment and potentially costing them customers. I am fairly confident that I can eventually decipher the TWC firmware to get a definitive answer as to whether it's possible to stop protocol 2 firmware from charging. It's also possible that Maxem actually burns protocol 1 firmware or otherwise modified firmware onto TWCs they operate in order to stop them charging, in which case sniffing them wouldn't help.

BTW, I've been running protocol 1 firmware on my originally protocol 2 TWC for 2.5 weeks and it still hasn't been 'upgraded' to protocol 2 by the car. Maybe the cars aren't running firmware updates after all. Or they're programmed not to upgrade a protocol 1 TWC to protocol 2.
 
Last edited:
A bit off topic, but on the TWC firmware update: I have noticed that since two or three weeks it is now possible to unplug a TWC from a (EU) car when charging has stopped. This has changed with a recent fw update on the car but I suspect also a fw update on the TWC. I have a type 2 charging cable with a button to open the charge door/unlock the charging cable and the same trick does not work with that cable.
So there is definitely some communication between the car and the TWC so that the car knows it is on a Tesla charger.
 
This has changed with a recent fw update on the car but I suspect also a fw update on the TWC.

You can get the TWC firmware version by sending command FB 1B 00 00 00 00 00 00 00 00 00 00 00 00 00. It will return something like FD 1B 04 04 0D 00 00 00 00 00 00 00 00 00 00 which I believe means version 4.4.13 (aka 04 04 0D). My p1 TWC returns 4.3.11 (aka 04 03 0B). I'd be curious to know what values other TWCs report. I've traced where command FB 1B leads in the firmware and the 04 04 0D response is hard coded, so it definitely represents a non-changing value in each firmware, most likely firmware version.
 
This has changed with a recent fw update on the car but I suspect also a fw update on the TWC.

I did a test today and was able to unplug the TWC from the car without unlocking the car after the car was done charging. TWC is still running older p1 firmware. So if this is a new capability (it's not something I remember testing before), it's done purely in the car firmware.

Also, the second XDS100v2 I ordered from the link I mentioned awhile back arrived DOA, so be wary of the cheap (ish) clones. It had no red LED when I plugged it in to computer via USB and the computer gave no sign that it could tell I plugged in anything at all. I compared it to the working one I got a couple months ago and found the middle pin of an AMS1117 voltage regulator was putting out 0.47V on the bad one and 3.3V on the good one. So I soldered a 3.3v external power supply to that pin and now it seems to work fine. Glad I don't have to wait 2-3 weeks to get another one.

Another problem with the clone is they both have the same serial number. Normally you can connect two probes to one computer and debug two devices at once, but only if you can identify the two XDS100v2 with unique serial numbers. So I have to use two computers, one to run each probe.
 
Last edited:
  • Informative
Reactions: robertvg
...
I'd be curious to know what values other TWCs report. ...

I tried with the py version and the http command:
Code:
http://192.168.0.144/index.php?sendTWCMsg=FB1B00000000000000000000000000&submit=Submit

It just gives me:
Code:
Timed out waiting for response from TWCManager script.
If the script is running, make sure the $twcScriptDir parameter in the source of this web page points to the directory containing the TWCManager script.

Response:

But if I run:
Code:
http://192.168.0.144/index.php?submit=1&dumpState=1
it works fine and gives me the dumpState
 
Timed out waiting for response from TWCManager script.

That happens because I deleted the code in TWCManager.py that handles the 'sendTWCMsg' web command. I did that to prevent people from bricking their TWCs by sending the wrong message. At this point I'm pretty sure I understand which messages can harm a TWC and I filter them out with an error if you try to send them, so I've attached a new TWCManager bundle with that new code. Using it, you can get the firmware version using this URL:

Code:
http://(pi addr)/index.php?sendTWCMsg=FB1B&submit=Submit

Also, I found FD_Prog can change the serial number in an XDS100v2 so I got both my XDSs running off one CCS interface, compared working and non-working TWCs, and found where they check firmware checksum. I put the correct checksum into a firmware modified to avoid the bad OTP memory in my broken TWCs and now the broken TWC works normally. Squeeee!
 

Attachments

  • TWCManagerCarAPI v2.zip
    41.7 KB · Views: 53
M_VdM helpfully pointed out that TWCManagerCarAPI v2.zip has the wrong baud rate set on line 193:

Code:
baud = 9200

It should read:

Code:
baud = 9600

Unfortunately I can't delete or modify the file, but I'm attaching a corrected version. I didn't notice the 9200 setting causing major problems during testing, but looking back there is some evidence it caused messages to be lost/corrupted periodically.

Now that I have a working P1 TWC for testing on, I've discovered that setting it to 0A won't stop it from charging a fake car device! It will only stop a real Tesla from charging. I suspect this means that charge stop requires negotiation using the Tesla proprietary communication protocol. What's really bad about this is it means the countless hours of testing I did with a P2 TWC to try to stop it from charging a fake car were completely wasted!

ARRRRRGH!!!!

The only good thing here is it means there are again a ton of options that might stop a P2 TWC from charging a real car... but I have to test them with a real car plugged in, which I really don't like. *sigh*
 

Attachments

  • TWCManagerCarAPI v3.zip
    41.7 KB · Views: 49