linux 驱动之定时器编程

Table of Contents

1、jiffies和HZ

1.1、jiffies

1.2、HZ

2、时间比较

3、时间转换

4、延时操作

4.1、忙等待机制延时

4.2、让出cpu机制延时

5、定时器编程


1、jiffies和HZ


1.1、jiffies

  1. jiffies 是内核滴答定时器的计数值,每发生定时中断jiffies值就更新一次
  2. 内核源码针对32位和64位设计了jiffiesjiffies_64
  3. 正常一般都是使用jiffies,而设计jiffies的目的是考虑到32位jiffies会溢出
  4. 如果要读取jiffies_64的值必须使用get_jiffies_64函数,因为如果直接读取的话,jiffies_64的地32位值很快已经更新了,而那个函数保证的原子性

1.2、HZ

  1. 系统定时器频率,与体系结构相关,系统启动根据HZ设置定时器硬件
  2. HZ = (100) (ARM 平台 即周期是10ms)

使用实例:


unsigned long j,t1,t2;

j = jiffies ; //读取当前计数值

t1 = jiffies + 2*HZ; //未来2秒
t2 = jiffies + 2;    //未来20毫秒

2、时间比较


unsigned long cmp_time;

cmp_time = jiffies + HZ; //未来一秒

while(jiffies<cmp_time)
{

    //do things
}

以上代码看似合理,但是如果jiffies溢出就会出问题。

因此需要使用内核提供的时间比较函数才能更安全稳定

time_after(a,b) //如果a在b之后(a的时间点还没到达b的时间点)则返回true

time_before(a,b); //如果a在b之前(即a已经超过了b的时间点)则返回true

time_after_eq(a,b) //如果a在b之后或者相等则返回true

time_before_eq(a,b); //如果a在b之前或者相等则返回true

正确实例:

unsigned long cmp_time;

cmp_time = jiffies + HZ; //未来一秒

while(time_after(jiffies,cmp_time))
{

    //do things
}

 

3、时间转换


	int jiffies_to_msecs(const unsigned long j)
	int jiffies_to_usecs(const unsigned long j)
	u64 jiffies_to_nsecs(const unsigned long j)


	long msecs_to_jiffies(const unsigned int m)
	long usecs_to_jiffies(const unsigned int u) 
	unsigned long nsecs_to_jiffies(u64 n)

 

4、延时操作


4.1、忙等待机制延时

延时原理就是自加/减操作,类似于单片机裸机编程延时机制,这是牺牲cpu为代价的延时操作

内核提供的函数:

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

 

4.2、让出cpu机制延时

让出cpu即延时的时候休眠,不占用cpu资源

内核提供的函数:

void msleep(usigned int msecs); //延时多少毫秒

 

5、定时器编程


 

#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <asm/gpio.h>
#include <plat/gpio-cfg.h>

//分配定时器
static struct timer_list mytimer;
static int mydata = 0x5555;

//超时处理函数
static void mytimer_func(unsigned long data)
{
    int *pdata = (int *)data;
    
    printk("hello,kernel, data = %#x\n", *pdata);

    //重新添加定时器,如果不添加,定时器处理函数只执行一次
    mod_timer(&mytimer, jiffies + msecs_to_jiffies(2000));
}

static int mytimer_init(void)
{
    //初始化定时器
    init_timer(&mytimer);
    //指定定时器超时时候的时间
    mytimer.expires = jiffies + msecs_to_jiffies(2000); //2s
    mytimer.function = mytimer_func; //超时处理函数
    mytimer.data = (unsigned long)&mydata; //给超时处理函数传递参数

    //启动定时器
    add_timer(&mytimer);
    
    printk("add timer ok!\n");
    return 0;
}

static void mytimer_exit(void)
{
    del_timer(&mytimer); 
    printk("del timer ok!\n");
}
module_init(mytimer_init);
module_exit(mytimer_exit);
MODULE_LICENSE("GPL");

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值