Subject: | limitation in shiftdr function |
I was reading the source code because I'm considering doing something
similar for a different hardware interface. It appears that the function
shiftdr will work reading a 32-bit register when that tap controller is
the last device in the chain. I'd guess it also would work writing a
register if it is in the first tap controller of the chain. The author
has confirmed that a bug may exist here. He wrote:
Toby wrote:
I think you've identified some bugs, or shortcomings, that happened to
work for my setup (32 bit data register) where the device I always read
from was last in the JTAG chain. Please do file a bug report and I'll
work on it. I'm glad some one has found this useful. You might also
check out the Device:JTAG:USB module as it got more of my attention and
might be further developed than the PP version.
I'm still planning on doing something similar for different hardware. If
so, I'll be able to 'test' a fix and post a patch. Currently I only have
an untested fix. The fix involves adding additional '0' bits to $data
(lsb) to compensate for bypassed taps before and after the desired
device. Also the last line of the routine would select the appropriate
bits and not always 32. The untested concept is shown below:
sub shiftdr {
my $self = shift;
my $device = shift;
my $data = shift;
my $tdo = undef;
#print "Sending data $data to device $device...\n";
# assumes RTI is beginning state
# Go to the SELECT-DR state
set_tms($self,1);
tog_tck($self,1);
# Go to the SHIFT-DR state
set_tms($self,0);
tog_tck($self,2);
# The first bit of data we want is now sitting on TDO of the selected
# device. If there are any devices in the chain after the selected
# device, the data we want must get through the each subsequent
# device's BYPASS register, which is 1 bit long. This means that if
# there are N devices in the chain after the selected device, and the
# number of bits of data being shifted is M, the total number of shifts
# must be N+M. Additionally, the first N bits of data received on
# TDO should be discarded.
$tdo = get_tdo($self);
# Find the number of devices on the scan chain
my $numdev = scalar(@{$self->{CHAIN}});
# compute how many extra leading bits may be required (to get first
bit to the device and receive first bit from the device)
# this is dependent upon the number of tap controllers preceeding and
following the addressed tap controller
my $dlen = length($data);
my $max = $numdev - $device - 1; # number of devices following
if ($max < $device) { $max = $device }
$data = $data . '0' x $max;
# Shift data, the rightmost bit goes first
for ($b=length($data)-1;$b>=0;$b--) {
set_tdi($self,substr($data,$b,1));
my $tms = $b eq 0? 1 : 0; #set TMS=1 on the last shift to go to the
EXIT1-IR state
set_tms($self,$tms);
tog_tck($self,1);
$tdo = get_tdo($self) . $tdo; # get tdo, build word from right to left
}
# Return to RTI state
set_tms($self,1);
tog_tck($self,1);
set_tms($self,0);
tog_tck($self,1);
# Find the number of subsequent devices on the chain following the
selected device
my $subdev = ($numdev-1)-$device;
# Return tdo as hex string
return convert_hex(substr($tdo, -1*($dlen+$subdev), $dlen));
}