You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Timer::start()implementation breaks if the ticks value calculated inside the start function is an exact multiple of (1 << 16).
Numerical example
If ticks is 1 << 16 == 65536 then psc, which is (ticks - 1) / (1 << 16) becomes 0 because the division result is ever so slightly less than one and thus trucated.
Now we calculate u16(ticks / u32(psc + 1)). But since psc is 0,psc + 1 is 1, so ticks / u32(psc + 1) is still 65536, which is then cast to a u16.
But since 65536 is 1 << 16, it doesn't fit in the u16 range from 0 to 1 << 16 - 1 and we unwrapp an Err(Overflow) value.
Clock configuration example
Pretty simple actually, the MSI clock source outputs frequencies that (except for MSI range 0) are all multiple of 1 << 16.
For example, MSI clock source of range 1 produces a 65536 Hz clock.
When attempting to start a timer with frequency 1 with this clock, the error occurs.
Code example
use cast::{u16, u32,Error};// simplified version of calculations inside Timer::start()fntimer_settings(sysclk:u32,frequency:u32) -> Result<(u16,u16),Error>{let ticks = sysclk / frequency;println!("{}", ticks % (1 << 16));let psc = u16((ticks - 1) / (1 << 16))?;let arr = u16(ticks / u32(psc + 1))?;Ok((psc, arr))}fnmain(){// all of these return Err()for n in1..100{println!("{n} {:?}", timer_settings((2 << 16)* n, n).unwrap_err());}// all of these return Ok()for n in1..100{println!("{n} {:?}", timer_settings((2 << 16)* n - 1, n).unwrap());}}
Possible solution
I'm not 100% sure on this, but I think u16(ticks / u32(psc + 1)) can be changed to u16((ticks - 1) / u32(psc + 1)), such that both divisions have the same numerator.
The text was updated successfully, but these errors were encountered:
The
Timer::start()
implementation breaks if theticks
value calculated inside the start function is an exact multiple of(1 << 16)
.Numerical example
If
ticks
is1 << 16 == 65536
thenpsc
, which is(ticks - 1) / (1 << 16)
becomes0
because the division result is ever so slightly less than one and thus trucated.Now we calculate
u16(ticks / u32(psc + 1))
. But sincepsc
is0
,psc + 1
is1
, soticks / u32(psc + 1)
is still65536
, which is then cast to au16
.But since
65536
is1 << 16
, it doesn't fit in theu16
range from0
to1 << 16 - 1
and we unwrapp anErr(Overflow)
value.Clock configuration example
Pretty simple actually, the
MSI
clock source outputs frequencies that (except for MSI range 0) are all multiple of1 << 16
.For example, MSI clock source of range 1 produces a 65536 Hz clock.
When attempting to start a timer with frequency 1 with this clock, the error occurs.
Code example
Possible solution
I'm not 100% sure on this, but I think
u16(ticks / u32(psc + 1))
can be changed tou16((ticks - 1) / u32(psc + 1))
, such that both divisions have the same numerator.The text was updated successfully, but these errors were encountered: