So, many of you use JTAG?
I’ve been using JTAG for many years now, which started with FPGAs, and has mostly been for CPLDs and FPGAs since- but it’s also a pretty widely used protocol for programming and debugging mid range microcontrollers all the way up to high end CPUs. I’ve always wanted to look into how JTAG worked in more depth, but never really had the time.
Now, I do have some time (and some projects which depend on JTAG hacking) – so this post will go into the world of JTAG.
Many of you have probably seen the following diagram, usually in some CPU or FPGA datasheet where it talks about the JTAG port. And it probably clicks to a degree, you see there’s a state model you can move around in, and the TMS signal causes that – but what doesn’t really get said is really a lot simpler than all that.
There are really only a few core truths and fundamental operations to know about when working with JTAG:
- There are 4 data lines important to JTAG: TDI, TDO, TMS, TCK – All of them are expected to be pulled up with resistors (either in the chip or externally). Some devices provide a “TRST” signal, which just does essentially the same as navigating to “Reset” through the state machine (only possibly without the side effect of committing a register change)
- Pins are named in a Chip-Centric way. TDI goes into the chip, TDO is data out of the chip. TMS and TCK are controlled by the programmer
- The device samples on the rising edge of TCK, and you should listen for its response on the falling edge.
- A JTAG Reset should reset the test circuitry. Enter the reset state by cycling with TMS = 1 for 6 cycles (or more) – and then usually move to the “run/test/idle” state.
- Idle in the ”run/test/idle” state by cycling the clock when TMS=0. Some devices depend on having idle clocks like this in order to perform their programming functions.
- Write to the Instruction register – you do this by entering the Shift-IR state, Stay in this and shift bits (set TDI to your value, and listen on TDO). You need to set TMS = 1 for the last bit you shift.
- Write to the Data register – Exactly the same way, just by entering Shift-DR
- Another rule which it helps to know, is bitstreams are usually sent bottom-bit first – and are almost always represented with first sent bit on the right side. Important strings in documentation have been always specified in this form, in my experience (though it’s anybody’s guess what order the manufacturer will use to push their data into the port.
- JTAG is inherently a multi-chip protocol. You can chain multiple chips by connecting TMS and TCK to all chips in the chain, Connect TDI to the first device, and connect the first device’s TDO to the second device’s TDI – And so on, finally connecting the last chip’s TDO to the header.
Most of the other logic in the state machine is for devices that are tied to a fixed clock, and need to be wedged for a while if the host can’t keep up with shifting data.
At this point though, you can think of the JTAG system as memory mapped I/O, except for that the read/write widths are variable. Each transaction (Traveling through Capture-DR, shifting data, and then returning through Update-DR) has an impact on the system, which could be very small or very big. Everything is hardware specified, and every bit -could- have a meaning. That being said though, there are a few rules that make this manageable!
First, the Instruction register is typically very small. It exists so you can tell the device what mode to work in – And usually the size (Bit width) of the data register is fixed and based on the mode you are in.
There are a few mandated modes – The boundary scan modes were the original intent of the JTAG system – they exist so you can control and listen on the I/O pins of the device. JTAG was primarily designed as a way to test electrical connections on circuit boards between chips – This is implemented as the EXTEST and SAMPLE modes, for which the specific instruction register values are not rigidly specified (it varies per device)
There is a mandated “Bypass” mode, which is defined as an instruction word filled with ones – so you can technically use it even with chips that you don’t know anything about in the JTAG chain. When a chip is in BYPASS mode, it’s data register is a single bit. (Which will always clear itself to 0 when you start a new data transaction by entering Capture-DR)
When you enter JTAG Reset, the chip will automatically enter either IDCODE or BYPASS. IDCODE is an optional mode which is usually implemented; Its data register is a fixed 32bit value uniquely identifying the chip type, which MUST start with a ’1′ bit. The (slightly inobvious) advantage to this, is after resetting a JTAG chain, you can easily identify the number of devices in the chain and their types, if they entered the IDCODE state, just by shifting some bits through the data register! Based on whether the bit you receive is 0 or 1, either you know there is a bypassed device, or you will have 31 additional IDCODE bits to identify the current device with. Provided that you’re shifting in ’1′ bits into TDI, you can also identify the end of the chain when you encounter an IDCODE of all ones.
Another thing defined for your convenience, is the instruction register doubles as a status register. The (variable size) instruction word is required to shift out as “xxxx01″; where one is sent *first* (rightmost first), and the “x” bits could be status from the device. This also gives you some clue as to how big the instruction registers are, if you didn’t know about all the devices in your chain. Though, even with this it may not be possible to concretely identify the sizes of the instruction registers in your chain. Well, there may be another trick/requirement but I don’t know it – I have been working entirely off of public documentation :)
It’s definitely easiest to work with chains that only have one device, but it is not too hard to set all the uninteresting devices to BYPASS if you can identify their instruction register sizes.
As for actually doing stuff with JTAG? Well, I think I’ll have to go over that some other time. The idea is to set some instruction, and then you get to send a data word, which is some data, some control bits, and some very strange logic sometimes. The device also trades you back a value in the exchange, and frequently you receive the results of the previous command you entered.
I have been starting to reverse engineer the JTAG protocols used by some Xilinx FPGAs and CPLDs (just in order to build my own programmer for them) – it’s been an interesting project that has repeatedly broken many of my assumptions about how JTAG is used. I’ll post more about this when I have worked it all out. Some things are very simple, others seem to be highly complex and mysterious, littered with commands that don’t make much sense and (apparently) unused data. (Seems I’m mostly interested in the complex ones – oh well.)
On the bright side, I have found a new use for my AVR USB Stick, it currently has a bundle of wires attached to it for JTAG purposes :) I’ve written a simple protocol on the virtual serial port that lets me do JTAG stuff easily, and am probably going to set up a new PCB for dedicated USB programming, just because it’s so much faster than my existing serial port based programmer.