全局变量 jiffies 用来记录自系统启动以来产生的节拍总数,启动时为0,此后每秒增加Hz(一秒内时钟中断次数)
定时器频率配置在 .config中,内核固定不能修改。举例CONFIG_Hz = 250,即 1秒/250 = 4ms jiffies+1
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/timer.h>
/*
myleds{
led1=<&gpioe 10 0>;
led2=<&gpiof 10 0>;
led3=<&gpioe 8 0>;
};
*/
struct device_node* node;
struct gpio_desc* desc;
//一:定义一个定时器结构体变量
struct timer_list mytimer;
/*
struct timer_list {
struct hlist_node entry; //内核链表
unsigned long expires; //定时的时间
void (*function)(struct timer_list *); //定时器处理函数(定时到了执行的函数)
unsigned long data; //向定时器处理函数传递的参数
u32 flags; //0
};
*/
//三:填写定时器处理函数
void timer_led_blink(struct timer_list *timer)
{
gpiod_set_value(desc,!gpiod_get_value(desc));
//四:再次启动定时器
mod_timer(&mytimer,jiffies+HZ);
}
static int __init mycdev_init(void)
{
// 1.获取节点
node = of_find_node_by_path("/myleds");
if (node == NULL) {
printk("parse node error\n");
return -EINVAL;
}
//2.获取一个引脚
desc = gpiod_get_from_of_node(node,"led2",0,GPIOD_OUT_HIGH,0);
if (IS_ERR(desc)) {
printk("get gpio desc error\n");
return PTR_ERR(desc);
}
//3.将指定的gpio管脚添加到pin_ctrl子系统中管理,避免其他外设使用
if(gpiod_request(desc,NULL)){
printk("request gpio error\n");
return -EAGAIN;
}
//二:初始化定时器
mytimer.expires = jiffies+HZ;
timer_setup(&mytimer,timer_led_blink,0);
//五:注册并启动定时器
add_timer(&mytimer);
return 0;
}
static void __exit mycdev_exit(void)
{
//六:注销定时器
del_timer(&mytimer);
//设置电平
gpiod_set_value(desc, 0);
//释放gpio
gpiod_put(desc);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");