uefi中使用watchdog

本文详细介绍了如何在UEFI环境中使用Watchdog定时器。通过具体代码示例展示了如何设置定时器周期,以及如何取消正在运行的Watchdog定时器。此外,还解释了在不同条件下Watchdog定时器的实现机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一般要在uefi中使用watchdog,会按照如下格式。

  gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);

 XXXXXXXXXXXX

  gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
即首先调用gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);来是指5分钟到期的watchdog,如果事情在5分钟之内做完,就调用
gBS->SetWatchdogTimer 来关掉watchdog
gBS->SetWatchdogTimer 其实指向的是WatchdogSetTimerPeriod这个函数.
EFI_STATUS
EFIAPI
WatchdogSetTimerPeriod (
  IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL   *This,
  IN UINT64                                   TimerPeriod   // In 100ns units
  )
{
  UINTN       SystemCount;
  EFI_STATUS  Status;


  if (TimerPeriod == 0) {
    mNumTimerTicks = 0;
    return WatchdogDisable ();
  }

  // Work out how many timer ticks will equate to TimerPeriod
  mNumTimerTicks = (mTimerFrequencyHz * TimerPeriod) / TIME_UNITS_PER_SECOND;

  //
  // If the number of required ticks is greater than the max number the
  // watchdog's offset register (WOR) can hold, we need to manually compute and
  // set the compare register (WCV)
  //
  if (mNumTimerTicks > MAX_UINT32) {
    //
    // We need to enable the watchdog *before* writing to the compare register,
    // because enabling the watchdog causes an "explicit refresh", which
    // clobbers the compare register (WCV). In order to make sure this doesn't
    // trigger an interrupt, set the offset to max.
    //
    Status = WatchdogWriteOffsetRegister (MAX_UINT32);
    if (EFI_ERROR (Status)) {
      return Status;
    }
    WatchdogEnable ();
    SystemCount = ArmGenericTimerGetSystemCount ();
    Status      = WatchdogWriteCompareRegister (SystemCount + mNumTimerTicks);
  } else {
    Status = WatchdogWriteOffsetRegister ((UINT32)mNumTimerTicks);
    WatchdogEnable ();
  }

  return Status;
}
可以看到,如果TimerPeriod==0,就调用WatchdogDisable 关掉watchdog.正常情况下设定的watchdog到期时间不会超过MAX_UINT32。因此首先调用将TimerPeriod 转成ticks
  mNumTimerTicks = (mTimerFrequencyHz * TimerPeriod) / TIME_UNITS_PER_SECOND;
然后写寄存器
Status = WatchdogWriteOffsetRegister ((UINT32)mNumTimerTicks);
最后enable watchdog
    WatchdogEnable ();

在dxemain.c 中
  (EFI_SET_WATCHDOG_TIMER)                      CoreSetWatchdogTimer,                     // SetWatchdogTimer
会注册SetWatchdogTimer的回调函数为CoreSetWatchdogTimer

EFI_STATUS
EFIAPI
CoreSetWatchdogTimer (
  IN UINTN    Timeout,
  IN UINT64   WatchdogCode,
  IN UINTN    DataSize,
  IN CHAR16   *WatchdogData OPTIONAL
  )
{
  EFI_STATUS  Status;

  //
  // Check our architectural protocol
  //
  if (gWatchdogTimer == NULL) {
    return EFI_NOT_AVAILABLE_YET;
  }

  //
  // Attempt to set the timeout
  //
  Status = gWatchdogTimer->SetTimerPeriod (gWatchdogTimer, MultU64x32 (Timeout, WATCHDOG_TIMER_CALIBRATE_PER_SECOND));

  //
  // Check for errors
  //
  if (EFI_ERROR (Status)) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

所以后面调用gBS->SetWatchdogTimer 就相当于调用CoreSetWatchdogTimer。而在CoreSetWatchdogTimer 中是直接调用gWatchdogTimer->SetTimerPeriod
 由于watchdog是在dxemain.c 中才注册的,也就是说只有dxe之后包括bds才可以使用watchdog函数.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值