]> jspc29.x-matter.uni-frankfurt.de Git - daqtools.git/commitdiff
introducing flash_settings.pl ... a utility to write slow control settings in a dedic...
authorMichael Wiebusch <m.wiebusch@gsi.de>
Thu, 13 Aug 2015 13:41:18 +0000 (15:41 +0200)
committerMichael Wiebusch <m.wiebusch@gsi.de>
Thu, 13 Aug 2015 13:41:18 +0000 (15:41 +0200)
tools/flash_settings.pl [new file with mode: 0755]

diff --git a/tools/flash_settings.pl b/tools/flash_settings.pl
new file mode 100755 (executable)
index 0000000..bc8ede0
--- /dev/null
@@ -0,0 +1,277 @@
+#!/usr/bin/perl -w
+
+use strict;
+use warnings;
+use POSIX;
+use File::Basename;
+# use Data::Dumper;
+
+use Getopt::Long;
+
+my $help=0;
+my $verbose=0;
+my $yestoall=0;
+my $clear=0;
+my $info=0;
+my $noverify=0;
+
+Getopt::Long::Configure(qw(gnu_getopt));
+GetOptions(
+           'help|h'    => \$help,
+#            'verbose|v' => \$verbose,
+           'y'         => \$yestoall,
+           'clear|c'   => \$clear,
+           'info|i'    => \$info,
+           'noverify|v'  => \$noverify,
+          );
+
+
+          
+
+my @pages;
+my $page;
+
+my $header_page_addr = 0x7000;
+
+my $trbflash = "trbflash";
+
+my $FPGA            = $ARGV[0];
+my $settings_file   = (defined($ARGV[1])) ? $ARGV[1] : "/dev/null";
+
+if ($help or not(defined($FPGA)) ) {
+help();
+}
+
+if ($info) {
+
+#   my $infostring ="";
+#   my $raw_page = qx"$trbflash dumppage $FPGA $header_page_addr";
+#   for my $line (split("\n",$raw_page)) {
+#     if ($line =~ m/^0x\S\S  (\S\S ){16}  ((\S){16})/){
+#       $infostring.=$2;
+#     }
+#   }
+  
+  my $infostring = get_page($FPGA,$header_page_addr);
+  
+  unless ( substr($infostring,0,8) eq "SLOWCTRL" ) {
+    print "found no default slow control settings in FPGA $FPGA\n";
+    exit;
+  }
+  
+  my $filename        = substr($infostring,32,32);
+  my $flash_date      = substr($infostring,96,32);
+  my $setfile_moddate = substr($infostring,64,32);
+  my $no_pages        = unpack("l",reverse(split("",substr($infostring,12,4))));
+  my $no_registers    = unpack("l",reverse(split("",substr($infostring,8,4))));
+  
+  $filename        =~ s/\.+$//;
+  $flash_date      =~ s/\.+$//;
+  $setfile_moddate =~ s/\.+$//;
+  
+  print "found default slow control settings in FPGA $FPGA\n";
+  print "  from settings file  $filename\n";
+  print "  last modified at    $setfile_moddate\n";
+  print "  flashed at          $flash_date\n";
+  print "  number of pages     $no_pages\n";
+  print "  number of registers $no_registers\n";
+  
+  exit;
+}
+
+
+my $epoch_timestamp = (stat($settings_file))[9];
+my $settings_file_mod_date = strftime("%Y-%m-%d_%H:%M:%S\n",localtime($epoch_timestamp)); # modification date
+my $flash_timestamp        = strftime("%Y-%m-%d_%H:%M:%S\n",localtime());                 # now
+
+my $registers_per_page = 42;
+
+my $sc_data = {};
+
+
+
+
+
+
+if (defined($settings_file) and not($settings_file eq "/dev/null") ) {
+
+  # load settings from settings file
+  open(FH,$settings_file) or die "could not open settings file $settings_file\n";
+  my @lines = <FH>;
+  close(FH);
+
+  for my $line (@lines) {
+    $line =~ m/(^[xXa-fA-F0-9]+)\s+([xXa-fA-F0-9]+)/;
+    $sc_data->{eval($1)} = eval($2); # convert hex/binary/decimal strings to numbers
+  }
+
+} elsif ($clear) {
+  print "clearing the settings in FPGA $FPGA\n";
+} else {
+  help();
+}
+
+# write slow control data to pages
+
+my $registers_to_read = 0;
+my $register_counter_on_page = 0;
+$page = chr(0) x 256; # initialize empty page;
+
+my @addresses = sort { $a <=> $b } keys $sc_data;
+for my $addr (@addresses) {
+  
+  insert_at(\$page,6*$register_counter_on_page,   my_uint($addr,             2) );
+  insert_at(\$page,6*$register_counter_on_page+2, my_uint($sc_data->{$addr}, 4) );
+  
+  $registers_to_read++;
+  $register_counter_on_page = ($registers_to_read)%($registers_per_page);
+  
+  if ( ($register_counter_on_page == 0) or ($registers_to_read == scalar(@addresses)) ) {
+    push(@pages,$page);
+    $page = chr(0) x 256; # initialize empty page;
+  }
+  
+}
+
+
+# compose header page
+$page = chr(0) x 256; # initialize empty page;
+
+my $pages_to_read = ceil($registers_to_read/42); 
+unless($clear) {
+  insert_at(\$page,0,  "SLOWCTRL" );
+
+  insert_at(\$page,8,  my_uint($registers_to_read, 4) );
+  insert_at(\$page,12, my_uint($pages_to_read,     4) );
+
+  insert_at(\$page,32,(fileparse($settings_file))[0]); # filename only
+  insert_at(\$page,64,$settings_file_mod_date); # modification date timestamp
+  insert_at(\$page,96,$flash_timestamp); # flash timestamp
+}
+unshift(@pages,substr($page,0,256)); # push current page to the pages array, 
+
+
+
+
+
+my $trbflash_options = "";
+$trbflash_options.= " -y " if $yestoall;
+
+  my $temp_file = qx%mktemp%;
+  open(FILE,"> $temp_file") or die "could not open temporary file $temp_file for writing!\n";
+  binmode(FILE);
+  print FILE join("",@pages);
+  close(FILE);
+  system("$trbflash $trbflash_options flash_at_page $FPGA $header_page_addr $temp_file");
+  system("rm $temp_file");
+
+
+unless ($noverify) {
+  #read header page
+#   my $raw_page = qx"$trbflash dumppage $FPGA $header_page_addr";
+
+  my $header_page = get_page($FPGA, $header_page_addr);
+  my $no_pages    = unpack("l",reverse(split("",substr($header_page,12,4))));
+#   print "number of pages : $no_pages\n";
+  my $mismatch = 0;
+  
+  if ($no_pages == $pages_to_read) {
+    for (my $i = 0; $i le $no_pages; $i++) {
+      my $cur_page;
+      if($i == 0) {
+        $cur_page = $header_page;
+      } else {
+        $cur_page = get_page($FPGA,$header_page_addr+$i);
+      }
+      if ($cur_page eq $pages[$i]) {
+        print "page $i/$no_pages verified\n";
+      } else {
+        print "page $i/$no_pages mismatch!\n";
+        $mismatch++;
+      }
+    }
+  
+  
+  } else {
+    print "number of pages mismatch!";
+    $mismatch++;
+  }
+  
+  die "Memory verification failed! To ensure a safe FPGA behaviour, try again, or at least issue\n".
+      "flash_settings.pl $FPGA --clear\nto clear the corrupted default settings\n" if $mismatch;
+  
+  
+}
+
+# system("xxd $temp_file");
+# print "$temp_file\n";
+
+
+
+
+
+sub get_page {
+  my $FPGA = shift;
+  my $page = shift;
+  my $raw_page = qx"$trbflash dumppage $FPGA $page 2>&1";
+  my $data;
+  for my $line (split("\n",$raw_page)) {
+    if ($line =~ m/^0x\S\S  ((\S\S ){16})  ((\S){16})/){
+      my $hex_nibbles = $1;
+      $hex_nibbles =~ s/\s//g;
+      $data .= pack("H*",$hex_nibbles);
+    }
+  }
+  return $data if (length($data) == 256);
+  die "could not read page $page from flash";
+}
+
+
+sub insert_at {
+
+  my $pageRef = shift;
+  my $pos     = shift;
+  my $string  = shift;
+  
+  substr($$pageRef,$pos,length($string)) = $string;
+}
+
+sub my_uint {
+  my $number = floor(shift);
+  my $bytes  = shift;
+  my @out = ();
+  
+  for my $i (1..$bytes) {
+    push(@out,chr($number & 0xFF));
+    $number = floor($number/256);
+  }
+  
+  return join("",reverse @out);
+}
+
+sub help {
+print <<EOF;
+usage:
+
+  flash_settings.pl [options] <FPGA addr> [settings file]
+  
+options:
+
+  --help|-h       show help message
+  -y              pass "yes to all" option to trbflash
+  --clear|-c      clear settings in given FPGA
+  --noverify|-v   do not verify the written memory area
+  --info|-i       show information summary about settings
+                  in the flash
+  
+settings file format:
+
+<sc addr> <value>
+<sc addr> <value>
+<sc addr> <value>
+...
+
+2015 by Michael Wiebusch (m.wiebusch\@gsi.de)
+EOF
+exit;
+}