驱动开发(五):Linux内核定时器

 驱动开发系列文章:
                驱动开发(一):驱动代码的基本框架    
                驱动开发(二):创建字符设备驱动
                驱动开发(三):内核层控制硬件层 

                驱动开发(四):Linux内核中断

                驱动开发(五):Linux内核定时器

目录

定时器介绍

定时器的当前时间如何获取?

定时器加1代表走了多长时间?

定时器的使用 

1.声明一个定时器 

2.初始化定时器

 3.启动定时器

   3.1添加定时器

   3.2使用定时器

4.删除定时器

参考代码


定时器介绍

在大部分操作系统中,系统时钟是由计算机硬件提供的。它通常以固定的频率发送时钟信号给计算机的中央处理器(CPU)。这个时钟信号会被操作系统内核接收并用于计算时间。操作系统通过不断监视系统时钟的变化来进行时间的跟踪,从而实现定时功能。

Linux内核中的定时器是一种机制,用于在一定的时间间隔或特定的时间点执行某个任务或触发某个事件。定时器在内核中广泛使用,用于实现各种功能,如任务调度、延迟处理、超时处理等。

定时的本质是计时,计时的本质是计数。LInux内核定时器是一种基于未来时间点的计时方式,以当前时刻来启动的时间点,以未来的某一时刻为终止点。

因此,我们要实现定时需要两个值,一个是当前时刻值(起始时间),一个是目标时间值(触发中断时间)

定时器的当前时间如何获取?

jiffies:内核当前时钟节拍数

jiffies是在板子上电这一刻开始计数,只要板子不断电,这个值一直在增加(64位)。在驱动代码中直接使用即可。

定时器加1代表走了多长时间?

Linux内核会使用CONFIG_HZ来设置自己的系统时钟。

在内核顶层目录下有.config

Kconfig(组成菜单) ---->menuconfig(配置) ------>.config(最终) 可以直接改.config

CONFIG_HZ=1000

周期 = 1/CONFIG_HZ

所以每加一个数是加1ms;

 在内核顶层目录下使用 vi .config 

定时器的使用 

 内核提供了一个封装好的结构体 struct timer_list 用来表示定时器。

struct timer_list 结构体里的内容:

struct timer_list {/** All fields that change during normal runtime grouped to the* same cacheline*/struct list_head entry;  unsigned long expires;    //定时到的时间struct tvec_base *base;void (*function)(unsigned long);  //定时器的处理函数unsigned long data;       //向定时器处理函数中填写的值int slack;#ifdef CONFIG_TIMER_STATSint start_pid;void *start_site;char start_comm[16];
#endif
#ifdef CONFIG_LOCKDEPstruct lockdep_map lockdep_map;
#endif
};

1.声明一个定时器 

可以使用内核给你提供的这个接口直接声明自己的定时器。声明定时器的数量没有限制,想开几个开几个。

struct timer_list mytimer;    //声明一个结构体变量

2.初始化定时器

声明完之后还需要对结构体的基本内容进行填充

mytimer.expires = jiffies + 1000;  //1s
mytimer.function = timer_function;  //名字叫timer_function的中断处理函数
mytimer.data = 0;    void timer_function(unsigned long data) //定时器的处理函数
{}

 填完基本的参数之后,剩下的可以交给内核自动填充

init_timer(&mytimer);  //内核帮你填充你未填充的对象	

 3.启动定时器

   3.1添加定时器

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

同一个定时器只能被添加一次,在你添加定时器的时候定时器会先启动一次

void add_timer(struct timer_list *timer);
   3.2使用定时器

除了第一次开启定时器使用add_timer,其他时间再次使用定时器要使用mod_timer。

int mod_timer(struct timer_list *timer, unsigned long expires)
//再次启动定时器,参数unsigned long expires为定时时间

4.删除定时器

int del_timer(struct timer_list *timer)    //删除定时器

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

参考代码

 用定时器实现按键消抖

#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/timer.h>#define GPIONO(m, n) m * 32 + n
#define GPIO_B8 (GPIONO(1, 8))
#define GPIO_B16 (GPIONO(1, 16))
int gpiono[] = {GPIO_B8, GPIO_B16};
char *name[] = {"gpio_it_8", "gpio_it_16"};
int ret;
int i;
struct timer_list mytimer;
irqreturn_t handler(int irqno, void *dev)
{mod_timer(&mytimer,jiffies + 10);return IRQ_HANDLED;
}
void timer_function(unsigned long data) //定时器的处理函数
{int B8 = gpio_get_value(GPIO_B8);int B16 = gpio_get_value(GPIO_B16);if (B8 == 0){printk(KERN_ERR "------------\n");}if (B16 == 0){printk(KERN_ERR "++++++++++++\n");}
}static int __init hello_init(void)
{mytimer.expires = jiffies + 10;mytimer.function = timer_function;mytimer.data = 0;init_timer(&mytimer);  //内核帮你填充你未填充的对象	add_timer(&mytimer);    //开启一次定时器for (i = 0; i < sizeof(gpiono) / sizeof(int); i++){ret = request_irq(gpio_to_irq(gpiono[i]), handler, IRQF_TRIGGER_FALLING, name[i], NULL);if (ret != 0){printk(KERN_ERR "%s request irq err\n", name[i]);return ret;}}return 0;
}
static void __exit hello_exit(void)
{for (i = 0; i < sizeof(gpiono) / sizeof(int); i++){free_irq(gpio_to_irq(gpiono[i]), NULL);}del_timer(&mytimer);
}module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

现象: 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/27927.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

移动端超超超详细知识点总结(Part4)

rem基础 1. rem单位 rem (root em)是一个相对单位&#xff0c;类似于em&#xff0c;em是父元素字体大小。不同的是rem的基准是相对于html元素的字体大小。比如&#xff0c;根元素&#xff08;html&#xff09;设置font-size12px; 非根元素设置width:2rem;则换成px表示就是24p…

数据防泄漏的六个步骤|数据防泄漏软件有哪些

在当前复杂多变的网络安全环境下&#xff0c;数据防泄漏软件成为了企业信息安全架构中不可或缺的一环。下面以安企神软件为例&#xff0c;告诉你怎么防止数据泄露&#xff0c;以及好用的防泄露软件。 1. 安企神软件 安企神软件是当前市场上备受推崇的企业级数据防泄漏解决方案…

CPU中的寄存器CPU能理解的指令(指令集)

CPU中的寄存器 寄存器有很多种。如指令寄存器&#xff0c;专门存储指令 问&#xff1a;CPU的寄存器存的是什么? 答&#xff1a;CPU寄存器是中央处理器&#xff08;CPU&#xff09;内部的一小部分高速存储资源&#xff0c;用于快速访问和存储各种类型的数据和信息。以下是CPU…

Nvidia TensorRT系列01-TensorRT的功能1

Nvidia TensorRT系列01-TensorRT的功能1 B站&#xff1a;肆十二-的个人空间-肆十二-个人主页-哔哩哔哩视频 (bilibili.com) 博客&#xff1a;肆十二-CSDN博客 问答&#xff1a;(10 封私信 / 72 条消息) 肆十二 - 知乎 (zhihu.com) C和Python API TensorRT的API同时支持C和Pyth…

【网络协议栈】TCP/IP相关知识点收集

TCP/IP知识点收集 1 TCP分段 在TCP/IP协议栈中&#xff0c;“MSS”&#xff08;Maximum Segment Size&#xff09;是一个关键参数&#xff0c;它指定了TCP协议在发送数据时可以使用的最大数据段&#xff08;segment&#xff09;的大小。这个参数是TCP连接建立时通过三次握手&…

web前端任职条件:全面解析

web前端任职条件&#xff1a;全面解析 在当今数字化快速发展的时代&#xff0c;Web前端技术已经成为互联网行业不可或缺的一部分。作为一名Web前端开发者&#xff0c;需要具备哪些任职条件呢&#xff1f;本文将从四个方面、五个方面、六个方面和七个方面为您深入剖析。 四个方…

【ARM-Linux篇】智能家居语音模块配置

1. pin脚配置&#xff1a; 2. 命令词自定义基本信息&#xff1a; 3. 命令词自定控制详情: • 测试&#xff1a;串口模块可先通过串口助手验证每个指令的准确性&#xff0c; 然后运行wiringOP中的serialTest程序(需把/dev/ttyS2改成/dev/ttyS5) 然后语音接收到指令后(比如喊你好…

Ionic 复选框:实现与应用详解

Ionic 复选框&#xff1a;实现与应用详解 Ionic 是一个强大的开源框架&#xff0c;用于构建高性能、高质量的移动和网页应用程序。它结合了 Angular 的强大功能和 Cordova 的设备访问能力&#xff0c;使得开发者能够轻松地创建跨平台的应用程序。在 Ionic 应用中&#xff0c;复…

10大wordpress外贸主题

手动工具wordpress外贸模板 适合生产套筒扳、管钳、工具箱、斧子、锤子、防爆工具、螺丝刀、扳手等手动工具的厂家。 https://www.jianzhanpress.com/?p4806 Invisible Trade WP外贸网站模板 WordPress Invisible Trade外贸网站模板&#xff0c;做进出口贸易公司官网的word…

开源高效API管理工具:RAP

RAP&#xff1a;简化API开发&#xff0c;提升团队协作效率- 精选真开源&#xff0c;释放新价值。 概览 RAP&#xff08;RESTful API Project&#xff09;是一个开源的API管理工具&#xff0c;由阿里巴巴团队开发并维护。它旨在帮助前后端开发人员通过一个统一的平台来设计、开…

软件方案评审与模块优化:从FOC模块出发的电控平台建设

一、背景 洞悉模块发展趋势&#xff0c;定制行业应用特点&#xff0c;明确优化方向与阶段性目标 随着科技进步的飞速发展&#xff0c;模块化设计已成为众多行业产品开发的核心理念。无论是软件系统、硬件组件&#xff0c;还是复杂系统中的功能模块&#xff0c;都需要对其发展…

DVR系统设计的大致思路和模块划分

DVR系统设计的大致思路和模块划分 1. 源由2. 设计步骤2.1 需求分析2.2 系统架构设计2.3 硬件设计与选择2.4 软件开发2.5 测试与调试2.6 部署与运维2.7 持续优化 3. 模块切割3.1 摄像头3.2 视频处理单元3.3 存储系统3.4 网络模块3.5 视频编码/解码3.6 接口与连接3.7 控制与操作3…

如何提高软件质量

你写的程序是否有这些问题&#xff1a;命名不规范、函数设计不合理、分层不清晰、没有模块化概念、代码结构混乱、高度耦合等等。只是为了完成功能&#xff0c;从来没有考虑过代码质量问题、代码设计问题。 这样的代码维护起来非常费劲&#xff0c;添加或者修改一个功能&#…

怀庄之醉和豫腾贸易的关系

豫腾贸易是珠海香洲豫腾贸易商行的简称&#xff0c;位于中国广东省珠海市香洲区&#xff0c;是一家集线上线下为一体的酒类销售平台。 该商行自成立以来&#xff0c;依托于珠海这一沿海开放城市的地理优势&#xff0c;积极拓展业务范围&#xff0c;致力于为客户提供多元化的商…

Vue部分文件说明

1.eslintignore文件 Eslint会忽略的文件 # Eslint 会忽略的文件.DS_Store node_modules dist dist-ssr *.local .npmrc 2.gitignore # Git 会忽略的文件.DS_Store node_modules dist dist-ssr .eslintcache# Local env files *.local# Logs logs *.log npm-debug.log* yarn-de…

洛谷题解 - P1036 [NOIP2002 普及组] 选数

目录 题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示代码 题目描述 已知 n n n 个整数 x 1 , x 2 , ⋯ , x n x_1,x_2,\cdots,x_n x1​,x2​,⋯,xn​&#xff0c;以及 1 1 1 个整数 k k k&#xff08; k < n k<n k<n&#xff09;。从 n n n 个整数…

不可不知的Java SE技巧:如何使用for each循环遍历数组

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

HTML+CSS 旋转呼吸加载器

效果演示 实现了一个旋转加载动画效果&#xff0c;包括一个圆形的加载框和两个不同颜色的圆形旋转动画。加载框和动画都使用了CSS的动画属性&#xff0c;实现了旋转和缩放的效果。整个加载动画的样式比较简单&#xff0c;使用了黑色和黄色的背景色&#xff0c;以及白色的文本颜…

基于SVD的点云配准(下)

点云配准及特征提取详细解读 本篇博客将介绍一个用于点云配准的 C++ 代码示例,该示例使用 PCL(Point Cloud Library)库来处理和配准两个点云数据集。我们将逐步解析代码的关键部分,并解释每个步骤的作用。 代码说明 代码的整体结构及其主要功能: int main(int argc, ch…

【C++】【期末考】【基本概念和语法】概括总结——期末速成

目录 1. C简介 C的历史与发展 C的特点与优势 2. 基本语法 注释 数据类型与变量 常量 运算符 输入与输出 3. 控制结构 条件语句 循环语句 4. 函数 函数定义与声明 参数传递 返回值 函数重载 5. 数组与字符串 一维数组 多维数组 字符串处理 6. 指针 指针的…