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
366 lines
14 KiB
12 years ago
|
|
||
|
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.
|
||
|
|