文章目录
中断是基于硬件实现的,因此有无操作系统均能实现中断
一、异常处理流程
(一)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. 异常处理流程四大步三小步
保存现场:
- 将cpsr保存到spsr中
- 修改cpsr程序状态寄存器
① 设置为ARM的工作状态
② 修改为对应的工作模式
③ 如果有必要禁止中断 - 保存LR
- 设置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>;
};
(四)按键中断实例