linux 中断子系统 层级中断编程

虚拟中断控制器代码:

#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/clk.h>
#include<linux/err.h>
#include<linux/init.h>
#include<linux/interrupt.h>
#include<linux/io.h>
#include<linux/irq.h>
#include<linux/irqdomain.h>
#include<linux/of.h>
#include<linux/gpio.h>
#include<linux/platform_device.h>
#include<linux/of_device.h>
#include<linux/irqchip/chained_irq.h>
#include<linux/of_irq.h>static struct irq_domain *virt_intc_domain;
static u32 upper_hwirq_base;static void virt_intc_irq_ack(struct irq_data *d)
{printk("%s %d\n", __FUNCTION__, __LINE__);irq_chip_ack_parent(d);
}static void virt_intc_irq_mask(struct irq_data *d)
{printk("%s %d\n", __FUNCTION__, __LINE__);irq_chip_mask_parent(d);
}static void virt_intc_irq_mask_ack(struct irq_data *d)
{printk("%s %d\n", __FUNCTION__, __LINE__);
}static void virt_intc_unmask(struct irq_data *d)
{printk("%s %d\n", __FUNCTION__, __LINE__);irq_chip_unmask_parent(d);
}static void virt_intc_irq_eoi(struct irq_data *d)
{printk("%s %d\n", __FUNCTION__, __LINE__);irq_chip_eoi_parent(d);
}/*在回调函数里加打印观察调用顺序,理解调用过程*/
static struct irq_chip virt_intc_irq_chip = {.name = "virt_intc",.irq_ack = virt_intc_irq_ack,.irq_mask = virt_intc_irq_mask,.irq_mask_ack = virt_intc_irq_mask_ack,.irq_unmask = virt_intc_unmask,.irq_eoi = 	virt_intc_irq_eoi,
};//利用改函数解析设备树
static int virt_intc_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec,unsigned long *out_hwirq, unsigned int *out_type)
{if(is_of_node(fwspec->fwnode)) {if(fwspec->param_count != 2)return -EINVAL;*out_hwirq = fwspec->param[0]; //硬件中断号*out_type = fwspec->param[1]; //触发类型printk("param[0] = %d, param[1] = %d\n", fwspec->param[0], fwspec->param[1]);return 0;}return -EINVAL;
}//这个虚拟中断控制器的alloc函数主要设置irq_domain里的啥?
static int virt_intc_domain_alloc(struct irq_domain *domain, unsigned int virq,unsigned int nr_irqs, void *data)
{struct irq_fwspec *fwspec = data;struct irq_fwspec parent_fwspec;irq_hw_number_t hwirq;int i;//这里的参数domain指的是virt_intc_domainhwirq = fwspec->param[0];printk("virq = %d, hwirq = %ld, nr_irqs = %d, domain = %px\n", virq, hwirq, nr_irqs, domain);for(i = 0; i < nr_irqs; i++)//设置irq_desc[virq].irq_data的相关变量. handle_irq不设置吗?(不需要)irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, &virt_intc_irq_chip, NULL);//virt的domain的父domainparent_fwspec.fwnode = domain->parent->fwnode; //gic中断信息parent_fwspec.param_count = 3;//描述层级关系是如何对应的parent_fwspec.param[0] = GIC_SPI;parent_fwspec.param[1] = fwspec->param[0] + upper_hwirq_base;parent_fwspec.param[2] = fwspec->param[1];/*1:函数会根据传入的参数,找到对应的父中断控制器,并在父中断控制器中为这些中断分配irq号2:配置父控制器的irq_desc(包括handle_irq和irq_chip)3:完成中断链路的配置(子控制器中断能够通过父控制器进行处理)//调用domain->parent的alloc函数继续设置*/return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_fwspec);
}static const struct irq_domain_ops virt_intc_domain_ops = {.translate = virt_intc_domain_translate, .alloc = virt_intc_domain_alloc,
};static int virt_intc_probe(struct platform_device *pdev)
{struct device_node *parent_node;struct irq_domain *parent_domain;of_property_read_u32(node, "upper_hwirq_base", &upper_hwirq_base);printk("%s %d upper_hwirq_base = %d\n", __FUNCTION__, __LINE__, upper_hwirq_base);parent_node = of_irq_find_parent(pdev->dev.of_node);parent_domain = irq_find_host(parent_node);virt_intc_domain = irq_domain_add_hierarchy(parent_domain, 0, 4, pdev->dev.of_node, &virt_intc_domain_ops, NULL);printk("parent_domain = %px, virt_intc_domain = %px\n", parent_domain, virt_intc_domain);return 0;
}static void virt_intc_remove(struct platform_device *pdev)
{printk("%s %d\n", __FUNCTION__, __LINE__);
}static const struct of_device_id virt_intc_of_match[] = {{ .compatible = "hvirt_intc", },{ },
};static struct platform_driver virt_intc_driver = {.probe = virt_intc_probe,.remove = virt_intc_remove,.driver = {.name = "virt_intc",.of_match_table = of_match_ptr(virt_intc_of_match),}
};static int __init virt_intc_init(void)
{printk("%s %d\n", __FUNCTION__, __LINE__);return platform_driver_register(&virt_intc_driver);
}static void __exit virt_intc_exit(void)
{printk("%s %d\n", __FUNCTION__, __LINE__);platform_driver_unregister(&virt_intc_driver);
}module_init(virt_intc_init);
module_exit(virt_intc_exit);MODULE_AUTHOR("Tan xujia");
MODULE_LICENSE("Dual BSD/GPL");
/*
//虚拟中断控制器设备树(层级)
virt_intc:virt_intc {compatible = "hvirt_intc";interrupt-controller;#interrupt-cells = <2>;interrupt-parent = <&gic>; //intc有irq_domainupper_hwirq_base = <210>;
};参考:gpc.c arch\arm\mach-imx
*/

虚拟按键代码

#include<linux/module.h>
#include<linux/fs.h>
#include<linux/errno.h>
#include<linux/init.h>
#include<linux/major.h>
#include<linux/irq.h>
#include<linux/interrupt.h>
#include<linux/kernel.h>
#include<linux/of_irq.h>
#include<linux/of_gpio.h>
#include<linux/gpio/consumer.h>
#include<linux/platform_device.h>
#include<linux/slab.h>struct gpio_key {int irq;int cnt;char name[20];
};static struct gpio_key gpio_keys[4];static irqreturn_t gpio_key_isr(int irq, void *dev_id)
{struct gpio_key *g_key = dev_id;printk("%s %d name = %s, cnt = %d\n", __FUNCTION__, __LINE__, g_key->name, g_key->cnt++);return IRQ_HANDLED;
}static int gpio_key_probe(struct platform_device *pdev)
{//struct device_node *node = pdev->dev.of_node;int irq, err, i = 0;while(1) {//根据设备树这里能获取到4个虚拟中断号irq = platform_get_irq(pdev, i); //0-3, i等于4时退出if(irq < 0)break;//将虚拟中断号保存在这里gpio_keys[i].irq = irq;sprintf(gpio_keys[i].name, "gpio_key-%d", i);//注册中断err = devm_request_irq(&pdev->dev, gpio_keys[i].irq, gpio_key_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, gpio_keys[i].name, &gpio_keys[i]);printk("err = %d, irq = %d\n", err, irq); /*16-19*/i++;}printk("%s %d\n", __FUNCTION__, __LINE__);return 0;
}static void gpio_key_remove(struct platform_device *pdev)
{printk("%s %d\n", __FUNCTION__, __LINE__);
}static const struct of_device_id gpio_key_of_match[] = {{ .compatible = "gpio_key", },{ },
};static struct platform_driver gpio_key_driver = {.probe = gpio_key_probe,.remove = gpio_key_remove,.driver = {.name = "gpio_key",.of_match_table = of_match_ptr(gpio_key_of_match),}
};static int __init gpio_key_init(void)
{printk("%s %d\n", __FUNCTION__, __LINE__);return platform_driver_register(&gpio_key_driver);
}static void __exit gpio_key_exit(void)
{printk("%s %d\n", __FUNCTION__, __LINE__);platform_driver_unregister(&gpio_key_driver);
}module_init(gpio_key_init);
module_exit(gpio_key_exit);MODULE_AUTHOR("Tan xujia");
MODULE_LICENSE("Dual BSD/GPL");//虚拟按键设备树(链式和层级)
/*
gpio_keys:gpio_keys {compatible = "gpio_key";interrupt-parent = <&virt_intc>; //virt_intc有irq_domaininterrupts = <0 IRQ_TYPE_LEVEL_HIGH>,<1 IRQ_TYPE_LEVEL_HIGH>,<2 IRQ_TYPE_LEVEL_HIGH>,<3 IRQ_TYPE_LEVEL_HIGH>;
};
*/

参考:https://blog.csdn.net/caiji0169/article/details/143862261

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

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

相关文章

虾皮(Shopee)商品详情 API 接口概述及 JSON 数据返回参考

前言 一、接口概述 Shopee 商品详情 API 接口是 Shopee 平台为开发者提供的&#xff0c;用于获取商品详细信息的接口服务。通过该接口&#xff0c;开发者可以获取商品的标题、价格、库存、描述、图片、规格参数、销量、评价等详细信息。这些数据为电商数据分析、商品比价工具…

three.js中的instancedMesh类优化渲染多个同网格材质的模型

three.js小白的学习之路。 在上上一篇博客中&#xff0c;简单验证了一下three.js中的网格共享。写的时候就有一些想法&#xff0c;如果说某个场景中有一万棵树&#xff0c;这些树共享一个geometry和material&#xff0c;有没有好的办法将其进行一定程度上的渲染优化&#xff0…

MySQL-自定义函数

自定义函数 函数的作用 mysql数据库中已经提供了内置的函数&#xff0c;比如&#xff1a;sum&#xff0c;avg&#xff0c;concat等等&#xff0c;方便我们日常的使用&#xff0c;当需要时mysql支持定义自定义的函数&#xff0c;方便与我们对于需用复用的功能进行封装。 基本…

ESP32上C语言实现JSON对象的创建和解析

在ESP32上使用C语言实现JSON对象的创建和解析&#xff0c;同样可以借助cJSON库。ESP-IDF&#xff08;Espressif IoT Development Framework&#xff09;本身已经集成了cJSON库&#xff0c;你可以直接使用。以下是详细的步骤和示例代码。 1. 创建一个新的ESP-IDF项目 首先&…

【FAQ】PCoIP 会话后物理工作站本地显示器黑屏

# 问题 工作人员从家里建立了到办公室工作站的 PCoIP 连接&#xff0c;该工作站安装了 HP Anyware Graphics Agent&#xff0c;并且还连接了本地显示器。然后&#xff0c;远程用户决定去办公室进行本地工作&#xff0c;工作站显示器显示黑屏&#xff08;有时没有信号&#xff…

el-table 目录树列表本地实现模糊查询

table目录树结构实现模糊查询 <el-form :model"queryParams" ref"queryForm" size"small" :inline"true" v-show"showSearch"><el-form-item label"名称:" prop"Name"><el-input v-mode…

力扣hot100 LeetCode 热题 100 Java 哈希篇

两数之和 1. 两数之和 - 力扣&#xff08;LeetCode&#xff09; 直接暴力 class Solution {public int[] twoSum(int[] nums, int target) {for(int i0;i<nums.length;i){for(int ji1;j<nums.length;j){long ans nums[i]nums[j];if(ans>target)continue;if(anstarg…

前后端部署

#在学习JavaWeb之后&#xff0c;进行了苍穹外卖的学习。在进行苍穹外卖的部署的时候&#xff0c;作者遇到了下面的问题# 1.前端工程nginx无法启动&#xff1a; 当我双击已经部署好的nginx工程中nginx.exe文件的时候&#xff0c;在服务中&#xff0c;并没有找到ngnix成功运行。…

基于 EFISH-SBC-RK3588 的无人机环境感知与数据采集方案

一、核心硬件架构设计‌ ‌高性能算力引擎&#xff08;RK3588 处理器&#xff09;‌ ‌异构计算架构‌&#xff1a;集成 8 核 CPU&#xff08;4Cortex-A762.4GHz 4Cortex-A551.8GHz&#xff09;&#xff0c;支持动态调频与多任务并行处理&#xff0c;单线程性能较传统四核方案…

什么是Maven

Maven的概念 Maven是一个一键式的自动化的构建工具。Maven 是 Apache 软件基金会组织维护的一款自动化构建工具&#xff0c;专注服务于Java 平台的项目构建和依赖管理。Maven 这个单词的本意是&#xff1a;专家&#xff0c;内行。Maven 是目前最流行的自动化构建工具&#xff0…

mongo客户端操作mongodb记录

背景&#xff1a; 长时间不操作mongodb数据库&#xff0c;已经遗忘了命令&#xff0c;今天正好用到&#xff0c;温习一下 直接上命令 #进入mongodb数据库安装bin目录cd /opt/mongodb/bin#连接mongodb ./mongo #查看所有的数据库 show dbs; #选择数据库 use xx; #查看表 show …

rocky9.4部署k8s群集v1.28.2版本(containerd)(纯命令)

文章目录 前言三个节点的主机名 所有节点操作主机名和ip解析关闭交换分区&#xff0c;关闭防火墙&#xff0c;关闭selinux更换阿里云yum源时间同步修改内核参数修改系统最大打开文件数开启bridge网桥过滤&#xff0c;加载br_netfilter模块&#xff0c;加载配置文件安装ipset及i…

解析塔能科技:绿色低碳智慧节能一站式破局之匙

在能源问题日益凸显的当下&#xff0c;绿色低碳、高效节能成为全球发展的重要课题。对各类节能方案进行深入剖析后&#xff0c;可以发现塔能科技的绿色低碳智慧节能一站式解决方案极具创新性与实用性&#xff0c;切实为众多行业面临的能源困境提供了有效解决路径。 直面行业痛点…

精选面试题

1、js中set和map的作用和区别? 在 JavaScript 中&#xff0c;Set 和 Map 是两种非常重要的集合类型 1、Set 是一种集合数据结构&#xff0c;用于存储唯一值。它类似于数组&#xff0c;但成员的值都是唯一的&#xff0c;没有重复的值。Set 中的值只能是唯一的&#xff0c;任何…

Flutter之路由和导航

目录&#xff1a; 1、flutter路由和导航简介2、路由的使用2.1、使用 Navigator2.2、使用命名路由2.3、使用路由器 3、应用中添加Tab导航4、页面跳转一个新页面和回退5、传递数据到新页面6、使用 RouteSettings 传递参数 1、flutter路由和导航简介 Flutter 提供了一个完整的系统…

KMS工作原理及其安全性分析

在当今数字化时代&#xff0c;数据安全已经成为企业和个人最为关注的话题之一。随着云计算和大数据的快速发展&#xff0c;如何安全地管理密钥成为了一个重要的挑战。KMS&#xff08;Key Management Service&#xff0c;密钥管理服务&#xff09;作为一种专业的密钥管理解决方案…

机器学习在网络安全中的应用:守护数字世界的防线

一、引言 随着信息技术的飞速发展&#xff0c;网络安全问题日益凸显&#xff0c;成为全球关注的焦点。传统的网络安全防护手段&#xff0c;如防火墙、入侵检测系统&#xff08;IDS&#xff09;和防病毒软件&#xff0c;虽然在一定程度上能够抵御攻击&#xff0c;但在面对复杂多…

Java在excel中导出动态曲线图DEMO

1、环境 JDK8 POI 5.2.3 Springboot2.7 2、DEMO pom <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version></dependency><dependency><groupId>commons…

Android APP 爬虫操作

工具 夜神模拟器、charles、mitm 等 mitm的使用参考:Mitmproxy对Android进行抓包&#xff08;真机&#xff09;_mitmproxy 安卓-CSDN博客 charles的使用参考&#xff1a;【全网最详细】手把手教学Charles抓包工具详细自学教程&#xff0c;完整版安装教程&#xff0c;详细介绍…

Redis的LFU策略具体怎么工作?

Redis的LFU&#xff08;Least Frequently Used&#xff09;策略通过动态跟踪键的访问频率实现淘汰决策&#xff0c;其核心工作逻辑可分为以下四个部分&#xff1a; 数据结构设计‌ 字段拆分‌&#xff1a;每个Redis对象&#xff08;redisObject&#xff09;的lru字段&#xff…