It should be more than enough to write an emulator for use with xocd and a driver for OpenOCD.
The official software does not check all bytes sent by the device, so don't bet on them to have the values listed below across all firmware versions.
Numbers are in decimal unless prefixed with 0x.
Pinout when looking at the EJ-1:
/--------GND
| /------VREF
| | /----SB0
| | | /--SB1
| | | |
__---------__
1 3 5 7 9 11
2 4 6 8 10 12
-------------
| | | |
| | | \--TDI
| | \------TMS
| \--------TDO
\----------TCK
EJ-1 is an MC9S12NE64CPV and a XC2C64A.
Level shifting is done by three NC7WP125K8X for outputs and one FXLP34P5X for TDO.
TDI, TMS, and TCK have a 22,6 Ohm resistor in series.
Communication over UDP port 10000.
One message per UDP packet.
No initialization sequence required.
Catapult does _not_ swap src and dst ports in reply. Therefore bind to port 10000 first.
scan for devices:
send char[4]{10, 6, 1, 0} to 255.255.255.255:10000
recv char[28]{6, 6, 1, 1, mac1, mac2, mac3, mac4, mac5, mac6, ip1, ip2, ip3, ip4, mask1, mask2, mask3, mask4, gw1, gw2, gw3, gw4, sn1, sn2, sn3, sn4, sn5, sn6}
get inventory:
devid == 0x000B => EJ2
send char[64]{10, 3}
recv char[516] = {6, 3, 0, 1, devidhi, devidlo, clkhi, clklo, ., ., ., ., fwrev1, fwrev2, fwrev3, fwrev4, sn1, sn2, sn3, sn4, sn5, sn6, mac1, mac2, mac3, mac4, mac5, mac6, ., ., ., ., ., ., ., ., dhcp?0:255, ., ip1, ip2, ip3, ip4, mask1, mask2, mask3, mask4, gw1, gw2, gw3, gw4, ., ., ., ., ., ., ., ., ., ., ., ., dhcpT1lo, dhcpT1hi, dhcpT2lo, dhcpT2hi, dhcpretrlo, dhcpretrhi}
jtag data:
data in = high nibble TMS, low nibble TDI, lsb first
data out = low nibble TDO, msb first
yes, the output has its bits reversed
bits max 1268 * 4
seq = start at 1, increment by 1, skip 0
sequence number appears to be ignored by catapult EJ-1
send char[4..1272]{rw?3:5, seq, bitslo, bitshi, data...}
if (rw)
recv char[0..1272]{4, seq, bitslo, bitshi, data...}
else
recv char[0..1272]{6, 0, 0, 0}
change inventory (save to non volatile memory)
don't know when to use subcommand 4 or 5
send char[516]{10, arg?5:4, ...}
restore factory settings:
not all fw versions
send char[10]{10, 8, 1, 0, sn1, sn2, sn3, sn4, sn5, sn6} to 255.255.255.255:10000
reset:
not all fw versions
send char[4]{10, 7, 1, 0}
set tck speed:
EJ1 rateidx:
0x40 = 12000 Hz, not all fw versions
0x43 = 390625 Hz, not all fw versions
0x02 = 2083000 Hz
0x01 = 3125000 Hz
0x00 = 6250000 Hz
0x03 = 12500000 Hz
EJ2 rateidx:
0x40 = 12207 Hz
0x42 = 390625 Hz
0x03 = 2500000 Hz
0x02 = 3125000 Hz
0x01 = 4167000 Hz
0x00 = 6250000 Hz
0x43 = 12500000 Hz
send char[4]{10, 2, rateidx, 0}
recv char[4]{6, 2, rateidx, 0}
set red error led:
red led blinks as long as no voltage is detected on VREF
send char[4]{10, 1, arg, 0}
recv char[4]{6, 1, arg, 0}
set sideband pin:
channel = 0..1
state == 0 => pull low
state == 1 => pull high
state == 2 => tri state (_not_ the default after power up!)
send char[4]{8, 0, channel, state}
recv char[4]{6, 0, retvalhi, retvallo}
return value contains information about the current settings
there appears to be no way to read the value of a tri stated pin
retval & (1 << 2) == channel 0 output value
retval & (1 << 3) => channel 0 output enabled
retval & (1 << 4) == channel 1 output value
retval & (1 << 5) => channel 1 output enabled
delay:
send char[4]{9, 0, useclo, usechi}
recv char[4]{6, 0, useclo, usechi}
set test mode:
send char[4]{7, 0, arglo, argchi}
recv char[4]{6, 0, 0, 0}
I think there is one mode where tdi xor tms is internally looped back to tdo
lock device:
not all fw versions
send char[4]{10, 9, 0, 1}
recv char[6]{., ., ., 1 == ok, handlelo, handlehi}
unlock device:
not all fw versions
apparently handle == 0x1234 always works
send char[6]{10, 10, 0, 1, handlelo, handlehi}
recv char[4]{., ., ., .}