mbed-os/TESTS/host_tests/timing_drift_auto.py

136 lines
5.8 KiB
Python

"""
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
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%.
#
"""
__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
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")
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)
def compute_parameter(self, failure_criteria=0.05):
t_max = self.round_trip_final_end - self.round_trip_base_start
t_min = self.round_trip_final_start - self.round_trip_base_end
t_max_hi = t_max * (1 + failure_criteria)
t_max_lo = t_max * (1 - failure_criteria)
t_min_hi = t_min * (1 + failure_criteria)
t_min_lo = t_min * (1 - failure_criteria)
device_time = (self.device_time_final - self.device_time_base) / self.mega
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("DUT base time : {}".format(self.device_time_base))
self.log("DUT end time : {}".format(self.device_time_final))
self.log("min_pass : {} , max_pass : {} for {}%%".format(t_max_lo, t_min_hi, failure_criteria * 100))
self.log("min_inconclusive : {} , max_inconclusive : {}".format(t_min_lo, t_max_hi))
self.log("Time reported by device: {}".format(device_time))
if t_max_lo <= device_time <= t_min_hi:
self.log("Test passed !!!")
self.__result = True
elif t_min_lo <= device_time <= t_max_hi:
self.log("Test inconclusive due to transport delay, retrying")
self.__result = False
else:
self.log("Time outside of passing range. Timing drift seems to be present !!!")
self.__result = False
return self.__result
def result(self):
return self.__result
def teardown(self):
pass