YDeeps1 wrote:
And I don't want to make a new thread for this but just to confirm, if I would like to go slower than ~54ms per interrupt, would I have to use one shots to set my desired count downs?
Exactly.
My timer is two layered. I have a platform specific timer, which has a one shot API, and specifies how long in microseconds the next call back needs to be. The platform specific layer then programs the timing source to call the callback using whatever mechanism the platform provides.
I only have a PIT provider at the moment, and as you've noticed, the longest timer that can provide is ~54ms (65535 cycles of the PIT 1193182Hz clock, but it can be 65536 cycles) So every PIT interrupt, I just subtract 65535 from however many cycles I have left. When that remaining time is less than 65535 cycles, reprogram the PIT timer to that number of cycles, then next interrupt, I fire the callback.
So, for example, to wait 1 second, I use the following sequence of PIT 1 shot timeouts:
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 65535
- 13552
After this last interrupt, the callback is called, having waited 1193182 cycles (= 1 second). This layer can be easily replaced with some other one shot timer, such as the APIC timer.
The higher layer is just an ordered list of pending timers, sorted by interval to next time out. The upper layer timer just programs the lower layer to the interval at the head of the list, and waits for the callback.
It gets a little complicated, if halfway through waiting for this 1 second callback, another timer is started that would expire before the 1 second timer. Then, the lower level one shot is cancelled (we get back how long is left), and the new timer is scheduled instead. Then we can restart the 1 second timer, based on how long the intermediate timer was and how long we had left.