设为首页 加入收藏

TOP

1.Linux电源管理-休眠与唤醒(四)
2019-09-01 23:09:39 】 浏览:132
Tags:1.Linux 电源 管理 休眠 唤醒
if (bdata->button->wakeup) pm_stay_awake(bdata->input->dev.parent); //如果是唤醒源,则通知pm子系统,处理唤醒事件,并等待结束 if (bdata->timer_debounce) mod_timer(&bdata->timer,jiffies + msecs_to_jiffies(bdata->timer_debounce));//如果设置防抖动,则启动定时器并退出 else schedule_work(&bdata->work); //否则调用bdata->work对应的函数gpio_keys_gpio_work_func() return IRQ_HANDLED; }

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

static void gpio_keys_gpio_work_func(struct work_struct *work)
{
         struct gpio_button_data *bdata= container_of(work, struct gpio_button_data, work);  

         gpio_keys_gpio_report_event(bdata); //上传input按键事件
        
     if (bdata->button->wakeup)       pm_relax(bdata->input->dev.parent); //如果是唤醒源,则通知pm子系统,唤醒中断处理结束。 }

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

pm_stay_awake();                   //在中断入口调用,告知启动唤醒
pm_relax();                        //在中断出口调用,告知结束唤醒

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

 

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

pm_wakeup_event(struct device *dev, unsigned int msec);

         //通知pm子系统在msec后处理唤醒事件, msec=0,则表示立即唤醒

 

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

static int gpio_keys_setup_key(struct platform_device *pdev,
                                   struct input_dev *input,
                                   struct gpio_button_data *bdata,
                                   const struct gpio_keys_button *button)
{
         const char *desc = button->desc ? button->desc : "gpio_keys"; //获取平台设备设置的名字
         //… …
         error = gpio_request_one(button->gpio, GPIOF_IN, desc);//申请button->gpio引脚,并将引脚设为输入引脚,名字设置为desc

         if (button->debounce_interval)    
         {
        bdata->timer_debounce =button->debounce_interval;      //设置防抖动时间 
      }  
      irq = gpio_to_irq(button->gpio);                     //获取管脚对应的中断号  
      if (irq < 0) 
      {  
//… …      goto fail;         }      bdata->irq = irq;   INIT_WORK(&bdata->work, gpio_keys_gpio_work_func);     //初始化bdata->work,使bdata->work与gpio_keys_gpio_work_func()函数关联起来     //后面当调用schedule_work(&bdata->work)时,便会执行gpio_keys_gpio_work_func()函数        setup_timer(&bdata->timer, gpio_keys_gpio_timer, (unsigned long)bdata);   //设置gpio_keys_gpio_timer()定时器超时函数,用来实现防抖动,函数参数为bdata   irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;   //中断标志位   isr = gpio_keys_gpio_isr;   input_set_capability(input, button->type ?: EV_KEY, button->code); //使input 支持EV_KEY键盘事件,并使键盘事件支持button->code按键值 error = request_any_context_irq(bdata->irq, isr, irqflags, desc, bdata);   //通过request_any_context_irq()函数注册按键中断:         //中断号为bdata->irq,中断名叫: button.desc("power key")         //中断标志位为(IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)         //中断服务函数为gpio_keys_gpio_isr(),设置中断函数参数dev_id为bdata return 0;    }

 

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

休眠时:

enable_irq_wake (bdata->irq);             
//将要睡眠的中断号屏蔽掉,实现休眠时保持中断唤醒

唤醒后:

disable_irq_wake(bdata->irq);      //关闭唤醒 

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

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

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

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

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

 

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

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h
首页 上一页 1 2 3 4 5 6 下一页 尾页 4/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Linux分页机制之分页机制的实现详.. 下一篇Linux内存描述之概述--Linux内存..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目