内核定时器
(1)内核是给应用层提供接口的,一般延时都是由用户来完成的。所以在内核中不会使用延时函数,都是用内核定时器来完成
struct timer_list {
unsigned long expires;
//定时的时间
void (*function)(struct timer_list *);
//定时器处理函数
};
1.分配对象
struct timer_list mytimer;
2.对象初始化
jiffies:时钟节拍数,在内核启动的时候,这个
值随着系统的运行一直在增加。
CONFIG_HZ=100 ----> 0.01s = 10ms
void mytimer_function(struct timer_list *)
{
}
mytimer.expires = jiffies + HZ; //HZ代表定义1s钟
timer_setup(&mytimer, mytimer_function, 0);
注:最后一个参数是flags:这个flags是和定时器运行在
那个cpu上相关的一个标志位,默认填充0即可。
timer->flags = flags | raw_smp_processor_id();
3.注册
void add_timer(struct timer_list *timer)
//将timer_list放入内核链表,并开启内核定时
//定时器只会启动一次
int mod_timer(struct timer_list *timer,
unsigned long expires)
//再次启动定时器
4.注销定时
int del_timer(struct timer_list *timer)
----------------------------------------------------
代码实例
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/timer.h>
/*
fsled{
compatible = "fsmp1a,fsled";
core_led = <&gpioz 5 0>,<&gpioz 6 0>,<&gpioz 7 0>;
extend_led =<&gpioe 10 0>,<&gpiof 10 0>,<&gpioe 8 0>;
};
*/
int core_led[3] = {0};
int extend_led[3] = {0};
struct timer_list mytimer;
struct device_node *fsled;
int get_fsled_node(void)
{
fsled = of_find_node_by_path("/fsled");
if(fsled == NULL){
printk("get fsled node error\n");
return -ENODEV;
}
return 0;
}
int fsled_all_init(void)
{
int i,ret;
for(i=0;i<ARRAY_SIZE(core_led);i++){
core_led[i] = of_get_named_gpio(fsled,"core_led",i);
if(core_led[i] < 0){
printk("get node gpio error\n");
return core_led[i];
}
extend_led[i] = of_get_named_gpio(fsled,"extend_led",i);
if(extend_led[i] < 0){
printk("get node gpio error\n");
return extend_led[i];
}
printk("core_led[%d] = %d,extend_led[%d] = %d\n",
i,core_led[i],i,extend_led[i]);
ret = gpio_request(core_led[i] ,NULL);
if(ret){
printk("gpio %d request error\n",core_led[i]);
return ret;
}
gpio_direction_output(core_led[i],1);
ret = gpio_request(extend_led[i] ,NULL);
if(ret){
printk("gpio %d request error\n",extend_led[i]);
return ret;
}
gpio_direction_output(extend_led[i],1);
}
return 0;
}
void mytimer_function(struct timer_list *timer)
{
//set led
int i;
for(i=0;i<ARRAY_SIZE(core_led);i++){
gpio_set_value(core_led[i],!gpio_get_value(core_led[i]));
gpio_set_value(extend_led[i],!gpio_get_value(extend_led[i]));
}
//再次启动计时器,再次启动不能调用add_timer 得用mod_timer
mod_timer(&mytimer,jiffies + HZ);
}
static int __init fsled_init(void)
{
int ret;
if((ret = get_fsled_node())<0){
return ret;
}
if((ret = fsled_all_init())<0){
return ret;
}
//初始化计时器
mytimer.expires = jiffies + HZ;
timer_setup(&mytimer,mytimer_function,0);
//启动计时器
add_timer(&mytimer);
return 0;
}
static void __exit fsled_exit(void)
{
int i;
del_timer(&mytimer);
for(i=0;i<ARRAY_SIZE(core_led);i++){
gpio_free(core_led[i]);
gpio_set_value(core_led[i],0);
gpio_free(extend_led[i]);
gpio_set_value(extend_led[i],0);
}
}
module_init(fsled_init);
module_exit(fsled_exit);
MODULE_LICENSE("GPL");