Fix RTC synchronization after sleep, add many more tests

There were two issues with the tests

1. Incorrect print formats causing incorrect output.

2. The RTC driver was not waiting for the shadow registers to be
updated after sleeping, their reset values to be read.
This commit is contained in:
2020-04-22 09:09:31 -07:00
parent 2fa4a5e658
commit f455ce9113
20 changed files with 700 additions and 94 deletions

View File

@@ -20,7 +20,6 @@
# THE SOFTWARE.
import pytest
import subprocess
import serial
import serial.tools.list_ports
import logging
@@ -29,6 +28,7 @@ import time
import os
import sys
import re
import subprocess
PYTEST_DIR = os.path.dirname(os.path.abspath(__file__))
DEFAULT_FW_DIR = os.path.abspath(PYTEST_DIR + "../../../../firmware/")
@@ -49,19 +49,18 @@ def logger():
@pytest.fixture
def context_factory():
def create_context(
fw_rel_path: str,
mcu: str = "STM32L412RB",
addr: int = 0x8000000,
leave_halted: bool = False,
):
ports = [
p
for p in serial.tools.list_ports.comports()
if p.product == "FT232R USB UART"
]
def create_context(fw_rel_path: str,
mcu: str = "STM32L412RB",
addr: int = 0x8000000,
leave_halted: bool = False):
proc = subprocess.run(["make", "BOARD=devboard", fw_rel_path],
cwd=DEFAULT_FW_DIR,
capture_output=True,
check=True)
logging.info("Make process stdout: {}".format(proc.stdout))
ports = serial.tools.list_ports.comports()
if len(ports) == 0:
raise RuntimeError("No serial devices found")
if len(ports) > 1:
@@ -82,9 +81,7 @@ def context_factory():
assert jlink.halted()
jlink.reset(halt=True)
serial_dev = serial.Serial(port=ports[0].device,
baudrate=115200,
timeout=1)
serial_dev = serial.Serial(port=ports[0].device, baudrate=115200, timeout=2)
if leave_halted:
return serial_dev, jlink
@@ -93,15 +90,15 @@ def context_factory():
while True:
try:
logging.info("Waiting for firmware to start...")
assert serial_dev \
.read_until(TEST_START_TEXT) \
.endswith(TEST_START_TEXT), \
"Timed out starting test firmware application"
assert serial_dev.read_until(TEST_START_TEXT).endswith(
TEST_START_TEXT
), "Timed out starting test firmware application"
logging.debug("Test execution started")
except serial.serialutil.SerialException:
continue
break
return serial_dev, jlink
return create_context
@@ -131,15 +128,28 @@ def test_meta_nostart(context_factory, logger):
def test_watch(context_factory, logger):
serial_dev, jlink = context_factory("Application/main.bin",
leave_halted=True)
serial_dev, jlink = context_factory("Application/main.bin", leave_halted=True)
jlink.reset(halt=False)
def test_set_time(context_factory, logger):
serial_dev, jlink = context_factory("Test/set_time.bin")
text = serial_dev.read_until(TEST_PASS_TEXT)
print("Text:", text.decode())
assert text.endswith(TEST_PASS_TEXT)
def test_periodic_alarms(context_factory, logger):
serial_dev, jlink = context_factory("Test/periodic_alarms.bin")
serial_dev.timeout = 6
text = serial_dev.read_until(TEST_PASS_TEXT)
print("Text:", text.decode())
assert text.endswith(TEST_PASS_TEXT)
def test_clock(context_factory, logger):
serial_dev, jlink = context_factory("Test/clock.bin")
EXPECTED_RUNTIME = 10
TOLERANCE = .1
TOLERANCE = 0.1
serial_dev.timeout = EXPECTED_RUNTIME * 1.2
@@ -148,23 +158,53 @@ def test_clock(context_factory, logger):
start_text = serial_dev.read_until(START_MARKER)
start = time.monotonic()
print("Start text:", start_text)
assert start_text.endswith(START_MARKER)
end_text = serial_dev.read_until(END_MARKER)
end = time.monotonic()
print("Time:", end - start)
assert end_text.endswith(END_MARKER)
delta = end - start
logger.debug("Serial text: {}".format(start_text))
logger.debug("Serial text: {}".format(end_text))
logger.info("Serial text: {}".format(start_text))
logger.info("Serial text: {}".format(end_text))
logger.info("Start time: {}".format(start))
logger.info("End time: {}".format(end))
logger.info("Delta time: {}".format(delta))
# TODO: Using a single pin, instead of UART, would make this more
# accurate. Add support via sigrok.
assert start_text.endswith(START_MARKER)
assert end_text.endswith(END_MARKER)
assert (delta - EXPECTED_RUNTIME) < TOLERANCE
def test_wakeup_irq(context_factory, logger):
serial_dev, jlink = context_factory("Test/wakeup_irq.bin")
serial_dev.timeout = 65
pattern = re.compile("Requested=(\\d*) Actual=(\\d*) Wakeups=(\\d*)")
while True:
line = serial_dev.readline()
if line == TEST_PASS_TEXT:
break
line = line.decode("ascii", errors="ignore")
print(line.strip())
match = pattern.match(line)
assert match
req = int(match.group(1))
actual = int(match.group(2))
wakeups = int(match.group(3))
delta = req - actual
assert wakeups == 1, "Expected one wakeup per line of test output"
if req < 32000:
assert abs(delta < req * (2.0 / 100.0)) or (delta <= 1)
else:
# Delays > 32sec have reduced resolution (1 sec)
assert abs(delta) < 1000
def test_stop(context_factory, logger):
serial_dev, jlink = context_factory("Test/stop.bin")
serial_dev.timeout = 65
@@ -189,6 +229,70 @@ def test_stop(context_factory, logger):
# Delays > 32sec have reduced resolution (1 sec)
assert abs(delta) < 1000
"sigrok-cli -C D3 -d fx2lafw -c samplerate=1M --time 1s -P timing:data=D3"
def measure_frequency(
period: float,
pin_name: str,
executable: str = "sigrok-cli",
driver_name: str = "fx2lafw",
):
cmd = [
executable,
"-C",
pin_name,
"-d",
driver_name,
"-c",
"samplerate=1M",
"--time",
"{}ms".format(int(period * 1000)),
"-P",
"timing:data={}".format(pin_name),
"-A",
"timing=time",
]
print("sigrok-cli cmd {}".format(cmd))
proc = subprocess.run(cmd, capture_output=True, check=True)
lines = proc.stdout.decode("utf-8").split("\n")
reg = re.compile(".*:\\W(\\d+.\\d+)\\W(\\w+)")
periods = []
for line in lines:
m = reg.match(line)
if not m:
break
num = float(m.groups(1)[0])
units = m.groups(1)[1]
if units == "ms":
periods.append(num / 1000)
elif units == "μs":
periods.append(num / 1000000)
else:
assert False
return periods[::2], periods[1:][::2]
def test_lptim(context_factory, logger):
serial_dev, jlink = context_factory("Test/lptim.bin")
state0_periods, state1_periods = measure_frequency(1, "D1")
num_periods = min(len(state0_periods), len(state1_periods))
periods = [state0_periods[i] + state1_periods[i] for i in range(num_periods)]
freqs = list(map(lambda x: 1 / x, periods))
assert (
periods
), "No LPTIM changes detected, is the right analyzer being used? Is the device connected?"
min_f = min(freqs)
max_f = max(freqs)
avg_f = sum(freqs) / len(freqs)
print("min:{}, max:{}, avg:{}".format(min_f, max_f, avg_f))
assert abs(avg_f - 50) < 0.25
assert min_f > 49
assert max_f < 51
def main():
pytest.main(sys.argv)