It allows to use multiple JTAG chains connected to the SCANSTA111 bridge.
Additionally it optimizes JTAG accesses through the high latency I/O interface,
which is slow at single accesses, but can perform fast block transfers
(eg. some implementations of VME or USB).
The code is published as public domain code
Wojciech M. Zabolotny
wz...@ise.pw.edu.pl
============== DISCLAIMER =================================================
Please note, that this is a Q&D code, so I do not assume any responsibility
for results of its use...
I do not give any warranty that the above code will work at all,
neither that it will not damage your hardware. If you want to use it,
you need to understand it and to match it to your hardware!!!
==========================================================================
The file my_jtag.c replaces some low level functions in the original jamstub.c
int jam_jtag_io(int tms, int tdi, int read_tdo)
void jam_delay(long microseconds)
void initialize_jtag_hardware()
void close_jtag_hardware()
int jam_vector_io
(
int signal_count,
long *dir_vect,
long *data_vect,
long *capture_vect
)
(I have just modified the name of the original functions in the jamstub.c,
adding them the "_orig" suffix).
You have to provide your own implementations of a few functions suited
to control your hardware.
Start and stop your i/o interface:
extern int my_io_init(void);
extern void my_io_release(void);
Read and write the JTAG register (with bit-mapped JTAG lines):
extern void my_jtag_write(unsigned char value);
extern unsigned char my_jtag_read(void);
Fast block transfer of JTAG register values (encoded like
for my_jtag_write). This function should also
provide the proper timing:
extern int my_io_block_write(unsigned char * data, int len);
Control of the SCANSTA111 bridge is built into the my_jtag_init
function (which is called by initialize_jtag_hardware).
The idea to make transmission faster is implemented by caching of
all JTAG writes until:
1) The cache is full or:
2) The JTAG read is requested
3) The jam_delay is called.
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2.1).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2007-03-19 10:57 CET by <wzab@wzlaphp>.
# Source directory was `/home/wzab/jam_player_mod'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 6347 -rw-r--r-- my_jtag.c
# 151 -rw-r--r-- my_jtag.h
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
if test "$gettext_dir" = FAILED && test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
set `$dir/gettext --version 2>&1`
if test "$3" = GNU
then
gettext_dir=$dir
fi
fi
if test "$locale_dir" = FAILED && test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
echo=echo
else
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
shar_touch='touch -am $3$4$5$6$2 "$8"'
else
shar_touch=:
echo
$echo 'WARNING: not restoring timestamps. Consider getting and'
$echo "installing GNU \`touch', distributed in GNU File Utilities..."
echo
fi
rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
#
if mkdir _sh08316; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
exit 1
fi
# ============= my_jtag.c ==============
if test -f 'my_jtag.c' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'my_jtag.c' '(file already exists)'
else
$echo 'x -' extracting 'my_jtag.c' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'my_jtag.c' &&
/*
X Public domain code, written by Wojciech M. Zabolotny (wz...@ise.pw.edu.pl)
X (09.2006-03.2007 )to extend
X the Altera Jam STAPL Player with the functionality to drive multiple JTAG chains
X connected to the SCANSTA111 bridge, and to optimize programming via the high
X latency fast interfaces.
X */
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include "my_jtag.h"
#include <stdio.h>
#include <sched.h>
X
extern int jtag_hardware_initialized; // Was type BOOL in jamstub.c!!!
extern int dcc_number;
extern int jtag_output_chain;
unsigned char jtag_reg = (1<<JTG_ENA) | (1<<JTG_TRST);
int jam_jtag_io(int tms, int tdi, int read_tdo);
int low_jtag_io(int tms, int tdi, int read_tdo);
void flush_io_cache(void);
void wait_usec(long microsec);
void wait_nanosec(long nanosec);
X
extern int my_io_init(void); // Your JTAG I/O initialization
extern void my_io_release(void); //Your JTAG I/O switch-off routine
extern void my_jtag_write(unsigned char value); //Set JTAG lines
extern unsigned char my_jtag_read(void); //Read JTAG lines (TDO)
extern int my_io_block_write(unsigned char * data, int len); //Sequential setting of JTAG lines
X
void jtag_scan_ir(unsigned char data)
{
X int i;
X unsigned char tdi=0;
X //We send the 8 bits from data
X //At the entry we are in the Select-DR-Scan state
X //Go to shift IR
X low_jtag_io(1,tdi,0); // go to Select-IR-Scan
X low_jtag_io(0,tdi,0); // go to Capture-IR
X low_jtag_io(0,tdi,0); // go Shift-IR
X for(i=0;i<8;i++) {
X tdi=data & 1;
X data >>= 1;
X low_jtag_io(i==7 ? 1 : 0 ,tdi, 0);
X }
X //We are in the Exit-IR state
X low_jtag_io(1,tdi,0); // go to Update-IR state
X low_jtag_io(1,tdi,0); // go to Select-DR-Scan state
X //At the return we are also in the Select-DR-Scan state
X return;
}
X
void my_jtag_init(void)
{
X unsigned char scansta_addr=0, scansta_chain=0;
X int i;
X int res;
X /*
X struct sched_param schedp;
X schedp.sched_priority=99;
X fprintf(stderr,"Set scheduling policy\n");
X if(sched_setscheduler(0, SCHED_RR, &schedp)) {
X fprintf(stderr,"Error setting the scheduling policy :-(\n");
X exit(1);
X };
X */
X if((jtag_output_chain<1) || (jtag_output_chain>2)) {
X fprintf(stderr,"Wrong JTAG chain number: %d (must be between 1 and 2)\n",jtag_output_chain);
X exit(1);
X }
X scansta_addr=MY_SCANSTA_ADDR;
X scansta_chain=0xa0+jtag_output_chain;
X res=my_io_init();
X if(res != 0) {
X fprintf(stderr,"my_jtag_init access error: %d\n",res);
X exit(1);
X }
X fprintf(stderr,"JTAG reg: %lx\n",my_jtag_read());
X // We do reset JTAG!!!
X my_jtag_write(1<< JTG_ENA);
X fprintf(stderr,"JTAG reg: %lx\n",my_jtag_read());
X my_jtag_write((1 << JTG_ENA) | (1 << JTG_TRST) );
X fprintf(stderr,"JTAG reg: %lx\n",my_jtag_read());
X //Now we can start with the setting of SCANSTA111
X //First soft reset of the TAP (well, it is not necessare, but I'm a little paranoid ;-) )
X for (i=0;i<10;i++)
X low_jtag_io(1,0,0);
X low_jtag_io(0,0,0); // go to Run-Test-Idle
X low_jtag_io(1,0,0); // go to Select-DR-Scan
X jtag_scan_ir(scansta_addr); //Send 8-bits to IR, goo to Select-DR-Scan
X jtag_scan_ir(scansta_chain); //Send 8-bits to IR, goo to Select-DR-Scan
X //jam_jtag_io(?,0,0); // go to Run-Test-Idle
X //Reset the connected chain (SCANSTA111 does not get RESET, it needs the TRST reset!!!)
X for (i=0;i<10;i++)
X low_jtag_io(1,0,0);
}
X
void my_jtag_release(void)
{
X //Here you should stop the communication over
X //your communication interface
X my_io_release();
}
X
void initialize_jtag_hardware()
{
X my_jtag_init();
}
void close_jtag_hardware()
{
X //First we flush the I/O cache
X flush_io_cache();
X //Then we wait for a few miliseconds
X wait_usec(1000);
X //And finally we set the reset line in active state
X my_jtag_write(1 << JTG_ENA );
X //Again we wait for a few miliseconds
X wait_usec(1000);
X //And finally we release the my_jtag
X my_jtag_release();
}
X
X
X
/* read the TDO bit and store it in val */
unsigned char read_tdo_bit()
{
X unsigned long val;
X val=my_jtag_read();
X return val & (1<<JTG_TDO) ? 1 : 0;
}
X
//Buffers used for caching of write accesses
#define IO_CACHE_LEN (1024)
unsigned char data[IO_CACHE_LEN];
X
//Pointer used to cache
int io_cache_cnt = 0;
X
void flush_io_cache()
{
X int res;
X if(io_cache_cnt) {
X res=my_io_block_write(data,io_cache_cnt);
X if(res != 0) {
X fprintf(stderr,"access error in flush_io_cache: %d\n",res);
X exit(1);
X }
X io_cache_cnt = 0;
X }
}
X
void io_cache_write(unsigned long val)
{
X if(io_cache_cnt>=IO_CACHE_LEN) flush_io_cache();
X data[io_cache_cnt]=val;
X io_cache_cnt++;
}
X
int low_jtag_io(int tms, int tdi, int read_tdo)
{
X int tdo=0;
X if(tms) {
X jtag_reg |= (1 << JTG_TMS);
X } else {
X jtag_reg &= 0xff ^ (1 << JTG_TMS);
X }
X if(tdi) {
X jtag_reg |= (1 << JTG_TDI);
X } else {
X jtag_reg &= 0xff ^ (1 << JTG_TDI);
X }
X if(read_tdo) {
X //read is requested, flush the cached writes
X flush_io_cache();
X my_jtag_write(jtag_reg);
X tdo = read_tdo_bit();
X } else {
X io_cache_write(jtag_reg);
X }
X jtag_reg |= (1 << JTG_TCK);
X io_cache_write(jtag_reg);
X jtag_reg &= 0xff ^ (1 << JTG_TCK);
X io_cache_write(jtag_reg);
X return tdo;
}
X
//More advanced version of the low_jtag_io - all write requests are cached, until read
//request is issued,
//the cache is emptied when 1) read of TDO is requested, 2) jam_delay is called
//3) the cache is full
X
int jam_jtag_io(int tms, int tdi, int read_tdo)
{
X int tdo=0;
X if (!jtag_hardware_initialized)
X {
X fprintf(stderr,"JTAG not initialized yet...\n");
X initialize_jtag_hardware();
X jtag_hardware_initialized = 1; //we must set it in advance
X }
X return low_jtag_io(tms, tdi, read_tdo);
}
X
int jam_vector_io
(
X int signal_count,
X long *dir_vect,
X long *data_vect,
X long *capture_vect
X )
{
X fprintf(stderr,"VECTOR functions not implemented!!!\n");
X exit(1);
}
X
void wait_usec(long microsec)
{
X wait_nanosec(microsec*1000);
}
X
void wait_nanosec(long nanosec)
{
X struct timespec rec;
X int res;
X rec.tv_sec=0;
X rec.tv_nsec=nanosec;
X for(;;) {
X res=nanosleep(&rec, &rec);
X if (res==0) break;
X else {
X if (errno==EINVAL){
X fprintf(stderr,"nanosleep error\n",res);
X exit(1);
X }
X }
X }
}
void jam_delay(long microseconds)
{
X if(jtag_hardware_initialized) flush_io_cache();
X //usleep(microseconds);
X wait_nanosec(1000*microseconds);
}
SHAR_EOF
(set 20 07 03 19 10 54 59 'my_jtag.c'; eval "$shar_touch") &&
chmod 0644 'my_jtag.c' ||
$echo 'restore of' 'my_jtag.c' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'my_jtag.c:' 'MD5 check failed'
d99eab29acfbc339dbf9cc5332cd3ae3 my_jtag.c
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'my_jtag.c'`"
test 6347 -eq "$shar_count" ||
$echo 'my_jtag.c:' 'original size' '6347,' 'current size' "$shar_count!"
fi
fi
# ============= my_jtag.h ==============
if test -f 'my_jtag.h' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'my_jtag.h' '(file already exists)'
else
$echo 'x -' extracting 'my_jtag.h' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'my_jtag.h' &&
#define MY_SCANSTA_ADDR (15)
#define JTG_TDO (0)
#define JTG_TMS (3)
#define JTG_TCK (2)
#define JTG_TDI (1)
#define JTG_TRST (4)
#define JTG_ENA (7)
X
SHAR_EOF
(set 20 07 03 19 10 57 00 'my_jtag.h'; eval "$shar_touch") &&
chmod 0644 'my_jtag.h' ||
$echo 'restore of' 'my_jtag.h' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'my_jtag.h:' 'MD5 check failed'
e0157b6178ae4e99c7878db953280bc3 my_jtag.h
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'my_jtag.h'`"
test 151 -eq "$shar_count" ||
$echo 'my_jtag.h:' 'original size' '151,' 'current size' "$shar_count!"
fi
fi
rm -fr _sh08316
exit 0