zoukankan      html  css  js  c++  java
  • 1.Linux电源管理-休眠与唤醒

    1.休眠方式

     在内核中,休眠方式有很多种,可以通过下面命令查看

    常用的休眠方式有freeze,standby, mem, disk

    • freeze:   冻结I/O设备,将它们置于低功耗状态,使处理器进入空闲状态,唤醒最快,耗电比其它standby, mem, disk方式高
    • standby:除了冻结I/O设备外,还会暂停系统,唤醒较快,耗电比其它 mem, disk方式高
    • mem:      将运行状态数据存到内存,并关闭外设,进入等待模式,唤醒较慢,耗电比disk方式高
    • disk:       将运行状态数据存到硬盘,然后关机,唤醒最慢

    示例:

    2.唤醒方式

    当我们休眠时,如果想唤醒,则需要添加中断唤醒源,使得在休眠时,这些中断是设为开启的,当有中断来,则会退出唤醒,常见的中断源有按键,USB等.

    3.以按键驱动为例(基于内核3.10.14)

    在内核中,有个input按键子系统"gpio-keys"(位于driver/input/keyboard/gpio.keys.c),该平台驱动platform_driver已经在内核中写好了(后面会简单分析)

    我们只需要在内核启动时,注册"gpio-keys"平台设备platform_device,即可实现一个按键驱动.

    方式1-修改对应板卡的defconfig文件,添加宏:

    方式2-进入make menuconfig

    3.2修改好后,接下来写my_button.c文件,来注册platform_device

    上面的arch_initcall()表示:

    会将button_base_init函数放在内核链接脚本.initcall3.init段中,然后在内核启动时,会去读链接脚本,然后找到button_base_init()函数,并执行它.

    通常,在内核中,platform 设备的初始化(注册)用arch_initcall()调用

    而驱动的注册则用module_init()调用,因为module_init()在arch_initcall()之后才调用

    因为在init.h中定义:

    3.3然后将my_button.c文件添加到Makefile中

    编译内核后,便实现一个简单的按键唤醒休眠了.

    接下来开始分析platform_driver(位于driver/input/keyboard/gpio.keys.c),看看是如何注册按键和实现唤醒的.

    4.1该文件里有常用的函数有

    设置按键和input_dev,注册input-key子系统

    设置GPIO,设置input结构体支持的按键值,设置中断,设置防抖动机制

    按键中断函数,如果是中断源,则通过pm_stay_awake()通知pm子系统唤醒,英文电影推荐如果有防抖动,则延时并退出,否则通过schedule_work()来调用gpio_keys_gpio_work_func()一次

    定时器超时处理函数,用来实现防抖动,里面会通过schedule_work()来调用一次gpio_keys_gpio_work_func();

    处理gpio事件函数,用来上报input事件,并判断按键中断源,如果是的话,则调用pm_relax(),通知pm子系统唤醒工作结束

    通知pm(power manager), 唤醒休眠

    休眠函数,休眠之前会被调用

    唤醒函数,唤醒之前被调用

    SIMPLE_DEV_PM_OPS宏位于pm.h,它将会定义一个dev_pm_ops结构体,用来被pm子系统调用,实现休眠唤醒

    <span "="" src="https://images2018.cnblogs.com/blog/1182576/201809/1182576-20180911183215927-1124377797.png">

    gpio_keys_probe()函数定义如下所示:

    dev->power.should_wakeup来做不同的操作

    4.4 其中gpio_keys_suspend()休眠函数定义如下所示:

    从上面函数可以看到,进入休眠之前,我们需要调用enable_irq_wake()来设置唤醒源

    4.5 然后在中断函数中,判断是否需要上报唤醒事件,中断函数如下所示:

    其中gpio_keys_gpio_work_func()函数如下所示:

    从上面两个函数可以看到,唤醒休眠时,需要使用两个函数实现:

    在中断前调用pm_stay_awake(),中断结束时再调用一次pm_relax()函数.

    4.6 如果想延时唤醒,也可以使用另一种唤醒休眠,则只需要一个函数实现:

    4.7 接下来来看gpio_keys_setup_key(),如何设置按键的(只加了重要的部分)

    通过gpio.keys.c,得出唤醒流程:

    休眠时:

    唤醒后:

    中断时,有两种唤醒PM模式

    模式1-使用两个函数实现:

    • 进入中断时调用一次pm_stay_awake().
    • 退出时也调用一次pm_relax(bdata->input->dev.parent);

    模式2-只需一个函数实现:

    • 进入中断时调用pm_wakeup_event(struct device *dev, unsigned int msec).

    5.接下来,我们自己写个按键字符驱动,实现休眠唤醒

    应用测试代码如下:

     试验:


    文章来源:https://www.cnblogs.com/lifexy/p/9629699.html

  • 相关阅读:
    JSTL和EL
    JSP
    Servlet基础知识
    JSON基础知识
    jQuery基础知识
    ajax基础知识
    索引实战
    反射
    设计模式
    JVM的异常处理
  • 原文地址:https://www.cnblogs.com/xiongjim/p/9673905.html
Copyright © 2011-2022 走看看