Используйте таймер HPET с платформой EDK2.

В настоящее время я разрабатываю программу UEFI с использованием платформы EDK2 и хотел бы получить время HPET или использовать прерывание HPET в качестве таймера обратного отсчета. Я попытался использовать HpetTimerDxe из PcAtChipsetPkg, но понятия не имею, как это реализовать.

В Интернете имеется ограниченное количество информации и статей по этой теме, но я все же надеюсь использовать ее для решения проблем, связанных со временем.

  • Целевая архитектура: x86_64.
  • Версия edk2: edk2-stable202105
      EFI_STATUS
FindHpetTable(
    EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER **HpetTable)
{
   EFI_STATUS Status;
   EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
   EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
   UINTN EntryCount;
   UINTN Index;

   Status = EfiGetSystemConfigurationTable(
       &gEfiAcpi20TableGuid,
       (VOID **)&Rsdp);
   if (EFI_ERROR(Status))
   {
      return Status;
   }

   Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->XsdtAddress;
   EntryCount = (Xsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64);

   for (Index = 0; Index < EntryCount; Index++)
   {
      EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
      CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(((UINT64 *)(Xsdt + 1))[Index]);

      if (CurrentTable->Signature == EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE)
      {
         *HpetTable = (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *)CurrentTable;
         return EFI_SUCCESS;
      }
   }

   return EFI_NOT_FOUND;
}
      VOID AccessHpetRegisters(
    EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *HpetTable)
{
   if (HpetTable == NULL)
   {
      return;
   }

   UINT64 HpetBaseAddress = HpetTable->BaseAddressLower32Bit.Address;

   // Access HPET registers using HpetBaseAddress
   // Read the General Capabilities and ID Register
   UINT64 CapabilitiesAndId = *(volatile UINT64 *)HpetBaseAddress;
   Print(L"HPET General Capabilities and ID Register: 0x%lX\n", CapabilitiesAndId);

   // Read the Main Counter Value register
   UINT64 MainCounterValue = *(volatile UINT64 *)(HpetBaseAddress + HPET_MAIN_COUNTER_OFFSET);
   Print(L"HPET Main Counter Value: 0x%lX\n", MainCounterValue);

   UINT64 HpetPeriod = MmioRead32(HpetBaseAddress + 0x4);

   // 1 femtosecond = 1e-15 seconds
   UINT64 timeValue = DivU64x64Remainder(MultU64x64(MainCounterValue, HpetPeriod), 1000000000000ULL, NULL);
   Print(L"time in microsecond: %llu\n", timeValue);
}
      // in UefiMain
EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *HpetTable;

Status = FindHpetTable(&HpetTable);
if (EFI_ERROR(Status))
{
  Print(L"HPET table not found.\n");
  return Status;
}

AccessHpetRegisters(HpetTable);

0 ответов

Другие вопросы по тегам