get tap name from openocd using scan_chain
authorDobrica Pavlinusic <dpavlin@rot13.org>
Sat, 16 Jul 2016 19:29:21 +0000 (21:29 +0200)
committerDobrica Pavlinusic <dpavlin@rot13.org>
Sat, 16 Jul 2016 19:29:21 +0000 (21:29 +0200)
also, do some sanity checks to see if correct bsdl is loaded

openocd-jtag-boundary-scan.pl

index 2a3d9eb..93b1834 100755 (executable)
@@ -27,6 +27,8 @@ my $parse_in = 0;
 my $parse_regex = join('|', qw(
        PIN_MAP_STRING
        INSTRUCTION_OPCODE
+       INSTRUCTION_LENGTH
+       IDCODE_REGISTER
 ));
 
 $|=1; # flush stdout
@@ -42,6 +44,7 @@ while(<$bsdl>) {
                $parse->{$1} .= $_;
        } elsif ( $parse_in ) {
                next if m/^\s*--/;
+               s/\s+--.+$//; # remove comments and EOL
                $parse->{$parse_in} .= $_;
                $parse_in = 0 if m/;/;
        } elsif ( m/"(\d+)\s+\(BC_\d+,\s+(\S+),\s+(\S+)/ ) {
@@ -66,6 +69,10 @@ foreach my $chunk ( keys %$parse ) {
        $parse->{$chunk} =~ s/^.+?"//s; # strip upto first quote
        $parse->{$chunk} =~ s/"\s*;.*?$//s; # strip everything after closing
        $parse->{$chunk} =~ s/\s+/ /gs;
+       $parse->{$chunk} =~ s/^\s+//;
+       $parse->{$chunk} =~ s/\s+$//;
+       $parse->{$chunk} =~ s/attribute\s+$chunk\s+of\s+$entity\s+:\s+entity\s+is\s+(\d+)\s*;/$1/;
+
 }
 
 warn "# parse = ",dump($parse);
@@ -131,7 +138,7 @@ foreach my $pin_file ( glob "pins/$entity*.tsv" ) {
                if ( $set =~ m/set_location_assignment/i && $op =~ m/-to/i && $pin =~ s/^PIN_//ig ) {
                        $pin_desc->{$pin} = $desc; # overwrite pin description
                } else {
-                       warn "# ignored $_\n";
+                       #warn "## ignored $_\n";
                }
        }
        close($fh);
@@ -159,6 +166,7 @@ sub bits {
 my $last_bits = '';
 sub print_io {
        my $bits = shift;
+       return unless length($bits) == $BOUNDARY_LENGTH;
        my $o_bits = $bits;
        $bits = reverse $bits; # make substr work as expected
        my $last_bits_r = reverse $last_bits;
@@ -215,6 +223,7 @@ sub hex2bin {
 
 sub bin2hex {
         my $b = shift;
+       $b =~ s/\s+//g;
         my $blen = length($b);
         my $hlen = $blen / 4;
         return unpack("H$hlen", pack("B$blen", $b));
@@ -226,35 +235,56 @@ print $sock "jtag names\n"; # will fill-in $tap variable from openocd
 
 my $BSR;
 
+my $scan_chain;
+
 while(1) {
 
 while (<$sock>) {
        warn "<< ",dump($_);
        chomp;
        s/[\r\x00]+//g;
-       if ( /^\s*([A-F0-9]+)/ ) {
+       if ( ! $tap && m/^(\w+\.tap)$/ ) {
+               $tap = $1;
+               warn "# using TAP $tap\n";
+
+               print $sock "scan_chain\n";
+               $scan_chain = 0;
+
+       } elsif ( ! $scan_chain && m/\d+\s+$tap\s+Y\s+0x([0-9a-f]+)\s+0x[0-9a-f]+\s+(\d+)/ ) {
+
+               my ($IdCode,$IrLen) = ( $1, $2 );
+
+               my $bsdl_id_code = bin2hex( $parse->{IDCODE_REGISTER} );
+               die "IdCode != IDCODE_REGISTER $IdCode != $bsdl_id_code" if lc($IdCode) ne lc($bsdl_id_code);
+
+               die "IrLen != INSTRUCTION_LENGTH $IrLen != $parse->{INSTRUCTION_LENGTH}" if $IrLen != $parse->{INSTRUCTION_LENGTH};
+
+               warn "# OK IdCode $IdCode IrLen $IrLen\n";
+               $scan_chain = 1;
+
+               # first sample
+               print $sock "irscan $tap $opcode->{SAMPLE}\n"; # SAMPLE/PRELOAD
+               print $sock "drscan $tap $BOUNDARY_LENGTH 0\n";
+
+       } elsif ( /^\s*([A-F0-9]+)$/ ) {
                my $hex = $1;
                my $bin = hex2bin($hex);
+               $bin = substr($bin,0, $BOUNDARY_LENGTH) if length($bin) > $BOUNDARY_LENGTH;
                diff_bits($BSR, $bin);
                $BSR = $bin;
                print_io $bin if $bin ne $last_bits;
                gpio::pins() if $have_gpio;
                last;
-       } elsif ( m/^(\w+\.tap)$/ && !$tap ) {
-               $tap = $1;
-               warn "# using TAP $tap";
-
-               # first sample
-               print $sock "irscan $tap $opcode->{SAMPLE}\n"; # SAMPLE/PRELOAD
-               print $sock "drscan $tap $BOUNDARY_LENGTH 0\n";
-
+       } elsif ( m/>\s+\S+/ ) {
+               # ignore command echo
        } else {
-               warn "# in ",dump($_);
+               warn "# ignored ",dump($_);
        }
 }
 
 sub diff_bits {
        my ($old, $new) = @_;
+       return unless $old && $new;
        $old = reverse $old; # extra bits must be on the end
        $new = reverse $new;
        $old =~ s/(...)/$1 /g;