mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
hw cortex-a9 timer: raise translation precision
If we do the tics-to-us translation with one division and multiplication over the whole argument, like before, we loose microseconds granularity although the timer frequency allows for such granularity. Thus, we treat the most significant half and the least significant half of the tics value separate. Each half is shifted to the best bit position for the translation, then translated, and then shifted back. Ref #2347
This commit is contained in:
parent
0b30cf0ab6
commit
05655a9d88
@ -85,8 +85,36 @@ class Genode::Timer : public Mmio
|
||||
*/
|
||||
void start_one_shot(time_t const tics, unsigned const);
|
||||
|
||||
time_t tics_to_us(time_t const tics) const {
|
||||
return (tics / TICS_PER_MS) * 1000; }
|
||||
time_t tics_to_us(time_t const tics) const
|
||||
{
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static_assert(TICS_PER_MS >= 1000, "Bad TICS_PER_MS value");
|
||||
enum {
|
||||
TICS_WIDTH = sizeof(time_t) * 8,
|
||||
TICS_HALF_WIDTH = TICS_WIDTH / 2,
|
||||
|
||||
TICS_MSB_MASK = ~0UL << TICS_HALF_WIDTH,
|
||||
TICS_LSB_MASK = ~0UL >> TICS_HALF_WIDTH,
|
||||
|
||||
TICS_MSB_RSHIFT = 10,
|
||||
TICS_LSB_LSHIFT = TICS_HALF_WIDTH - TICS_MSB_RSHIFT,
|
||||
};
|
||||
time_t const tics_msb = (tics & TICS_MSB_MASK) >> TICS_MSB_RSHIFT;
|
||||
time_t const tics_lsb = (tics & TICS_LSB_MASK) << TICS_LSB_LSHIFT;
|
||||
|
||||
time_t const us_msb = ((tics_msb * 1000) / TICS_PER_MS) << TICS_MSB_RSHIFT;
|
||||
time_t const us_lsb = ((tics_lsb * 1000) / TICS_PER_MS) >> TICS_LSB_LSHIFT;
|
||||
|
||||
return us_msb | us_lsb;
|
||||
}
|
||||
|
||||
time_t us_to_tics(time_t const us) const {
|
||||
return (us / 1000) * TICS_PER_MS; }
|
||||
|
Loading…
Reference in New Issue
Block a user