且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

PowerManager & Wake-up Function of USB Client

更新时间:2022-08-13 18:42:17

今天下午只是大概了解了一下,流程中的一些地方看不到代码, 所以这些看不到代码的地方只能猜想WINCE的行为了.

首先是注意到bul_usbfn.cpp里的BulUsbDevice::SetPowerState函数. 这是由UfnPdd_IOControl调用的, 这和WINCE HELP里的要求一致. 而根据WINCE HELP, 设备应该有D0~D4五种电源状态,而实际上PXA27X的USB只有POWER ON和POWER OFF两种状态, 所以该函数的开头作了一下几种状态的判断转换.  

接下来驱动里调用了一个API: SetDevicePowerState,   这个API的具体代码看不到.文档上说This function requests that the bus driver set this device to the power state specified by PowerState. 但比较纳闷的是这函数不应该从硬件上操作模块的寄存器啊,因为这是下一步做的.

然后就调用BulUsbDevice::PowerMgr(FLASE)进行硬件操作, 把UDE关掉.值得注意的是在USB初始化和关闭函数中,UDE的开启关闭和USB CLOCK的开启关闭都是同时的,但是这里的USB的CLOCK并没有关闭. 我个人猜测这应该就是为了后面把USB的SYSINTR发给系统WAKE-UP用的. 也就是说UDE关掉,CLOCK开启, 那么模块的IRQ还是能进来并转换为SYSINTR的.

下面几行就是针对D0~D4进行操作, 其中D1,D2状态已经合并到D0状态.其中注意各状态和IOCTL_HAL_DISABLE_WAKE, IOCTL_HAL_ENABLE_WAKE的对应关系. 而这两个IOCTL操作, 是在oal_ioctl_tab.h里和OAL函数相对应成一个TABLE. 我们只看与电源管理相关的三个:

{ IOCTL_HAL_DISABLE_WAKE,                   0,  OALIoCtlHalDisableWake      },
{ IOCTL_HAL_ENABLE_WAKE,                    0,  OALIoCtlHalEnableWake       },
{ IOCTL_HAL_GET_WAKE_SOURCE,          0,  OALIoCtlHalGetWakeSource    },

所对应的三个函数在platformname\src\common\power\pxa27x\ioctl.c里面可以看到.这个是由OEM完成的. 也就是说, 驱动里调了KernelIoControl, KernelIoControl里又调了OALIoCtlHalxxxxxxx. 而KernelIoControl里面的操作是不可见的.

好象扯远了,回头看BulUsbDevice::SetwerState函数, 调用KernelIoControl(IOCTL_HAL_ENABLE_WAKE, &m_dwSysIntr,  sizeof(m_dwSysIntr), NULL, 0, NULL) 就是让USB的系统中断号SYSINTR能够把系统从SLEEP状态里WAKE-UP起来. 而具体这步操作, 在PM的OALIoCtlHalEnableWake函数里实现, 修改了PXA27X Clock & Power Manager里面的寄存器, 在硬件上ENABLE指定模块的唤醒功能.

再下面是要求开电源时, 操作硬件开启UDE的代码.

那么总结一下流程,假设现在USB CLIENT的电源状态为D0,全开, 而这时系统要进入SLEEP状态, 这时候系统就根据注册表中的值来决定把USB CLIENT切换到D3状态. 通过IOCTL函数告知USB CLIENT DRIVER, 一路走到SetPowerState. 这时候D3<D0, 所以把UDE关闭, 但保持USB CLIENT CLOCK开启. 接着通过KernelIoControl去和那个IOCTL映射表去修改power manager register,使能USB CLIENT的唤醒功能.

系统进入SLEEP状态并且USB CLIENT WAKE-UP ENABLE后,如果来了个USB CLIENT的中断,那么我个人猜想该IRQ转换成SYSINTR后应该不是去走USB驱动里的IST了,而是通知系统WAKE-UP.系统被唤醒后,反过来改变USB CLIENT的POWER STATE为D0, 从而禁能USB CLIENT的WAKE-UP功能, 同时开启UDE. 然后是个人猜测UDE被开启后才使得该IRQ进到驱动的IST中处理 . 系统完全运行起来.

这篇文章是为了记录下午的思路, 很多地方没有看到代码或没有严格论证,想当然地推倒, 是很不严谨的.


本文转自Walzer博客园博客,原文链接:http://www.cnblogs.com/walzer/archive/2006/02/05/325594.html,如需转载请自行联系原作者