我试图弄清楚mach-omap2是如何实现挂起/唤醒的,特别是在针对TI out 3530/‘m 3730的Linux2.6.37中。
下面是一些相关代码:
http://lxr.free-electrons.com/source/arch/arm/mach-omap2/pm34xx.c?v=2.6.37
static int omap3_pm_suspend(void)
{
struct power_state *pwrst;
int state, ret = 0;
if (wakeup_timer_seconds || wakeup_timer_milliseconds)
omap2_pm_wakeup_on_timer(wakeup_timer_seconds,
wakeup_timer_milliseconds);
/* Read current next_pwrsts */
list_for_each_entry(pwrst, &pwrst_list, node)
pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
/* Set ones wanted by suspend */
list_for_each_entry(pwrst, &pwrst_list, node) {
if (omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
goto restore;
if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm))
goto restore;
}
omap_uart_prepare_suspend();
omap3_intc_suspend();
omap_sram_idle();
restore:
/* Restore next_pwrsts */
list_for_each_entry(pwrst, &pwrst_list, node) {
state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
if (state > pwrst->next_state) {
printk(KERN_INFO "Powerdomain (%s) didn't enter "
"target state %d\n",
pwrst->pwrdm->name, pwrst->next_state);
ret = -1;
}
omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
}
if (ret)
printk(KERN_ERR "Could not enter target state in pm_suspend\n");
else
printk(KERN_INFO "Successfully put all powerdomains "
"to target state\n");
return ret;
}我真的很难理解它是怎么工作的。
看起来,当挂起过程在omap_sram_idle();之后运行时,系统已经处于挂起模式,在这个函数的上下文中,所有东西都会冻结在那里。当它醒来时,它只是继续从restore:中恢复一切。这是正确的吗?
发布于 2015-05-20 21:28:52
系统挂起发生在的中间 of omap_sram_idle()。omap_sram_idle()的第二部分实际上是还原代码。更准确地说,实际睡眠是通过wfi ARM指令在omap34xx_cpu_suspend()汇编程序函数中完成的。详情请进一步阅读。
挂起路径
_omap_sram_idle()调用(这里)。_omap_sram_idle()指向以前复制到SRAM的暂停()汇编程序函数(因此它不会在关闭内存时丢失);请看下面的代码行:1. [\_omap\_sram\_idle() assignment](http://lxr.linux.no/#linux+v2.6.37/arch/arm/mach-omap2/pm34xx.c#L998) (notice that first parameter that is passed to it is `omap34xx_cpu_suspend` function address)
2. [omap\_sram\_push()](http://lxr.linux.no/#linux+v2.6.37/arch/arm/plat-omap/sram.c#L247) implementation; pay attention to [memcpy() call](http://lxr.linux.no/#linux+v2.6.37/arch/arm/plat-omap/sram.c#L256): `omap_sram_ceil` is start address of SRAM memory, `start` is address of `omap34xx_cpu_suspend() function`
3. [omap34xx\_cpu\_suspend()](http://lxr.linux.no/#linux+v2.6.37/arch/arm/mach-omap2/sleep34xx.S#L187) implementation; it's the actual function being executed at [this line](http://lxr.linux.no/#linux+v2.6.37/arch/arm/mach-omap2/pm34xx.c#L446) (instead of `_omap_sram_idle()`). Take a look at comment above this function:/* *强制OMAP进入空闲状态** omap34xx_suspend() -这段代码只对普通的idles执行WFI *。**注意:此代码在启动时被复制到内部SRAM中。当OMAP *醒来的时候,它会在睡觉的时候继续执行。*/
omap34xx_cpu_suspend()函数中);处理器将休眠,只有当某些IRQ发生时它才会醒来。omap34xx_cpu_suspend()中有两个地方可以执行wfi:
恢复路径
一旦出现了一些唤醒信号,CPU将在wfi指令之后继续执行指令(这首先使它进入睡眠状态)。因此,您的系统在omap34xx_cpu_suspend()汇编程序函数(从wait_sdrk_ok:标签开始)中醒来,然后返回到omap_sram_idle() (到这行),然后返回到omap3_pm_suspend(),返回到restore:标签。
https://stackoverflow.com/questions/30337804
复制相似问题