我试图弄清楚suspend/wakeup是如何为mach-omap2实现的,特别是在针对tiomap530/dm3730的linux 2.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;
}

我真的很难理解它是如何工作的。
似乎,当suspend过程在omap_sram_idle();之后运行时,系统已经处于suspend模式,并且在该函数的上下文中,所有内容都冻结在那里。当它醒来时,它只是从restore:继续并恢复所有内容。这是对的吗?

最佳答案

系统挂起发生在omap_sram_idle()的中间。omap_sram_idle()的第二部分实际上是恢复代码。更准确地说,实际的睡眠是通过汇编函数中的arm指令来完成的。详情请进一步阅读。
挂起路径
看看omap_sram_idle()函数实现
您可以看到(从注释判断)系统进入睡眠状态之前的最后一行是wfi调用(here
omap34xx_cpu_suspend()指向omap34xx_cpu_suspend()汇编程序函数,该函数先前复制到SRAM(因此在ram断电期间不会丢失);请看下一行代码:
_omap_sram_idle() assignment(注意传递给它的第一个参数是_omap_sram_idle()函数地址)
omap_sram_push()实现;注意memcpy() call_omap_sram_idle()是sram存储器的起始地址,omap34xx_cpu_suspendomap_sram_ceil的地址
omap34xx_cpu_suspend()实现;它是在this line执行的实际函数(而不是start)。查看此函数上方的注释:

/*
 * Forces OMAP into idle state
 *
 * omap34xx_suspend() - This bit of code just executes the WFI
 * for normal idles.
 *
 * Note: This code get's copied to internal SRAM at boot. When the OMAP
 *       wakes up it continues execution at the point it went to sleep.
 */

实际休眠发生在wfi(等待中断)arm指令中(在omap34xx_cpu_suspend() function函数中);处理器将休眠,只有在发生某些irq时才会唤醒
当可以执行_omap_sram_idle()时,omap34xx_cpu_suspend()中有两个位置:
如果不需要上下文保存:here
如果需要保存上下文:here
还原路径
一旦某个唤醒信号发生,CPU将在指令之后继续执行指令(首先使它进入睡眠状态)。因此,您的系统在汇编函数中唤醒(从omap34xx_cpu_suspend()label开始),然后返回wfi(返回this行),然后返回wfi,返回omap34xx_cpu_suspend()label。

08-27 00:35