mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-23 04:25:21 +00:00
hw pit: fix precision reduction to milliseconds
Due to the simplicity of the algorithm that translated from timer ticks to time, we lost microseconds precision although the timer allows for it. Ref #2400
This commit is contained in:
parent
02bbb2efaf
commit
16745946e0
@ -64,6 +64,7 @@ Timer_driver::Timer_driver(unsigned)
|
||||
|
||||
/* Calculate timer frequency */
|
||||
ticks_per_ms = pit_calc_timer_freq();
|
||||
assert(ticks_per_ms >= 1000);
|
||||
}
|
||||
|
||||
|
||||
@ -84,7 +85,29 @@ void Timer::_start_one_shot(time_t const ticks) {
|
||||
|
||||
|
||||
time_t Timer::_ticks_to_us(time_t const ticks) const {
|
||||
return (ticks / _driver.ticks_per_ms) * 1000; }
|
||||
|
||||
/*
|
||||
* If we would do the translation with one division and
|
||||
* multiplication over the whole argument, we would loose
|
||||
* microseconds granularity although the timer frequency would
|
||||
* allow for such granularity. Thus, we treat the most significant
|
||||
* half and the least significant half of the argument separate.
|
||||
* Each half is shifted to the best bit position for the
|
||||
* translation, then translated, and then shifted back.
|
||||
*/
|
||||
enum {
|
||||
HALF_WIDTH = (sizeof(time_t) << 2),
|
||||
MSB_MASK = ~0UL << HALF_WIDTH,
|
||||
LSB_MASK = ~0UL >> HALF_WIDTH,
|
||||
MSB_RSHIFT = 10,
|
||||
LSB_LSHIFT = HALF_WIDTH - MSB_RSHIFT,
|
||||
};
|
||||
time_t const msb = ((((ticks & MSB_MASK) >> MSB_RSHIFT)
|
||||
* 1000) / _driver.ticks_per_ms) << MSB_RSHIFT;
|
||||
time_t const lsb = ((((ticks & LSB_MASK) << LSB_LSHIFT)
|
||||
* 1000) / _driver.ticks_per_ms) >> LSB_LSHIFT;
|
||||
return msb + lsb;
|
||||
}
|
||||
|
||||
|
||||
time_t Timer::us_to_ticks(time_t const us) const {
|
||||
|
Loading…
x
Reference in New Issue
Block a user