linux驱动-定时器

目录

1、设置系统节拍率

1.1、CONFIG_HZ

2、jiffies

2.1、jiffies_64

2.2、系统运行时间

2.3、时间绕回

3、API函数

4、内核定时器

4.1、timer_list结构体

4.2、init_timer()函数

4.3、add_timer()函数

4.4、del_timer()函数

4.5、del_timer_sync()函数

4.6、mod_timer()函数

5、Linux 内核短延时函数


1、设置系统节拍率

在编译 Linux 内核的时候可以通过图形化界面设置系统节拍率。

-> Kernel Features
    -> Timer frequency

1.1、CONFIG_HZ

HZ 表示一秒的节拍数,Linux 内核会使用 CONFIG_HZ 来设置自己的系统时钟(include/asm-generic/param.h)

#undef HZ
#define HZ CONFIG_HZ
#define USER_HZ 100
#define CLOCKS_PER_SEC (USER_HZ)

2、jiffies

Linux 内核使用全局变量 jiffies 来记录系统从启动以来的系统节拍数(jiffies 定义在文件 include/linux/jiffies.h 中)。

#define __jiffy_data  __attribute__((section(".data")))

extern u64 __jiffy_data jiffies_64;
extern unsigned long volatile __jiffy_data jiffies;

2.1、jiffies_64

jiffies_64 用于 64 位系统,而 jiffies 用于 32 位系统。为了兼容不同的硬件, jiffies 其实就是 jiffies_64 的低 32 位。

2.2、系统运行时间

HZ 表示每秒的节拍数, jiffies 表示系统运行的 jiffies 节拍数,所以 jiffies/HZ 就是系统运行时间,单位为秒。

2.3、时间绕回

不管是 32 位还是 64 位的 jiffies,都有溢出的风险,溢出以后会重新从 0 开始计数。假如 HZ 为最大值 1000 的时候, 32 位的 jiffies 只需要 49.7 天就发生了wrap,对于 64 位的 jiffies 来说大概需要5.8 亿年才能绕回,因此 jiffies_64 的wrap忽略不计。

3、API函数

时间比较函数
time_after(unkown, known)如果 unkown 超过 known 的话,返回真,否则返回假。
time_before(unkown, known)如果 unkown 没有超过 known 的话,返回真,否则返回假。
time_after_eq(unkown, known)如果 unkown 超过或等于 known 的话,返回真,否则返回假。
time_before_eq(unkown, known)如果 unkown 没有超过或等于 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)将微秒转换为 jiffies 类型。
unsigned long nsecs_to_jiffies(u64 n)将纳秒转换为 jiffies 类型。

4、内核定时器

内核定时器并不是周期性运行的,超时以后就会自动关闭,因此如果想要实现周期性定时,那么就需要在定时处理函数中重新开启定时器(定义在include/linux/timer.h中)。

4.1、timer_list结构体

Linux 内核使用 timer_list 结构体表示内核定时器。

struct timer_list {
	struct list_head entry;
	unsigned long expires;
	struct tvec_base *base;

	void (*function)(unsigned long);
	unsigned long data;

	int slack;

#ifdef CONFIG_TIMER_STATS
	int start_pid;
	void *start_site;
	char start_comm[16];
#endif
#ifdef CONFIG_LOCKDEP
	struct lockdep_map lockdep_map;
#endif
}
entry链表节点
expires定时器超时时间,单位为节拍数
function定时处理函数
data要传递给 function 函数的参数

4.2、init_timer()函数

init_timer 函数负责初始化 timer_list 类型变量。

void init_timer(struct timer_list *timer)

参数 timer:要初始化定时器。

4.3、add_timer()函数

add_timer 函数用于向 Linux 内核注册定时器。

void add_timer(struct timer_list *timer)

参数 timer:要注册的定时器。

4.4、del_timer()函数

del_timer 函数用于删除一个定时器,不管定时器有没有被激活,都可以使用此函数删除。

int del_timer(struct timer_list * timer)

timer:要删除的定时器。
返回值: 0,定时器还没被激活; 1,定时器已经激活。
注:在多处理器系统上,定时器可能会在其他的处理器上运行,因此在调用 del_timer 函数删除定时器之前要先等待其他处理器的定时处理器函数退出。

4.5、del_timer_sync()函数

del_timer_sync 函数是 del_timer 函数的同步版,会等待其他处理器使用完定时器再删除,
del_timer_sync 不能使用在中断上下文中。

int del_timer_sync(struct timer_list *timer)

timer:要删除的定时器。
返回值: 0,定时器还没被激活; 1,定时器已经激活。

4.6、mod_timer()函数

mod_timer 函数用于修改定时值,如果定时器还没有激活的话, mod_timer 函数会激活定时器

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

timer:要修改超时时间(定时值)的定时器。
expires:修改后的超时时间。
返回值: 0,调用 mod_timer 函数前定时器未被激活; 1,调用 mod_timer 函数前定时器已
被激活。
 

5、Linux 内核短延时函数

void ndelay(unsigned long nsecs)纳秒延时函数。
void udelay(unsigned long usecs)微秒延时函数。
void mdelay(unsigned long mseces)毫秒延时函数。


 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux内核驱动中的定时器是一种常见的机制,可以在指定的时间间隔内触发中断。它的主要作用是进行定时操作,如周期性地刷新屏幕、进行数据采集等。下面是一个简单的Linux内核驱动定时器中断的代码示例: ``` #include <linux/timer.h> #include <linux/init.h> #include <linux/module.h> struct timer_list my_timer; void my_timer_callback(unsigned long data) { printk(KERN_INFO "my_timer_callback called (%ld).\n", jiffies); } static int __init timer_init(void) { int ret; printk(KERN_INFO "timer_init() called\n"); // 设置定时器 setup_timer(&my_timer, my_timer_callback, 0); ret = mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000)); // 定时1秒 if (ret) printk(KERN_ERR "Error in mod_timer\n"); return 0; } static void __exit timer_exit(void) { int ret; ret = del_timer(&my_timer); if (ret) printk(KERN_ERR "The timer is still in use...\n"); printk(KERN_INFO "timer_exit() called\n"); } module_init(timer_init); module_exit(timer_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Linux Timer Driver"); ``` 在上面的示例中,我们定义了一个名为`my_timer`的定时器,并将其设置为1秒钟后触发中断。当定时器到期时,它会调用`my_timer_callback()`函数来处理中断。这个函数会输出一条信息,表明它已被调用。 上述示例只是一个简单的示例,实际上在Linux内核驱动中使用定时器有许多不同的方法和实现方式。如果你需要更深入地了解Linux内核驱动定时器中断代码,你可以查阅相关的文档或书籍,例如《Linux设备驱动开发详解》等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值