Commit ca0dd298 authored by Christian Fibich's avatar Christian Fibich Committed by Stefan Tauner
Browse files

Added fault detection decoding to message parser. Added a 'fix' to a possible...

Added fault detection decoding to message parser. Added a 'fix' to a possible CRC error when sending multiple configurations one after another and an underrun occurs.
The function would have returned with the underrun message instead of the conf-done message.
parent a9f02b10
......@@ -16,7 +16,7 @@ use Switch;
use Log::Log4perl qw(get_logger);
use Digest::CRC "crc";
use Time::HiRes "usleep";
use Data::Dumper;
use FIJI::AnySerialPort;
## @method init ($portname, $baudrate)
......@@ -152,9 +152,9 @@ sub sanitize_config {
$logger->error(sprintf("Configuration value \"%s\" is negative (%d).", $k, $config_ref->{$k}));
return 1;
}
my $max_val = 2 ** $consts_ref->{'TIMER_WIDTH'} - 1;
my $max_val = 2 ** ($consts_ref->{'TIMER_WIDTH'}*8) - 1;
if ($config_ref->{$k} > $max_val) {
$logger->error(sprintf("Configuration value \"%s\" is too big (%d) for %d bits.", $k, $config_ref->{$k}, $consts_ref->{'TIMER_WIDTH'}));
$logger->error(sprintf("Configuration value \"%s\" is too big (%d) for %d bytes.", $k, $config_ref->{$k}, $consts_ref->{'TIMER_WIDTH'}));
return 1;
}
}
......@@ -202,13 +202,13 @@ sub send_config {
my $t1_duration = $config_ref->{'t1_duration'};
my @t1_duration_arr;
for (my $i = 0; $i < $consts_ref->{'TIMER_WIDTH'} / 8; $i++) {
for (my $i = 0; $i < $consts_ref->{'TIMER_WIDTH'}; $i++) {
push(@t1_duration_arr, ($t1_duration >> ($i * 8)) & 0xFF);
}
my $t2_duration = $config_ref->{'t2_duration'};
my @t2_duration_arr;
for (my $i = 0; $i < $consts_ref->{'TIMER_WIDTH'} / 8; $i++) {
for (my $i = 0; $i < $consts_ref->{'TIMER_WIDTH'}; $i++) {
push(@t2_duration_arr, ($t2_duration >> ($i * 8)) & 0xFF);
}
......@@ -282,6 +282,7 @@ sub send_config {
my @rcv_buf = ();
my %err;
my %fd;
my $msg_type;
# if block_till_ready... wait for ready message first
if (defined($block_till_ready) && $block_till_ready != 0) {
......@@ -289,14 +290,15 @@ sub send_config {
$logger->error("Receiving READY message failed");
return 1;
}
$msg_type = _parse_return_message($rcv_buf[0], \%err);
$msg_type = _parse_return_message($rcv_buf[0], \%err, \%fd);
print Dumper(\%err);
if (!defined($msg_type) || $msg_type ne 'READY') {
$logger->error(sprintf("Received message is not a valid READY message (but %s).", defined($msg_type) ? $msg_type : "invalid"));
return 1;
return {msg_type => $msg_type, fault_detect => \%fd, error => \%err};
}
if ($err{'ANY'} != 0 ) {
$logger->error("Received READY message indicates errors on the DUT side.");
return 1;
return {msg_type => $msg_type, fault_detect => \%fd, error => \%err};
}
}
......@@ -307,26 +309,34 @@ sub send_config {
}
# wait for CONF_DONE message and check for errors
@rcv_buf = ();
if ((_rcv_bitstream($port, 1, $timeout, \@rcv_buf) != 0) || ((scalar @rcv_buf) != 1)) {
$logger->error("Receiving CONF_DONE message failed");
return 1;
}
$msg_type = _parse_return_message($rcv_buf[0], \%err);
if (!defined($msg_type) || $msg_type ne 'CONF_DONE') {
$logger->error(sprintf("Received message is not a valid CONF_DONE message (but %s).", defined($msg_type) ? $msg_type : "invalid"));
return 1;
}
if ($err{'ANY'} != 0) {
$logger->error("Received message indicated errors.");
return 1;
$msg_type = undef;
# loop tries to clear away an UNDERRUN messages still in the buffer
# else, we return to the caller too early (he might try to send another
# pattern while the current config is still active.
while(!defined $msg_type || $msg_type ne 'CONF_DONE') {
@rcv_buf = ();
if ((_rcv_bitstream($port, 1, $timeout, \@rcv_buf) != 0) || ((scalar @rcv_buf) != 1)) {
$logger->error("Receiving CONF_DONE message failed");
return 1;
}
$msg_type = _parse_return_message($rcv_buf[0], \%err, \%fd);
if (!defined($msg_type) || $msg_type ne 'CONF_DONE') {
$logger->error(sprintf("Received message is not a valid CONF_DONE message (but %s).", defined($msg_type) ? $msg_type : "invalid"));
#return {msg_type => $msg_type, fault_detect => \%fd, error => \%err};
}
if ($err{'ANY'} != 0) {
$logger->error("Received message indicated errors.");
return {msg_type => $msg_type, fault_detect => \%fd, error => \%err};
}
}
# exit early if requested to not wait for another READY message
if (!defined($wait_for_ready) || $wait_for_ready == 0) {
$logger->debug("Returning after successfully receiving CONF_DONE message due to unset wait_for_ready.");
return 0;
return {msg_type => $msg_type, fault_detect => \%fd, error => \%err};
}
# wait for READY/UNDERRUN message
......@@ -335,17 +345,17 @@ sub send_config {
$logger->error("Receiving READY message failed");
return 1;
}
$msg_type = _parse_return_message($rcv_buf[0], \%err);
$msg_type = _parse_return_message($rcv_buf[0], \%err, \%fd);
if (!defined($msg_type) || $msg_type ne 'READY') {
$logger->error(sprintf("Received message is not a valid READY message (but %s).", defined($msg_type) ? $msg_type : "invalid"));
return 1;
return {msg_type => $msg_type, fault_detect => \%fd, error => \%err};
}
if ($err{'ANY'} != 0 ) {
$logger->error("Received READY message indicates errors on the DUT side.");
return 1;
return {msg_type => $msg_type, fault_detect => \%fd, error => \%err};
}
return 0;
return {msg_type => $msg_type, fault_detect => \%fd, error => \%err};
}
......@@ -463,13 +473,18 @@ sub _rcv_bitstream {
# Possible types are: 'CONF_DONE', 'UNDERRUN', 'READY'
sub _parse_return_message {
my $logger = get_logger();
my ($message_byte, $error_ref) = @_;
my ($message_byte, $error_ref, $fd_ref) = @_;
if (defined($error_ref) && ref($error_ref) ne 'HASH') {
$logger->error("Parameter is not a reference to a hash.");
$logger->error("Second parameter is not a reference to a hash.");
return undef;
}
if (defined($fd_ref) && ref($fd_ref) ne 'HASH') {
$logger->error("Third parameter is not a reference to a hash.");
return undef;
}
$error_ref->{ANY} = 0; # be optimistic :) and ease error handling in callers
$error_ref->{'ANY'} = 0; # be optimistic :) and ease error handling in callers
$fd_ref->{'ANY'} = 0; # be optimistic :)
# Even parity bit calculation:
# Hardware XORs the seven LSB and transmits result as 8th bit.
......@@ -484,11 +499,6 @@ sub _parse_return_message {
return undef;
}
my $fault_state = ($message_byte & 0x18) >> 3;
if ($fault_state != 0) {
$logger->warn(sprintf("Return message has indicates fault state %d.", $fault_state));
}
if (defined($error_ref)) {
$error_ref->{C} = (($message_byte & 0x01) != 0);
$error_ref->{I} = (($message_byte & 0x02) != 0);
......@@ -505,6 +515,20 @@ sub _parse_return_message {
$logger->debug("Return message indicates an RX UART error.");
}
}
if (defined($fd_ref)) {
$fd_ref->{1} = (($message_byte & 0x08) != 0);
$fd_ref->{2} = (($message_byte & 0x10) != 0);
$fd_ref->{ANY} = (($message_byte & 0x18) != 0);
if ($fd_ref->{1} != 0) {
$logger->debug("Fault detection signal 1 active.");
}
if ($fd_ref->{2} != 0) {
$logger->debug("Fault detection signal 2 active.");
}
}
switch(($message_byte >> 5) & 0x03) {
case 0x01 { return 'CONF_DONE'; }
case 0x02 { return 'READY'; }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment