芯灵思Sinlinx A64开发板Linux内核定时器编程

开发平台 芯灵思Sinlinx A64 内存: 1GB 存储: 4GB 开发板详细参数 https://m.tb.cn/h.3wMaSKm 开发板交流 641395230

Linux 内核定时器是内核用来控制在未来某个时间点(基于jiffies)调度执行某个函数的一种机制,其实现位于 <Linux/timer.h> 和 kernel/timer.c 文件中。 内核定时器的数据结构

struct timer_list {
    struct list_head entry;  //双向链表元素list:用来将多个定时器连接成一条双向循环队列。
    unsigned long expires; //expires 字段表示期望定时器执行的 jiffies 值,到达该 jiffies 值时,将调用 function 函数,并传递 data 作为参数。
    void (*function)(unsigned long); //指向一个可执行函数。当定时器到期时,内核就执行function所指定的函数。而data域则被内核用作function函数的调用参数。
    unsigned long data;
    struct tvec_base *base;
    /* ... */
};

时间比较操作 在定时器应用中经常需要比较两个时间值,以确定timer是否超时,所以Linux内核在timer.h头文件中定义了4个时间关系比较操作宏。这里我们说时刻a在时刻b之后,就意味着时间值a≥b。 Linux强烈推荐用户使用它所定义的下列4个时间比较操作宏(include/linux/timer.h):

#define time_after(a,b) ((long)(b) - (long)(a) < 0)
#define time_before(a,b) time_after(b,a)
#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)
#define time_before_eq(a,b) time_after_eq(b,a)

Linux 内核时间相关转换函数

  1. unsigned long usecs_to_jiffies(const unsigned int u) 功能: 把微秒转换成时钟节拍 参数: u 时间微秒 返回: 对应的时钟节拍数量
  2. unsigned long msecs_to_jiffies(const unsigned int m) 功能: 把毫秒转换成时钟节拍 参数: u 时间毫秒 返回: 对应的时钟节拍数量 示例: 要定时从现在开始, 3 毫秒执行一个函数 expires 设置为 jiffies+ msecs_to_jiffies(3)

Linux 内核定时器操作相关 API

  1. 静态定义结构体变量并且初始化(宏) DEFINE_TIMER(_name, _function, _expires, _data) 功能: 定义一个名字为_name 的 struct timer_list 结构的变量, 并且初始化它的 function, expires, data 成员

  2. 定时器初始化(宏) init_timer(timer) 功能: 只是对 struct timer_list 结构成员进行一些基础初始化操作, function, expires, data 成员还需要用户自 己填充。

3.设置定时器(宏) setup_timer(timer, fn, data) 功能: 设置定时器中的 function, data 和一些基础成员, expires 并没有初始化, 需要用户自己进行初始化

  1. 注册定时器到内核 void add_timer(struct timer_list *timer) 功能: 向内核注册一个定时器, 注册后会马上开始计时。 5.从内核注销定时器 int del_timer(struct timer_list * timer) 功能: 从内核定时链表上删除指定的定时器, 删除后就不会再执行绑定的函数

  2. 修改定时器定时时间值, 并且重新注册 int mod_timer(struct timer_list *timer, unsigned long expire0.s) 功能: 修改定时器定时时间值, 并且重新注册, 不管这个定时的超时函数是否执行过。 执行完成后会马上启 动定时。

内核定时器编程步骤

Step1 定义timer_list 结构变量

Step2 定义超时函数

Step3 对timer_list结构变量进行初始化

Step4 注册定时器,启动定时

Step5 注销定时器

驱动代码:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>

void tasklet_fun(unsigned long data);
//Step1 定义并静态初始化tasklet_struct 结构变量
DECLARE_TASKLET(mytasklet, tasklet_fun, 651);
//Step2 tasklet服务函数
void tasklet_fun(unsigned long data)
{
        static unsigned long count = 0;
        printk("count:%lu,%s is call! data:%lu\r\n",count++,__FUNCTION__,data);
        tasklet_schedule(&mytasklet); //在工作函数中重新调度自己,这样会循环调用tasklet_fun
}
static int __init mytasklet_init(void)
{
        //Step3 开始调度 mytasklet
        tasklet_schedule(&mytasklet);
        printk("%s is call!\r\n",__FUNCTION__);
        return 0;
}
static void __exit mytasklet_exit(void) //Module exit function specified by module_exit()
{
        //Step4 删除 tasklet
        tasklet_kill(&mytasklet);
}
module_init(mytasklet_init);
module_exit(mytasklet_exit);
MODULE_LICENSE("GPL");

实验现象

转载于:https://my.oschina.net/u/4078822/blog/3021498

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值