Additional logging of kernel.timer.timer_behavior_external test case statistics for timer drift, variance, etc. as JSON-formatted records to make easier data collection and its further analysis. These log records will be processed by the Twister Harness recording feature which captures and parses timer statistics from the log output, then composes it into twister.json and recording.csv files. Signed-off-by: Dmitrii Golovanov <dmitrii.golovanov@intel.com>
90 lines
3.2 KiB
Python
90 lines
3.2 KiB
Python
# Copyright (c) 2023-2024 Intel Corporation
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
# Sample code showing an external tool Python module helper for Saleae Logic 2
|
|
# compatible logic analyzer.
|
|
# To use it, the Saleae Logic 2 Automation server must be enabled. For more
|
|
# information on it, check
|
|
# https://saleae.github.io/logic2-automation/getting_started.html
|
|
|
|
import numpy as np
|
|
import tempfile
|
|
|
|
from pathlib import Path
|
|
from saleae import automation
|
|
from saleae.automation import (CaptureConfiguration, LogicDeviceConfiguration,
|
|
DigitalTriggerCaptureMode, DigitalTriggerType)
|
|
|
|
def do_collection(device_id, address, port, channel, sample_rate, threshold_volts,
|
|
seconds, output_dir):
|
|
with automation.Manager.connect(address=address, port=port) as manager:
|
|
|
|
device_configuration = LogicDeviceConfiguration(
|
|
enabled_digital_channels=[channel],
|
|
digital_sample_rate=sample_rate,
|
|
digital_threshold_volts=threshold_volts,
|
|
)
|
|
|
|
capture_mode = DigitalTriggerCaptureMode(DigitalTriggerType.RISING,
|
|
channel,
|
|
after_trigger_seconds=seconds)
|
|
capture_configuration = CaptureConfiguration(capture_mode=capture_mode)
|
|
|
|
with manager.start_capture(
|
|
device_id=device_id,
|
|
device_configuration=device_configuration,
|
|
capture_configuration=capture_configuration) as capture:
|
|
|
|
capture.wait()
|
|
|
|
capture.export_raw_data_csv(directory=output_dir,
|
|
digital_channels=[channel])
|
|
|
|
def do_analysis(output_dir):
|
|
file_name = Path(output_dir) / 'digital.csv'
|
|
all_data = np.loadtxt(file_name, delimiter=',', skiprows=1, usecols=0)
|
|
|
|
# Pre trigger data is negative on CSV
|
|
non_negative = all_data[all_data >= 0]
|
|
|
|
# Last sample is just captured at last moment of capture, not related
|
|
# to gpio toggle. Discard it
|
|
data = non_negative[:-1]
|
|
|
|
diff = np.diff(data)
|
|
|
|
mean = np.mean(diff)
|
|
std = np.std(diff)
|
|
var = np.var(diff)
|
|
minimum = np.min(diff)
|
|
maximum = np.max(diff)
|
|
total_time = data[-1]
|
|
|
|
return {'mean': mean, 'stddev': std, 'var': var, 'min': minimum,
|
|
'max': maximum, 'total_time': total_time}, len(diff)
|
|
|
|
|
|
# options should be a string of the format:
|
|
# [device-id=<device_id>,]port=<saleae_logic2_server_port>,
|
|
# channel=<channel_number>,sample-rate=<sample-rate>,
|
|
# threshold-volts=<threshold-volts>
|
|
def run(seconds, options):
|
|
options = [i for p in options.split(',') for i in p.split('=')]
|
|
options = dict(zip(options[::2], options[1::2]))
|
|
|
|
device_id = options.get('device-id')
|
|
address = str(options.get('address'))
|
|
port = int(options.get('port'))
|
|
channel = int(options.get('channel'))
|
|
sample_rate = int(options.get('sample-rate'))
|
|
threshold_volts = float(options.get('threshold-volts'))
|
|
|
|
with tempfile.TemporaryDirectory() as output_dir:
|
|
output_dir = tempfile.mkdtemp()
|
|
# Add one second to ensure all data is captured
|
|
do_collection(device_id, address, port, channel, sample_rate, threshold_volts,
|
|
seconds + 1, output_dir)
|
|
|
|
return do_analysis(output_dir)
|