注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
jiereliyi的个人空间 https://home.eeworld.com.cn/space-uid-53209.html [收藏] [复制] [分享] [RSS]
日志

PowerButton驱动分析

已有 1467 次阅读2010-7-28 18:36

PowerButton驱动分析

DWORD

PBT_Init(DWORD dwContext)

{

DWORD IDPowerButtonThread;

DWORD IDResetButtonThread;

HMODULE hmCore;

//

// Obtain a pointer to the power manager function "SetSystemPowerState"

// from the core library so we can call into it.

//

pfnSetSystemPowerState = NULL;

hmCore = (HMODULE) LoadLibrary(_T("coredll.dll"));

if(hmCore != NULL)

{

pfnSetSystemPowerState = (PFN_SetSystemPowerState) GetProcAddress(hmCore, _T("SetSystemPowerState"));

if(pfnSetSystemPowerState == NULL)

{

FreeLibrary(hmCore);

}

}

// Initialize addresses now as opposed to when interrupts are handled so there are no race conditions

InitializeAddresses();//初始化硬件地址

// Create a thread to handle the power button event, and one to handle the reset button event.

ResetButtonIntrThreadHandle = CreateThread( //返回线程句柄

0,//必须为0

0, //忽略,线程堆栈大小由连接器设置决定

(LPTHREAD_START_ROUTINE)ResetButtonIntrThread,//指定线程函数名

0,

0,

&IDResetButtonThread //使用IDResetButtonThread接收线程标志符

DWORD IDPowerButtonThread;

);

if (ResetButtonIntrThreadHandle == 0)

{

RETAILMSG(1, (TEXT("PBT: CreateThread() Fail\r\n")));

}

PowerButtonIntrThreadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) PowerButtonIntrThread, 0, 0, &IDPowerButtonThread);

if (PowerButtonIntrThreadHandle == 0)

{

RETAILMSG(1, (TEXT("PBT: CreateThread() Fail\r\n")));

}

return (dwContext);

}

static BOOL

InitializeAddresses(VOID)

{

BOOL RetValue = FALSE;

// IO Register Allocation

v_pIOPregs = (volatile S3C2410X_IOPORT_REG *)VirtualAlloc(

0, //分配内存的开始地址由系统指定

sizeof *v_pIOPregs,//分配内存大小

MEM_RESERVE,// 保留虚拟地址空间以便以后提交。

PAGE_NOACCESS//任何访问该区域的操作将被拒绝

);

if (v_pIOPregs == NULL)

{

ERRORMSG(1,(TEXT("PBT: VirtualAlloc failed!\r\n")));

} else {

if (

!VirtualCopy(//绑定一块物理内存到当前进程虚拟地址空间

(PVOID)v_pIOPregs, //指针,指向虚拟地址的起始地址

(PVOID)(S3C2410X_BASE_REG_PA_IOPORT >> 8), //物理地址右移8位。

sizeof *v_pIOPregs, //保留空间的大小

PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)//物理地址,可读可写,无缓存。

)

{

ERRORMSG(1,(TEXT("PBT: VirtualCopy failed!\r\n")));

VirtualFree((PVOID)v_pIOPregs, 0, MEM_RELEASE);

v_pIOPregs = NULL;

}

}

s2410INT = (volatile S3C2410X_INTR_REG *)VirtualAlloc(0, sizeof *s2410INT, MEM_RESERVE, PAGE_NOACCESS);

if (s2410INT == NULL)

{

ERRORMSG(1,(TEXT("PBT: VirtualAlloc failed!\r\n")));

} else {

if (!VirtualCopy((PVOID)s2410INT, (PVOID)(S3C2410X_BASE_REG_PA_INTR >> 8), sizeof *s2410INT, PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))

{

ERRORMSG(1,(TEXT("PBT: VirtualCopy failed!\r\n")));

VirtualFree((PVOID)s2410INT, 0, MEM_RELEASE);

s2410INT = NULL;

}

}

EnableResetButtonInterrupt(VOID)

{

v_pIOPregs->GPFCON &= ~(0x3 << 4);// Set EINT2(GPF2) as EINT2

v_pIOPregs->GPFCON |= (0x2 << 4);

v_pIOPregs->EXTINT0 &= ~(0x7 << 8);// Configure EINT2 as Falling Edge Mode

v_pIOPregs->EXTINT0 |= (0x2 << 8);

}

if(v_pIOPregs && s2410INT)

{

RetValue = TRUE;

}

return (RetValue);

}

static DWORD

ResetButtonIntrThread(PVOID pArg)

{

EnableResetButtonInterrupt();配置寄存器状态

ResetButtonIntrEvent = CreateEvent( //创建事件, 成功返回一个事件对象句柄

NULL,//必须为NULL

FALSE,// 系统在等待线程被释放后自动重置状态为不可触发状态

FALSE,// 初始状态,为不可触发状态

NULL//创建事件对象没有名称

);

//

// Request a SYSINTR value from the OAL.

//

if (

!KernelIoControl( //根据IRQ获取一个SYSINTR

IOCTL_HAL_REQUEST_SYSINTR, //IO控制代码

&ResetButtonIrq, //指向一个缓冲区,其包含执行操作所必须的数据IRQ

static DWORD ResetButtonIrq = IRQ_EINT2; // Determined by SMDK2410 board layout.

sizeof ResetButtonIrq, //缓冲区的大小

&ResetButtonSysIntr, //指向输出缓冲区,用来接收操作数据SYSINTR

Static DWORD ResetButtonSysIntr = SYSINTR_UNDEFINED;

sizeof ResetButtonSysIntr, //定输出缓冲区的大小

NULL

))

{

RETAILMSG(1, (TEXT("PBT: Error! Failed to request sysintr value for reset button interrupt.\r\n")));

return(0);

}

if (!(InterruptInitialize(//关联SYSINTR和之前创建的事件

ResetButtonSysIntr,// 虚拟中断标示符

ResetButtonIntrEvent, //当中断触发时,同时触发ResetButtonIntrEvent事件。

0, //不适用数据块

0 //数据块大小为0

)))

{

RETAILMSG(1, (TEXT("ERROR: ResetButton: Interrupt initialize failed.\r\n")));

}

// Handle power button presses.

for (;;)

{

WaitForSingleObject(//函数检查指定对象的当前状态。如果对象的状态为不可触发的。

//则调用线程进入一个高效率等待状态。在等待事件对象变为可触

//发或间隔时间超时,线程消耗很少的处理时间

ResetButtonIntrEvent, //指向事件的句柄

INFINITE//永不超时

);

//Mask the storage device interrupt EINT11 so we don't service it before reboot is finished

s2410INT->INTMSK = (s2410INT->INTMSK | (0x1 << 0x5));

if (ResetButtonIsPushed()) // Guard against noise triggering an interrupt.

{

//

// Soft reset and standard suspend-resume both start with suspend for now.

// Call whichever shutdown API is available.

//

if(pfnSetSystemPowerState != NULL)

{

RETAILMSG(1,(TEXT("PBT: Signalling power manager to reset...\r\n")));

pfnSetSystemPowerState(NULL, POWER_STATE_RESET, POWER_FORCE);

} else {

RETAILMSG(1,(TEXT("PBT: Resetting by calling KernelIoControl(IOCTL_HAL_REBOOT)...\r\n")));

KernelIoControl(IOCTL_HAL_REBOOT,NULL,0,NULL,0,NULL);

}

//

// Acquiesce to other threads since our work is complete as of

// the call to PowerOffSystem, or the signalling of the power

// manager.

//

Sleep(0);

}

else

RETAILMSG(1,(TEXT("PBT: Feeble button press or noise triggered it (ignored)\r\n")));

InterruptDone(ResetButtonSysIntr);//该函数通知内核中断处理完毕

}

}

总结:

中断驱动书写过程。

1. 设置物理地址到虚拟地址映射。因为wince启动后是对虚拟地址操作。InitializeAddresses

2. 创建一个线程。指定线程函数。获得线程句柄CreateThread

3. 配置GPIO口和中断寄存器状态。EnableResetButtonInterrupt

4. 创建一个事件。并初始化该事件为不可触发状态,自动触发。获得事件句柄CreateEvent

5. 根据IRQ获取一个SYSINTR KernelIoControl

6. 初始化,关联SYSINTR和之前创建的事件InterruptInitialize

7. 等待事件触发WaitForSingleObject

8. 处理中断进程

9. 通知内核中断处理完毕InterruptDone

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章