From dc6338c866a8fbbb6634f534e509966ef0a6de96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20N=C3=A9ri?= <158544+dne@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:39:22 +0200 Subject: [PATCH] Fix off-by-one-tick in timer period calculation --- src/timer.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/timer.rs b/src/timer.rs index 06d881d0..5ff96973 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -424,7 +424,7 @@ macro_rules! hal { } /// Sets the timer's prescaler and auto reload register so that the timer will reach - /// the ARR after `ticks` amount of timer clock ticks. + /// the ARR after `ticks - 1` amount of timer clock ticks. /// /// ``` /// // Set auto reload register to 50000 and prescaler to divide by 2. @@ -567,7 +567,8 @@ fn calculate_timeout_ticks_register_values(ticks: u32) -> (u16, u16) { // resulting in a value that always fits in 16 bits. let psc = u16(ticks / (1 << 16)).unwrap(); // Note (unwrap): Never panics because the divisor is always such that the result fits in 16 bits. - let arr = u16(ticks / (u32(psc) + 1)).unwrap(); + // Also note that the timer counts `0..=arr`, so subtract 1 to get the correct period. + let arr = u16(ticks / (u32(psc) + 1)).unwrap().saturating_sub(1); (psc, arr) } @@ -929,17 +930,17 @@ mod tests { #[test] fn timeout_ticks_register_values() { assert_eq!(calculate_timeout_ticks_register_values(0), (0, 0)); - assert_eq!(calculate_timeout_ticks_register_values(50000), (0, 50000)); - assert_eq!(calculate_timeout_ticks_register_values(100000), (1, 50000)); - assert_eq!(calculate_timeout_ticks_register_values(65535), (0, 65535)); - assert_eq!(calculate_timeout_ticks_register_values(65536), (1, 32768)); + assert_eq!(calculate_timeout_ticks_register_values(50000), (0, 49999)); + assert_eq!(calculate_timeout_ticks_register_values(100000), (1, 49999)); + assert_eq!(calculate_timeout_ticks_register_values(65535), (0, 65534)); + assert_eq!(calculate_timeout_ticks_register_values(65536), (1, 32767)); assert_eq!( calculate_timeout_ticks_register_values(1000000), - (15, 62500) + (15, 62499) ); assert_eq!( calculate_timeout_ticks_register_values(u32::MAX), - (u16::MAX, u16::MAX) + (u16::MAX, u16::MAX - 1) ); } }