Linux子系统之中断

1.中断子系统

1.1中断子系统实现原理

异常处理流程:4大步,3小步
在这里插入图片描述

1.2中断子系统的API

unsigned int irq_of_parse_and_map(struct device_node *dev,int index)
功能:解析得到软中断号
参数:
    @dev:节点的指针
	@inde:索引号
返回值:成功返回软中断,失败返回0
        
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
	    const char *name, void *dev)
功能:注册中断
参数:
    @irq:软中断号
	@handler:中断处理函数
        	irqreturn_t irq_handle(int irqno, void * dev)
    		{
   
   
        		return IRQ_NONE; //中断处理函数执行失败
				return IRQ_HANDLED; //中断处理函数执行成功了
    		}
	@flags:中断触发方式
        IRQF_TRIGGER_RISING	 :上升沿
        IRQF_TRIGGER_FALLING :下降沿	
        IRQF_TRIGGER_HIGH	 :高电平
        RQF_TRIGGER_LOW	     :低电平
		IRQF_SHARED:共享中断
	@name:中断的名字
        cat /proc/interrupts
	@dev:向中断处理函数传递的参数
返回值:成功返回0,失败返回错误码

const void *free_irq(unsigned int irq, void *dev_id)
功能:释放中断
参数:
    @irq:软中断号
	@dev_id:向中断处理函数传递的参数
返回值:是中断注册时候的第四个参数

1.3中断子系统的设备树添加

1.3.1按键中断的硬件原理图

在这里插入图片描述

1.3.2控制器的设备树

stm32mp151.dtsi

gic设备树
intc: interrupt-controller@a0021000 {
   
   
    compatible = "arm,cortex-a7-gic";
    #interrupt-cells = <3>;
    interrupt-controller;
    reg = <0xa0021000 0x1000>,
          <0xa0022000 0x2000>;
};

exti设备树
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>;
    }};
gpiof的设备树
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>;
        status = "okay";
    };
};

1.3.3参考内核帮助文档,编写自己的设备树

Documentation/devicetree/bindings/interrupt-controller$ vi interrupts.txt

  b) 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

myirq{
   
   
     compatilbe = "hqyj,irq";
     interrupt-parent = <&gpiof>;
     interrupts = <9 0>, <7 0>,<8 0>;
};

1.4按键中断的实例(一个按键)

#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
// myirq{
   
   
//      compatilbe = "hqyj,irq";
//      interrupt-parent = <&gpiof>;
//      interrupts = <9 0>, <7 0>,<8 0>;
// };
struct device_node *node;
unsigned int irqno;
irqreturn_t key_irq(int irq, void *dev)
{
   
   
    printk("key1 down..........\n");
    return IRQ_HANDLED;
}
static int __init myirq_init(void)
{
   
   
    int ret;
    //1.获取到设备树的节点
    node = of_find_compatible_node(NULL,NULL,"hqyj,irq");
    if(node == NULL){
   
   
        printk("get node error\n");
        return -ENODATA;
    }
    //2.解析得到软中断号
    irqno = irq_of_parse_and_map(node,0);
    if(irqno==0){
   
   
        printk("get irq number error\n");
        return -EAGAIN;
    }
    //3.注册中断
    ret = request_irq(irqno,key_irq,IRQF_TRIGGER_FALLING,"keyirq",NULL);
    if(ret){
   
   
        printk("reqest irq error\n");
        return ret;
    }
    return 0;
}
static void __exit myirq_exit(void)
{
   
   
    free_irq(irqno,NULL);
}
module_init(myirq_init);
module_exit(myirq_exit);
MODULE_LICENSE("GPL");

1.5按键中断的实例(三个按键)

#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
// myirq{
   
   
//      compatilbe = "hqyj,irq";
//      interrupt-parent = <&gpiof>;
//      interrupts = <9 0>, <7 0>,<8 0>;
// };
struct device_node* node;
unsigned int irqno[3] = {
   
    0 };
char* name[] = {
   
    "key1", "key2", "key3" };
irqreturn_t key_irq(int irq, void* dev)
{
   
   
    switch ((int)dev) {
   
   
    case 0:
        printk("key1 down..........\n");
        break;
    case 1:
        printk("key2 down..........\n");
        break;
    case 2:
        printk("key3 down..........\n");
        break;
    }

    return IRQ_HANDLED;
}
static int __init myirq_init(void)
{
   
   
    int ret, i;
    // 1.获取到设备树的节点
    node = of_find_compatible_node(NULL, NULL, "hqyj,irq");
    if (node == NULL) {
   
   
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值