zephyr/tests/kernel/timer/timer_behavior/pytest/saleae_logic2.py
Dmitrii Golovanov 014a0983fb tests: kernel: timer_behavior_external: Additional stats recording
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>
2024-06-14 09:41:52 -04:00

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)