mbed-os/TESTS/host_tests/timing_drift_auto.py

141 lines
6.1 KiB
Python
Raw Normal View History

2016-08-30 19:38:30 +00:00
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from mbed_host_tests import BaseHostTest
import time
2016-08-30 19:38:30 +00:00
class TimingDriftSync(BaseHostTest):
"""
This works as master-slave fashion
1) Device says its booted up and ready to run the test, wait for host to respond
2) Host sends the message to get the device current time i.e base time
#
# *
# * |
#<---* DUT<- base_time | - round_trip_base_time ------
# * | |
# * - |
# - |
# | |
# | |
# | - measurement_stretch | - nominal_time
# | |
# | |
# - |
# * - |
# * | |
#<---* DUT <-final_time | - round_trip_final_time------
# * |
# * -
#
#
# As we increase the measurement_stretch, the error because of transport delay diminishes.
# The values of measurement_stretch is propotional to round_trip_base_time(transport delays)
# by factor time_measurement_multiplier.This multiplier is used is 80 to tolerate 2 sec of
# transport delay and test time ~ 180 secs
#
# Failure in timing can occur if we are ticking too fast or we are ticking too slow, hence we have
# min_range and max_range. if we cross on either side tests would be marked fail. The range is a function of
# tolerance/acceptable drift currently its 5%.
#
2016-08-30 19:38:30 +00:00
"""
__result = None
mega = 1000000.0
max_measurement_time = 180
# this value is obtained for measurements when there is 0 transport delay and we want accurancy of 5%
time_measurement_multiplier = 80
def _callback_timing_drift_check_start(self, key, value, timestamp):
self.round_trip_base_start = timestamp
self.send_kv("base_time", 0)
def _callback_base_time(self, key, value, timestamp):
self.round_trip_base_end = timestamp
self.device_time_base = float(value)
self.round_trip_base_time = self.round_trip_base_end - self.round_trip_base_start
2016-08-30 19:38:30 +00:00
self.log("Device base time {}".format(value))
measurement_stretch = (self.round_trip_base_time * self.time_measurement_multiplier) + 5
if measurement_stretch > self.max_measurement_time:
self.log("Time required {} to determine device timer is too high due to transport delay, skipping".format(measurement_stretch))
else:
self.log("sleeping for {} to measure drift accurately".format(measurement_stretch))
time.sleep(measurement_stretch)
self.round_trip_final_start = time.time()
self.send_kv("final_time", 0)
def _callback_final_time(self, key, value, timestamp):
self.round_trip_final_end = timestamp
self.device_time_final = float(value)
self.round_trip_final_time = self.round_trip_final_end - self.round_trip_final_start
self.log("Device final time {} ".format(value))
# compute the test results and send to device
results = "pass" if self.compute_parameter() else "fail"
self.send_kv(results, "0")
2016-08-30 19:38:30 +00:00
def setup(self):
self.register_callback('timing_drift_check_start', self._callback_timing_drift_check_start)
self.register_callback('base_time', self._callback_base_time)
self.register_callback('final_time', self._callback_final_time)
2016-08-30 19:38:30 +00:00
def compute_parameter(self, failure_criteria=0.05):
nominal_time = (self.round_trip_final_start + self.round_trip_final_end) / 2.0 - (self.round_trip_base_start + self.round_trip_base_end) / 2.0
transport_error = self.round_trip_final_time / 2.0 + self.round_trip_base_time / 2.0
2016-08-30 19:38:30 +00:00
min_range = nominal_time * (1 - failure_criteria)
max_range = nominal_time * (1 + failure_criteria)
device_time = (self.device_time_final - self.device_time_base) / self.mega
min_pass_value = (device_time - transport_error)
max_pass_value = (device_time + transport_error)
self.log("Compute host events")
self.log("Transport delay 0: {}".format(self.round_trip_base_time))
self.log("Transport delay 1: {}".format(self.round_trip_final_time))
self.log("Transport dealy avg : {} ".format(transport_error))
self.log("DUT base time : {}".format(self.device_time_base))
self.log("DUT end time : {}".format(self.device_time_final))
self.log("Actual Time : {}".format(device_time))
self.log("Nominal Time : {}".format(nominal_time))
self.log("min_pass : {} , max_pass : {}".format(min_pass_value, max_pass_value))
self.log("min_range : {} , max_range : {}".format(min_range, max_range))
if (min_pass_value >= min_range) and (max_pass_value <= max_range):
self.log("Test passed !!!")
self.__result = True
elif (min_pass_value > max_range) or (max_pass_value < min_pass_value):
self.log("Time outside of passing range. Timing drift seems to be present !!!")
2016-08-30 19:38:30 +00:00
self.__result = False
else:
self.log("Test inconclusive due to transport delay, retrying")
self.__result = False
2016-08-30 19:38:30 +00:00
return self.__result
def result(self):
return self.__result
2016-08-30 19:38:30 +00:00
def teardown(self):
pass