linux 中斷子系統鏈式中斷編程

直接貼代碼了:
虛擬中斷控制器代碼,chained_virt.c

#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>static struct irq_domain *virt_intc_domain;static void virt_intc_irq_ack(struct irq_data *d)
{//ffff800080b68be0, ffff000101d37100, ffff800080717500printk("irq = %d, hwirq = %ld, %px, %px, %px\n", d->irq, d->hwirq, d->chip, d->domain, d->domain->ops);printk("%s %d\n", __FUNCTION__, __LINE__);
}static void virt_intc_irq_mask(struct irq_data *d)
{printk("irq = %d, hwirq = %ld, %px, %px, %px\n", d->irq, d->hwirq, d->chip, d->domain, d->domain->ops);printk("%s %d\n", __FUNCTION__, __LINE__);
}static void virt_intc_irq_mask_ack(struct irq_data *d)
{printk("irq = %d, hwirq = %ld, %px, %px, %px\n", d->irq, d->hwirq, d->chip, d->domain, d->domain->ops);printk("%s %d\n", __FUNCTION__, __LINE__);
}static void virt_intc_unmask(struct irq_data *d)
{//ffff800080b68be0, ffff000101d37100, ffff800080717500printk("irq = %d, hwirq = %ld, %px, %px, %px\n", d->irq, d->hwirq, d->chip, d->domain, d->domain->ops);printk("%s %d\n", __FUNCTION__, __LINE__);
}/*在回調函數里加打印觀察調用順序,理解調用過程*/
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,
};/*
為virq(irq_desc)設置irq chip, highlevel irq-events handle和irq chip data*/
static int virt_intc_irq_map(struct irq_domain *domain, unsigned int virq, irq_hw_number_t hwirq)
{irq_set_chip_data(virq, domain->host_data);/*給virq提供處理函數,給irq_chip提供ops處理集,handle_level_irq里會調用request_irq注冊的函數()*/irq_set_chip_and_handler(virq, &virt_intc_irq_chip, handle_edge_irq);/* 調用過程如下:handle_level_irq->handle_irq_event->handle_irq_event_percpu->__handle_irq_event_percpu->action->handler(irq, action->dev_id);*///irq_set_nested_thread(virq, 1);//irq_set_noprobe(virq); //domain -> ffff000101d37100printk("%s %d, virq = %d, hwirq = %ld, doamin = %px\n", __FUNCTION__, __LINE__, virq, hwirq, domain);return 0;
}static const struct irq_domain_ops virt_intc_domain_ops = {.xlate = irq_domain_xlate_onecell, //解析設備樹,得到硬件中斷號和觸發類型.map = virt_intc_irq_map, //調用時機。創建或者更新hw_irq和virq關系時(創建irq_domain)
};static u8 virt_intc_get_hwirq(void)
{return get_random_u8() % 0x3;
}static void virt_intc_irq_handler(struct irq_desc *desc) //發生200號中斷時對應的15->irq_desc
{int hwirq;struct irq_chip *chip = irq_desc_get_chip(desc);printk("desc = %px,  chip = %px\n", desc, chip);//gic mask/ack 200號中斷 調用gic的chip提供的回調函數處理chained_irq_enter(chip, desc); //鏈式處理函數的入口函數//分便是哪一個中斷(隨機數產生)hwirq = virt_intc_get_hwirq(); //下一級的設備樹解析得到的是0,1,2,3//ffff80008070e810printk("%s %d, hwirq = %d, %px\n", __FUNCTION__, __LINE__, hwirq, chip);/*根據gpio hwirq找到對應的virq, 依靠注冊的域virt_intc_domain調用其對應的handle_irq(handleC), 這里的handle應該是下一級提供的*/generic_handle_irq(irq_find_mapping(virt_intc_domain, hwirq)); //這里調用的就是virt_intc_irq_map函數里設置的handle_edge_irq//gic unmask 200號中斷 調用gic的chip提供的回調函數處理chained_irq_exit(chip, desc); //鏈式處理函數的退出函數
}static int virt_intc_probe(struct platform_device *pdev)
{struct device_node *np = pdev->dev.of_node;int irq_to_parent;/*上一級是gic, 根據gic里irq_domain的ops解析設備樹得到hwirq和type并分配/找到irq_desc得到virq*/irq_to_parent = platform_get_irq(pdev, 0); //上一級是gic所以用gic的irq_domain_ops函數解析printk("irq_to_parent = %d\n", irq_to_parent); //15 hwirq = 200//為irq_desc[irq_to_parent].handle_irq設置回調函數(handleB)irq_set_chained_handler_and_data(irq_to_parent, virt_intc_irq_handler, NULL); //highlevel irq-events handler -> virt_intc_irq_handler#if 0//注冊virt_intc_domain時需要irq_base參數,這里先進行分配,返回的是描述符的下標(連續的4個)int irq_base = irq_alloc_descs(-1, 0, 4, numa_node_id());//為virt_intc_domain,irq_base(相當于virq和desc),hwirq(np里面有硬件中斷號描述信息)形成映射關系virt_intc_domain = irq_domain_add_legacy(np, 4, irq_base, 0, &virt_intc_domain_ops, NULL); //ffff000101d37100printk("%s %d virt_intc_domain = %px, irq_base = %d\n", __FUNCTION__, __LINE__, virt_intc_domain, irq_base);
#else/*Usage:a. dts:定義使用那個hwirqb. 內核解析設備樹時分配irq_des, 得到virqc. (hwirq, virq) =>存入domain下一級使用到interrupt-parent = <&virt_intc>時,使用virt_intc_domain_ops里的xlate函數解析設備樹*/virt_intc_domain = irq_domain_add_linear(np, 4, &virt_intc_domain_ops, NULL);
#endifreturn 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 = "virt_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");
//devmem 0xf0001218 w 0x00000100
/*
//虛擬中斷控制器設備樹(鏈式)
virt_intc:virt_intc {compatible = "virt_intc";interrupt-controller;#interrupt-cells = <2>;interrupt-parent = <&gic>; //intc有irq_domaininterrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>; //對應的gic中斷號就是200
};產生中斷的外設需定義:
1:interrupt-parent
2:interrupts中斷控制器需定義:
1:interrupt-controller
2:#interrupt-cells
*//*
對應關系:
irq_desc[15].handle_irq = virt_intc_irq_handler;
irq_desc[15].irq_data.chip = gic_irq_chip;
irq_desc[15].irq_data.domain = gic_domain;
irq_desc[15].irq_data.domain.ops = gic_domain_ops;
irq_desc[15].irq_data.hwirq = 200;
irq_desc[15].irq_data.irq = 15;irq_desc[16].handle_irq = handle_edge_irq;
irq_desc[16].irq_data.chip = virt_intc_irq_chip;
irq_desc[16].irq_data.domain = virt_intc_domain;
irq_desc[16].irq_data.domain.ops = virt_intc_domain_ops;
irq_desc[16].irq_data.hwirq = 0;
irq_desc[16].irq_data.irq = 16;irq_desc[17].handle_irq = handle_edge_irq;
irq_desc[17].irq_data.chip = virt_intc_irq_chip;
irq_desc[17].irq_data.domain = virt_intc_domain;
irq_desc[17].irq_data.domain.ops = virt_intc_domain_ops;
irq_desc[17].irq_data.hwirq = 1;
irq_desc[17].irq_data.irq = 17;irq_desc[18].handle_irq = handle_edge_irq;
irq_desc[18].irq_data.chip = virt_intc_irq_chip;
irq_desc[18].irq_data.domain = virt_intc_domain;
irq_desc[18].irq_data.domain.ops = virt_intc_domain_ops;
irq_desc[18].irq_data.hwirq = 2;
irq_desc[18].irq_data.irq = 18;irq_desc[19].handle_irq = handle_edge_irq;
irq_desc[19].irq_data.chip = virt_intc_irq_chip;
irq_desc[19].irq_data.domain = virt_intc_domain;
irq_desc[19].irq_data.domain.ops = virt_intc_domain_ops;
irq_desc[19].irq_data.hwirq = 3;
irq_desc[19].irq_data.irq = 19;
*/

gpio按鍵代碼:gpio_key.c

#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.pswp.cn/web/76979.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76979.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76979.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

容器修仙傳 我的靈根是Pod 第10章 心魔大劫(RBAC與SecurityContext)

第四卷&#xff1a;飛升之劫化神篇 第10章 心魔大劫&#xff08;RBAC與SecurityContext&#xff09; 血月當空&#xff0c;林衍的混沌靈根正在異變。 每道經脈都爬滿黑色紋路&#xff0c;神識海中回蕩著蠱惑之音&#xff1a;"破開藏經閣第九層禁制…奪取《太古弒仙訣》……

基于c#,wpf,ef框架,sql server數據庫,音樂播放器

詳細視頻: 【基于c#,wpf,ef框架,sql server數據庫&#xff0c;音樂播放器。-嗶哩嗶哩】 https://b23.tv/ZqmOKJ5

精益數據分析(21/126):剖析創業增長引擎與精益畫布指標

精益數據分析&#xff08;21/126&#xff09;&#xff1a;剖析創業增長引擎與精益畫布指標 大家好&#xff01;在創業和數據分析的探索道路上&#xff0c;我一直希望能和大家攜手共進&#xff0c;共同學習。今天&#xff0c;我們繼續深入研讀《精益數據分析》&#xff0c;剖析…

Spark-streaming核心編程

1.導入依賴?&#xff1a; <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming-kafka-0-10_2.12</artifactId> <version>3.0.0</version> </dependency> 2.編寫代碼?&#xff1a; 創建Sp…

Kafka的ISR機制是什么?如何保證數據一致性?

一、Kafka ISR機制深度解析 1. ISR機制定義 ISR&#xff08;In-Sync Replicas&#xff09;是Kafka保證數據一致性的核心機制&#xff0c;由Leader副本&#xff08;復雜讀寫&#xff09;和Follower副本(負責備份)組成。當Follower副本的延遲超過replica.lag.time.max.ms&#…

Docker 基本概念與安裝指南

Docker 基本概念與安裝指南 一、Docker 核心概念 1. 容器&#xff08;Container&#xff09; 容器是 Docker 的核心運行單元&#xff0c;本質是一個輕量級的沙盒環境。它基于鏡像創建&#xff0c;包含應用程序及其運行所需的依賴&#xff08;如代碼、庫、環境變量等&#xf…

數據庫監控 | MongoDB監控全解析

PART 01 MongoDB&#xff1a;靈活、可擴展的文檔數據庫 MongoDB作為一款開源的NoSQL數據庫&#xff0c;憑借其靈活的數據模型&#xff08;基于BSON的文檔存儲&#xff09;、水平擴展能力&#xff08;分片集群&#xff09;和高可用性&#xff08;副本集架構&#xff09;&#x…

OpenFeign和Gateway

OpenFeign和Gateway 一.OpenFeign介紹二.快速上手1.引入依賴2.開啟openfeign的功能3.編寫客戶端4.修改遠程調用代碼5.測試 三.OpenFeign參數傳遞1.傳遞單個參數2.多個參數、傳遞對象和傳遞JSON字符串3.最佳方式寫代碼繼承的方式抽取的方式 四.部署OpenFeign五.統一服務入口-Gat…

spark-streaming(二)

DStream創建&#xff08;kafka數據源&#xff09; 1.在idea中的 pom.xml 中添加依賴 <dependency><groupId>org.apache.spark</groupId><artifactId>spark-streaming-kafka-0-10_2.12</artifactId><version>3.0.0</version> </…

JAVA聚焦OutOfMemoryError 異常

個人主頁 文章專欄 在正文開始前&#xff0c;我想多說幾句&#xff0c;也就是吐苦水吧…最近這段時間一直想寫點東西&#xff0c;停下來反思思考一下。 心中萬言&#xff0c;真正執筆時又不知先寫些什么。通常這個時候&#xff0c;我都會隨便寫寫&#xff0c;文風極像散文&…

如何在Spring Boot中配置自定義端口運行應用程序

Spring Boot 應用程序默認在端口 8080 上運行嵌入式 Web 服務器&#xff08;如 Tomcat、Jetty 或 Undertow&#xff09;。然而&#xff0c;在開發、測試或生產環境中&#xff0c;開發者可能需要將應用程序配置為在自定義端口上運行&#xff0c;例如避免端口沖突、適配微服務架構…

linux嵌入式(進程與線程1)

Linux進程 進程介紹 1. 進程的基本概念 定義&#xff1a;進程是程序的一次執行過程&#xff0c;擁有獨立的地址空間、資源&#xff08;如內存、文件描述符&#xff09;和唯一的進程 ID&#xff08;PID&#xff09;。 組成&#xff1a; 代碼段&#xff1a;程序的指令。 數據…

智馭未來:NVIDIA自動駕駛安全白皮書與實驗室創新實踐深度解析

一、引言&#xff1a;自動駕駛安全的范式革新 在當今數字化浪潮的推動下&#xff0c;全球自動駕駛技術正大步邁入商業化的深水區。隨著越來越多的自動駕駛車輛走上道路&#xff0c;其安全性已成為整個行業乃至社會關注的核心命題。在這個關鍵的轉折點上&#xff0c;NVIDIA 憑借…

多模態大模型 Qwen2.5-VL 的學習之旅

Qwen-VL 是阿里云研發的大規模視覺語言模型&#xff08;Large Vision Language Model, LVLM&#xff09;。Qwen-VL 可以以圖像、文本、檢測框作為輸入&#xff0c;并以文本和檢測框作為輸出。Qwen-VL 系列模型性能強大&#xff0c;具備多語言對話、多圖交錯對話等能力&#xff…

Redis 與 Memcache 全面對比:功能、性能與應用場景解析

Redis 和 Memcache 都是常用的內存數據庫&#xff0c;以下是它們在多個方面的能力比較&#xff1a; 一、數據類型 Redis&#xff1a;支持豐富的數據類型&#xff0c;如字符串&#xff08;String&#xff09;、哈希&#xff08;Hash&#xff09;、列表&#xff08;List&#x…

Oracle--PL/SQL編程

前言&#xff1a;本博客僅作記錄學習使用&#xff0c;部分圖片出自網絡&#xff0c;如有侵犯您的權益&#xff0c;請聯系刪除 PL/SQL&#xff08;Procedural Language/SQL&#xff09;是Oracle數據庫中的一種過程化編程語言&#xff0c;構建于SQL之上&#xff0c;允許編寫包含S…

新增優惠券

文章目錄 概要整體架構流程技術細節小結 概要 接口分析 一個基本的新增接口&#xff0c;按照Restful風格設計即可&#xff0c;關鍵是請求參數。之前表分析時已經詳細介紹過這個頁面及其中的字段&#xff0c;這里不再贅述。 需要特別注意的是&#xff0c;如果優惠券限定了使…

力扣面試經典150題(第二十三題)- KMP算法

問題 給你兩個字符串 haystack 和 needle &#xff0c;請你在 haystack 字符串中找出 needle 字符串的第一個匹配項的下標&#xff08;下標從 0 開始&#xff09;。如果 needle 不是 haystack 的一部分&#xff0c;則返回 -1 。 示例 1&#xff1a; 輸入&#xff1a;haysta…

PostgreSQL 的 MVCC 機制了解

PostgreSQL 的 MVCC 機制了解 PostgreSQL 使用多版本并發控制(MVCC)作為其核心并發控制機制&#xff0c;這是它與許多其他數據庫系統的關鍵區別之一。MVCC 允許讀操作不阻塞寫操作&#xff0c;寫操作也不阻塞讀操作&#xff0c;從而提供高度并發性。 一 MVCC 基本原理 1.1 M…

互聯網大廠Java面試:RocketMQ、RabbitMQ與Kafka的深度解析

互聯網大廠Java面試&#xff1a;RocketMQ、RabbitMQ與Kafka的深度解析 面試場景 面試官&#xff1a;馬架構&#xff0c;您好&#xff01;歡迎參加我們的面試。今天我們將圍繞消息中間件展開討論&#xff0c;尤其是RocketMQ、RabbitMQ和Kafka。您有十年的Java研發和架構設計經…