前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Linux系统GIC驱动程序分析

Linux系统GIC驱动程序分析

作者头像
韦东山
发布于 2021-12-08 02:19:34
发布于 2021-12-08 02:19:34
4.3K00
代码可运行
举报
文章被收录于专栏:韦东山嵌入式韦东山嵌入式
运行总次数:0
代码可运行

资料下载

coding无法使用浏览器打开,必须用git工具下载:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git

视频观看

百问网驱动大全

第五章GIC驱动程序分析

参考资料:

1. 回顾GIC中断处理流程

使用逐步演进的方法才能形象地理解。

1.1 一级中断控制器处理流程

对于irq_desc,内核有两种分配方法:

  • 一次分配完所有的irq_desc
  • 按需分配(用到某个中断才分配它的irq_desc

现在的内核基本使用第1种方法。

  • 假设GIC可以向CPU发出161019号中断,这些数字被称为hwirq。015用于Process之间通信,比较特殊。
  • 假设要使用UART模块,它发出的中断连接到GIC的32号中断,分配的irq_desc序号为16
  • 在GIC domain中会记录(32, 16)
  • 那么注册中断时就是:request_irq(16, ...)
  • 发生UART中断时
    • 程序从GIC中读取寄存器知道发生了32号中断,通过GIC irq_domain可以知道virq为16
    • 调用irq_desc[16]中的handleA函数,它的作用是调用action链表中用户注册的函数
1.2 多级中断控制器处理流程
  • 假设GPIO模块下有4个引脚,都可以产生中断,都连接到GIC的33号中断
  • GPIO也可以看作一个中断控制器,对于它的4个中断
  • 对于GPIO模块中0~3这四个hwirq,一般都会一下子分配四个irq_desc
  • 假设这4个irq_desc的序号为100~103,在GPIO domain中记录(0,100) (1,101)(2,102) (3,103)
  • 对于KEY,注册中断时就是:request_irq(102, ...)
  • 按下KEY时:
    • 程序从GIC中读取寄存器知道发生了33号中断,通过GIC irq_domain可以知道virq为16
    • 调用irq_desc[16]中的handleB函数
      • handleB读取GPIO寄存器,确定是GPIO里2号引脚发生中断
      • 通过GPIO irq_domain可以知道virq为102
      • 调用irq_desc[102]中的handleA函数,它的作用是调用action链表中用户注册的函数

2. GIC中的重要函数和结构体

沿着中断的处理流程,GIC涉及这4个重要部分:

  • CPU从异常向量表中调用handle_arch_irq,这个函数指针是有GIC驱动设置的
    • GIC才知道怎么判断发生的是哪个GIC中断
  • 从GIC获得hwirq后,要转换为virq:需要有GIC Domain
  • 调用irq_desc[virq].handle_irq函数:这也应该由GIC驱动提供
  • 处理中断时,要屏蔽中断、清除中断等:这些函数保存在irq_chip里,由GIC驱动提供

从硬件上看,GIC的功能是什么?

  • 可以使能、屏蔽中断
  • 发生中断时,可以从GIC里判断是哪个中断

在内核里,使用gic_chip_data结构体表示GIC,gic_chip_data里有什么?

  • irq_chip:中断使能、屏蔽、清除,放在irq_chip中的各个函数里实现
  • irq_domain
    • 申请中断时
      • 在设备树里指定hwirq、flag,可以使用irq_domain的函数来解析设备树
      • 根据hwirq可以分配virq,把(hwirq, virq)存入irq_domain中
    • 发生中断时,从GIC读出hwirq,可以通过irq_domain找到virq,从而找到处理函数

所以,GIC用gic_chip_data来表示,gic_chip_data中重要的成员是:irq_chip、irq_domain。

3. GIC初始化过程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
start_kernel (init\main.c)
    init_IRQ (arch\arm\kernel\irq.c)
    	irqchip_init (drivers\irqchip\irqchip.c)
    		of_irq_init (drivers\of\irq.c)
    			desc->irq_init_cb = match->data;

                ret = desc->irq_init_cb(desc->dev,
                            desc->interrupt_parent);
2.1 内核支持多种GIC

按照设备树的套路:

  • 驱动程序注册platform_driver
  • 它的of_match_table里有多个of_device_id,表示能支持多个设备
  • 有多种版本的GIC,在内核为每一类GIC定义一个结构体of_device_id,并放在一个段里:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// drivers\irqchip\irq-gic.c
IRQCHIP_DECLARE(gic_400, "arm,gic-400", gic_of_init);
IRQCHIP_DECLARE(arm11mp_gic, "arm,arm11mp-gic", gic_of_init);
IRQCHIP_DECLARE(arm1176jzf_dc_gic, "arm,arm1176jzf-devchip-gic", gic_of_init);
IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init);
IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init);
IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);
IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
IRQCHIP_DECLARE(pl390, "arm,pl390", gic_of_init);

把宏IRQCHIP_DECLARE展开:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// include\linux\irqchip.h
#define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn)

#define OF_DECLARE_2(table, name, compat, fn) \
		_OF_DECLARE(table, name, compat, fn, of_init_fn_2)

#define _OF_DECLARE(table, name, compat, fn, fn_type)			\
	static const struct of_device_id __of_table_##name		\
		__used __section(__irqchip_of_table)			\
		 = { .compatible = compat,				\
		     .data = (fn == (fn_type)NULL) ? fn : fn  }

展开示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);
展开后得到:
static const struct of_device_id __of_table_cortex_a7_gic		\
	__used __section(__irqchip_of_table)			\
	 = { .compatible = "arm,cortex-a7-gic",				\
		 .data = gic_of_init  }
2.2 在设备树里指定GIC

在设备树中指定GIC,内核驱动程序根据设备树来选择、初始化GIC。

drivers\irqchip\irqchip.c中并没有定义一个platform_driver,但是套路是一样的。

调用过程:

of_irq_init:

  • 内核有一个__irqchip_of_table数组,里面有多个of_device_id,表示多种GIC
  • 要使用哪类GIC?在设备树里指定
  • 根据设备树,找到__irqchip_of_table树组中对应的项,调用它的初始化函数
    • IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);
2.3 gic_of_init分析

看视频

3. 申请GIC中断

3.1 在设备树里指定中断
3.2 内核对设备树的处理

函数调用过程如下,使用图片形式可以一目了然:

函数调用过程如下,使用文字格式方便复制:

4. GIC中断处理流程源码分析

看视频。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/08/23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Linux系统驱动之链式中断控制器驱动程序编写_linear方式
linear、legacy方式,都是用来编写链式中断控制器驱动程序,它们的关系如下表所示。
韦东山
2021/12/08
7770
Linux系统驱动之编程_配置时钟_基于IMX6ULL
资料下载 coding无法使用浏览器打开,必须用git工具下载: git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git 视频观看 百问网驱动大全 资料下载 coding无法使用浏览器打开,必须用git工具下载: git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git 视频观看 百问网驱动大全 编程_
韦东山
2021/12/08
8860
Linux系统驱动之编程_配置时钟_基于IMX6ULL
i.MX283开发板按键驱动和GPIO中断
由于手头上的i.MX283开发板没有独立按键,所以只能用一个IO口手动拉高拉低来模拟按键,但是这样会造成一个小问题,这个后面会提到。按键驱动与LED驱动最大的区别就是前者是GPIO输入,后者是GPIO输出,我们只需要读取IO口电平即可,同样的这也是一个字符设备,按照字符设备驱动框架编写驱动即可。
知否知否应是绿肥红瘦
2025/02/19
640
i.MX283开发板按键驱动和GPIO中断
吐血整理 | 肝翻 Linux 中断所有知识点
GIC,Generic Interrupt Controller。是ARM公司提供的一个通用的中断控制器。主要作用为:接受硬件中断信号,并经过一定处理后,分发给对应的CPU进行处理。
刘盼
2021/08/25
4K1
吐血整理 | 肝翻 Linux 中断所有知识点
Linux系统驱动之两类中断控制器处理流程_链式和层级
在后续课程中我们把GIC之下的中断控制器分为两类:链式(chained)、层级(hierarchy)。
韦东山
2021/12/08
1.1K0
Linux系统驱动之两类中断控制器处理流程_链式和层级
Linux系统驱动之层级中断控制器驱动程序编写
怎么把handleA、GIC Domain和GPIO Domain、irq_chipA和irq_chipB这4个结构体组织起来,irq_domain是核心。
韦东山
2021/12/08
1.5K0
Linux系统驱动之层级中断控制器驱动程序编写
韦东山:剥丝抽茧分析linux中断系统的重要数据结构
最核心的结构体是irq_desc,之前为了易于理解,我们说在Linux内核中有一个中断数组,对于每一个硬件中断,都有一个数组项,这个数组就是irq_desc数组。
韦东山
2020/09/30
1.2K0
韦东山:剥丝抽茧分析linux中断系统的重要数据结构
第五课. 内核中断系统中的设备树
这节课讲解如何在中断系统中使用设备树,也就是用设备树如何描述中断。 中断体系在4.x内核中变化很大,中断体系又跟pinctrl系统密切相关,pinctrl中又涉及GPIO子系统,这样讲下去的话,设备树课程就变成驱动专题了,所以我打算只讲中断体系统,对于pinctrl、gpio等系统留待以后在驱动课程中扩展。
韦东山
2020/09/30
1.2K0
第五课. 内核中断系统中的设备树
Linux系统驱动之链式中断控制器驱动程序编写
沿着中断的处理流程,GIC之下的中断控制器涉及这4个重要部分:handleB、GPIO Domain、handleC、irq_chip
韦东山
2021/12/08
1.6K0
Linux系统驱动之链式中断控制器驱动程序编写
Linux系统驱动之GIC驱动程序对中断的处理流程
资料下载 coding无法使用浏览器打开,必须用git工具下载: git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git 视频观看 百问网驱动大全 GIC驱动程序对中断的处理流程 资料下载 视频观看 1. 一级中断控制器处理流程 2. 多级中断控制器处理流程 参考资料: linux kernel的中断子系统之(七):GIC代码分析 使用逐步演进的方法才能形象地理解。 1. 一级中断控制器处
韦东山
2021/12/08
2.2K0
Linux系统驱动之GIC驱动程序对中断的处理流程
Linux内核笔记之中断映射
在Linux 内核笔记之高层中断处理一文中,介绍了ARM gic中断控制器对于硬中断的处理过程。gic的中断处理程序是从ack一个硬件中断开始的, 在gic的中断处理过程中,会根据中断的映射去寻找对应的虚拟中断号, 再去进行后续的中断处理。gic_handle_irq->handle_domain_irq
刘盼
2021/07/05
5.1K0
Linux内核笔记之中断映射
GICv3驱动初始化
linux驱动支持GICv1, GICv2, GICv3, GICv4驱动,本节我们重点来描述下GICv3的驱动初始化,结合ARM-Cortex平台详细描述
DragonKingZhu
2020/04/09
2.1K0
5.分析内核中断运行过程,以及中断3大结构体:irq_desc、irq_chip、irqaction(详解)
本节目标:    分析在linux中的中断是如何运行的,以及中断3大结构体:irq_desc、irq_chip、irqaction 在裸板程序中(参考stmdb和ldmia详解): 1.按键按下, 2
诺谦
2018/01/03
1.6K0
5.分析内核中断运行过程,以及中断3大结构体:irq_desc、irq_chip、irqaction(详解)
Linux中断初始化
__irqchip_of_table在RK3399中断控制器GICv3初始化时赋值。
花落花相惜
2021/11/22
4.3K0
韦东山:在Linux设备树(DTS)中指定中断_在代码中获得中断
内核Documentation\devicetree\bindings\interrupt-controller\interrupts.txt
韦东山
2020/09/30
8.8K0
韦东山:在Linux设备树(DTS)中指定中断_在代码中获得中断
基于input子系统的sensor驱动调试(一)
要想弄明白世界的本质,就要追根溯源;代码也是一样的道理; 最近调试几个sensor驱动,alps sensor驱动、compass sensor驱动、G-sensor驱动都是一样的架构; 一、基于in
233333
2018/03/07
2.7K0
基于input子系统的sensor驱动调试(一)
Linux设备树语法详解
Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写。引入了设备树之后,驱动代码只负责处理驱动的逻辑,而关于设备的具体信息存放到设备树文件中,这样,如果只是硬件接口信息的变化而没有驱动逻辑的变化,驱动开发者只需要修改设备树文件信息,不需要改写驱动代码。比如在ARM Linux内,一个.dts(device tree source)文件对应一个ARM的machine,一般放置在内核的"arch/arm/boot/dts/"目录内,比如exynos4412参考板的板级设备树文件就是"arch/arm/boot/dts/exynos4412-origen.dts"。这个文件可以通过$make dtbs命令编译成二进制的.dtb文件供内核驱动使用。
用户7678152
2020/09/16
6K0
Linux设备树语法详解
网友说Linux驱动讲不彻底,原来这才是Linux驱动
总线、设备和驱动模型,如果把它们之间的关系比喻成生活中的例子是比较容易理解的。举个例子,充电墙壁插座安静的嵌入在墙面上,无论设备是电脑还是手机,插座都能依然不动的完成它的使命——充电,没有说为了满足各种设备充电而去更换插座的。其实这就是软件工程强调的高内聚、低耦合概念。
嵌入式Linux内核
2022/10/22
1.6K0
网友说Linux驱动讲不彻底,原来这才是Linux驱动
郭健: Linux时间子系统之ARM generic timer驱动代码分析
关注ARM平台上timer driver(clocksource chip driver和clockevent chip driver)的驱动工程师应该会注意到timer硬件的演化过程。在单核时代,各个SOC vendor厂商购买ARM core的IP,然后自己设计SOC上的peripherals,这里面就包括了timer的硬件。由于没有统一的标准,各个厂商的设计各不相同,这给驱动工程师带来了工作量。然而,如果仅仅是工作量的话就还好,实际上,不仅仅如此。linux的时间子系统要求硬件timer提供下面两种能力:一是free running的counter,此外需要能够在指定的counter值上产生中断的能力。有些硬件厂商会考虑到软件的需求(例如:PXA270的timer硬件),但是有些硬件厂商做的就不够,例如:S3C2451的timer硬件。我们在写PXA270的timer硬件驱动的时候是毫无压力的,而在写S3C2451的timer的驱动的时候,最大的愿望就是把三星的HW timer的设计人员拉出来打一顿。
Linux阅码场
2019/10/08
3.7K0
郭健: Linux时间子系统之ARM generic timer驱动代码分析
第三课:linux内核对设备树的处理
转载请注明文章地址 http://wiki.100ask.org/Linux_devicetree
韦东山
2020/09/30
1.5K0
第三课:linux内核对设备树的处理
推荐阅读
相关推荐
Linux系统驱动之链式中断控制器驱动程序编写_linear方式
更多 >
LV.1
深圳百问网科技有限公司技术总监
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文