Linux 内核中断子系统

Last edited
Last updated July 13, 2023
Pages
Tags

1. 内核中断的处理过程和实现原理

notion image
依照原理图,将中断注册进内核的步骤为:
  1. 获取中断在 irq_desc 数组中的位置(软中断号)
  1. 定义中断处理函数
  1. 申请一个 irqaction 空间,将中断处理相关的信息保存在这个空间
  1. 将 irqaction 看似首地址保存至这个中断的 irq_desc 空间中

2. 内核中断子系统相关 API

  1. 解析中断相关的设备树节点:通过名字、路径或者 conpatible,参考 GPIO 子系统笔记
  1. 解析设备树节点获取当前设备对应中断的软中断号
int irq_of_parse_and_map(struct device_node *node, int index) 功能: 对当前设备进行分析并且映射出当前中断的软中断号 参数: node: 设备树节点结构体指针 index: 索引号 返回值: 成功返回软中断号,失败返回 0
  1. 注册中断
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev) 功能: 注册中断 参数: irq: 软中断 handler: 中断处理函数的函数指针 typedef irqreturn_t (*irq_handler_t)(int , void *); 中断处理函数的返回值: IRQ_NONE 不是这个设备的中断,没有被处理 IRQ_HANDLED 中断被正常处理 IRQ_WAKE_THREAD 唤醒一个处理线程去处理中断 flags: 用于设置中断的触发方式 IRQF_TRIGGER_RISING 上升沿触发 IRQF_TRIGGER_FALLING 下降沿触发 IRQF_TRIGGER_HIGH 高电平触发 IRQF_TRIGGER_LOW 低电平触发 IRQF_SHARED 设置当前中断为共享中断 name: 中断名 dev: 传递进入中断处理函数的参数 返回值: 成功返回 0,失败返回错误码

3. 按键中断的设备树编写

3.1 按键中断的硬件原理图

notion image
stm32mp157a.dtsi 文件中以及有 gic\exti\gpio 的设备树节点的封装了,需要我们做的是添加按键的设备树节点,并且和 gpiof 在中断层次上实现关联。

3.2 中断处理相关的设备树节点

GPIOF
//定义位置:stm32mp151.dtsi pinctrl: pin-controller@50002000 { interrupt-parent = <&exti>;//指定当前节点的中断父节点为exti gpiof: gpio@50007000 { //一个空属性,将节点声明为接收中断信号的设备 interrupt-controller; //其他节点引用此节点作为中断控制节点是用于描述的u32的个数 #interrupt-cells = <2>; reg = <0x5000 0x400>; clocks = <&rcc GPIOF>; st,bank-name = "GPIOF"; status = "disabled"; }; }; //引用位置:stm32mp15xxac-pinctrl.dtsi &pinctrl { gpiof: gpio@50007000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 80 16>;  }; };
EXTI
soc { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; interrupt-parent = <&intc>;//当前节点的中断父节点时intc ranges; exti: interrupt-controller@5000d000 { compatible = "st,stm32mp1-exti", "syscon"; interrupt-controller;//声明当前节点是一个中断控制节点 //引用此节点作为中断控制时需要用2个u32进行描述 #interrupt-cells = <2>; reg = <0x5000d000 0x400>; }; };
GIC
intc: interrupt-controller@a0021000 { compatible = "arm,cortex-a7-gic"; #interrupt-cells = <3>; interrupt-controller;//声明当前节点是一个中断控制节点 reg = <0xa0021000 0x1000>, <0xa0022000 0x2000>;  };

3.3 添加按键的设备树节点

查看 Linux 官方设备树中断手册:Device Tree Usage - eLinux.org
📖
四个属性用于描述中断连接:
  • interrupt-controller:一个空属性,将节点声明为接收中断信号的设备
  • #interrupt-cells:用于声明引用此节点作为中断控制器节点时使用的u32的个数
  • interrupt-parent:设备节点的属性,其中包含它所附加到的中断控制器的句柄。没有中断父属性的节点也可以从其父节点继承该属性。
  • interrupts:设备节点的属性,包含中断说明符列表,设备上的每个中断输出信号对应一个
进入内核顶层目录 /Documentation/devicetree/bindings/interrupt-controller
文档相关内容节选
Nodes that describe devices which generate interrupts must contain an "interrupts" property, an "interrupts-extended" property, or both. If both are present, the latter should take precedence; the former may be provided simply for compatibility with software that does not recognize the latter. These properties contain a list of interrupt specifiers, Example:
interrupt-parent = <&intc1>;
interrupts = <5 0>, <6 0>;
The "interrupt-parent" property is used to specify the controller to which interrupts are routed and contains a single phandle referring to the interrupt controller node. Interrupts listed in the "interrupts" property are always in reference to the node's interrupt parent. The "interrupts-extended" property is a special form; useful when a node needs to reference multiple interrupt parents or a different interrupt parent than the inherited one. Example:
interrupts-extended = <&intc1 5 1>, <&intc2 1 0>;
2) Interrupt controller nodes A device is marked as an interrupt controller with the "interrupt-controller" property. This is a empty, boolean property. An additional "#interrupt-cells" property defines the number of cells needed to specify a single interrupt. two cells
The #interrupt-cells property is set to 2 and the first cell defines the index of the interrupt within the controller, while the second cell is used to specify any of the following flags: - bits[3:0] trigger type and level flags
1 = low-to-high edge triggered 2 = high-to-low edge triggered 4 = active high level-sensitive 8 = active low level-sensitive
添加按键的设备树节点:
mykeys{ interrupt-parent=<&gpiof>; //9表示引用中断父节点时的索引信息 0表示默认设置 interrupts=<9 0>,<7 0>,<8 0>; }; //或者 mykeys{ interrupts-extended = <&gpiof 9 0>, <&gpiof 7 0>, <&gpiof 8 0>; };

4. 按键中断编写实例

5. 三个按键实例