tests: add timer monotonic test

k_cycle_get_32() needs to return a monotonically increasing value,
except in cases of 32-bit integer overflow. Enforce this with a
test case.

We also check that the number of cycles elapsed after sleeping for 1
second is at the expected value. This can help catch errors on platforms
that use different timer sources for the system clock and timestamps.

This test case adapted from some code provided by Sergey Arkhipov
when troubleshooting ZEP-1546.

Issue: ZEP-1546
Change-Id: If27fff026ea6de659f7b41b60ff26f4962b734d4
Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2017-02-15 14:19:52 -08:00
commit 9c48b54d65
5 changed files with 92 additions and 0 deletions

View file

@ -0,0 +1,4 @@
CONF_FILE = prj.conf
BOARD ?= qemu_x86
include $(ZEPHYR_BASE)/Makefile.test

View file

@ -0,0 +1,4 @@
ccflags-y += -I${ZEPHYR_BASE}/tests/include
obj-y = main.o

View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <inttypes.h>
#include <tc_util.h>
int test_frequency(void)
{
uint32_t start, end, delta, pct;
TC_PRINT("Testing system tick frequency\n");
start = k_cycle_get_32();
k_sleep(1000);
end = k_cycle_get_32();
delta = end - start;
pct = (uint64_t)delta * 100 / sys_clock_hw_cycles_per_sec;
printk("delta: %u expected: %u %u%%\n", delta,
sys_clock_hw_cycles_per_sec, pct);
/* Heuristic: if we're more than 10% off, throw an error */
if (pct < 90 || pct > 110) {
TC_PRINT("Clock calibration is way off!\n");
return -1;
}
return 0;
}
void main(void)
{
uint32_t t_last, t_now, i, errors;
int32_t diff;
int rv = TC_PASS;
errors = 0;
TC_PRINT("sys_clock_us_per_tick = %d\n", sys_clock_us_per_tick);
TC_PRINT("sys_clock_hw_cycles_per_tick = %d\n",
sys_clock_hw_cycles_per_tick);
TC_PRINT("sys_clock_hw_cycles_per_sec = %d\n",
sys_clock_hw_cycles_per_sec);
TC_START("test monotonic timer");
t_last = k_cycle_get_32();
for (i = 0; i < 1000000; i++) {
t_now = k_cycle_get_32();
if (t_now < t_last) {
diff = t_now - t_last;
TC_PRINT("diff = %" PRId32 " (t_last = %" PRIu32
" : t_now = %" PRIu32 "); i = %u\n",
diff, t_last, t_now, i);
errors++;
}
t_last = t_now;
}
if (errors) {
TC_PRINT("errors = %d\n", errors);
rv = TC_FAIL;
} else {
TC_PRINT("Cycle results appear to be monotonic\n");
}
if (test_frequency()) {
rv = TC_FAIL;
}
TC_END_REPORT(rv);
}

View file

@ -0,0 +1,3 @@
[test]
tags = timer