等待队列和内核线程 在触摸屏代码中的应用

相关的头文件




#include "tpd.h"

#include <linux/interrupt.h>
#include <cust_eint.h>
#include <linux/i2c.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/rtpm_prio.h>
#include <linux/wait.h>
#include <linux/time.h>
#include <linux/delay.h>


#include "tpd_custom_ft5206.h"




#include "cust_gpio_usage.h"


 
 
extern struct tpd_device *tpd;
 
struct i2c_client *i2c_client = NULL;
struct task_struct *thread = NULL;
 

static DECLARE_WAIT_QUEUE_HEAD(waiter);  //定义等待队列头



 
static int touch_event_handler(void *unused)
 {
  
    struct touch_info cinfo, pinfo;

	 struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };
	 sched_setscheduler(current, SCHED_RR, ¶m);
 
	 do
	 {
	  mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); 
		 set_current_state(TASK_INTERRUPTIBLE); //设置当前进程状态为 可中断睡眠
		  wait_event_interruptible(waiter,tpd_flag!=0);// 把进程加入到waiter的等待队列上面睡觉去,然后等待tpd_flag=1 发生
						 
			 tpd_flag = 0;//如果发生 重置tpd_flag

			 
		 set_current_state(TASK_RUNNING);//让进程进去运行态
		 

		  if (tpd_touchinfo(&cinfo, &pinfo)) {
		  TPD_DEBUG("point_num = %d\n",point_num);
		  
            if(point_num >0) {
                tpd_down(cinfo.x[0], cinfo.y[0], 1);
             if(point_num>1)
             	{
			 	tpd_down(cinfo.x[1], cinfo.y[1], 1);
			   if(point_num >2) tpd_down(cinfo.x[2], cinfo.y[2], 1);
             	}
                input_sync(tpd->dev);
				TPD_DEBUG("press --->\n");
				
            } else  {
            TPD_DEBUG("release --->\n"); 
                input_mt_sync(tpd->dev);
                input_sync(tpd->dev);
            }
        }

 }while(!kthread_should_stop());
 
	 return 0;
 }

static void tpd_eint_interrupt_handler(void)// 中断处理函数
 {
	 TPD_DEBUG("TPD interrupt has been triggered\n");
	 tpd_flag = 1;//设置上面内核线程等待条件
	 wake_up_interruptible(&waiter);//唤醒在waiter上面睡觉的进程,
	 
 }
 static int __devinit tpd_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {	 
	int retval = TPD_OK;
	char data;
	i2c_client = client;

	#ifdef TPD_CLOSE_POWER_IN_SLEEP	 
	hwPowerDown(TPD_POWER_SOURCE,"TP");
	hwPowerOn(TPD_POWER_SOURCE,VOL_3300,"TP");
	msleep(100);
	#else
	mt_set_gpio_mode(GPIO_CTP_EN_PIN, GPIO_CTP_EN_PIN_M_GPIO);
    mt_set_gpio_dir(GPIO_CTP_EN_PIN, GPIO_DIR_OUT);
	mt_set_gpio_out(GPIO_CTP_EN_PIN, GPIO_OUT_ONE);
	msleep(100);
	mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);
    mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);
    mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);
	#endif

	mt_set_gpio_mode(GPIO_CTP_EINT_PIN, GPIO_CTP_EINT_PIN_M_EINT);
    mt_set_gpio_dir(GPIO_CTP_EINT_PIN, GPIO_DIR_IN);
    mt_set_gpio_pull_enable(GPIO_CTP_EINT_PIN, GPIO_PULL_ENABLE);
    mt_set_gpio_pull_select(GPIO_CTP_EINT_PIN, GPIO_PULL_UP);
 
	  mt65xx_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_SENSITIVE);
	  mt65xx_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);
	  mt65xx_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_EN, CUST_EINT_TOUCH_PANEL_POLARITY, tpd_eint_interrupt_handler, 1); // 注册中断号 中断处理程序
	  mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);
 

从下面的注释我们可以看出,
wait_event_interruptible_timeout(wq, condition, timeout)
检查条件是在执行了
wake_up() 或者变体函数看下面的函数,一旦中断发生,这个中断处理函数就要执行,唤醒等待队列中上的进程,然后才会执行这个函数
wait_event_interruptible(waiter,tpd_flag!=0);,所以有些朋友说,发生中断了,怎么我的进程没有唤醒呢? 答案就是你没执行wake_up()这个操作。


 static void tpd_eint_interrupt_handler(void)
{
	TPD_DEBUG("TPD interrupt has been triggered\n");
	tpd_flag = 1;
	wake_up_interruptible(&waiter);
}

 
/**
 * wait_event_interruptible_timeout - sleep until a condition gets true or a timeout elapses
 * @wq: the waitqueue to wait on
 * @condition: a C expression for the event to wait for
 * @timeout: timeout, in jiffies
 *
 * The process is put to sleep (TASK_INTERRUPTIBLE) until the
 * @condition evaluates to true or a signal is received.
 * The @condition is checked each time the waitqueue @wq is woken up.
 *
 * wake_up() has to be called after changing any variable that could
 * change the result of the wait condition.
 *
 * The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it
 * was interrupted by a signal, and the remaining jiffies otherwise
 * if the condition evaluated to true before the timeout elapsed.
 */
#define wait_event_interruptible_timeout(wq, condition, timeout)	\
({									\
	long __ret = timeout;						\
	if (!(condition))						\
		__wait_event_interruptible_timeout(wq, condition, __ret); \
	__ret;								\
})

#define __wait_event_interruptible_exclusive(wq, condition, ret)	\
do {									\
	DEFINE_WAIT(__wait);						\
									\
	for (;;) {							\
		prepare_to_wait_exclusive(&wq, &__wait,			\
					TASK_INTERRUPTIBLE);		\
		if (condition) {					\
			finish_wait(&wq, &__wait);			\
			break;						\
		}							\
		if (!signal_pending(current)) {				\
			schedule();					\
			continue;					\
		}							\
		ret = -ERESTARTSYS;					\
		abort_exclusive_wait(&wq, &__wait, 			\
				TASK_INTERRUPTIBLE, NULL);		\
		break;							\
	}								\
} while (0)

原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124206.html