ArmPkg: Fix timer wrap-around
The timer counter register can wrap around and when this happens, we'll get misbehavior for any MicroSecondDelay() calls. This adds handling for that. Signed-off-by: Carsten Haitzler <carsten.haitzler@foss.arm.com>
This commit is contained in:
parent
4ef87f455b
commit
af15e4535d
|
@ -62,6 +62,8 @@ MicroSecondDelay (
|
|||
{
|
||||
UINT64 TimerTicks64;
|
||||
UINT64 SystemCounterVal;
|
||||
UINT64 PreviousSystemCounterVal;
|
||||
UINT64 DeltaCounterVal;
|
||||
|
||||
// Calculate counter ticks that represent requested delay:
|
||||
// = MicroSeconds x TICKS_PER_MICRO_SEC
|
||||
|
@ -75,13 +77,17 @@ MicroSecondDelay (
|
|||
);
|
||||
|
||||
// Read System Counter value
|
||||
SystemCounterVal = ArmGenericTimerGetSystemCount ();
|
||||
|
||||
TimerTicks64 += SystemCounterVal;
|
||||
PreviousSystemCounterVal = ArmGenericTimerGetSystemCount ();
|
||||
|
||||
// Wait until delay count expires.
|
||||
while (SystemCounterVal < TimerTicks64) {
|
||||
while (TimerTicks64 > 0) {
|
||||
SystemCounterVal = ArmGenericTimerGetSystemCount ();
|
||||
// Get how much we advanced this tick. Wrap around still has delta correct
|
||||
DeltaCounterVal = (SystemCounterVal - PreviousSystemCounterVal)
|
||||
& (MAX_UINT64 >> 8); // Account for a lesser (minimum) size
|
||||
// Never wrap back around below zero by choosing the min and thus stop at 0
|
||||
TimerTicks64 -= MIN (TimerTicks64, DeltaCounterVal);
|
||||
PreviousSystemCounterVal = SystemCounterVal;
|
||||
}
|
||||
|
||||
return MicroSeconds;
|
||||
|
|
Loading…
Reference in New Issue