HPET(High Precision Event Timer) 俗称高精度定时器,最低时钟频率为10MHZ,而且定义了比较严格的精确度(间隔 >= 1 毫秒的允许 +-0.05% 的误差,间隔 <=100 微妙的允许 +-0.2% 的误差)。x86 架构中一般支持 HPET 定时器。在 HPET 体系结构中规定 32 个定时器组成一个定时器块,最多可支持 8 个块,也就是 256 个定时器。实际设备中可使用的定时器数量可以从相关寄存器中查询。每个定时器均可以单独配置成一个中断。

在 x86 中使用 HPET 需要如下步骤:

1、在 _G_pAcpiHpet 结构中获取 HPET 寄存器操作地址操作地址;

2、在寄存器 General Capability 读取当前定时器的频率,这里的值表示每个时钟的周期,单位为飞秒(10^-15 秒);

3、配置中断,HPET 有三种中断模式:原始模式、标准模式、FSB 模式。这里我们使用标准模式,不对其他两种模式做过多解释。

在寄存器 Configuration Register 中通过配置 LEG_RT_CNF 控制关闭原始模式(默认关闭)

在具体的 Timer 配置寄存器中通过 TN_FSB_EN_CNF 位关闭 FSB 模式

标准模式下每个定时器的中断通过 Tn_INT_ROUTE_CNF 指定,Tn_INT_ROUTE_CAP 表示哪些中断号是有效的。

通过 Tn_INT_ENB_CNF 位使能定时器中断

4、配置比较寄存器 ,主计数器是 64 位的,会一直按照固定周期累加。若主计数器与比较寄存器中的值相同则会触发中断。通过调整比较寄存器的值可以调整中断触发周期。

例程:

hpet_drv.c

#define  __SYLIXOS_KERNEL
#include <module.h>
#include "hpet_drv.h"
#include "arch/x86/common/x86Idt.h"
#include "arch/x86/acpi/x86AcpiLib.h"
/*********************************************************************************************************HPET 控制器定义
*********************************************************************************************************/
struct hpet_controller{LW_DEV_HDR                  HPET_devHdr;                            /*  必须是第一个结构体成员      */LW_LIST_LINE_HEADER         HPET_fdNodeHeader;                      /*  表头                        */UINT32                      HPET_uiChannel;                         /*  通道号                      */addr_t                      HPET_addrBase;                          /*  基址                        */spinlock_t                  HPET_slSpinlock;                        /*  自旋锁                      */LW_OBJECT_HANDLE            HPET_ulMutex;                           /*  互斥锁                      */LW_OBJECT_HANDLE            HPET_ulSem;                             /*  信号量                      */ULONG                       HPET_ulIrqNum;                          /*  定时器中断号                */UINT32                      HPET_ulFsPerCnt;                        /*  时钟源周期                  */HPET_CFG                    HPET_cfg;                               /*  配置                        */
};
typedef struct hpet_controller   HPET_CONTROLER;
typedef struct hpet_controller  *PHPET_CONTROLER;
/*********************************************************************************************************HEPT 驱动号
*********************************************************************************************************/
static INT  _G_iHpetDrvNum   = PX_ERROR;
/*********************************************************************************************************HPET 宏配置
*********************************************************************************************************/
#define HPET_NUMBER                     (32)                            /*  32 路 HPET                  */
/*********************************************************************************************************HPET 寄存器定义
*********************************************************************************************************/
#define HPET_BASE                       (pHpetDev->HPET_addrBase)#define HPET_ID_LO                      (HPET_BASE + 0)
#define HPET_ID_HI                      (HPET_ID_LO + 4)#define HPET_CONFIG_LO                  (HPET_BASE + 0x10)
#define HPET_CONFIG_HI                  (HPET_CONFIG_LO + 4)#define HPET_STATUS_LO                  (HPET_BASE + 0x20)
#define HPET_STATUS_HI                  (HPET_STATUS_LO + 4)#define HPET_COUNTER_LO                 (HPET_BASE + 0xf0)
#define HPET_COUNTER_HI                 (HPET_COUNTER_LO + 4)#define HPET_TIMER_CONFIG_LO(t)         (HPET_BASE + 0x100 + (t) * 0x20)
#define HPET_TIMER_CONFIG_HI(t)         (HPET_TIMER_CONFIG_LO(t) + 4)
#define HPET_INT_ROUTE_MSK              (0x1F)#define HPET_TIMER_COMPARATOR_LO(t)     (HPET_BASE + 0x108 + (t) * 0x20)
#define HPET_TIMER_COMPARATOR_HI(t)     (HPET_TIMER_COMPARATOR_LO(t) + 4)#define HPET_TIMER_FSB_INTR_LO(t)       (HPET_BASE + 0x110 + (t) * 0x20)
#define HPET_TIMER_FSB_INTR_HI(t)       (HPET_TIMER_FSB_INTR_LO(t) + 4)
/*********************************************************************************************************
** 函数名称: __acpiHpetMap
** 功能描述: 映射 ACPI HPET 表
** 输  入  : ulAcpiPhyAddr         ACPI HPET 表物理地址
**           ulAcpiSize            ACPI HPET 表长度
** 输  出  : ACPI HPET 表虚拟地址
** 返  回  : ERROR_CODE
*********************************************************************************************************/
static VOID  *__acpiHpetMap (addr_t  ulAcpiPhyAddr, size_t  ulAcpiSize)
{addr_t  ulPhyBase = ROUND_DOWN(ulAcpiPhyAddr, LW_CFG_VMM_PAGE_SIZE);addr_t  ulOffset  = ulAcpiPhyAddr - ulPhyBase;addr_t  ulVirBase;ulAcpiSize += ulOffset;ulAcpiSize  = ROUND_UP(ulAcpiSize, LW_CFG_VMM_PAGE_SIZE);ulVirBase = (addr_t)API_VmmIoRemapNocache((PVOID)ulPhyBase, ulAcpiSize);if (ulVirBase) {return  (VOID *)(ulVirBase + ulOffset);} else {return  (VOID *)(LW_NULL);}
}
/*********************************************************************************************************
** 函数名称: __HpetIsrHandle
** 功能描述: HPET 中断处理
** 输  入  : pHpetDev              HPET 结构
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
static irqreturn_t  __HpetIsrHandle (PHPET_CONTROLER  pHpetDev)
{UINT64 u64Value;if (pHpetDev == LW_NULL) {return  LW_IRQ_HANDLED;}if (read32(HPET_STATUS_LO) & (UINT32)(1 << pHpetDev->HPET_uiChannel)) {LW_SPIN_LOCK(&pHpetDev->HPET_slSpinlock);/** 清中断*/write32((UINT32)1 << pHpetDev->HPET_uiChannel, HPET_STATUS_LO);/** 重新计算比较值*/u64Value  = read64(HPET_TIMER_COMPARATOR_LO(pHpetDev->HPET_uiChannel));if (pHpetDev->HPET_ulFsPerCnt != 0 && pHpetDev->HPET_cfg.uiHz != 0) {u64Value += 1000000000000000ULL / pHpetDev->HPET_ulFsPerCnt / pHpetDev->HPET_cfg.uiHz;}write64(u64Value, HPET_TIMER_COMPARATOR_LO(pHpetDev->HPET_uiChannel));/** 中断处理*/if (pHpetDev->HPET_cfg.hpetIntHandle) {pHpetDev->HPET_cfg.hpetIntHandle(pHpetDev->HPET_cfg.pIntArg);}/** 投递信号量*/API_SemaphoreBPost(pHpetDev->HPET_ulSem);LW_SPIN_UNLOCK(&pHpetDev->HPET_slSpinlock);}return  (LW_IRQ_HANDLED);
}
/*********************************************************************************************************
** 函数名称: __hpetTimerInit
** 功能描述: 初始化 hpet 时钟
** 输  入  : pHpetDev              HPET 结构
**           pAcpiHpetPhy          ACPI HPET 表
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
static INT  __hpetTimerInit (PHPET_CONTROLER  pHpetDev, ACPI_TABLE_HPET  *pAcpiHpetPhy)
{ACPI_TABLE_HPET  *pAcpiHpet;UINT32            ulhpetTimerCfg;UINT32            ulIntRouteCap;if (!pHpetDev || !pAcpiHpetPhy) {return  (PX_ERROR);}/** 映射 ACPI HPET 表*/pAcpiHpet = __acpiHpetMap((addr_t)pAcpiHpetPhy, LW_CFG_VMM_PAGE_SIZE);if (!pAcpiHpet) {return  (PX_ERROR);}/** 映射 HPET 寄存器*/HPET_BASE = (addr_t)API_VmmIoRemapNocache((PVOID)(addr_t)(pAcpiHpet->Address.Address),LW_CFG_VMM_PAGE_SIZE);/** 解除映射 ACPI HPET 表*/API_VmmIoUnmap((PVOID)(((addr_t)pAcpiHpet) & LW_CFG_VMM_PAGE_MASK));if (!HPET_BASE) {                                                   /*  映射 HPET 寄存器失败        */return  (PX_ERROR);}/** 读取时钟源周期*/pHpetDev->HPET_ulFsPerCnt = read32(HPET_ID_HI);/** 校验中断合法性*/ulIntRouteCap = read32(HPET_TIMER_CONFIG_HI(pHpetDev->HPET_uiChannel));if (!(ulIntRouteCap & (1 << pHpetDev->HPET_ulIrqNum))) {printk(KERN_ERR "[HPET] %s %d: IRQ NUM Check Error! INT_ROUTE_CAP = 0x%x\n",__func__, __LINE__, ulIntRouteCap);return  (PX_ERROR);}/** 配置定时器模式*/ulhpetTimerCfg  = read32(HPET_TIMER_CONFIG_LO(pHpetDev->HPET_uiChannel));ulhpetTimerCfg &= ~(1 << 15);                                       /*  禁用 FSB INT                */ulhpetTimerCfg &= ~(HPET_INT_ROUTE_MSK << 9);ulhpetTimerCfg |= pHpetDev->HPET_ulIrqNum << 9;                     /*  设置中断                    */ulhpetTimerCfg &= ~(1 << 8);                                        /*  64 位模式                   */ulhpetTimerCfg &= ~(1 << 3);                                        /*  单次触发模式                */ulhpetTimerCfg &= ~(1 << 2);                                        /*  禁止中断                    */ulhpetTimerCfg |=  (1 << 1);                                        /*  电平触发模式                */write32(ulhpetTimerCfg, HPET_TIMER_CONFIG_LO(pHpetDev->HPET_uiChannel));/*  配置定时器                  */return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: __hpetTimerDeinit
** 功能描述: 解除初始化 hpet 时钟
** 输  入  : pHpetDev              HPET 结构
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
static INT  __hpetTimerDeinit (PHPET_CONTROLER  pHpetDev)
{if (!pHpetDev) {return  (PX_ERROR);}LW_SPIN_LOCK(&pHpetDev->HPET_slSpinlock);write32(0, HPET_TIMER_CONFIG_LO(pHpetDev->HPET_uiChannel));bzero(&pHpetDev->HPET_cfg, sizeof(HPET_CFG));LW_SPIN_UNLOCK(&pHpetDev->HPET_slSpinlock);return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: __hpetTimerStart
** 功能描述: 启动 hpet 时钟
** 输  入  : pHpetDev              HPET 结构
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
static INT  __hpetTimerStart (PHPET_CONTROLER  pHpetDev)
{UINT32  ulhpetTimerCfg;UINT64  u64Value;if (!pHpetDev) {return  (PX_ERROR);}/** 清除信号量信号*/API_SemaphoreBClear(pHpetDev->HPET_ulSem);/** 清中断*/write32((UINT32)1 << pHpetDev->HPET_uiChannel, HPET_STATUS_LO);/** 配置中断*/API_InterVectorConnect(pHpetDev->HPET_ulIrqNum,(PINT_SVR_ROUTINE)__HpetIsrHandle,pHpetDev,"hpetIsr");API_InterVectorEnable(pHpetDev->HPET_ulIrqNum);                     /*  使能中断                    *//** 计算比较寄存器值*/LW_SPIN_LOCK(&pHpetDev->HPET_slSpinlock);u64Value  = read64(HPET_COUNTER_LO);if (pHpetDev->HPET_ulFsPerCnt != 0 && pHpetDev->HPET_cfg.uiHz != 0) {u64Value += 1000000000000000ULL / pHpetDev->HPET_ulFsPerCnt / pHpetDev->HPET_cfg.uiHz;}write64(u64Value, HPET_TIMER_COMPARATOR_LO(pHpetDev->HPET_uiChannel));/** 开启定时器*/ulhpetTimerCfg  = read32(HPET_TIMER_CONFIG_LO(pHpetDev->HPET_uiChannel));ulhpetTimerCfg |= (1 << 2);                                         /*  使能中断                    */write32(ulhpetTimerCfg, HPET_TIMER_CONFIG_LO(pHpetDev->HPET_uiChannel));LW_SPIN_UNLOCK(&pHpetDev->HPET_slSpinlock);return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: __hpetTimerStop
** 功能描述: 停止 hpet 时钟
** 输  入  : pHpetDev              HPET 结构
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
static INT  __hpetTimerStop (PHPET_CONTROLER  pHpetDev)
{UINT32  ulhpetTimerCfg;if (!pHpetDev) {return  (PX_ERROR);}LW_SPIN_LOCK(&pHpetDev->HPET_slSpinlock);ulhpetTimerCfg  = read32(HPET_TIMER_CONFIG_LO(pHpetDev->HPET_uiChannel));ulhpetTimerCfg &= ~(1 << 2);                                        /*  禁止中断                    */write32(ulhpetTimerCfg, HPET_TIMER_CONFIG_LO(pHpetDev->HPET_uiChannel));API_InterVectorDisable(pHpetDev->HPET_ulIrqNum);                    /*  禁止中断                    */LW_SPIN_UNLOCK(&pHpetDev->HPET_slSpinlock);/** 清除信号量信号*/API_SemaphoreBClear(pHpetDev->HPET_ulSem);return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: __hpetIoctl
** 功能描述: 控制 HPET 设备
** 输  入  : pFdEntry              文件结构
**           iCmd                  命令
**           lArg                  参数
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
static INT  __hpetIoctl (PLW_FD_ENTRY  pFdEntry, INT  iCmd, LONG  lArg)
{INT              iRet     = ERROR_NONE;PHPET_CONTROLER  pHpetDev = (PHPET_CONTROLER)pFdEntry->FDENTRY_pdevhdrHdr;API_SemaphoreMPend(pHpetDev->HPET_ulMutex, LW_OPTION_WAIT_INFINITE);switch (iCmd) {case CMD_HPET_CONFIG:if (lArg) {LW_SPIN_LOCK(&pHpetDev->HPET_slSpinlock);pHpetDev->HPET_cfg = *(PHPET_CFG)lArg;LW_SPIN_UNLOCK(&pHpetDev->HPET_slSpinlock);} else {iRet = PX_ERROR;}break;case CMD_HPET_START:__hpetTimerStart(pHpetDev);break;case CMD_HPET_STOP:__hpetTimerStop(pHpetDev);break;case CMD_HPET_INT_WAIT:/** 等待中断信号量前先解互斥锁,防止造成死锁*/API_SemaphoreMPost(pHpetDev->HPET_ulMutex);API_SemaphoreBPend(pHpetDev->HPET_ulSem, LW_OPTION_WAIT_INFINITE);break;default:iRet = PX_ERROR;}if (iCmd != CMD_HPET_INT_WAIT) {API_SemaphoreMPost(pHpetDev->HPET_ulMutex);}return  (iRet);
}
/*********************************************************************************************************
** 函数名称: __hpetOpen
** 功能描述: 打开 HPET 设备
** 输  入  : pFdEntry              文件结点
**           pcName                设备名字
**           iFlags                标志
**           iMode                 模式
** 输  出  : NONE
** 返  回  : 文件节点或者出错
*********************************************************************************************************/
static LONG  __hpetOpen (PHPET_CONTROLER  pHpetDev, PCHAR  pcName, INT  iFlags, INT  iMode)
{PLW_FD_NODE       pFdNode;BOOL              bIsNew;if (pcName == LW_NULL) {_ErrorHandle(ERROR_IO_NO_DEVICE_NAME_IN_PATH);return  (PX_ERROR);} else {API_SemaphoreMPend(pHpetDev->HPET_ulMutex, LW_OPTION_WAIT_INFINITE);pFdNode = API_IosFdNodeAdd(&pHpetDev->HPET_fdNodeHeader, (dev_t)pHpetDev, 0,iFlags, iMode, 0, 0, 0, LW_NULL, &bIsNew);if (pFdNode == LW_NULL) {API_SemaphoreMPost(pHpetDev->HPET_ulMutex);printk(KERN_ERR "[HPET] %s %d: failed to add fd node!\n", __func__, __LINE__);return  (PX_ERROR);}if (LW_DEV_INC_USE_COUNT(&pHpetDev->HPET_devHdr) == 1) {}API_SemaphoreMPost(pHpetDev->HPET_ulMutex);return  ((LONG)pFdNode);}
}
/*********************************************************************************************************
** 函数名称: __hpetClose
** 功能描述: 关闭 HPET 设备
** 输  入  : pFdEntry              文件结构
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
static INT  __hpetClose (PLW_FD_ENTRY  pFdEntry)
{PLW_FD_NODE      pfdnode    = (PLW_FD_NODE)pFdEntry->FDENTRY_pfdnode;PHPET_CONTROLER  pHpetDev   = (PHPET_CONTROLER)pFdEntry->FDENTRY_pdevhdrHdr;if (!pFdEntry) {return  (PX_ERROR);}if (pFdEntry && pfdnode) {API_SemaphoreMPend(pHpetDev->HPET_ulMutex, LW_OPTION_WAIT_INFINITE);API_IosFdNodeDec(&pHpetDev->HPET_fdNodeHeader, pfdnode, NULL);if (LW_DEV_DEC_USE_COUNT(&pHpetDev->HPET_devHdr) == 0) {__hpetTimerStop(pHpetDev);}API_SemaphoreMPost(pHpetDev->HPET_ulMutex);return  (ERROR_NONE);} else {return (PX_ERROR);}
}
/*********************************************************************************************************
** 函数名称: hpetDrvInstall
** 功能描述: 安装 HPET 驱动
** 输  入  : NONE
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
INT  hpetDrvInstall (VOID)
{struct file_operations  fileop;if (_G_iHpetDrvNum != PX_ERROR) {return  (ERROR_NONE);}lib_memset(&fileop, 0, sizeof(struct file_operations));fileop.owner     = THIS_MODULE;fileop.fo_create = __hpetOpen;fileop.fo_open   = __hpetOpen;fileop.fo_close  = __hpetClose;fileop.fo_ioctl  = __hpetIoctl;_G_iHpetDrvNum = iosDrvInstallEx2(&fileop, LW_DRV_TYPE_NEW_1);DRIVER_LICENSE(_G_iHpetDrvNum,     "Dual BSD/GPL->Ver 1.0");DRIVER_AUTHOR(_G_iHpetDrvNum,      "WangJingshi");DRIVER_DESCRIPTION(_G_iHpetDrvNum, "HPET driver.");return  (_G_iHpetDrvNum > 0) ? (ERROR_NONE) : (PX_ERROR);
}
/*********************************************************************************************************
** 函数名称: hpetDevCreate
** 功能描述: 创建 HPET 设备
** 输  入  : uiChannel             HPET 通道
**           cpcPath               HPET 设备文件路径
**           ulIrq                 HPET 分配中断号
** 输  出  : NONE
** 返  回  : ERROR_CODE
** 备  注  : 分配中断号注意不能与系统其他中断冲突
*********************************************************************************************************/
INT  hpetDevCreate (UINT32  uiChannel, CPCHAR  cpcPath, ULONG  ulIrq)
{PHPET_CONTROLER    pHpetDev;if (_G_iHpetDrvNum == PX_ERROR) {printk(KERN_ERR "[HPET] %s %d: driver number invalid!\n", __func__, __LINE__);return  (PX_ERROR);}if (cpcPath == LW_NULL) {printk(KERN_ERR "[HPET] %s %d: device path invalid!\n", __func__, __LINE__);return  (PX_ERROR);}if (uiChannel >= HPET_NUMBER) {printk(KERN_ERR "[HPET] %s %d: hpet channel invalid!\n", __func__, __LINE__);return  (PX_ERROR);}/** 创建设备结构*/pHpetDev = (PHPET_CONTROLER)sys_zalloc(sizeof(HPET_CONTROLER));if (pHpetDev == LW_NULL) {printk(KERN_ERR "[HPET] %s %d: memory error!\n", __func__, __LINE__);errno = ENOMEM;return  (PX_ERROR);}pHpetDev->HPET_uiChannel = uiChannel;pHpetDev->HPET_ulIrqNum  = ulIrq;LW_SPIN_INIT(&pHpetDev->HPET_slSpinlock);pHpetDev->HPET_ulMutex = API_SemaphoreMCreate("hpet_lock",LW_PRIO_HIGH,LW_OPTION_WAIT_PRIORITY |LW_OPTION_OBJECT_GLOBAL|LW_OPTION_INHERIT_PRIORITY |LW_OPTION_ERRORCHECK,LW_NULL);if (pHpetDev->HPET_ulMutex == LW_OBJECT_HANDLE_INVALID) {printk(KERN_ERR "[HPET] %s %d: mutex create failed.\n", __func__, __LINE__);goto  __error4;}pHpetDev->HPET_ulSem = API_SemaphoreBCreate("hpet_sem",LW_FALSE,LW_OPTION_WAIT_PRIORITY |LW_OPTION_OBJECT_GLOBAL,LW_NULL);if (pHpetDev->HPET_ulSem == LW_OBJECT_HANDLE_INVALID) {printk(KERN_ERR "[HPET] %s %d: sem create failed.\n", __func__, __LINE__);goto  __error3;}/** 初始化 HPET 定时器*/if (__hpetTimerInit(pHpetDev, _G_pAcpiHpet) != ERROR_NONE) {printk(KERN_ERR "[HPET] %s %d: hpet %d init fail!\n",__func__, __LINE__, pHpetDev->HPET_uiChannel);goto  __error2;}/**  向系统添加一个设备*/if (ERROR_NONE != API_IosDevAddEx(&pHpetDev->HPET_devHdr, cpcPath, _G_iHpetDrvNum, DT_CHR)) {printk(KERN_ERR "[HPET] %s %d: can not add device : %s\n", __func__, __LINE__, strerror(errno));goto  __error1;}return  (ERROR_NONE);__error1:__hpetTimerDeinit(pHpetDev);
__error2:API_SemaphoreBDelete(&pHpetDev->HPET_ulSem);
__error3:API_SemaphoreMDelete(&pHpetDev->HPET_ulMutex);
__error4:sys_free(pHpetDev);return  (PX_ERROR);
}
/*********************************************************************************************************
** 函数名称: module_init
** 功能描述: 模块初始化
** 输  入  : NONE
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
int module_init (void)
{hpetDrvInstall();hpetDevCreate(2, "/dev/hpet2", LW_IRQ_11);return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: module_exit
** 功能描述: 模块退出
** 输  入  : NONE
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
void module_exit (void)
{
}

hpet_drv.h

#ifndef __HPET_DRV_H
#define __HPET_DRV_H#define __SYLIXOS_KERNEL
#include <SylixOS.h>
#include "sys/ioccom.h"/*********************************************************************************************************HPET 配置结构
*********************************************************************************************************/
struct hpet_cfg {UINT32    uiHz;                                                     /*  定时频率                    */PVOID     pIntArg;                                                  /*  中断处理参数                */PVOID (*hpetIntHandle) (PVOID);                                     /*  中断处理 (注意:中断上下文) */
};
typedef struct hpet_cfg   HPET_CFG;
typedef struct hpet_cfg  *PHPET_CFG;/*********************************************************************************************************HPET ioctl 函数命令字
*********************************************************************************************************/#define CMD_HPET_CONFIG       _IOW('h', 1, HPET_CFG)                    /*  配置定时器                  */
#define CMD_HPET_START        _IO('h', 2)                               /*  定时器启动                  */
#define CMD_HPET_STOP         _IO('h', 3)                               /*  定时器停止                  */
#define CMD_HPET_INT_WAIT     _IO('h', 4)                               /*  等待中断触发                *//*********************************************************************************************************函数声明
*********************************************************************************************************/
INT  hpetDrvInstall(VOID);
INT  hpetDevCreate(UINT32  uiChannel, CPCHAR  cpcPath, ULONG  ulIrq);#endif                                                                  /*  __HPET_DRV_H                */

SylixOS x86 HPET 定时器驱动相关推荐

  1. SylixOS中APIC HPET定时器字符驱动实现

    1.简介 1.1 APIC介绍 "APIC"是Advanced Programmable Interrupt Controller的缩写,即高级可编程中断控制器.引入APIC机制是 ...

  2. STM8单片机定时器驱动的深度解析

    上一节给大家介绍了基于标准库STM8单片机GPIO的驱动,本节课主要给大家介绍一下STM8定时器的驱动. 我们先打开STM8L10x单片机的规格书,简单的了解一下STM8L10X单片机的定时器功能. ...

  3. HAL库配置STM32F1系列定时器驱动步进电机(三)

    之前的电机成功地转了起来,但其噪音非常大,因为之前尝试过自带细分功能的优质驱动器,关于其具体原理我没有系统学习,在使用L298N驱动电机时就感觉到有些吃力,于是在这里补一下步进电机微步细分原理的功课, ...

  4. hpet 定时器中断 8259 linux,[OSDEV]编程高精度定时器(HPET)

    高精度定时器HPET和I/O APIC一样,用的是内存映射,映射的地址保存在BIOS提供的ACPI表格中 我们首先来获取这个地址 获取HPET的I/O内存地址 先来看一下文档的30-31页: 关键就是 ...

  5. 由于高精度事件计时器(HPET)驱动过时导致AMD机器装Win10的卡死蓝屏问题记录

    AMD机型最近频繁卡死,蓝屏,特征在于:打游戏等高负载条件,电脑没有问题:闲置一定时间之后蓝屏或者死机,鼠标键盘无反应,界面全部卡死,只能按开机键重启.未保存的数据全部丢失. 近日蓝屏代码 有两类,一 ...

  6. 【春节歌曲回味 | STM32小音乐盒 】PWM+定时器驱动无源蜂鸣器(STM32 HAL库)

    l  STM32通过PWM与定时器方式控制无源蜂鸣器鸣响 l  STM32小音乐盒,歌曲进度条图形显示与百分比显示,歌曲切换 l  编程使用STM32 HAL库 l  IIC OLED界面编程,动画实 ...

  7. 定时器驱动数码管c语言,第五章 定时器和数码管

    1.1基本数字逻辑门电路 不管是数字电路,还是C语言,我们都会经常遇到逻辑运算和逻辑电路,在这里我介绍一下,大家先简单了解一下,知道有这么回事,回头遇到了,再详细研究. 首先,在"逻辑&qu ...

  8. 定时器驱动数码管c语言程序,74hc595驱动数码管时间程序

    74hc595驱动数码管时间程序 这里是电路图: 下面是51单片机驱动74hc595芯片的程序: #include                            //包含51单片机的头文件 # ...

  9. 定时器驱动数码管c语言程序,用c语言编写,实用定时器实现数码管15倒计时

    #include#define uchar unsigned char uchar miao,t0,flat,shiwei,gewei,; sbit dula = p2^6; sbit wela = ...

最新文章

  1. 设置 docker容器 禁用网络
  2. [杂笔]我的第一篇博客
  3. 在项目中使用JMail发送邮件
  4. java处理中文字符串_Java实现读取文章中重复出现的中文字符串
  5. Python 抓取图片
  6. efi引导文件_你们心心念念的oc通用EFI来了!
  7. wps计算机一级考试试题300,计算机一级考试WPS试题及答案
  8. python读音发音-python3 - 文本读音器
  9. C++笔试题整理(一)
  10. iOS-Senior19-FMDB第三方应用
  11. 基于SSM框架实现的房屋租赁管理系统
  12. Exif文件格式描述(转载)
  13. 视频下载软件Annie的安装及使用
  14. 当下的力量实践手册读书笔记(1.29)
  15. 机器学习笔记 十七:基于Gini Importance、Permutation Importance、Boruta的随机森林模型重要性评估的比较
  16. 手把手接入高德地图API——POI周边搜索功能实现
  17. R语言导入数据文件(数据导入、加载、读取)、使用read.table函数导入逗号分割文件CSV(Comma Delimited Text File)
  18. 2022Q4手机银行新版本聚焦提升客群专属、财富开放平台、智能化能力,活跃用户规模6.91亿人
  19. 软件编程学习网站汇总——持续更新中
  20. java.util.list源码_关于fest-util源码包Collections集合工具类过滤、判空、格式化及复制克隆处理...

热门文章

  1. 微信群发软件哪个好?好用的群发软件选择
  2. unity 3d iphone android 通用,在Unity3D中使用iPhone原生UI
  3. 微信小游戏 腾讯课堂《白鹭教育 - 成语大挑战小游戏开发》学习笔记
  4. (附源码)springboot基于微信小程序的高校计算机类课程思政库的设计与实现 毕业设计 271611
  5. 微信服务器 移动信号,微信消息延迟,只需更改手机这5个设置,效果“立竿见影”...
  6. java操作word,自动更新目录/域
  7. 【GD32F310开发板试用】编码器接口的使用
  8. iOS 一个带动画的等待指示器
  9. 使用Rust开发编译系统(C以及Rust编译的过程)
  10. Linux桌面基础:X Window System——Xorg