critical section 中断唤醒系统流程(3)

电脑杂谈  发布时间:2018-02-14 08:19:31  来源:网络整理

ret = set_irq_wake_real(irq, on);

if (ret)

desc->wake_depth = 0;

else

irqd_set(&desc->irq_data, IRQD_WAKEUP_STATE);

}

} else {

if (desc->wake_depth == 0) {

WARN(1, "Unbalanced IRQ %d wake disable\n", irq);

} else if (--desc->wake_depth == 0) {

ret = set_irq_wake_real(irq, on);

if (ret)

desc->wake_depth = 1;

else

irqd_clear(&desc->irq_data, IRQD_WAKEUP_STATE);

}

}

irq_put_desc_busunlock(desc, flags);

return ret;

}

1) 首先在set_irq_wake_real函数中通过irq_chip的irq_set_wake回调函数设置SoC相关wakeup寄存器使能中断唤醒功能,如果不使能的话,即使设备在那疯狂的产生中断signal,SoC可不会理睬你哦!

2) 设置irq的state为IRQD_WAKEUP_STATE,这步很重要,suspend流程会用到的。

2.2. Suspend to RAM流程

先画个图示意一下系统Suspend to RAM流程。我们可以看到图片画的很漂亮。从enter_state开始到suspend_ops->enter()结束。对于suspend_ops->enter()调用,我的理解是CPU停在这里了,待到醒来的时候,就从这里开始继续前行的脚步。

1) enable_irq_wake()可以有两种途径,一是在driver的suspend函数中由驱动开发者主动调用;二是在driver的probe函数中调用dev_pm_set_wake_irq()和device_init_wakeup()。因为suspend的过程中会通过dev_pm_arm_wake_irq()打开所有wakeup source的irq wake功能。我更推荐途径1,因为系统已经帮我们做了,何必重复造轮子呢!

2) 对于已经enable 并且使能wakeup的irq,置位IRQD_WAKEUP_ARMED,然后等待IRQ handler和threaded handler执行完成。后续详细分析这一块。

3) 针对仅仅enable的irq,设置IRQS_SUSPENDED标志位,并disable irq。

4) 图中第④步关闭noboot cpu,紧接着第⑤步diasble boot cpu的irq,即cpu不在响应中断。

5) 在cpu sleep之前进行最后一步操作就是syscore suspend。既然是最后suspend,那一定是其他device都依赖的系统核心驱动。后面说说什么的设备会注册syscore suspend。

2.3. resume流程

假设我们使用的是gic-v3代码,边沿触发中断设备。现在设备需要唤醒系统了,产生一个边沿电平触发中断。此时会唤醒boot cpu(因为noboot cpu在suspend的时候已经被disable)。你以为此时就开始跳转中断服务函数了吗?no!还记得上一节说的吗?suspend之后已经diasble boot cpu的irq,因此中断不会立即执行。什么时候呢?当然是等到local_irq_enable()之后。resume流程如下图。


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-77051-3.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...