5.1.7 Stall()
The Stall()
service waits for a specified number of microseconds. In 32-bit
environments, the range of supported delays is from 1 μs to a little over an
hour. In 64-bit execution environments, the range of supported delays is from 1uS to
about 500,000 years. However, the delays passed into this service should be
short and are typically in the range of a few microseconds to a few
milliseconds.
Caution: Implementations of the Stall()
service may disable interrupts
and may block execution of other UEFI drivers. If long delays are required, use
a Timer Event instead. See CreateEvent()
, CreateEventEx()
, and SetTimer()
for details._
The Stall()
service is very accurate and typically uses a high frequency
hardware timer or a calibrated software delay loop to implement the stall
functionality.
Caution: Stall()
may use a different timing source than the event
timer, and may have a higher or lower frequency and, hence, different accuracy.
For hardware devices requiring delays between register accesses, use the
Stall()
service. with a fixed stall value based in a hardware specification
for the device being accessed. The following example shows a use-case to
perform a fixed delay of 10 us between two PCI MMIO register writes.
Example 56-Fixed delay stall
#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/PciIo.h>
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT8 Value;
//
// Do a single 8-bit MMIO write to BAR #1, Offset 0x10 of 0xAA
//
Value = 0xAA;
Status = PciIo->Mem.Write (
PciIo, // This
EfiPciIoWidthUint8, // Width
1, // BarIndex
0x10, // Offset
1, // Count
&Value // Buffer
);
//
// Wait 10 uS
//
gBS->Stall (10);
//
// Do a single 8-bit MMIO write to BAR #1, Offset 0x10 of 0x55
//
Value = 0x55;
Status = PciIo->Mem.Write (
PciIo, // This
EfiPciIoWidthUint8, // Width
1, // BarIndex
0x10, // Offset
1, // Count
&Value // Buffer
);
In this example, a UEFI drivers sends a command to a controller and then waits
for the command to complete. Use the Stall()
service inside a loop to
periodically check for the completion status. The example below shows how to
poll for a completion status every millisecond and timeout after 100 ms.
Example 57-Poll for completion status using stalls
#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/PciIo.h>
EFI_STATUS Status;
UINTN TimeOut;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT8 Value;
//
// Loop waiting for the register at Offset 0 of Bar #0 of PciIo to
// become 0xE0 Wait 1 ms between each check of this register, and
// time out if it does not become 0xE0 after 100 mS.
//
for (TimeOut = 0; TimeOut <= 100000; TimeOut += 1000) {
//
// Do a single 8-bit MMIO read from BAR #0, Offset 0 into Value
//
Status = PciIo->Mem.Read (
PciIo, // This
EfiPciIoWidthUint8, // Width
0, // BarIndex
0, // Offset
1, // Count
&Value // Buffer
);
if (!EFI_ERROR (Status) && Value == 0xE0) {
return EFI_SUCCESS;
}
//
// Wait 1 ms
//
gBS->Stall (1000);
}
return EFI_TIMEOUT;