使用内核线程驱动SR501模块

除了使用中断方式读取SR501的信号以外,还有一种方式是使用内核线程,循环查询引脚的状态。

使用内核线程的框架和使用中断的框架类似,就是把中断的部分用内核线程替换掉。

(1)probe函数中,去掉中断注册代码,加入内核线程注册代码

static int sr501_probe(struct platform_device *pdev)
{
	int err;
	struct device_node *node = pdev->dev.of_node;
	int count;
	int i;
	//
	sr501_gpio=gpiod_get(&pdev->dev,NULL,0);
	if(IS_ERR(sr501_gpio))
	{
		dev_err(&pdev->dev,"Fail to get GPIO for sr501\n");
		return PTR_ERR(sr501_gpio);
	}
	gpiod_direction_input(sr501_gpio);
-irq=gpiod_to_irq(sr501_gpio);
-request_irq(irq,sr501_irq,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,"sr501_irq",NULL);
+sr501_thread=kthread_run(sr501_detect,NULL,"sr501_thread");
+if (IS_ERR(sr501_thread)) 
+{
	+return PTR_ERR(sr501_thread);
+}
	/* 注册file_operations 	*/
	major = register_chrdev(0, "sr501_chr", &sr501_drv); 
	sr501_class = class_create(THIS_MODULE, "100ask_sr501_class");
	if (IS_ERR(sr501_class)) {
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
		unregister_chrdev(major, "100ask_sr501");
		gpiod_put(sr501_gpio);
		return PTR_ERR(sr501_class);
	}
	device_create(sr501_class, NULL, MKDEV(major, 0), NULL, "sr501");
	printk("%s %s line %d,major:%d\n", __FILE__, __FUNCTION__, __LINE__,major);
	return 0;
}

(2)remove函数中,去掉注销中断代码,加入停止内核线程代码

static int sr501_remove(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node;
	int i;
	device_destroy(sr501_class, MKDEV(major, 0));
	class_destroy(sr501_class);
	unregister_chrdev(major, "sr501_chr");
	-free_irq(irq,&(pdev->dev));
    +kthread_stop(sr501_thread);
	gpiod_put(sr501_gpio);
	
	return 0;
}

(3)编写内核线程函数

static int sr501_detect(void *arg)
{
	int val;
	int pre=-1;
	while(1)
	{
		val=gpiod_get_value(sr501_gpio);
		if(val!=pre)
		{
			sr501_flag=0x80|val;
			printk("%s %s line %d,val=%x\n", __FILE__, __FUNCTION__, __LINE__,sr501_flag);
			wake_up(&sr501_wait);
			pre=val;
		}
		//必须要有这一句,否则不可休眠
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(HZ/5);
		//没有这一句会导致不能退出线程。
		if(kthread_should_stop())
		{
			set_current_state(TASK_RUNNING);
			break;
		}
	}
	return 0; 
}

需要特别注意的有两点:

(1)使用schedule_timeout让线程进入休眠之前,一定要使用                             set_current_state(TASK_INTERRUPTIBLE);函数配置线程状态,否则线程无法进入休眠。

(2)线程中一定要使用如下代码,通过程序跳出线程函数的方法来停止内核线程。

        if(kthread_should_stop())
        {
            set_current_state(TASK_RUNNING);
            break;
        }

因为kthread_stop(sr501_thread);只是配置了线程的状态位,并没有真正的停止线程。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式螺丝钉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值