Linux系统驱动(十二)中断子系统

中断是基于硬件实现的,因此有无操作系统均能实现中断

一、异常处理流程

(一)ARM处理器工作模式

user用户模式

system系统模式
SVC管理模式
FIQ模式
IRQ模型
Abort终止模式
Undef未定义模式

monitor安全监测模式

HYP虚拟化模式

(二)异常模式

SVC异常模式
IRQ异常模式
FIQ异常模式
未定义异常模式
终止异常模式

(三)异常源

reset复位异常
swi软中断异常
IRQ异常
FIQ异常
未定义异常
预取终止
数据访问终止

(四)ARM中的寄存器

7种工作模式是37个寄存器,8种工作模式是40个寄存器(cortex-a),9种工作模式是43个寄存器。

以八种工作模式为例:
在这里插入图片描述

1. CPSR寄存器

在这里插入图片描述

2. 异常处理流程四大步三小步

保存现场:

  1. 将cpsr保存到spsr中
  2. 修改cpsr程序状态寄存器
    ① 设置为ARM的工作状态
    ② 修改为对应的工作模式
    ③ 如果有必要禁止中断
  3. 保存LR
  4. 设置PC到对应的异常位置执行

恢复现场:
将spsr中的值赋值给cpsr
让PC指向异常处理前的位置执行

二、中断子系统执行流程

在这里插入图片描述

三、中断子系统API

cat /proc/devices 主设备号和设备名
cat /proc/interrupts 软中断号和中断名

unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
功能:解析得到软中断号
参数:
 @dev:节点的指针
 @index:下标
返回值:成功返回软中断号,失败返回0 

#include <linux/interrupt.h>
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 *);
        irqreturn_t irq_handle(int irq, void *dev) 
     {
         //中断处理函数
         return IRQ_HANDLED; //执行成功
         //return IRQ_NONE; //执行失败
     }
 @flags:中断触发方式
            #define IRQF_TRIGGER_RISING	0x00000001
            #define IRQF_TRIGGER_FALLING	0x00000002
            #define IRQF_TRIGGER_HIGH	0x00000004
            #define IRQF_TRIGGER_LOW	0x00000008
 @name:中断的名字  cat  /proc/interrupts
 @dev:向中断处理函数传递的参数
返回值:成功返回0,失败返回错误码

const void *free_irq(unsigned int irq, void *dev)
功能:注销中断
参数:
 @irq:软中断号
 @dev:向中断处理函数传递的参数
返回值:中断的名字

四、按键中断的设备树编写

(一)画出硬件连接图

在这里插入图片描述

  • 注:A7核是GIC,M4是NVIC
PF9	--- key1
PF7	--- key2
PF8 --- key3

(二)找出控制器设备树

STM32MP151.dtsi

intc: interrupt-controller@a0021000 {
	compatible = "arm,cortex-a7-gic";
	#interrupt-cells = <3>;
	interrupt-controller;
	reg = <0xa0021000 0x1000>,
	      <0xa0022000 0x2000>;
};
soc {
    compatible = "simple-bus";
    #address-cells = <1>;
    #size-cells = <1>;
    interrupt-parent = <&intc>;
    exti: interrupt-controller@5000d000 {
        compatible = "st,stm32mp1-exti", "syscon";
        interrupt-controller;
        #interrupt-cells = <2>;
        reg = <0x5000d000 0x400>;
    };
};

pinctrl: pin-controller@50002000 {
    #address-cells = <1>;
    #size-cells = <1>;
    compatible = "st,stm32mp157-pinctrl";
    interrupt-parent = <&exti>;
    gpiof: gpio@50007000 {
        interrupt-controller;
        #interrupt-cells = <2>;//2.子节点使用当前节点成员个数
        reg = <0x5000 0x400>;
        clocks = <&rcc GPIOF>;
        st,bank-name = "GPIOF";
        status = "disabled"; //1.控制器是否使能
    };
};

一般不在设备树中指定中断触发方式

SPI:(总中断号)32-287,共享外设中断256个(中断类型的终端号)0-255
PPI:私有外设中断 (总中断号)16-31,只能由固定某个CPU处理
SGI:中断号在前16位0-15,软中断,核与核之间

(三)参考内核编写自己的设备树

~/linux-5.10.61/Documentation/devicetree/bindings/interrupt-controller

在这里插入图片描述

mykeys{
    interrupt-parent = <&gpiof>;
    interrupts = <9 0>,<7 0>,<8 0>;
};

(四)按键中断实例


  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值