一、定时器的一些基本概念
1.1 定时器一般分为两大类:
软件定时器:由操作系统模拟的定时,没有真实存在的时钟源和计数器, 一般对时钟源和计数器硬件有一定的依赖,跨平台性较好。
硬件定时器:由真正存在的时钟源和计数器组成,跟硬件相关,跨平台的性能不好。
1.2 定时器一般由什么组成
一般的定时器都有两部分组成:
计数器和时钟源;
计数器:单纯的计数 如:RTC向上的计数器
时钟源:给计数提供一个节拍,说白了就是决定我们的计数器多久计数一次。比如说时钟源 100HZ
就表示我们的计数器一秒钟计数100次。
二、linux内核定时器
内核的定时器,指的就是Linux下的软件的定时,所有的软件定时器对硬件的定时器是有一定的依赖的,软件定时器也有硬件定时器的特性,软件定时器也有时钟源和计数器。
如果说我们使用linux3.5的内核里,时钟源默认的是 100HZ 每计数一次是10ms,在.config配置内核的编译配置的时候,改成了 200HZ --那么就是每5ms计数一次。
在linux内核里,计数器开始计数是从系统上电就开始的,并且只要我的系统不关闭,计数器就会一直计数,计数器从开机到现在所计的数在linux内核里有一个变量记录,这个变量的值是一直变化的,就类似与日历时间,这个变量就叫做jiffies,它的值是每隔5ms自加一次,假如我现在要定时5s去执行某一个动作,让计数器去计时5s,定时器计时五秒钟后,计数器应该计数的值:jiffies+5*HZ。
三、linux内核定时器相关的API
函数的功能:初始化一个内核的定时器
函数的头文件:
函数的原型:void init_timer(struct timer_list *timer)
函数的参数:struct timer_list *timer:内核定时器的核心的结构体
函数的返回值: 无
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
struct timer_list {
unsigned long expires:计数器要计的数值
void (*function)(unsigned long):计数器计数完成之后,要调用的回调函数
unsigned long data:传给回调函数的参数 一般不填
};
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
函数的功能:向内核注册一个定时器 并运行
函数的头文件:
函数的原型: void add_timer(struct timer_list *timer)
函数的参数:struct timer_list *timer:内核定时器的核心的结构体
函数的返回值:无
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
函数的功能:重新激活内核定时器
函数的头文件:
函数的原型:int mod_timer(struct timer_list *timer, unsigned long expires)
函数的参数:
struct timer_list *timer:内核定时器的核心结构体
unsigned long expires:新的计数器要计的数
函数的返回值:当前边的定时器时间还未到 返回1
否则 成功返回 0 失败返回 -1
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
函数的功能:删除一个内核定时器
函数的头文件:
函数的原型:int del_timer(struct timer_list *timer)
函数的参数: struct timer_list *timer:内核定时器的核心的结构体
函数的返回值:
成功返回 0
失败返回 -1
计数的时间假如为秒的话
计数的次数 直接就是jiffies+秒数*HZ
当计数的时间为微秒的时候
unsigned long usecs_to_jiffies(const unsigned int u)//指定时间单位us
到计数的时间为毫秒的时候
unsigned long msecs_to_jiffies(const unsigned int m)//指定时间单位ms
四、以下代码是练习代码和运行结果,仅供参考
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- int my_irq;
- int value;
- int count=0;
-
-
- struct timer_list mytime;
-
- dev_t mykey1;
-
- struct cdev mycdev;
- struct file_operations myfops;
-
- struct class * mykey1_class=NULL;
- struct device * mydevicekey1=NULL;
- int light=1;
-
- static DECLARE_WAIT_QUEUE_HEAD(myque);
- //定时器回调函数
- void my_fun(unsigned long data)
- {
- int ret1;
- ret1=gpio_get_value(EXYNOS4_GPX3(2));
- if(ret1 == 0)
- {
- count=1;
- wake_up_interruptible(&myque);
-
- //翻转LED1
- light =!light;
- gpio_set_value(EXYNOS4X12_GPM4(0),light);
-
- printk("翻转LED1\n");
- }
- //printk("我被调用了\n");
- }
- //中断函数
- irqreturn_t fun1(int num, void *arg)
- {
- //printk("num:%d\n",num);
- mod_timer(&mytime, jiffies+msecs_to_jiffies(20));
-
- return 0;
- }
-
- int myopen (struct inode *inode, struct file *file)
- {
- int fan;
- //1.申请中断号(key1)
- my_irq = gpio_to_irq(EXYNOS4_GPX3(2));
- if(my_irq < 0)
- {
- printk("申请中断失败\n");
- return -1;
- }
- printk("申请的中断号为:%d\n",my_irq);
- //2.使能中断
- enable_irq(my_irq);
- //3.向内核注册中断
- fan=request_irq(my_irq,fun1,IRQF_TRIGGER_FALLING,"mykey",NULL);
- printk("按键打开\n");
-
- return 0;
- }
- int myclose(struct inode *inode, struct file *file)
- {
- //1.注销中断号
- free_irq(my_irq, NULL);
- //2.使能中断
- disable_irq(my_irq);
-
- gpio_set_value(EXYNOS4X12_GPM4(0),1);
- printk("led1已关闭\n");
- //printk("按键关闭\n");
- return 0;
- }
- ssize_t myread(struct file *file, char __user *buf, size_t size, loff_t *oft)
- {
- int ret;
- //printk("开始读取\n");
- //到这陷入阻塞,放弃cpu
- count=0;
- wait_event_interruptible(myque,count);
-
- value=gpio_get_value(EXYNOS4_GPX3(2));
- ret=copy_to_user(buf,&value,1);
- return 0;
- }
- static int __init mykeys_init(void)
- {
- //定时器
- mytime.expires=jiffies+msecs_to_jiffies(20); //20ms
- mytime.function=my_fun;
- init_timer(&mytime); //初始化定时器
- add_timer(&mytime); //向内核注册一个定时器 并运行
-
- //linux2.6 设备注册
- int ret;
- //1:申请1个设备号,key1用
- ret=alloc_chrdev_region(&mykey1, 0, 1, "key1");
- if(ret < 0)
- {
- printk("申请设备号失败\n");
- return -1;
- }
- printk("mykey1:%d\n",mykey1);
- printk("key1主设备号:%d\n",MAJOR(mykey1));
- printk("key1次设备号:%d\n",MINOR(mykey1));
-
- //2:初始化linux2.6的核心结构体
- myfops.owner=THIS_MODULE;
- myfops.open=myopen;
- myfops.release=myclose;
- myfops.read=myread;
- cdev_init(&mycdev,&myfops);
-
- //3:向内核注册linux2.6的核心结构体
- cdev_add(&mycdev, mykey1, 1);
-
- //4:创建自动生成设备文件所需要的类结构体
- mykey1_class=class_create(THIS_MODULE, "key1");
- if(mykey1_class == NULL)
- {
- printk("创建类结构体失败\n");
- return -1;
- }
- //5:生成设备文件
- mydevicekey1=device_create(mykey1_class, NULL, mykey1, NULL, "key1");
- if(mydevicekey1 ==NULL)
- {
- printk("生成设备文件失败\n");
- }
-
- return 0;
- }
-
- static void __exit mykeys_exit(void)
- {
- //1:销毁设备文件
- device_destroy(mykey1_class, mykey1);
- //2:销毁类结构体
- class_destroy(mykey1_class);
- //3:从内核取消注册linux2.6的核心结构体
- cdev_del(&mycdev);
- //释放设备号
- unregister_chrdev_region(mykey1,1);
- }
-
- module_init(mykeys_init);
- module_exit(mykeys_exit);
- MODULE_LICENSE("GPL");
运行结果: