gTimer protocol的实现
来源:互联网 发布:淘宝开放平台 编辑:程序博客网 时间:2024/05/16 11:22
在Omap35xxpkg中的TimerDxe 有实现gTimer。
从inf中可以看到这个是一个DXE_DRIVER driver,其入口函数是TimerInitialize
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = BeagleBoardTimerDxe
FILE_GUID = 6ddbf08b-cfc9-43cc-9e81-0784ba312ca0
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = TimerInitialize
EFI_STATUS
EFIAPI
TimerInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_HANDLE Handle = NULL;
EFI_STATUS Status;
UINT32 TimerBaseAddress;
// Find the interrupt controller protocol. ASSERT if not found.
Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt);
ASSERT_EFI_ERROR (Status);
// Set up the timer registers
TimerBaseAddress = TimerBase (FixedPcdGet32(PcdOmap35xxArchTimer));
TISR = TimerBaseAddress + GPTIMER_TISR;
TCLR = TimerBaseAddress + GPTIMER_TCLR;
TLDR = TimerBaseAddress + GPTIMER_TLDR;
TCRR = TimerBaseAddress + GPTIMER_TCRR;
TIER = TimerBaseAddress + GPTIMER_TIER;
// Disable the timer
Status = TimerDriverSetTimerPeriod (&gTimer, 0);
ASSERT_EFI_ERROR (Status);
// Install interrupt handler
gVector = InterruptVectorForTimer (FixedPcdGet32(PcdOmap35xxArchTimer));
Status = gInterrupt->RegisterInterruptSource (gInterrupt, gVector, TimerInterruptHandler);
ASSERT_EFI_ERROR (Status);
// Turn on the functional clock for Timer
MmioOr32 (CM_FCLKEN_PER, CM_FCLKEN_PER_EN_GPT3_ENABLE);
// Set up default timer
Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod));
ASSERT_EFI_ERROR (Status);
// Install the Timer Architectural Protocol onto a new handle
Status = gBS->InstallMultipleProtocolInterfaces (
&Handle,
&gEfiTimerArchProtocolGuid, &gTimer,
NULL
);
ASSERT_EFI_ERROR(Status);
return Status;
}
在TimerInitialize 中首先通过LocateProtocol 找到gInterrupt的protocol,这样就可以通过gInterrupt来注册中断
从FixedPcd 中读到timer 寄存器的base address,然后分别得到控制timer的5个寄存器的地址.
// Set up the timer registers
TimerBaseAddress = TimerBase (FixedPcdGet32(PcdOmap35xxArchTimer));
TISR = TimerBaseAddress + GPTIMER_TISR;
TCLR = TimerBaseAddress + GPTIMER_TCLR;
TLDR = TimerBaseAddress + GPTIMER_TLDR;
TCRR = TimerBaseAddress + GPTIMER_TCRR;
TIER = TimerBaseAddress + GPTIMER_TIER;
关掉timer
Status = TimerDriverSetTimerPeriod (&gTimer, 0);
ASSERT_EFI_ERROR (Status);
EFI_STATUS
EFIAPI
TimerDriverSetTimerPeriod (
IN EFI_TIMER_ARCH_PROTOCOL *This,
IN UINT64 TimerPeriod
)
{
EFI_STATUS Status;
UINT64 TimerCount;
INT32 LoadValue;
if (TimerPeriod == 0) {
// Turn off GPTIMER3
MmioWrite32 (TCLR, TCLR_ST_OFF);
Status = gInterrupt->DisableInterruptSource(gInterrupt, gVector);
} else {
// Calculate required timer count
TimerCount = DivU64x32(TimerPeriod * 100, PcdGet32(PcdEmbeddedPerformanceCounterPeriodInNanoseconds));
// Set GPTIMER3 Load register
LoadValue = (INT32) -TimerCount;
MmioWrite32 (TLDR, LoadValue);
MmioWrite32 (TCRR, LoadValue);
// Enable Overflow interrupt
MmioWrite32 (TIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_ENABLE | TIER_MAT_IT_DISABLE);
// Turn on GPTIMER3, it will reload at overflow
MmioWrite32 (TCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON);
Status = gInterrupt->EnableInterruptSource(gInterrupt, gVector);
}
//
// Save the new timer period
//
mTimerPeriod = TimerPeriod;
return Status;
}
如果参数是0的话
MmioWrite32 (TCLR, TCLR_ST_OFF);
Status = gInterrupt->DisableInterruptSource(gInterrupt, gVector);
直接通过gInterrupt 关掉中断.
回到TimerInitialize 中,继续通过gInterrupt的RegisterInterruptSource 来注册gVector的中断处理函数TimerInterruptHandler
// Install interrupt handler
gVector = InterruptVectorForTimer (FixedPcdGet32(PcdOmap35xxArchTimer));
Status = gInterrupt->RegisterInterruptSource (gInterrupt, gVector, TimerInterruptHandler);
ASSERT_EFI_ERROR (Status);
然后再次调用TimerDriverSetTimerPeriod打开中断
// Set up default timer
Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod));
ASSERT_EFI_ERROR (Status);
在TimerDriverSetTimerPeriod 函数中参数这次不为0,是从FixedPcdGet32(PcdTimerPeriod) 读到的
TimerCount = DivU64x32(TimerPeriod * 100, PcdGet32(PcdEmbeddedPerformanceCounterPeriodInNanoseconds));
// Set GPTIMER3 Load register
LoadValue = (INT32) -TimerCount;
MmioWrite32 (TLDR, LoadValue);
MmioWrite32 (TCRR, LoadValue);
// Enable Overflow interrupt
MmioWrite32 (TIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_ENABLE | TIER_MAT_IT_DISABLE);
// Turn on GPTIMER3, it will reload at overflow
MmioWrite32 (TCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON);
Status = gInterrupt->EnableInterruptSource(gInterrupt, gVector);
计算TimerCount。设定寄存器后,最终通过EnableInterruptSource 重新使能中断.
最终在TimerInitialize中调用InstallMultipleProtocolInterfaces 来安装gTimer
// Install the Timer Architectural Protocol onto a new handle
Status = gBS->InstallMultipleProtocolInterfaces (
&Handle,
&gEfiTimerArchProtocolGuid, &gTimer,
NULL
);
这样别的程序就可以通过gEfiTimerArchProtocolGuid 得到gTimer,从而调用gTimer的四个函数。
EFI_TIMER_ARCH_PROTOCOL gTimer = {
TimerDriverRegisterHandler,
TimerDriverSetTimerPeriod,
TimerDriverGetTimerPeriod,
TimerDriverGenerateSoftInterrupt
};
先看第一个函数,由于uefi中只support 时间中断,因此会在TimerDriverRegisterHandler 中调用mTimerNotifyFunction 来通知其他函数已经产生中断了
TimerDriverGetTimerPeriod (
IN EFI_TIMER_ARCH_PROTOCOL *This,
OUT UINT64 *TimerPeriod
)
{
if (TimerPeriod == NULL) {
return EFI_INVALID_PARAMETER;
}
*TimerPeriod = mTimerPeriod;
return EFI_SUCCESS;
}
TimerDriverGetTimerPeriod 仅仅返回中断的周期mTimerPeriod,这个mTimerPeriod 我们是在TimerDriverSetTimerPeriod 中设定的
TimerDriverGenerateSoftInterrupt (
IN EFI_TIMER_ARCH_PROTOCOL *This
)
{
return EFI_UNSUPPORTED;
}
TimerDriverGenerateSoftInterrupt 是空函数,说明不支持软件中断.
从inf中可以看到这个是一个DXE_DRIVER driver,其入口函数是TimerInitialize
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = BeagleBoardTimerDxe
FILE_GUID = 6ddbf08b-cfc9-43cc-9e81-0784ba312ca0
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = TimerInitialize
EFI_STATUS
EFIAPI
TimerInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_HANDLE Handle = NULL;
EFI_STATUS Status;
UINT32 TimerBaseAddress;
// Find the interrupt controller protocol. ASSERT if not found.
Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt);
ASSERT_EFI_ERROR (Status);
// Set up the timer registers
TimerBaseAddress = TimerBase (FixedPcdGet32(PcdOmap35xxArchTimer));
TISR = TimerBaseAddress + GPTIMER_TISR;
TCLR = TimerBaseAddress + GPTIMER_TCLR;
TLDR = TimerBaseAddress + GPTIMER_TLDR;
TCRR = TimerBaseAddress + GPTIMER_TCRR;
TIER = TimerBaseAddress + GPTIMER_TIER;
// Disable the timer
Status = TimerDriverSetTimerPeriod (&gTimer, 0);
ASSERT_EFI_ERROR (Status);
// Install interrupt handler
gVector = InterruptVectorForTimer (FixedPcdGet32(PcdOmap35xxArchTimer));
Status = gInterrupt->RegisterInterruptSource (gInterrupt, gVector, TimerInterruptHandler);
ASSERT_EFI_ERROR (Status);
// Turn on the functional clock for Timer
MmioOr32 (CM_FCLKEN_PER, CM_FCLKEN_PER_EN_GPT3_ENABLE);
// Set up default timer
Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod));
ASSERT_EFI_ERROR (Status);
// Install the Timer Architectural Protocol onto a new handle
Status = gBS->InstallMultipleProtocolInterfaces (
&Handle,
&gEfiTimerArchProtocolGuid, &gTimer,
NULL
);
ASSERT_EFI_ERROR(Status);
return Status;
}
在TimerInitialize 中首先通过LocateProtocol 找到gInterrupt的protocol,这样就可以通过gInterrupt来注册中断
从FixedPcd 中读到timer 寄存器的base address,然后分别得到控制timer的5个寄存器的地址.
// Set up the timer registers
TimerBaseAddress = TimerBase (FixedPcdGet32(PcdOmap35xxArchTimer));
TISR = TimerBaseAddress + GPTIMER_TISR;
TCLR = TimerBaseAddress + GPTIMER_TCLR;
TLDR = TimerBaseAddress + GPTIMER_TLDR;
TCRR = TimerBaseAddress + GPTIMER_TCRR;
TIER = TimerBaseAddress + GPTIMER_TIER;
关掉timer
Status = TimerDriverSetTimerPeriod (&gTimer, 0);
ASSERT_EFI_ERROR (Status);
EFI_STATUS
EFIAPI
TimerDriverSetTimerPeriod (
IN EFI_TIMER_ARCH_PROTOCOL *This,
IN UINT64 TimerPeriod
)
{
EFI_STATUS Status;
UINT64 TimerCount;
INT32 LoadValue;
if (TimerPeriod == 0) {
// Turn off GPTIMER3
MmioWrite32 (TCLR, TCLR_ST_OFF);
Status = gInterrupt->DisableInterruptSource(gInterrupt, gVector);
} else {
// Calculate required timer count
TimerCount = DivU64x32(TimerPeriod * 100, PcdGet32(PcdEmbeddedPerformanceCounterPeriodInNanoseconds));
// Set GPTIMER3 Load register
LoadValue = (INT32) -TimerCount;
MmioWrite32 (TLDR, LoadValue);
MmioWrite32 (TCRR, LoadValue);
// Enable Overflow interrupt
MmioWrite32 (TIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_ENABLE | TIER_MAT_IT_DISABLE);
// Turn on GPTIMER3, it will reload at overflow
MmioWrite32 (TCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON);
Status = gInterrupt->EnableInterruptSource(gInterrupt, gVector);
}
//
// Save the new timer period
//
mTimerPeriod = TimerPeriod;
return Status;
}
如果参数是0的话
MmioWrite32 (TCLR, TCLR_ST_OFF);
Status = gInterrupt->DisableInterruptSource(gInterrupt, gVector);
直接通过gInterrupt 关掉中断.
回到TimerInitialize 中,继续通过gInterrupt的RegisterInterruptSource 来注册gVector的中断处理函数TimerInterruptHandler
// Install interrupt handler
gVector = InterruptVectorForTimer (FixedPcdGet32(PcdOmap35xxArchTimer));
Status = gInterrupt->RegisterInterruptSource (gInterrupt, gVector, TimerInterruptHandler);
ASSERT_EFI_ERROR (Status);
然后再次调用TimerDriverSetTimerPeriod打开中断
// Set up default timer
Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod));
ASSERT_EFI_ERROR (Status);
在TimerDriverSetTimerPeriod 函数中参数这次不为0,是从FixedPcdGet32(PcdTimerPeriod) 读到的
TimerCount = DivU64x32(TimerPeriod * 100, PcdGet32(PcdEmbeddedPerformanceCounterPeriodInNanoseconds));
// Set GPTIMER3 Load register
LoadValue = (INT32) -TimerCount;
MmioWrite32 (TLDR, LoadValue);
MmioWrite32 (TCRR, LoadValue);
// Enable Overflow interrupt
MmioWrite32 (TIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_ENABLE | TIER_MAT_IT_DISABLE);
// Turn on GPTIMER3, it will reload at overflow
MmioWrite32 (TCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON);
Status = gInterrupt->EnableInterruptSource(gInterrupt, gVector);
计算TimerCount。设定寄存器后,最终通过EnableInterruptSource 重新使能中断.
最终在TimerInitialize中调用InstallMultipleProtocolInterfaces 来安装gTimer
// Install the Timer Architectural Protocol onto a new handle
Status = gBS->InstallMultipleProtocolInterfaces (
&Handle,
&gEfiTimerArchProtocolGuid, &gTimer,
NULL
);
这样别的程序就可以通过gEfiTimerArchProtocolGuid 得到gTimer,从而调用gTimer的四个函数。
EFI_TIMER_ARCH_PROTOCOL gTimer = {
TimerDriverRegisterHandler,
TimerDriverSetTimerPeriod,
TimerDriverGetTimerPeriod,
TimerDriverGenerateSoftInterrupt
};
先看第一个函数,由于uefi中只support 时间中断,因此会在TimerDriverRegisterHandler 中调用mTimerNotifyFunction 来通知其他函数已经产生中断了
TimerDriverGetTimerPeriod (
IN EFI_TIMER_ARCH_PROTOCOL *This,
OUT UINT64 *TimerPeriod
)
{
if (TimerPeriod == NULL) {
return EFI_INVALID_PARAMETER;
}
*TimerPeriod = mTimerPeriod;
return EFI_SUCCESS;
}
TimerDriverGetTimerPeriod 仅仅返回中断的周期mTimerPeriod,这个mTimerPeriod 我们是在TimerDriverSetTimerPeriod 中设定的
TimerDriverGenerateSoftInterrupt (
IN EFI_TIMER_ARCH_PROTOCOL *This
)
{
return EFI_UNSUPPORTED;
}
TimerDriverGenerateSoftInterrupt 是空函数,说明不支持软件中断.
0 0
- gTimer protocol的实现
- protocol-“委托”的实现
- @protocol 的实现的细节
- iOS之Protocol的实现
- GTK Gossip: GTimer
- GTimer只是个计时器
- 一个基于protocol buffer的RPC实现
- protocol buffer 测试类的实现
- Google protocol buffer(4)—Google protocol buffer + socket实现message的连续传输
- iphone的跨类实现接口的特殊方式---protocol
- redis client protocol 实现
- NodeJs实现可续传的上传协议(tus resumable upload protocol)
- Extensible Messaging and Presence Protocol (XMPP) 的实现
- Extensible Messaging and Presence Protocol (XMPP) 的实现
- Swift中protocol的三种实现以及mutating关键词
- glib中的GList ,GSList,GString,GTree,GTimer
- 手机端实现Protocol Buffer
- OC-Protocol实现业务代理
- Intelli Idea全局替换
- JavaScript-说说为啥循环闭包只显示最后一个i的值
- 自定义视频播放器——VideoView和其他控件的组合
- ajax的data
- opencv实现车牌识别之车牌号定位_1
- gTimer protocol的实现
- servlet的自动加载+init方法+线程并发安全
- C++模板
- python格式化字符串和转义字符
- GraphLab Create API(中文文档)-deeplearning
- NAT与NAPT网络地址转换
- autofac 初识体会
- Tree (16) -- Validate Binary Search Tree
- Web 通信 之 长连接、长轮询(long polling)