4. chain_disconnect() then calls cable driver->cable_free()
After return from chain_disconnect() to cable driver->disconnect(), the cable_t
structure has been freed and must not be accessed anymore.
===== JTAG Activities =====
Currently the API provides five different functions for performing operations
at the JTAG interface on the low level signal level (using the four signals
TMS, TCK, TDI, and TDO).
* clock() takes values for TMS and TDI output as its parameters, ensures that actual cable signals are set accordingly, and does a 0-1 transition on TCK.
* get_tdo() returns the current value at the TDO input.
* set_trst() sets the TRST signal and returns the current value.
* get_trst() returns the current value of the TRST signal.
For many JTAG adapters, there's almost no delay when doing alternating clock()
and get_tdo(). Writing and reading happens immediately and the result is
available immediately as well. This is the case with most parallel port
adapters (but not when attached to USB-to-parallel adapters or USB docking
stations) and memory mapped IO (e.g. general purpose I/O pins of
microcontrollers).
But there are adapters, especially USB and Ethernet based adapters, which
exhibit a rather long delay between the initiation of reading a bit and the
delivery of the value of the bit. It is at least 1 millisecond with USB,
which would limit the transfer rate to 1 kHz. One way to workaround this
is to transmit bits compacted into bytes and chunks of bytes, which is
possible with the transfer() function.
The transfer() function does a series of TCK pulses, with data for TDI read as
bytes from memory. The bytes are automatically serialized. TMS is set to zero
during transfer()s. Optionally, prior to each bit shifted out to the interface,
TDO input can be read into memory (deserialized into a byte array of the same
size as the input array).
It still doesn't yield much improvement if the operation consists of many read
and write transitions (e.g. repeatedly writing an instruction and some data
register values, then reading from the data register, as it is necessary for
memory access). For that reason, the above functions are also available in
variants that don't cause immediate activity, but rather schedule it for later.
In the API, they're visible as
* cable_defer_clock()
* cable_defer_get_tdo()
* cable_defer_set_trst()
* cable_defer_get_trst()
* cable_defer_transfer()
These functions aren't implemented in the cable driver (but currently in
src/tap/cable.c). The cable driver just has to provide a flush() function to
actually execute the queued activity in some cable-specific optimal way, and
to store the results of get_tdo() and transfer() activity. The caller later
can pick up the results using these functions (implemented in cable.c):
* cable_get_tdo_late()
* cable_get_trst_late()
* cable_transfer_late()
As an example, consider the following sequence of activities:
1. clock()
2. get_tdo()
3. clock()
4. get_tdo()
If the result of the first get_tdo() isn't absolutely required before the
second clock(), the sequence can be optimized into the following sequence (if
1. defer_clock()
2. defer_clock()
3. flush()
4. get_tdo_late()
5. get_tdo_late()
The next section explains the queueing mechanism and its limits in detail.
===== JTAG activity queueing =====
The source in src/tap/cable.c provides to important functions to access the
two queues "todo" (with activity to be done) and "done" (with results):
* cable_add_queue_item
* cable_get_queue_item
In src/tap/cable/generic.c you'll find two implementations of dequeueing
algorithms, i.e. implementations of the flush() function. These could be used
by any new cable driver unless it provides a more sophisticated algorithm
itself:
* generic_flush_one_by_one() simply calls the "classic" functions one after
another. The performance of the cable driver using this implementation will
be the same whether the immediate or defer variants of the functions are used.
* generic_flush_using_transfer() tries to optimize as many clock() and
get_tdo() by transforming them into calls to transfer() instead. This can
give a slight advantage.
The generic implementations also serve as a template for new cable-specific
implementations.
===== Generic implementations =====
As a reference and in many cases completely sufficient for new cables, take a
look at the code in src/tap/cable/generic.c, which contains generic routines,
suitable for parallel port based cables (and some for other types of cables as
well).
=== Data file format ===
// By Marcel Telka
JTAG declarations files are located in directory "data". The files contains