@@ -28,6 +28,27 @@ struct timer_data {
28
28
*/
29
29
#define INEXACT_MS_CONVERT ((CONFIG_SYS_CLOCK_TICKS_PER_SEC % MSEC_PER_SEC) != 0)
30
30
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
+
31
52
static void duration_expire (struct k_timer * timer );
32
53
static void duration_stop (struct k_timer * timer );
33
54
@@ -541,6 +562,8 @@ void test_timer_remaining(void)
541
562
u32_t dur_ticks = k_ms_to_ticks_ceil32 (DURATION );
542
563
u32_t target_rem_ticks = k_ms_to_ticks_ceil32 (DURATION / 2 ) + 1 ;
543
564
u32_t rem_ms , rem_ticks , exp_ticks ;
565
+ s32_t delta_ticks ;
566
+ u32_t slew_ticks ;
544
567
u64_t now ;
545
568
546
569
k_usleep (1 ); /* align to tick */
@@ -566,16 +589,14 @@ void test_timer_remaining(void)
566
589
/* Half the value of DURATION in ticks may not be the value of
567
590
* half DURATION in ticks, when DURATION/2 is not an integer
568
591
* 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.
577
594
*/
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 );
579
600
580
601
/* Note +1 tick precision: even though we're calcluating in
581
602
* ticks, we're waiting in k_busy_wait(), not for a timer
0 commit comments