Step to UEFI (280)计算精确时间

一些情况下,我们需要得知操作消耗的时间,比如:通过硬盘读写操作耗费的时间能够计算出硬盘的速度。针对这个问题,之前有过研究,例如:GetTime 研究【参考1】、EADK clock()【参考2】。这里再次进行研究。

首先,在MdePkg\Include\Library\TimerLib.h给出了下面两个函数:

/**
  Retrieves the current value of a 64-bit free running performance counter.
  The counter can either count up by 1 or count down by 1. If the physical
  performance counter counts by a larger increment, then the counter values
  must be translated. The properties of the counter can be retrieved from
  GetPerformanceCounterProperties().
  @return The current value of the free running performance counter.
**/
UINT64
EFIAPI
GetPerformanceCounter (
  VOID
  );
/**
  Converts elapsed ticks of performance counter to time in nanoseconds.
  This function converts the elapsed ticks of running performance counter to
  time value in unit of nanoseconds.
  @param  Ticks     The number of elapsed ticks of running performance counter.
  @return The elapsed time in nanoseconds.
**/
UINT64
EFIAPI
GetTimeInNanoSecond (
  IN      UINT64  Ticks
  );
/**
  Retrieves the current value of a 64-bit free running performance counter.
  The counter can either count up by 1 or count down by 1. If the physical
  performance counter counts by a larger increment, then the counter values
  must be translated. The properties of the counter can be retrieved from
  GetPerformanceCounterProperties().
  @return The current value of the free running performance counter.
**/
UINT64
EFIAPI
GetPerformanceCounter (
  VOID
  );
/**
  Converts elapsed ticks of performance counter to time in nanoseconds.
  This function converts the elapsed ticks of running performance counter to
  time value in unit of nanoseconds.
  @param  Ticks     The number of elapsed ticks of running performance counter.
  @return The elapsed time in nanoseconds.
**/
UINT64
EFIAPI
GetTimeInNanoSecond (
  IN      UINT64  Ticks
  );

其中的GetPerformanceCounter() 返回CPU 当前经过的计数值或者说多少个 Ticks,GetTimeInNanoSecond() 函数能将经过的计数值转化为纳秒为单位的时间。

编写一个 UEFI Shell代码进行测试:

1. 在AppPkg.dsc 中加入 TimerLib

CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
  TimerLib|UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
###################################################################################################
#
# Components Section - list of the modules and components that will be processed by compilation
#

2.编写代码如下:

#include  <Uefi.h>
#include  <Library/UefiLib.h>
#include  <Library/ShellCEntryLib.h>
#include  <Library/TimerLib.h>
#include  <Library/UefiBootServicesTableLib.h>
INTN
EFIAPI
ShellAppMain (
  IN UINTN Argc,
  IN CHAR16 **Argv
  )
{
	UINT64	Start=GetPerformanceCounter();
	gBS->Stall(1000000UL);
	Print(L"You have dealyed [%llu]ns\n",
			GetTimeInNanoSecond(GetPerformanceCounter()-Start));
  return(0);
}

具体动作就是首先保存当前的 CPU 计数值,然后延时 1s, 最后输出以纳秒为单位的经过时间。可以看到每次运行耗时会有一点波动。

因为没有使用 CLIB , 所以 Build出来代码体积也比较小,只有9KB.

参考:

  1. https://www.lab-z.com/stugt-2/
  2. https://www.lab-z.com/stu14/

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注