栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux驱动学习记录-11.内核定时器

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux驱动学习记录-11.内核定时器

这章学习Linux内核定时器,介绍其API函数和用法。

目录标题
  • 一、时间管理
  • 二、内核定时器
  • 三、驱动程序
  • 四、测试
    • 1.测试App
    • 2.编译
    • 3.测试

一、时间管理

系统节拍默认100hz,即每秒100次,定义一个HZ=100
Linux内核使用全局变量jiffies来记录系统从启动以来的系统节拍数,系统启动时将jiffies初始化为0,定义在include/linux/jiffies.h中。
所以jiffies/HZ就是系统运行时间。

函数描述
time_after(unknow,know)unknown超过known返回真,否则返回假
time_before(unknow,known)没有超过返回真,否则返回假
time_after_eq(unknow,known)大于等于返回真,否则返回假
time_before_eq(unknown,known)小于等于返回真,否则返回假

unknown一般为jiffies,known是对比的值。
下面是jiffies和ms、us、ns之间的转换函数

函数描述
int jiffies_to_msecs(const unsigned long j)jiffies转换成毫秒
int jiffies_to_usecs(const unsigned long j)jiffies转换成微秒
u64 jiffies_to_nsecs(const unsigned long j)jiffies转换成纳秒
long msecs_to_jiffies(const unsigned int m)毫秒转换成jiffies
long usecs_to_jiffies(const unsigned int u)微妙转换成jiffes
unsigned long nsecs_to_jiffies(u64 n)纳秒转换成jiffies
二、内核定时器

提供超时时间和需要处理的函数即可。

struct timer_list {
	struct list_head entry;
	unsigned long expires;    
	struct tvec_base *base;
	void (*function) (unsigned long); 
	unsigned long data;   
	int slack; 
};

比如定义一个周期2s的定时器,超时时间定义为expires = jiffies+(2*HZ)。
下面是定时器的API函数

void init_timer (struct timer_list *timer)

void add_timer (struct timer_list *timer)

int del_timer (struct timer_list * timer)

int del_timer_sync (struct timer_list *timer)

int mod_timer (struct timer_list *timer, unsigned long expires)

Linux内核短延迟函数

函数描述
void ndelay(unsigned long nsecs)纳秒延迟
void udelay(unsignd long usces)微秒延迟
void mdelay(unsigned long msecs)毫秒延迟
三、驱动程序

使用定时器让led闪,输入时间控制闪烁频率。

#include 
#define TIMER_CNT 1
#define KEY_NAME  "timer"

struct timer_device {
    struct device_node *nd;
    int timer_gpio;
    struct timer_list timer;
    int period;
}
struct timer_device timer;
static int timer_open(struct inode *inode, struct file *filp)
{
    filp->private = &timer;
    timer.period = 1000;
}

static long timer_unlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
{
    struct timer_device *dev = filp->private;
    int ret;
    switch(cmd) {
        case CLOSE:
        ret = del_timer_sync(&dev->timer);
        break;
        case OPEN:
        mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->period));
        break;
        case SET:
        dev->period = arg;
        mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->period));
        break;
        default:
        break;
    }
    return 0;
}
static struct file_operations timer_fops = {
    .owner = THIS_MODULE,
    .open = timer_open,
    .unlocked_ioctl = timer_unlocked_ioctl,
};
void function(unsigned long arg)
{
    struct timer_device *t = (struct timer_device *)arg;
    static int temp = 0;
    if(temp % 2)
        gpio_set_value(t->timer_gpio, 1);
    else
        gpio_set_value(t->timer_gpio, 0);

    temp++;
    mod_timer (&t->limer, jiffies + msecs_to_jiffies(t->period));
}
static int __init timer_init(void)
{
    init_timer(&timer.timer);
    timer.timer.function = function;
    timer.timer.expires = jiffies + msecs_to_jiffies(1000);
    timer.timer.data = (unsigned long) &timer;

    return 0;

}
static void __exit timer_exit(void)
{
    del_timer_sync(&timer.timer);

    cdev_del(&timer.cdev);
    unreginser_chrdev_region(timer.devid, TIMER_CNT);
    device_destroy(timer.class, timer.devid);
    class_destroy(timer.class);
}

重复代码略写
这fops函数加了unlocked_ioctl函数,用于传递参数。
在del定时器后,可以不必初始化-注册定时器,因为只是从内核删除,本身还存在,所以再激活,只要add或者mod函数激活既可以使用。
定时器fun函数输入参数是dev结构体的地址(unsigned long),因此可以在fun函数继续使用结构体内的变量。
最后exit函数,记得删除定时器,删除建议使用sync函数。

四、测试 1.测试App
int main(int argc, char *argv[])
{
	int fd, ret;
	char *filename;
	unsigned int cmd;
	unsigned int arg;
	unsigned char str[100];
	filename = argv[1];

	fd = open(filename, O_RDWR);
	while (1) {
		printf("Input CMD:");
		ret = scanf("%d", &cmd);
		if (ret != 1) {				
			gets(str);				
		}

		if(cmd == 1)				
			cmd = CLOSE;
		else if(cmd == 2)			
			cmd = OPEN;
		else if(cmd == 3) {
			cmd = SET;	
			printf("Input Timer Period:");
			ret = scanf("%d", &arg);
			if (ret != 1) {			
				gets(str);			
			}
		}
		ioctl(fd, cmd, arg);			
	}
	close(fd);
}
2.编译

和前面一样

3.测试

参考App代码吧。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/342332.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号