[驱动开发]Linux内核定时器与中断的简单应用

这篇具有很好参考价值的文章主要介绍了[驱动开发]Linux内核定时器与中断的简单应用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

首先介绍一下定时器原理。
在linux系统中定时器有分为软定时和硬件定时器。
以海思某款芯片为例,定时器模块又称为Timer模块,主要实现定时、计数功能。
Timer 具有以下特点:

  • 带可编程 8 位预分频器的 32bit/16bit 减法定时器/计数器。
  • Timer 的计数时钟为 3MHz 时钟。
  • 支持 3 种计数模式:自由运行模式、周期模式和单次计数模式。
  • 有 2 种载入计数初值的方法,分别通过 TIMERx_LOAD 和 TIMERx_BGLOAD 寄存
    器实现。
  • 当前的计数值可随时读取。
  • 当计数值减到 0 时会产生一个中断。

Timer 基于一个 32bit/16bit(可配置)减法计数器。计数器的值在每个计数时钟的上
升沿减 1。当计数值递减到零,Timer 将产生一个中断。


而基于硬件提供的信号源,系统就可以按照信号中断来计数,计数在固定频率下对应固定的时间,根据预设的时间参数即可产生定时中断信号,这就是软定时。

本文主要介绍软定时器的使用

一、内核定时器

1.介绍

内核定时器是内核用来控制在未来某个时间点(基于jiffies(节拍总数))调度执行某个函数的一种机制,相关函数位于 <linux/timer.h> 和 kernel/timer.c 文件中。

当内核定时器定时时间到达时,会进入用户指定的函数,相当于软中断。内核定时器注册开启后,运行一次就不会再运行(相当于自动注销),我们可以重新设置定时器的超时时间,让定时器重复运行。

每当时钟中断发生时,全局变量jiffies(一个32位的unsigned long 变量)就加1,因此jiffies记录了linux系统启动后时钟中断发生的次数,驱动程序常利用jiffies来计算不同事件间的时间间隔。内核每秒钟将jiffies变量增加HZ次。因此,对于HZ值为100的系统,jiffy+1等于隔了10ms,而对于HZ为1000的系统,jiffy+1仅为1ms。

内核定时器结构体:下面列出了需要关心的成员

struct timer_list {
    unsigned long expires;           //设置超时时间,用jiffies作为基准值
    void (*function)(unsigned long); //类似中断服务函数,设置定时器到时后处理的函数 
    unsigned long data;              //中断服务函数的参数
}

expires设置:以当前时间为基准加上延时时间,时间基准用jiffies变量表示

2、定时器使用

2.1.初始化

定义定时器结构体

struct timer_list my_timer;
static unsigned int out_time = 5;	// 5秒

my_timer.expires = jiffies + out_time * HZ;	// 设置超时时间,jiffies是基准值

定义定时器到时后的处理函数

static void TimeOutFunc(unsigned long data)
{
    printk("TimeOut\n");
}

初始化定时器

timer_setup(&my_timer, TimeOutFunc, 0);

2.2.启动

add_timer(&my_timer);

初始化和启动一般可以写在内核模块驱动的module_init中

2.3.关闭

(void)del_timer(&my_timer);

关闭一般可以写在内核模块驱动的module_exit中


二、中断

1.介绍

不介绍了,反正就是硬件发出个中断信号,linux系统就响应然后执行一段程序(中断处理函数),执行完之后再回到断电处继续执行之前的工作。

介绍一下基本概念:
中断号(IRQ—interrupt request):中断号也叫中断线,每个中断都有一个中断号,通过中断号即可区分不同的中断。Linux 内核中使用一个 int 变量表示中断号。 Linux内核为每个中断线分配一个唯一的中断编号(IRQ)(可以使用gpio_to_irq函数,获取到对应的中断编号),也称为中断请求号。不同的计算机系统分配方式不同的。

2.使用

假设我们的中断由某个GPIO管脚上升沿触发
首先需要使用gpio_request函数向内核申请需要的GPIO引脚

gpio_request(GPIO_XX, NULL);

2.1 初始化

    unsigned int irq_num;
    unsigned int irqflags;
    int iRet;
	static unsigned int gpio_irq_type = RISING_EDGE;
	module_param(gpio_irq_type, uint, S_IRUGO);		// 只读
	MODULE_PARM_DESC(gpio_irq_type, "RISING_EDGE");	//上升沿
	
    /* 设置方向为输入 */
    gpio_dev_input(gpio_num);

    /* 上升沿 共享中断 */
    irqflags = IRQF_TRIGGER_RISING;
    irqflags |= IRQF_SHARED;

    /* 根据GPIO编号映射中断号 */
    irq_num = gpio_to_irq(gpio_num);

    /* 注册中断 */
    iRet = request_irq(irq_num, my_interrupt_func, irqflags, "MY_interrupt", &gpio_irq_type);

其中,中断处理函数

static irqreturn_t wiper_interrupt(int irq, void *dev_id)
{
	printk("interrupt func\n");
	mod_timer(&my_timer, jiffies + out_time * HZ);	// 刷新定时器
	return IRQ_HANDLED;
}

2.2 注销

	/* 释放注册的中断 */
	free_irq(gpio_to_irq(gpio_num), &gpio_irq_type);
	
    /* 释放注册的GPIO编号 */
    gpio_free(GPIO_XX);

	/* 清除定时器 */
	(void)del_timer(&wiper_timer);
    

假设我们的外设在正常运行时总是能每隔一段时间以中断的形式反馈运行状态。
我们通过在GPIO触发的中断里对定时器进行刷新,从而可以实现超时处理操作,也就是说,如果外设没有正常运行,外设没有能够在一定时间内反馈中断从而刷新定时器,则会导致定时器倒计时结束,触发定时器到时后的处理函数。文章来源地址https://www.toymoban.com/news/detail-828421.html

到了这里,关于[驱动开发]Linux内核定时器与中断的简单应用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux 内核定时器

    一、相关知识点 (一)知识点 1、内核定时器分类     1)标准定时器或系统定时器     2)高精度定时器(HRT)         头文件:#include linux/hrtimer.h 2、检查系统是否可用HRT     1)查看内核配置文件              2)查看机器         cat proc/timer_list  | grep \\\"resolution\\\" 

    2024年02月11日
    浏览(39)
  • 09_Linux内核定时器

    目录 Linux时间管理和内核定时器简介 内核定时器简介 Linux内核短延时函数 定时器驱动程序编写 编写测试APP 运行测试          学习过UCOS或FreeRTOS的同学应该知道, UCOS或FreeRTOS是需要一个硬件定时器提供系统时钟, 一般使用Systick作为系统时钟源。同理 , Linux要运行 , 也是需

    2024年02月13日
    浏览(39)
  • Linux内核 -高精度定时器

    高精度定时器使用示例

    2024年01月19日
    浏览(49)
  • Linux 内核定时器(高级字符设备五)

      在 Linux 内核中很多函数是基于定时器进行驱动的,但是内核定时器的精度并不高,所以不能作为高精度定时器使用。并且内核定时器的运行没有周期性,到达计时终点后会自动关闭。如果要实现周期性定时,就要在定时处理函数中重新开启定时器。   Linux 内核中使用

    2024年02月08日
    浏览(39)
  • 基于STM32CUBEMX驱动低压步进器电机驱动器STSPIN220(3)----定时器中断产生指定数量脉冲

    在步进电机控制过程中,为了实现精确的位置和速度控制,经常需要输出指定数量的脉冲。这就需要使用定时器功能来生成PWM脉冲信号。本文将详细介绍如何利用STM32CUBEMX配置定时器以输出指定数量的PWM脉冲。 定时器是STM32微控制器的一个重要功能模块,可用于生成各种定时

    2024年02月14日
    浏览(48)
  • STM32标准库开发——TIM定时器中断

    定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时 根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型 不仅具备基本的定时中断功能

    2024年01月18日
    浏览(40)
  • 【STM32笔记】STM32的定时器开发基础(二)(基于STM32CubeMX实现定时器中断)

      传统STM32外部中断 的设计步骤:  (1)将GPIO初始化为输入端口。  (2)配置相关I/O引脚与中断线的映射关系。  (3)设置该I/O引脚对印的中断触发条件。  (4)配置NVIC,并使能中断。  (5)编写中断服务函数。   基于STM32CubeMX的外部中断 设计步骤  (1)在STM3

    2024年02月20日
    浏览(57)
  • 【Linux 裸机篇(八)】I.MX6U EPIT 定时器中断、定时器按键消抖

    EPIT 的全称是: Enhanced Periodic Interrupt Timer,直译过来就是增强的周期中断定时器,它主要是完成周期性中断定时的。学过 STM32 的话应该知道, STM32 里面的定时器还有很多其它的功能,比如输入捕获、 PWM 输出等等。但是 I.MX6U 的 EPIT 定时器只是完成周期性中断定时的,仅此一

    2024年02月02日
    浏览(60)
  • 学习笔记|定时器|STC中断|定时器时间计算|STC32G单片机视频开发教程(冲哥)|第十一集:定时器的作用和意义

    什么是定时器:定时器-与非网 上节课的一段代码: TimeCount++然后一个延时1毫秒,每运行1ms,变量就会加一。 系统已经运行了多少个毫秒。 实际使用时的代码如下, 判断按键有沿有按下的时候,我们等待按键松开,还有一个while循环。 如果没有松开,会一直死在这一行。所以,

    2024年02月09日
    浏览(59)
  • STM32控制步进电机:基于HAL库定时器中断的闭环步进电机驱动+精准控制脉冲数

    该篇文章中用到的步进电机闭环驱动器为Emm42_V4.0步进电机闭环驱动器。该闭环驱动器自带FOC矢量闭环控制算法,能实现力矩、速度、位置三环控制。 如下图所示,该42步进闭环电机驱动器的A+、A-、B+、B-连接步进电机,通过右侧的使能、脉冲、方向端对步进电机进行驱动控制

    2024年02月01日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包