百问网技术交流群,百万嵌入式工程师聚集地:
https://www.100ask.net/page/2248041

资料下载

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

git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git

视频观看

百问网驱动大全

第五章GIC驱动程序分析

  • 资料下载
  • 视频观看
    • 1. 回顾GIC中断处理流程
      • 1.1 一级中断控制器处理流程
      • 1.2 多级中断控制器处理流程
    • 2. GIC中的重要函数和结构体
    • 3. GIC初始化过程
      • 2.1 内核支持多种GIC
      • 2.2 在设备树里指定GIC
      • 2.3 gic_of_init分析
    • 3. 申请GIC中断
      • 3.1 在设备树里指定中断
      • 3.2 内核对设备树的处理
    • 4. GIC中断处理流程源码分析

参考资料:

  • linux kernel的中断子系统之(七):GIC代码分析

  • Linux 4.9.88内核源码

    • Linux-4.9.88\drivers\irqchip\irq-gic.c
    • Linux-4.9.88/arch/arm/boot/dts/imx6ull.dtsi
  • Linux 5.4内核源码

    • Linux-5.4\drivers\irqchip\irq-gic.c
    • Linux-5.4/arch/arm/boot/dts/stm32mp151.dtsi

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初始化过程

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,并放在一个段里:
// 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展开:

// 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  }

展开示例:

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 内核对设备树的处理

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

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

  • 为设备树节点分配设备

      of_device_alloc (drivers/of/platform.c)dev = platform_device_alloc("", -1);  // 分配 platform_device   num_irq = of_irq_count(np);  // 计算中断数    // drivers/of/irq.c, 根据设备节点中的中断信息, 构造中断资源of_irq_to_resource_table(np, res, num_irq) of_irq_to_resource // drivers\of\irq.cint irq = irq_of_parse_and_map(dev, index);  // 获得virq, 中断号
    
  • 解析设备树映射中断: irq_of_parse_and_map

    // drivers/of/irq.c, 解析设备树中的中断信息, 保存在of_phandle_args结构体中
    of_irq_parse_one(dev, index, &oirq)// kernel/irq/irqdomain.c, 创建中断映射
    irq_create_of_mapping(&oirq);             irq_create_fwspec_mapping(&fwspec);// 调用irq_domain->ops的translate或xlate,把设备节点里的中断信息解析为hwirq, typeirq_domain_translate(domain, fwspec, &hwirq, &type)  // 看看这个hwirq是否已经映射, 如果virq非0就直接返回virq = irq_find_mapping(domain, hwirq); // 否则创建映射  if (irq_domain_is_hierarchy(domain)) {// 返回未占用的virq// 并用irq_domain->ops->alloc函数设置irq_descvirq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);if (virq <= 0)return 0;} else {/* Create mapping */// 返回未占用的virq// 并通过irq_domain_associate调用irq_domain->ops->map设置irq_descvirq = irq_create_mapping(domain, hwirq);if (!virq)return virq;}
    

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

看视频。


百问网技术交流群,百万嵌入式工程师聚集地:
https://www.100ask.net/page/2248041

百问网技术论坛:
http://bbs.100ask.net/

百问网嵌入式视频官网:
https://www.100ask.net/index

百问网开发板:
淘宝:https://100ask.taobao.com/
天猫:https://weidongshan.tmall.com/

Linux系统GIC驱动程序分析相关推荐

  1. Linux NAND FLASH驱动程序分析(mini2440)

    Linux NAND FLASH驱动程序分析(mini2440) 一.Linux-MTD Subsystem介绍 FLASH在嵌入式系统中是必不可少的,它是bootloader.linux内核和文件系 ...

  2. Linux下触摸屏驱动程序分析

    [摘要: 本文以 linux 3.5--Exynos4412仄台,剖析 触摸屏 驱动焦点内容.Linux下触摸屏驱动(以ft5x06_ts为例)须要懂得以下学问: 1. I2C协定 2. Exynos ...

  3. 一次Linux系统被***的分析过程

    IT行业发展到现在,安全问题已经变得至关重要,从最近的"棱镜门"事件中,折射出了很多安全问题,信息安全问题已变得刻不容缓,而做为运维人员,就必须了解一些安全运维准则,同时,要保护自 ...

  4. 基于Linux系统中进程调度分析

    本文作者(院 浩),请您在阅读本文时尊重作者版权. [摘要]Linux是一个多用户多任务的操作系统,Linux中实现了对多个进程公平.高效的调度,并不是采用单一的调度策略,而是几种调度策略有机地综合应 ...

  5. linux 系统级性能分析工具 perf 的介绍与使用

    目录 1. 背景知识 1.1 tracepoints 1.2 硬件特性之cache 2. 主要关注点 3. perf的使用 3.0 perf引入的overhead 3.1 perf list 3.2 ...

  6. (转载)一次Linux系统被攻击的分析过程

    IT行业发展到现在,安全问题已经变得至关重要,从最近的"棱镜门"事件中,折射出了很多安全问题,信息安全问题已变得刻不容缓,而做为运维人员,就必须了解一些安全运维准则,同时,要保护自 ...

  7. linux 系统命令被后门修改_一次Linux系统被攻击的分析过程

    作者:南非蚂蚁 来源:https://urlify.cn/M7NjIv IT行业发展到现在,安全问题已经变得至关重要,从之前的"棱镜门"事件中,折射出了很多安全问题,信息安全问题已 ...

  8. 一次Linux系统被攻击的分析过程

    点击上方 "程序员小乐"关注, 星标或置顶一起成长 每天凌晨00点00分, 第一时间与你相约 每日英文 I may not be perfect, but I'm always m ...

  9. linux 系统 centOS7 日志分析

    linux 系统 centOS 7日志分析 日志文件分析 日志文件用于记录linux系统运行中发生的各种类型的消息文件,包括 linux内核消息.用户登录消息.程序运行信息等. linux系统中日志文 ...

最新文章

  1. git github 快速入门
  2. 清华集训2014 day2 task1 简单回路
  3. 二维数组的地址表达方式
  4. jQuery可放大预览的图片滑块
  5. java nginx https_docker nginx 配置ssl,实现https
  6. Linux系统isosize指令用法
  7. @autowired注解注入为null_Java面试必备:依赖注入注解@Resource和@Autowired
  8. 智能一代云平台(十):Jboss远程访问流程总结
  9. 自定义训练中使用Tensorboard
  10. 一支口红用了5年_用了7年微信才知道!原来微信隐藏5大实用功能,比app更好用...
  11. MaxCompute SQL中的更新和删除如何实现
  12. Clevo P950系列拆机
  13. win7桌面我的计算机打不开怎么回事,win7系统双击我的电脑打不开的解决方法
  14. 二箱:比谷歌识图更全面,多引擎以图搜图工具
  15. H3C用户入网配置(radius、domain、802.1x)
  16. 浅谈矩阵加速——以时间复杂度为O(log n)的算法实现裴波那契数列第n项及前n之和使用矩阵加速法的优化求法
  17. java 高cpu占用问题解决
  18. 【8.6】代码源 - 【前缀集】【矩阵游戏】【谁才是最终赢家?】【放置多米诺骨牌】
  19. WEB工程师和设计师必学的10个IOS 8新鲜改变
  20. 遇到一个特别傻的问题。。。用charles抓包抓不到https的解决方法

热门文章

  1. 【Linux之Ubantu——乱记】5.U盘重装Linux系统(惠普)
  2. 数据结构 顺序查找和折半查找的平均查找长度分析关于ASL(平均查找长度)的简单总结
  3. shell学习-斐波那契数列
  4. 桌面只计算机图标发白,Win7电脑桌面图标变成白色如何解决?
  5. 外嫁女能否享受村民拆迁补偿待遇
  6. 以考拉之名,蒋凡、丁磊、黄峥的合纵连横!
  7. 别找了,小程序实现isbn扫码获取图书信息2022最新可用(保姆级教程内附接口)
  8. Windows Media Services 流媒体服务器架设教程
  9. Linux简易命令手册
  10. 使用切线法求解方程零点