You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

366 lines
14 KiB

Lib(X)SVF - A library for implementing SVF and XSVF JTAG players
******************************************************************
Please check the subversion repository for updates:
http://svn.clifford.at/libxsvf/trunk/
You also might want to have a look at the project homepage:
http://www.clifford.at/libxsvf/
In papers and reports, please refer to Lib(X)SVF as follows: "Clifford Wolf,
Lib(X)SVF: A library for implementing SVF and XSVF JTAG players.
http://www.clifford.at/libxsvf/", e.g. using the following BibTeX code:
@MISC{LibXSVF,
author = {Clifford Wolf},
title = {Lib(X)SVF: A library for implementing SVF and XSVF JTAG players},
howpublished = "\url{http://www.clifford.at/libxsvf/}"
}
Please send bug reports and fixes to <clifford@clifford.at>.
Copyright and Disclaimer
------------------------
Copyright (C) 2009 RIEGL Research ForschungsGmbH
Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Introduction
------------
JTAG (IEEE 1149.1, aka "Boundary Scan", [1], [2]) is a standard IC
testing, debugging and programming port.
SVF (Serial Vector Format, [3], [4]) is a file format for storing the
patterns that should be sent to the JTAG interface, as well as the
expected response. It is used as an exchange format between programms
that generate the JTAG input/output patterns and devices that can
physically talk to a JTAG interface.
XSVF (Xilinx Serial Vector Format, [5]) is a binary variant of the SVF
file format, optimized but not limited to programming Xilinx FPGA and
CPLD devices.
Often one wants to use an embedded host processor or microcontroller
to access the JTAG interface on an embedded device instead of using
an external JTAG probe. This library can be used to implement such a
solution. In addition to playing SVF and XSVF files this library is
also capable of scanning the devices in the JTAG chain.
Lib(X)SVF is free software licensed under the ISC license (a licence
that is functionally equivalent to the 2-clause BSD license).
[1] http://en.wikipedia.org/wiki/JTAG
[2] http://www.fpga4fun.com/JTAG.html
[3] http://en.wikipedia.org/wiki/Serial_Vector_Format
[4] http://www.asset-intertech.com/support/svf.pdf
[5] http://www.xilinx.com/bvdocs/appnotes/xapp503.pdf
Limitations and non-standard extensions
---------------------------------------
The SVF commands 'PIO' and 'PIOMAP' are unsupported. Any use of this
commands in an SVF input file is reported as error.
The SVF 'RUNTEST' command is implemented in a limited manner: The
'MAXIMUM' time parameter is ignored. Combining 'SCK' with a time
parameter results in first executing the specified number of clock
pulses followed by a delay of the specified timespan, instead of
performing the clock cycles and the delay in parallel.
The SVF commands 'HDR', 'HIR', 'SDR', 'SIR', 'TDR' and 'TIR' support
an additional non-standard 'RMASK' parameter. This is a mask for the
TDO bits, simmilar to the standard 'MASK' parameter. All TDO bits
marked using a '1' in 'RMASK' are reported back to the host application
using the the ret_tdo() callback function. This can be used to read
data (such as device serial numbers) using JTAG by providing SVF
templates.
Using and Porting
-----------------
The library itself is written in plain C and does not depend on any
library calls or headers, not even from the standard C library. So it
can be ported easily even to restricted environment, such as embedded
systems.
So far the libary has only been tested on 32 bit hosts. Using it on
16 bit processors might not be possible without performing some minor
fixes in the code.
The program 'xsvftool-gpio' (see xsvftool-gpio.c) is a good example
of how to use the library. Please have a look at this program first.
Note: See 'Host accessor macros' below for an alternative way of
integrating libxsvf into your host environment.
The host application must provide an libxsvf_host struct as defined
in libxsvf.h. This struct contains some function pointers that must
be set to implementations of the following functions:
int setup(struct libxsvf_host *h);
This function is called by libxsvf to setup/initialize the
jtag interface. It is executed before any other libxsvf_host
callback function is called.
This function should return 0 when setting up the jtag
interface went fine and -1 on an error.
int shutdown(struct libxsvf_host *h);
This function is called by libxsvf to shutdown the jtag
interface. No other libxsvf_host callback function will
be called after this function has been executed.
This function should return 0 when shutting down the jtag
interface went fine and -1 on an error.
void udelay(struct libxsvf_host *h, long usecs, int tms, long num_tck)
A function that delays execution for at least the specified
number of microseconds.
When the 'num_tck' argument is not 0 also the specified number tck
clock cycles (i.e. 1-0-1 transitions) must be generated with TMS set
to the value specified in the 'tms' argument.
A simple implementation may perform the delay and the clock cycles
after another instead of parallel. This only has an impact on the
runtime of the player, not on its functionality.
int getbyte(struct libxsvf_host *h);
A function that returns the next byte from the input file
or -1 on end of file.
int sync(struct libxsvf_host *h);
This function is only needed when writing bindings for an asynchronous
hardware interface (see 'Using libxsvf with asynchronous interfaces' below).
This function is optional and the function pointer may be set to a NULL
pointer on implementations using the simple synchronous interface.
void pulse_tck(struct libxsvf_host *h, int tms, int tdi, int tdo, int rmask, int sync)
This is the main JTAG I/O callback function.
It must perform the following tasks:
* Set the tms line to the value specified in the 'tms' argument.
* Set the tdi line to the value specified in the 'tdi' argument.
This argument may be '-1' to indicate that the value of the tdi
line is not important. In this case the tdi line may be set to
any value or may be left unchanged.
* Create a negative pulse (1-0-1) on the JTAG TCK line.
* Check the tdo line against the should-be value specified in
the 'tdo' argument. This argument may be '-1' to indicate that
the value of the tdo line doesn't need to be checked.
* Store the current tdo value if the 'rmask' value is set to '1'.
This step may be ignored if the RMASK feature (see "Limitations
and non-standard extensions" above) is not used.
The function must return the current value of the tdo line, or -1 on
a TDO-mismatch-error.
A simple implementation of this function would look like this:
--snip--
int my_pulse_tck(struct libxsvf_host *h, int tms, int tdi, int tdo, int rmask, int sync) {
int line_tdo;
setPort(TMS, tms);
if (tdi >= 0)
setPort(TDI, tdi);
setPort(TCK, 0);
setPort(TCK, 1);
line_tdo = getPort(TDO);
return tdo < 0 || line_tdo == tdo ? line_tdo : -1;
}
--snap--
The 'sync' argument can safely be ignored unless you are writing
bindings for an asynchronous hardware interface (see 'Using libxsvf
with asynchronous interfaces' below).
void pulse_sck(struct libxsvf_host *h);
A function to create a pulse on the JTAG SCK line.
This function is optional and the function pointer may
be set to a NULL pointer on implementations without an
SCK line. In this cases an SVF 'RUNTEST n SCK' command
has no effect.
void set_trst(struct libxsvf_host *h, int v);
A function to set the JTAG TRST line to the specified
value:
1 ... drive the line high
0 ... drive the line low
-1 ... do not drive the line (high impedance)
-2 ... got SVF 'TRST ABSENT' command
This function is optional and the function pointer may
be set to a NULL pointer on implementations without an
TRST line. In this cases an SVF 'TRST' command has no
effect.
int set_frequency(struct libxsvf_host *h, int v);
A function to set the JTAG CLK frequency to the specified
value in Hz. This function should return 0 when setting
the frequency was successful and -1 on error.
This function pointer is optional (may be set to NULL).
In this case an SVF FREQUENCY command always results in
an error.
void report_tapstate(struct libxsvf_host *h);
This function is called whenever the state of the TAP
state machine has changed. The TAP state can be read
using the h->tap_state enum.
This function pointer is optional (may be set to NULL)
and is for debugging purposes only.
void report_device(struct libxsvf_host *h, unsigned long idcode);
This function is called in scan mode for each device found
in the JTAG chain.
This function pointer is optional (may be set to NULL)
and is only called in the SCAN mode.
void report_status(struct libxsvf_host *h, const char *message);
This function is called each time before an SVF or XSVF
command is executed.
This function pointer is optional (may be set to NULL)
and is for debugging purposes only.
void report_error(struct libxsvf_host *h, const char *file, int line, const char *message);
This function is called whenever an error is detected
in libxsvf. It is not optional and should provide a
way to notify a user about the error.
void *realloc(struct libxsvf_host *h, void *ptr, int size, enum libxsvf_mem which);
This function must provide a way to allocate dynamic
memory. In cases where there is a standard c library
it may be a simple wrapper for the realloc() function.
The xsvftool-gpio command line option '-r' can be used to
auto-generate a realloc function for static buffers, based
on the requirements from an example svf or xsvf file.
Example given:
./xsvftool-gpio -r my_host_realloc -s demo.svf
(Re-)allocation may fail. In this cases a NULL pointer
must be returned. The library then generates an error,
frees all resources and returns.
After such a struct is prepared, the function libxsvf_play()
can be called, passing the libxsvf_host struct as first and the
mode (LIBXSVF_MODE_SVF, LIBXSVF_MODE_XSVF or LIBXSVF_MODE_SCAN)
as second argument.
Example given:
if (libxsvf_play(&h, LIBXSVF_MODE_XSVF) < 0) {
/* Error handling */
}
The libxsvf_host struct is passed back to all callback functions
and the 'user_data' member (a void pointer) can be used to pass
additional data (such as a file handle) to the callbacks.
Host accessor macros
--------------------
Despite its great flexibility, APIs based on callback functions
as the one used by libxsvf are unusual in the embedded community.
Basically because they introduce a slight overhead in the memory
footprint.
For those who prefer a more direct integration with their host
environments libxsvf also provides 'host accessor macros' in the
libxsvf.h header file. Simply remove the callback functions from
the libxsvf_host struct and modify the LIBXSVF_HOST_ macros
to fit your needs.
Using libxsvf with asynchronous interfaces
------------------------------------------
This library has been designed at first for a register mapped bit banging
interface as it can be found on many microcontrollers or host CPUs. But
some interfaces might require the JTAG data to be send and recivied in
blocks and/or asynchronously. This is not trivial with this library because the
pulse_tck() callback function is expected to transfer one single bit at a time.
The solution to this is to buffer all data sent to pulse_tck() and always
return a valid status (i.e. 'tdo < 0 ? 1 : tdo') and do the transfers when the
buffer is full or when an interface shutdown is requested.
However, some JTAG transaction must be performed synchronously (e.g. the last
transaction in an XSVF XREPEAT data shift. In this cases pulse_tck() is called
with the 'sync' argument set to 1. The pulse_tck() function must then perform
all buffered JTAG transactions and return the actual tdo value for this last
JTAG transaction or -1 if an error was detected before.
An asynchronous interface binding also must implement the sync() function. It
must perform all buffered JTAG transactions and return -1 if a TDO error was
detected an 0 otherwise.
Note: The returncode of pulse_tck is not checked in all conditions! So whenever
an error is detected all further calls to pulse_tck() up to and including
the next call of pulse_tck() with the 'sync' argument set or the next call to
sync() or shutdown() must return -1.
Have a look at the example program 'xsvftool-ft232h.c' for a reference
implementation.
Stripping down libxsvf
----------------------
It is possible to disable SVF, XSVF and/or SCAN support by setting the
LIBXSVF_WITHOUT_SVF, LIBXSVF_WITHOUT_XSVF or LIBXSVF_WITHOUT_SCAN
defines. In this cases one would not want to link against svf.o, xsvf.o
or scan.o.
One does not need to link agains statename.o and memname.o if the
libxsvf_state2str() and libxsvf_mem2str() functions are not needed.
Usually this functions are used for debugging purposes only.
It is possible to modify the LIBXSVF_HOST_REPORT_STATUS() and
LIBXSVF_HOST_REPORT_ERROR() macros in libxsvf.h to be empty
instructions. This drastically reduces the number of string
constants in the code.