中断深入-->定时器

本文详细介绍了Linux内核中的定时器工作原理,包括硬件定时器和软件定时器的设置方法,如setup_timer、add_timer、mod_timer和del_timer函数的使用。此外,还讲解了如何通过中断处理函数gpio_key_isr响应GPIO事件,并通过实例展示了如何编写设备驱动程序,包括文件操作函数和注册过程。最后,给出了应用程序示例,演示了如何读取设备节点获取按键信息。
摘要由CSDN通过智能技术生成

在此之前

我们今天描述的定时器是软件上的定时器,当超过设置的时间,就会唤醒响应的功能
然而怎么设置定时器的时间呢?
就有了硬件上的定时器,通过硬件的的时钟来设置我们的定时器

硬件定时器

在源码根目录下有个 .config,里面有各种配置参数
在这里插入图片描述
这里表示频率是100hz, 代表每秒100次,也就是10ms嘀嗒一下

定时器(软件)

所谓定时器,就是闹钟,时间到后你就要做某些事。有 2 个要素:时间、做事,换成程序员的话就是:
超时时间、函数
在内核中使用定时器很简单,涉及这些函数(参考内核源码 include\linux\timer.h):
① setup_timer(timer, fn, data):
设置定时器,主要是初始化 timer_list 结构体,设置其中的函数、参数。
② void add_timer(struct timer_list *timer):
向内核添加定时器。timer->expires 表示超时时间。当超时时间到达,内核就会调用这个函数:timer->function(timer->data)。
③ int mod_timer(struct timer_list *timer, unsigned long expires):
修改定时器的超时时间,它等同于:del_timer(timer); timer->expires = expires; add_timer(timer);
但是更加高效。
④ int del_timer(struct timer_list *timer):
删除定时器

时间单位

时间单位由上面的硬件来决定,在linux里面 有一个全局变量jiffies作为运行时间
所以硬件每嘀嗒一下 ->jiffies就会 +1

修改超时时间

① 在 add_timer 之前,直接修改:
timer.expires = jiffies + xxx; // xxx 表示多少个滴答后超时,也就是 xxx10ms
timer.expires = jiffies + 2
HZ; // HZ 等于 CONFIG_HZ,2HZ 就相当于 2 秒
② 在 add_timer 之后,使用 mod_timer 修改:
mod_timer(&timer, jiffies + xxx); // xxx 表示多少个滴答后超时,也就是 xxx
10ms
mod_timer(&timer, jiffies + 2HZ); // HZ 等于 CONFIG_HZ,2HZ 就相当于 2 秒

代码编写

驱动
#include <linux/module.h>
#include <linux/poll.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>

struct gpio_key{
   
	int gpio;
	struct gpio_desc *gpiod;
	int flag;
	int irq;
	struct timer_list key_timer;
} ;

static struct gpio_key *gpio_keys_100ask;

/* 主设备号                                                                 */
static int major = 0;
static struct class *gpio_key_class;

/* 环形缓冲区 */
#define BUF_LEN 128
static int g_keys[BUF_LEN];
static int r, w;

struct fasync_struct *button_fasync;

#define NEXT_POS(x) ((x+1) % BUF_LEN)

static int is_key_buf_empty(void)
{
   
	return (r == w);
}

static int is_key_buf_full(void)
{
   
	return (r == NEXT_POS(w));
}

static void put_key(int key)
{
   
	if (!is_key_buf_full())
	{
   
		g_keys[w] = key;
		w = NEXT_POS(w);
	}
}

static int get_key(void)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值