睡眠过程:
1.调用SetSystemPowerState进入睡眠状态.
2.电源管理驱动里设置设备的电源状态;
3.调用PowerOffSystem()进入内核处理;
4.调用各设备驱动的PowerDown();
5.调用OEMPowerOff():
(1).保存芯片所有的寄存器值到一个静态数组(就是堆栈中);
(2).先进行平台相关的动作,比如清屏,设置AD,USB等;
(3).设置IO,关闭kitl等;
(4).呼叫OALCPUPowerOff()进行挂起.
OALCPUPowerOff()是一个位于Startup.s中的汇编函数,它按照下面的流程实现挂起功能:
a.保存通用寄存器R4-R12,LR到堆栈;
b. 保存WakeUp后的地址,MMU寄存器,进入各模式将SP和LR寄存器保存到内存RAM的某一个位置,这个位置是由config.bib指定保留的.为什么不象之前一样保存到堆栈呢?因为系统唤醒后跳转到Reset开始执行,这时候堆栈还没有初始化.这也是PowerOff过程复杂的原因;
c.计算刚才保存的数据块的检验和并保存到GSTATUS3寄存器.(GSTATUS3和GSTATUS4是状态寄存器,挂起直到唤醒过程都会保存里面的值);
d.禁止中断;
e.清Cache;
f.使能唤醒中断,能唤醒可以是外部中断0,1,2,或者RTC中断;
g.设置SDRAM进入自刷新模式,最终CPU进入PowerOff状态.
唤醒过程:
CPU的PowerOff模式和其他睡眠模式不同,其他的睡眠模式唤醒后会从睡眠处继续运行,而PowerOff模式唤醒后是从Reset处执行.Reset有3种可能情况:
(1).正常的上电冷启动,包括Reset信号线有效造成的Reset.
(2).看门狗失效造成的Reset.
(3).PowerOff之后被外部中断或者RTC 中断唤醒的Reset.
在Reset之后可以根据GSTATUS2寄存器来判断是否从PowerOff唤醒.还有一个问题,不论何种方式Reset,都是先执行BootLoader的代码,所以唤醒过程需要BootLoader的参与配合.具体流程:
1.外部中断或者RTC中断唤醒CPU进入BootLoader
2.BootLoader中停止SDRAM的自刷新模式,然后跳到内核开始地址.有些BootLoader会做的更多,因为前面我们把数据都保存到了RAM中的某处,事实上只要知道这个RAM地址就可以取得数据进入唤醒过程.所以有些BootLoader会直接去唤醒.我认为这并不好,增加了BootLoader的依赖性,层次间的耦合性也高了.
3.检查CheckSum,因为之前设置SDRAM处于自刷新状态,在PowerOff期间SDRAM里面的数据会保持,增加CheckSum是有必要的安全措施.
4.从RAM取得之前保存的参数,其中包含了唤醒后应该跳转的地址,和MMU的配置数据以及各个模式的SP和LR.
5.启动MMU
6.跳到唤醒后的新地址.
7.进入各个模式恢复SP和LR.
8.恢复R4-R12,LR
9.跳转到LR,即相当于OALCPUPowerOff()返回,返回到OEMPowerOff()中.
10.打开kitl,恢复所有寄存器,恢复平台之前状态.
11.调用各设备驱动的PowerUp();
12.回到电源管理驱动中,更新各设备驱动的电源状态;
13.电源管理驱动发出系统状态变迁的消息通知;
14.恢复正常。
唤醒过程实际是一个挂起的逆过程.如此,系统成功唤醒,所有运行的应用程序不知道自己被系统挂起过而继续运行.
WINCE 睡眠与唤醒
最新推荐文章于 2014-09-04 14:22:21 发布