驱动开发,基于中断子系统完成按键的中断驱动,引入中断底半部

news2024/11/28 3:48:28

一.引入linux内核中断目的

        引入linux内核中断之前,内核访问设备要不断轮询访问;

        引入linux内核中断便于内核对设备的访问,当设备事件发生后主动通知内核,内核再去访问设备;

二.linux内核中断实现过程框图      

 根据软中断号回调当前中断的 中断函数 过程:

        中断注册进内核之后,中断信息会保存在一个struct irq_desc对象中,内核中存在一个struct irq_desc类型的数组,软中断号就是数组的下标,数组中每一个成员都是保存了一个注册进内核的设备中断信息,类型为struct irqaction,struct irqaction对象里有中断处理函数的函数指针,指向自定义中断处理函数;

三.添加按键的设备树节点

 在stm32mp157a-fsmp1a.dts文件的根节点内部添加如下内容:

myirq

{

compatible="myirq"; interrupt-parent=<&gpiof>; interrupts=<9 0>,<7 0>,<8 0>;

};

四.中断底半部

1.引入目的(解决问题)

        当一个中断被触发以后,会关闭抢占,一个单核CPU处理当前中断任务时,当前CPU无法处理其他任务,所有的CPU都会关闭当前中断线。在这种情况下,如果一个中断中有延时、耗时甚至休眠操作,最终会导致整个系统功能的延迟。所以一般在中断处理过程中不允许有延时、耗时甚至休眠的操作。但是有的时候又必须在中断的处理程序中进行一些耗时任务。

        这样就会产生一个冲突:中断不允许有耗时但是有时候需要耗时的冲突;

2.解决上面冲突,引入中断底半部

       将一个中断处理得分过程分为了中断顶半部和中断底半部,中断顶半部就是通过 request_irq注册的中断处理函数,在顶半部中主要进行一些重要的、不耗时的任务;中断底半部则是区进行一些耗时,不紧急的任务。在执行中断底半部时,会将执行中断顶半部时关闭的中断线启用以及抢占开启,这样进程以及其他的中断就可以正常的工作了。

3.中断底半部的实现机制

        实现机制有softirq(软中断)、tasklet以及工作队列;

1)软中断机制

        当顶半部即将执行结束时开启软中断,在软中断处理函数中取处理当前中断里的耗时任务。软中断存在数量限制(32个),一般留给内核开发者使用。

2)tasklet机制

  •         基于软中断工作原理进行的;
  •         tasklet没有使用数量的限制;
  •         中断底半部可以进行耗时任务,但不可以进行休眠操作;
  •         工作于中断上下文,不用于进程上下文;

3)工作队列机制

        内核中存在工作队列对应的内核线程,这个线程从内核启动就存在,处于休眠态。当有任务需要执行时,只需要将任务提交到工作队列中,然后唤醒休眠的内核线程,由内核线程去处理对应的任务即可。工作队列既可以用于中断,也可以用于进程。

4)tasklet机制驱动代码

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

struct device_node *dnode;
unsigned int irqno[3];
int i;
struct tasklet_struct tasklet;  //分配tasklet对象

//定义底半部处理函数
void key_callback(struct tasklet_struct *t)
{
    int i;
    //耗时事件
    for(i=0; i<100; i++)
    {
        printk("i=%d\n",i);
    }
    
}

// 定义中断处理函数
irqreturn_t key_handler(int irq, void *dev)
{
    int witch = (int)dev;
    switch (witch)
    {
    case 0:
        printk("KEY1_INTERRUPT\n");
        break;
    case 1:
        printk("KEY2_INTERRUPT\n");
        break;
    case 2:
        printk("KEY3_INTERRUPT\n");
        break;
    }

    //开启底半部
    tasklet_schedule(&tasklet);
    return IRQ_HANDLED;
}

static int __init mycdev_init(void)
{
    // 1解析按键的设备树节点
    dnode = of_find_compatible_node(NULL, NULL, "myirq");
    if (dnode == NULL)
    {
        printk("解析设备树节点失败\n");
        return -ENXIO;
    }
    printk("解析设备树节点成功\n");

    // 2解析按键的软中断号
    for (i = 0; i < 3; i++)
    {
        irqno[i] = irq_of_parse_and_map(dnode, i);
        if (!irqno[i])
        {
            printk("解析按键%d软中断号失败\n", i);
            return -ENXIO;
        }
        printk("解析按键%d软中断号成功%d\n", i, irqno[i]);

        // 3注册按键1中断
        int ret = request_irq(irqno[i], key_handler, IRQF_TRIGGER_FALLING, "key_int", (void *)i);
        if (ret < 0)
        {
            printk("注册按键%d中断失败\n", i);
            return ret;
        }
    }
    printk("注册按键中断成功\n");

    //初始化底半部
    tasklet_setup(&tasklet,key_callback);

    return 0;
}
static void __exit mycdev_exit(void)
{
    // 注销中断
    int i;
    for (i = 0; i < 3; i++)
    {
        free_irq(irqno[i], (void *)i);
    }
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

现象:

5)工作队列机制驱动代码

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

struct device_node *dnode;
unsigned int irqno[3];
int i;
struct work_struct work;  //分配工作队列对象

//定义底半部处理函数
void key_work(struct work_struct *t)
{
    int i;
    //耗时事件
    for(i=0; i<100; i++)
    {
        printk("i=%d\n",i);
    }
    
}

// 定义中断处理函数
irqreturn_t key_handler(int irq, void *dev)
{
    int witch = (int)dev;
    switch (witch)
    {
    case 0:
        printk("KEY1_INTERRUPT\n");
        break;
    case 1:
        printk("KEY2_INTERRUPT\n");
        break;
    case 2:
        printk("KEY3_INTERRUPT\n");
        break;
    }

    //开启底半部
    schedule_work(&work);
    return IRQ_HANDLED;
}

static int __init mycdev_init(void)
{
    // 1解析按键的设备树节点
    dnode = of_find_compatible_node(NULL, NULL, "myirq");
    if (dnode == NULL)
    {
        printk("解析设备树节点失败\n");
        return -ENXIO;
    }
    printk("解析设备树节点成功\n");

    // 2解析按键的软中断号
    for (i = 0; i < 3; i++)
    {
        irqno[i] = irq_of_parse_and_map(dnode, i);
        if (!irqno[i])
        {
            printk("解析按键%d软中断号失败\n", i);
            return -ENXIO;
        }
        printk("解析按键%d软中断号成功%d\n", i, irqno[i]);

        // 3注册按键1中断
        int ret = request_irq(irqno[i], key_handler, IRQF_TRIGGER_FALLING, "key_int", (void *)i);
        if (ret < 0)
        {
            printk("注册按键%d中断失败\n", i);
            return ret;
        }
    }
    printk("注册按键中断成功\n");

    //初始化队列项
    INIT_WORK(&work,key_work);
    

    return 0;
}
static void __exit mycdev_exit(void)
{
    // 注销中断
    int i;
    for (i = 0; i < 3; i++)
    {
        free_irq(irqno[i], (void *)i);
    }
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

现象:

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

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

相关文章

STM32F103RCT6学习笔记2:串口通信

今日开始快速掌握这款STM32F103RCT6芯片的环境与编程开发&#xff0c;有关基础知识的部分不会多唠&#xff0c;直接实践与运用&#xff01;文章贴出代码测试工程与测试效果图&#xff1a; 目录 串口通信实验计划&#xff1a; 串口通信配置代码&#xff1a; 测试效果图&#…

2007-2021年31省市财政环保支出占比数据(含原始数据+计算过程+测算结果)

2007-2021年31省市财政环保支出占比数据&#xff08;含原始数据计算过程测算结果&#xff09; 1、时间&#xff1a;2007-2021年 2、来源&#xff1a;整理自国家统计局和统计年鉴 3、指标&#xff1a;财政环境保护支出、财政一般预算支出、环保支出占比 4、计算公式&#xf…

【jmeter】jmeter引用变量,变量值传递失败

最近在用jmeter做接口测试的时候&#xff0c;发现有个变量&#xff0c;参数值一直没有传递进来&#xff0c;导致request的时候&#xff0c;请求体里面一直是${}变量的形式。 后来经过排查发现&#xff0c;是因为我在定义用户变量的时候&#xff0c;在这个now后面多加了一个空格…

leetcode25 K个一组反转链表

题目 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部…

【SMBghost CVE-2020-0796漏洞复现】

目录 一、漏洞原理 二、复现过程 三、防护 一、漏洞原理 最近在做内网渗透的时候发现一大批可以利用的win系统资产&#xff0c;其中这些资产中对于445的开放限制不多&#xff1b;对于smb3.1版本的window系统存在可被利用的漏洞&#xff0c;即永恒之黑漏洞。SMBv3.1没有正确处…

Python爬虫:动态获取页面

动态网站根据用户的某些操作产生一些结果。例如&#xff0c;当网页仅在向下滚动或将鼠标移动到屏幕上时才完全加载时&#xff0c;这背后一定有一些动态编程。当您将鼠标指针悬停在某些文本上时&#xff0c;它会为您提供一些选项&#xff0c;它还包含一些动态.这是是一篇关于动态…

problen(5)ubuntu版本问题

浅浅记录一下这段时间的血和泪吧&#xff0c;大概耗时快一个月了吧&#xff0c;终于解决了...... 因为需要开启pwn之旅&#xff0c;需要在Ubuntu上安装一些东西&#xff0c;就是下面的一条命令&#xff1a; sudo pip3 install pwntools -i Simple Index&#xff08;显示不太好了…

mybatis-plus报错:Invalid bound statement (not found)

mybatis报错&#xff1a;Invalid bound statement (not found)的原因很多&#xff0c;但是正如报错提示一样&#xff0c;找不到xml中的sql语句&#xff0c;报错的情况分为三种&#xff1a; 第一种&#xff1a;语法错误 Java DAO层接口 public void delete(Param("id&qu…

网站登录界面制作(three.js 3D特效背景)+ boostrap导航栏实现 + jQuery移动窗口【附加源代码】

网站登录界面制作&#xff08;three.js 3D特效背景&#xff09; boostrap导航栏实现 文章目录 网站登录界面制作&#xff08;three.js 3D特效背景&#xff09; boostrap导航栏实现前言登录界面效果图主页面效果图&#xff1a;主页面源代码 前言 学过Web前端的许多小伙伴都会面…

计算机三级信息安全技术九十道选择题

1、Windows7操作系统中&#xff0c;配置IPSec时支持的身份验证方法不包括 A、Kerberos协议 B、 数字证书 C、预共享密钥 D、 会话密钥 答案&#xff1a; D 解析&#xff1a; 2、企业销售商用密码产品时&#xff0c;应向国家密码管理机构申请&#xff0c;必需具备的条件是…

MHA、MQA、GQA区别和联系

2023 年7月&#xff0c;Meta发布了其最新版本LLaMA 2&#xff0c;其中 LLama2 的注意力机制使用了GQA&#xff0c;那么什么是GQA呢&#xff1f;和标准的MHA有什么区别呢&#xff1f;关于 LLM 更多信息&#xff0c;可参考笔者文章&#xff1a;AIGC入门 - LLM信息概览 本文将介绍…

携手并进 | 云畅科技与华商智造院签署战略合作协议

9 月 15 日&#xff0c;云畅科技与华商智造院的签约仪式顺利举行&#xff0c;湖南华商智造院董事长郭平、湖南华商智造院董事兼副总经理秦宇琳、湖南华商智造院湘江新区总经理郭蕊、云畅科技董事长兼 CEO 蔡鑫莹、云畅科技联合创始人兼 CMO 徐智峰等出席活动&#xff0c;共同见…

Kafka 杂谈

概览 什么是 Kafka&#xff1f; 这里先给出结论&#xff0c;我不太希望在解释概念 X 的时候&#xff0c;说到「为了了解 X&#xff0c;我们需要先了解一下 Y」&#xff0c;阅读的人思绪会被迁到另一个地方。既然小标题里说了要解释什么是 Kafka&#xff0c;那么我们就只说什么…

兔兔答题企业版1.0.0版本全网发布,同时开源前端页面到unicloud插件市场

项目说明 兔兔答题是用户端基于uniapp开发支持多端适配&#xff0c;管理端端采用TypeScriptVue3.jselement-plus&#xff0c;后端采用THinkPHP6PHP8Golang开发的一款在线答题应用程序。 问题反馈 线上预览地址 相关问题可以通过下方的二维码&#xff0c;联系到我。了解更多 …

15.状态模式(State)

UML 意图&#xff1a;允许一个对象在其内部状态改变时改变它的行为&#xff0c;使得对象看起来好像修改了它的类型一样。 Context&#xff1a;定义客户感兴趣的接口&#xff1b; 维护一个ConcreteState子类的实例&#xff0c;这个实例定义当前的状态。 State&#xff1a;定义一…

FPGA原理与结构(0)——目录与传送门

一、 简介 FPGA的设计和软件设计不同&#xff0c;我们所设计的RTL代码最终还是要落实到硬件底层来进行实例化&#xff0c;因此理解硬件底层的内容是很有意义的。 二、可编程逻辑块CLB 可配置逻辑块CLB&#xff08;Configurable Logic Block&#xff09;是xilinx系类FPGA的基本…

极验率先推出一键认证安全版,供客户自主免费升级,规避日常运营中的风险盲区

2017年6月1日&#xff0c;互联网服务开始响应《中华人民共和国网络安全法》的要求实施账号实名认证。由此&#xff0c;手机号码成为网络世界最主要的“身份证”&#xff0c;也让本机号码一键认证成为可能。其中&#xff0c;极验是最早的直连三大运营商的五家供应商之一&#xf…

Linux内核分析:输入输出,字符与块设备 31-35

CPU 并不直接和设备打交道,它们中间有一个叫作设备控制器(Device Control Unit)的组件,例如硬盘有磁盘控制器、USB 有 USB 控制器、显示器有视频控制器等。这些控制器就像代理商一样,它们知道如何应对硬盘、鼠标、键盘、显示器的行为。 输入输出设备我们大致可以分为两类…

“深入理解事件处理器、表单综合案例和组件通信“

目录 引言1. Vue的事件处理器2. Vue的表单综合案例3. Vue的组件通信总结 引言 Vue.js是一款流行的JavaScript框架&#xff0c;广泛应用于现代Web开发中。在Vue的世界里&#xff0c;事件处理器、表单综合案例和组件通信是三个重要的主题。本文将深入探讨这些主题&#xff0c;并…