四 中断

中断一般包括中断产生设备和中断处理设备。中断控制器负责处理中断,每一个中断都有对应的中断号及触发条件。中断产生设备可能有多个中断源,有时多个中断源对应中断控制器中的一个中断,这种情况中断产生设备的中断源称之为中断控制器中对应中断的子中断。一般情况中断产生设备数量要多于中断控制器,多个中断产生设备的中断都由一个中断控制器处理,这种多对一的关系也很像一个树形结构,所以在设备树中,中断也被描述成树,叫中断树。以下表述的时候为了明确是在说中断树,在父节点和子节点前边我们都加上“中断”二字,是为了防止和设备树的父节点、子节点混淆(虽然大部分情况设备树的父子关系就是中断树的父子关系,但是因为存在特例,所以我们还是强调是中断父子关系)。

中断产生设备用interrupts属性描述中断源(interrupt specifier),因为不同的硬件描述中断源需要的数据量不同,所以interrupts属性的类型也是<prop-encoded-array>。为了明确表示一个中断由几个u32表示,又引入了#interrupt-cells属性,#interrupt-cells属性的类型是u32,假如一个中断源需要2个u32表示(一个表示中断号,另一个表示中断类型),那么#interrupt-cells就设置成2。有些情况下,设备树的父节点不是中断的父节点(主要是中断控制器一般不是父节点),为此引入了interrupt-parent属性,该属性的类型是<phandle>,用来引用中断父节点(我们前边说过,一般用父节点的标签,这个地方说中断父节点而不是中断控制器是有原因的)。如果设备树的父节点就是中断父节点,那么可以不用设置interrupt-parent属性。interrupts属性和interrupt-parent属性都是中断产生设备节点的属性,但是#interrupt-cells属性不是,#interrupt-cells属性是中断控制器节点以及interrupt nexus节点的属性,这两类节点都可能是中断父节点。

中断控制器节点用interrupt-controller属性表示自己是中断控制器,这个属性的类型是空,不用设置值,只要存在这个节点就表示该节点是中断控制器。除了这个属性外,中断控制器节点还有#interrupt-cells属性,用来表示该中断控制器直接管理下的interrupt domain(后边我们会讲中断控制器的中断子节点interrupt nexus节点有单独的interrupt domain)用几个u32表示一个中断源(interrupt specifier)。中断控制器节点就包括interrupt-controller和#interrupt-cells两个关于中断的属性。中断控制器的#address-cells属性和中断映射有关系,但是该属性不是为中断设计的,中断映射只是用到了这个属性而已。

前边说中断控制器中的一个中断可能对应中断产生设备中的多个中断源,那这种对应关系用什么描述呢?我们还说过#interrupt-celll属性不仅是中断控制器节点的属性,还是interrupt nexus节点的属性,这个interrupt nexus节点就是描述中断映射关系的,该节点通过interrupt-map,interrupt-map-mask属性描述中断映射关系。interrupt-map属性是<prop-encoded-array>类型的,每个元素表示一个中断映射关系(注意是一个"中断映射关系",不是"一个中断"映射关系),从前向后包括:中断子设备地址,中断子设备中断源(interrupt specifier),中断父设备,中断父设备地址,中断父设备中断源(interrupt specifier)五部分。中断子设备地址具体由几个u32组成是由中断子设备所在总线(不是中断父设备)的#address-cells属性决定的,这个地方为什么用中断设备地址而不用中断设备的phandle,是有原因的,因为中断设备会用interrupt-parrent属性指向中断父节点,所以中断子设备是可以确定的,不需要说明。还因为中断子设备地址可以做与运算,通过interrupt-map-mask属性就可以实现多对一的映射。中断子设备中断源(interrupt specifier)由几个u32组成是由该interrupt nexus节点下的#interrupt-cell决定的。中断父设备是一个指向中断父设备的<phandle>属性,一般情况下是中断控制器,但是按照中断树的逻辑,也可能是更高一级的interrupt nexus节点。中断父设备地址具体由几个u32组成是由中断父设备节点下的#address-cells属性决定的(注意,不是中断父设备所在总线的#address-cells属性)。中断父设备中断源(interrupt specifier)由几个u32组成是由中断父设备的#interrupt-cells属性决定的。

还记得前边说过中断设备的中断源和中断控制器的中断源可能是多对一的关系,如果每个子中断都用interrupt-map中的一行表示,那么interrupt-map属性将非常大。为了让多个子中断共享映射关系,引入了interrupt-map-mask属性,该属性的类型也是<prop-enacoded-array>,包含中断子设备地址和中断子设备中断源的bit mask,给定一个子中断源,那么首先和interrupt-map-mask做与运算,运算结果再通过interrupt-map属性查找对应的中断父设备中断源。这就是我们前边为什么说interrupt-map属性的一行是一个“中断映射关系”,而不是“一个中断”映射关系的原因。

我们再来复习一下,整个中断树的最底层是中断产生设备(也可能是从interrupt nexus节点),中断产生设备用interrupts属性描述他能产生的中断。因为他的中断父设备可能和设备树的父设备不同,那么用interrupt-parent属性指向他的中断父设备。他的中断父设备可能是中断控制器(如果中断产生设备的中断和中断控制器的中断是一一对应的,或者最底层是interrupt nexus节点),也可能是interrupt nexus节点(如果最底层是中断产生设备,且需要映射)。interrupt nexus节点及他的所有直接子节点构成了一个interrupt domain,在该interrupt domain下中断源怎样表示由#interrupt-cells属性决定,如何由中断子设备中断源找到中断父设备中断源由interrupt-map和interrupt-map-mask属性决定。interrupt nexus的父节点可能还是一个interrupt nexus父节点,也可能是一个中断控制器,当向上找到最后一个中断控制器,并且该中断控制器再也没有中断父设备时,整个中断树就遍历完成了。中断控制器用interrupt-controller属性表示自己是中断控制器,并且用#interrupt-cells属性表示他所直接管理的interrupt domain用几个u32表示一个中断源。根据中断树的特性,一个设备树中是有可能有多个中断树的。

以上是中断在设备树中如何描述的规则,听起来是挺复杂的,但只要理解了就很简单,为了帮助理解我们举一个实际的例子。为了突出中断部分,我们做了简化。
/ {
    model = "Marvell Armada 375 family SoC";
    compatible = "marvell,armada375";
    soc {
        #address-cells = <2>;
        #size-cells = <1>;
        interrupt-parent = <&gic>;

internal-regs {
            compatible = "simple-bus";
            #address-cells = <1>;
            #size-cells = <1>;

timer@c600 {
                compatible = "arm,cortex-a9-twd-timer";
                reg = <0xc600 0x20>;
                interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(2))>;
                clocks = <&coreclk 2>;
            };

gic: interrupt-controller@d000 {
                compatible = "arm,cortex-a9-gic";
                #interrupt-cells = <3>;
                #address-cells = <0>;
                interrupt-controller;
                reg = <0xd000 0x1000>,
                      <0xc100 0x100>;
            };
        }

pcie-controller {
            compatible = "marvell,armada-370-pcie";
            #address-cells = <3>;
            #size-cells = <2>;

pcie@1,0 {
                #address-cells = <3>;
                #size-cells = <2>;
                #interrupt-cells = <1>;
                interrupt-map-mask = <0 0 0 0>;
                interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
            };
        };
}

首先我们看到timer@c600这个设备节点下定义了interrupts属性,这说明该设备可以产生中断,但是这个属性下描述了几个中断我们是看不出来的(如果有经验了,我们能猜出只是一个中断,现在我们按照规则确认)。因为该节点没有interrupt-parent属性,那么认为设备树的父节点internal-regs就是中断父节点,在internal-regs父节点下还是没有interrupt-parent属性,那么还是继续找设备树父节点,找到了soc,在该节点下边有interrupt-parent属性。该属性引用的标签为gic,搜索整个设备树,interrupt-controller@d000的标签为gic。gic节点下有interrupt-controller属性,说明他是一个中断控制器。gic节点还有属性#interrupt-cells = <3>,说明在该控制器的interrupt domain下,中断源(interrupt specifier)用3个u32表示,我们再看timer@c600下的interrupts属性也确实由3个u32组成(可以参考GIC的规范,第一个u32表示中断类型,第二个是中断号,第三个是中断触发条件)。这个例子说明如果中断产生设备的中断源和中断控制器的中断源是一一对应的,那么可以不需要interrupt nexus节点及相关的属性来表示中断映射。

再看pcie@1,0这个节点,有#interrupt-cells属性,但是没有interrupt-controller属性,这说明他是一个interrupt nexus节点。该节点的#interrupt-cells属性为1,说明该interrupt nexus节点管辖下的中断源用1个u32表示就可以了。在pcie@1,0节点下边没有子节点,且也没有节点的interrupt-parent属性指向pcie@1,0节点,所以从设备树上看不到该interrupt domain下的中断产生设备,可能的原因是这些中断产生设备软件可以动态识别所以不需要设备树描述。因为interrupt-map-mask属性是由中断产生设备的地址和中断源(interrupt specifier)组成,且中断源用1个u32表示,那么可以推测中断产生设备地址由3个u32组成。这里需要注意的是pcie@1,0节点的#address-cells属性为3,是说该总线下边的设备地址用3个u32表示,但并不代表中断产生设备的设备地址也一定3个u32表示,此处不能说是巧合,但是我们要清楚中断产生设备的地址由几个u32组成是由该设备所在总线决定的,对于pcie总线也确实是3,但是其他总线可能存在其他种的情况。现在我们来分析interrupt-map属性,前三个数字是中断设备地址,第四个数字是中断设备的中断源。因为interrupt-map-mask是全0,这样不管与什么数字做与运算结果都是0,interrupt-map属性的前4个数字也都是0,这说明在pcie@1,0下边所有的中断映射到中断父节点的中断都是一个中断。接着是指向gic的<phandle>,因为gic节点下#address-cells属性为0,所以后边不需要描述中断父设备的地址了,后边3个数字都是表示中断父设备中断源的。一句话描述就是pcie@1,0下的所有中断都映射到gic,GIC_SPI类型的第29号中断,触发类型为高电平触发。这个例子说明在中断树的最下边可以是interrupt nexus节点。

以上例子中断树的根是gic,gic下边有两个孩子,一个是中断设备timer@c600,一个是interrupt nexus节点pcie@1,0。gic直接管辖的interrupt domain用3个u32表示中断源,timer@c600在这个interrupt domain下。pcie@1,0下定义了一个新的interrupt domain,在该interrupt domain下,中断源用1个u32表示,pcie@1,0用interrupt-map和interrupt-map-mask属性将下边所有设备的中断映射到一个gic下边的中断上。

我眼中的Linux设备树(四 中断)相关推荐

  1. 我眼中的Linux设备树(一 概述)

    一 概述 设备树(Device tree)是一套用来描述硬件属相的规则.ARM Linux采用设备树机制源于2011年3月份Linux创始人Linus Torvalds发的一封邮件,在这封邮件中他提倡 ...

  2. 我眼中的Linux设备树(六 memorychosen节点)

    六 memory&chosen节点 根节点那一节我们说过,最简单的设备树也必须包含cpus节点和memory节点.memory节点用来描述硬件内存布局的.如果有多块内存,既可以通过多个memo ...

  3. 我眼中的Linux设备树(五 根节点)

    五 根节点 一个最简单的设备树必须包含根节点,cpus节点,memory节点.根节点的名字及全路径都是"/",至少需要包含model和compatible两个属性.model属性我 ...

  4. 我眼中的Linux设备树(二 节点)

    二 节点(node)的表示 首先说节点的表示方法,除了根节点只用一个斜杠"/"表示外,其他节点的表示形式如"node-name@unit-address".@前 ...

  5. 我眼中的Linux设备树(三 属性)

    三 属性(property) device_type = "memory"就是一个属性,等号前边是属性,后边是值.节点是一个逻辑上相对独立的实体,属性是用来描述节点特性的,根据需要 ...

  6. 【正点原子Linux连载】第四十三章 Linux设备树 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  7. 【正点原子MP157连载】第二十三章 Linux设备树-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  8. linux 视频教程 韦山东,韦东山 linux 设备树详解

    简 介 设备树视频录制完毕,29节,现在只要69元.学员对此课程的评价:这是最翔实最实惠最精益求精的设备树教程,感兴趣的了解一下, 以下是课程详情~ [设备树是什么?] 设备树是一种机制,用文本的方式 ...

  9. 基于设备树的中断实现 (24x0平台)

    文章目录 一.平台信息 1. 平台信息 二.中断的驱动实现方式 2. 不使用设备树的中断实现 2.1 mach-mini2440.c文件中注册中断 2.2 注册中断 3. 使用设备树的中断实现 设备树 ...

最新文章

  1. drupal cve-2018-7600 远程代码执行漏洞 简介
  2. 从针对接口编程到依赖注入
  3. AVS软件解码器的优化
  4. 【leetcode刷题笔记】Single Number
  5. Android Camera框架
  6. 米斯特白帽培训讲义(v2)漏洞篇 SSRF
  7. 东南大学的计算机类和电子信息哪个专业好,东南大学王牌专业有哪些及专业排名...
  8. core 实例化接口_实例讲解Springboot整合MongoDB进行CRUD操作的两种方式
  9. Ubuntu安装php
  10. HDU 5273 Dylans loves sequence【 树状数组 】
  11. 【STM32】8.简单呼吸灯的制作教程,附代码、效果视频
  12. 思维模型 后天天赋(盖洛普天赋分析)
  13. 我的团长我的团——真正的中国军人
  14. 充分利用居室空间 让阳台尽显万种风情
  15. ping不通的常见原因和解决办法
  16. RAxML下载与使用与ML建树原理
  17. [随笔]魏晋风度与竹林七贤系列之二 嵇康任气有侠名
  18. storm滑动时间窗口实现
  19. 教你如何用android系统通过Remote Desktop远程控制电脑
  20. python新浪微博数据分析_Python 爬取新浪微博数据分析90后单身原因

热门文章

  1. 双精度数举例_Aladdin阿拉丁:一套土木工程结构无损检测领域先进的双极化天线阵雷达...
  2. 012_union操作符
  3. 035_jQuery Ajax的ajaxSetup方法
  4. 如何用html绘制阴影图形,HTML5 给图形绘制阴影
  5. mysql数据库的增删改查命令_MySQL 初识别语句,数据库、表、行的增删改查
  6. java按钮不显示中文_java - 按钮没有显示日志也不吐司[复制] - SO中文参考 - www.soinside.com...
  7. Android 四大组件之——Acitivity(四) Activity是如何加载显示内容的?
  8. 联想无线网卡 linux驱动,ubuntu14.04手动安装博通官方无线网卡驱动时报错,
  9. nmcli命令详解_【高新课堂】第一百二十五期Liunx必备命令
  10. NIO详解(九):Channel详解