Skip to content

Commit ac94ffe

Browse files
pabigotcarlescufi
authored andcommitted
tests: kernel: timer_api: use slew for remaining timer threshold
This test sets a timer using one clock, waits using a second clock, then sees whether the remaining time is the expected value. When the two clocks are skewed the comparison requires a threshold. Provide a means to estimate the maximum expected error. Signed-off-by: Peter Bigot <[email protected]>
1 parent cab4ffc commit ac94ffe

File tree

1 file changed

+30
-9
lines changed
  • tests/kernel/timer/timer_api/src

1 file changed

+30
-9
lines changed

tests/kernel/timer/timer_api/src/main.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,27 @@ struct timer_data {
2828
*/
2929
#define INEXACT_MS_CONVERT ((CONFIG_SYS_CLOCK_TICKS_PER_SEC % MSEC_PER_SEC) != 0)
3030

31+
#if CONFIG_NRF_RTC_TIMER
32+
/* On Nordic SOCs one or both of the tick and busy-wait clocks may
33+
* derive from sources that have slews that sum to +/- 13%.
34+
*/
35+
#define BUSY_TICK_SLEW_PPM 130000U
36+
#else
37+
/* On other platforms assume the clocks are perfectly aligned. */
38+
#define BUSY_TICK_SLEW_PPM 0U
39+
#endif
40+
#define PPM_DIVISOR 1000000U
41+
42+
/* If the tick clock is faster or slower than the busywait clock the
43+
* remaining time for a partially elapsed timer in ticks will be
44+
* larger or smaller than expected by a value that depends on the slew
45+
* between the two clocks. Produce a maximum error for a given
46+
* duration in microseconds.
47+
*/
48+
#define BUSY_SLEW_THRESHOLD_TICKS(_us) \
49+
k_us_to_ticks_ceil32((_us) * BUSY_TICK_SLEW_PPM \
50+
/ PPM_DIVISOR)
51+
3152
static void duration_expire(struct k_timer *timer);
3253
static void duration_stop(struct k_timer *timer);
3354

@@ -541,6 +562,8 @@ void test_timer_remaining(void)
541562
u32_t dur_ticks = k_ms_to_ticks_ceil32(DURATION);
542563
u32_t target_rem_ticks = k_ms_to_ticks_ceil32(DURATION / 2) + 1;
543564
u32_t rem_ms, rem_ticks, exp_ticks;
565+
s32_t delta_ticks;
566+
u32_t slew_ticks;
544567
u64_t now;
545568

546569
k_usleep(1); /* align to tick */
@@ -566,16 +589,14 @@ void test_timer_remaining(void)
566589
/* Half the value of DURATION in ticks may not be the value of
567590
* half DURATION in ticks, when DURATION/2 is not an integer
568591
* multiple of ticks, so target_rem_ticks is used rather than
569-
* dur_ticks/2.
570-
*
571-
* Also if the tick clock is faster or slower than the
572-
* busywait clock the remaining time in ticks will be larger
573-
* or smaller than expected, so relax the tolerance. 3 ticks
574-
* variance has been observed on hardware where the busywait
575-
* clock is 0.7% slow and the 32 KiHz tick clock is 60 ppm
576-
* fast relative to a stable external clock.
592+
* dur_ticks/2. Also set a threshold based on expected clock
593+
* skew.
577594
*/
578-
zassert_true(abs((s32_t)(rem_ticks - target_rem_ticks)) <= 3, NULL);
595+
delta_ticks = (s32_t)(rem_ticks - target_rem_ticks);
596+
slew_ticks = BUSY_SLEW_THRESHOLD_TICKS(DURATION * USEC_PER_MSEC / 2U);
597+
zassert_true(abs(delta_ticks) <= MAX(slew_ticks, 1U),
598+
"tick/busy slew %d larger than test threshold %u",
599+
delta_ticks, slew_ticks);
579600

580601
/* Note +1 tick precision: even though we're calcluating in
581602
* ticks, we're waiting in k_busy_wait(), not for a timer

0 commit comments

Comments
 (0)