diff --git a/include/nuttx/timers/clkcnt.h b/include/nuttx/timers/clkcnt.h index 98cc91575e0..31310b5ecba 100644 --- a/include/nuttx/timers/clkcnt.h +++ b/include/nuttx/timers/clkcnt.h @@ -84,7 +84,7 @@ void clkcnt_best_multshift(uint32_t freq, uint32_t scale, { uint32_t logfreq = log2floor(freq); - /* Be careful of the round-nearest behavior here. + /* Do not use the round-nearest behavior here. * It may lead to the converted result is larger than the * integer division. * In rare cases, this can cause the converted tick to be greater @@ -103,7 +103,7 @@ void clkcnt_best_multshift(uint32_t freq, uint32_t scale, * affecting the accuracy of time compensation. */ - *mult = (((uint64_t)scale << logfreq) + (freq >> 1)) / freq; + *mult = ((uint64_t)scale << logfreq) / freq; *shift = logfreq; } diff --git a/include/nuttx/timers/oneshot.h b/include/nuttx/timers/oneshot.h index f72ca4372f3..74ed607c96f 100644 --- a/include/nuttx/timers/oneshot.h +++ b/include/nuttx/timers/oneshot.h @@ -44,6 +44,8 @@ * Pre-processor Definitions ****************************************************************************/ +#define ONESHOT_NSEC_TOLERANT 5 + /* IOCTL commands ***********************************************************/ /* These commands are used by applications to access the oneshot lower-half @@ -293,12 +295,15 @@ void oneshot_count_init(FAR struct oneshot_lowerhalf_s *lower, &lower->cnt2nsec_mult, &lower->cnt2nsec_shift); - /* Ensure the maximum error of the mult-shift is less than 5ns. */ + /* Ensure the maximum error of the mult-shift is less than + * ONESHOT_NSEC_TOLERANT. + */ result = clkcnt_delta_cnt2nsec_fast(frequency, lower->cnt2nsec_mult, lower->cnt2nsec_shift); - ASSERT(NSEC_PER_SEC - 5 <= result && NSEC_PER_SEC + 5 >= result); + ASSERT(NSEC_PER_SEC - ONESHOT_NSEC_TOLERANT <= result && + NSEC_PER_SEC >= result); # ifdef CONFIG_ONESHOT_FAST_DIVISION /* invdiv requires the invariant-divsor > 1. */ @@ -402,6 +407,8 @@ int oneshot_current(FAR struct oneshot_lowerhalf_s *lower, cnt -= sec * freq; ts->tv_nsec = oneshot_delta_cnt2nsec(lower, cnt); ts->tv_sec = sec; + + DEBUGASSERT(cnt < freq && ts->tv_nsec < NSEC_PER_SEC); #else ret = lower->ops->current(lower, ts); #endif