中断子系统的简单使用

GIC是ARM推出的一个通用的中断控制器,全志H3中使用了GIC的多核方案,符合GIC V2规格。ARM多核处理器一般搭建一个GIC来提供中断控制功能,中端控制器是连接外设中断系统和CPU系统的桥梁。

 

ARM上把中断分为三类:

  • PPI(private peripheral interrupt) 16~31

这些中断一般是发送给特定的Cpu的,比如每个Cpu有自己对应的Physicaltimer,产生的中断信号就发送给这个特定的cpu进行处理

  • SPI(shared processor interrupts)

这是常见的外部设备中断,也定义为共享中断,比如按键触发一个中断,手机触摸屏触发的中断,共享的意思是说可以多个Cpu或者说Core处理,不限定特定的Cpu。一般定义的硬件中断号范围31~1019.Cortex-A15和A9上的GIC最多支持224个SPI。

  • SGI(software generated interrupts)

软件出发产生的中断,中断号范围0~15,也就是最前的16个中断,相当于IPI,简单的说Cpu_1要给Cpu_2发送特定信息,比如时间同步,全局进程调度信息,就通过软件中断方式,目标Cpu接受到这样的中断信息,可以获取到信息是哪个Cpu发送过来的,具体的中断ID是哪个数字,从而找到对应处理方式进行处理。

 

全志H3中断体系结构的拓扑如下所示,4个CPU核连接到root GIC,然而子中断控制器(比如GPIO控制器)不与CPU直接相连,而是上报至root GIC的某个SPI中断上,root GIC负责接收子中断控制器信息然后向某个CPU汇报。

 

 

在全志H3中,不是每个GPIO bank都可以作为中断控制器的,只有PA,PG,和PL可以作为中断控制器。PA这一bank下的PA0,PA1,PA2。。。等request line公用一个SPI-43号中断。

 

使用nanopi-m1的PA9 外部中断

 

在设备树源文件sun8i-h3-nanopi-m1.dts添加interrupt-demo节点

interrupt_demo: interrupt_demo {
	compatible = "nanopi-m1,interrupt_demo";
	interrupt-parent = <&pio>;
	//interrupts = <0 9 IRQ_TYPE_EDGE_FALLING>; 
	key-gpio = <&pio 0 9 GPIO_ACTIVE_LOW>;
};

 

interrupt-demo节点用interrupt-parent属性指明其中断父亲属于pinctrl,pinctrl节点的描述如下所示,其中interrupt-cells为3说明interrupt-demo节点的interrupts属性值需要3个bytes来表示,

        pio: pinctrl@01c20800 {
            /* compatible is in per SoC .dtsi file */
            reg = <0x01c20800 0x400>;
            interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
                     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
            clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&osc32k>;
            clock-names = "apb", "hosc", "losc";
            gpio-controller;
            #gpio-cells = <3>;
            interrupt-controller;
            #interrupt-cells = <3>;
            ......
    };

驱动程序

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/interrupt.h>

typedef struct
{
    int gpio;
    int irq;
}int_demo_data_t;

static irqreturn_t int_demo_isr(int irq, void *dev_id)
{
    int_demo_data_t *data = dev_id;

    printk("%s enter, gpio:%d, irq: %d\n", __func__,  data->gpio, data->irq);

    return IRQ_HANDLED;
}

static int int_demo_probe(struct platform_device *pdev) {
    struct device *dev = &pdev->dev;
    int irq_gpio = -1;
    int irq = -1;
    int ret = 0;
    int i = 0;
    int_demo_data_t *data ;

    printk("%s enter.\n", __func__);


    data = devm_kmalloc(dev, sizeof(*data), GFP_KERNEL);
    if (!data) {
        printk("malloc fail for data\n");
        return -1;
    }



        irq_gpio = of_get_named_gpio(dev->of_node,"key-gpio", 0);

        data[0].gpio = irq_gpio;

        irq = gpio_to_irq(irq_gpio);


        data[0].irq = irq;

        printk("%s: gpio: %d ---> irq (%d)\n", __func__, irq_gpio, irq);

        ret = devm_request_any_context_irq(dev, irq,
            int_demo_isr, IRQF_TRIGGER_FALLING, "key-gpio", data);
        if (ret < 0) {
            dev_err(dev, "Unable to claim irq %d; error %d\n",
                irq, ret);
            return -1;
        }


    return 0;


}

static int int_demo_remove(struct platform_device *pdev) {

    printk("%s enter.\n", __func__);

    return 0;
}

static const struct of_device_id int_demo_dt_ids[] = {
    { .compatible = "nanopi-m1,interrupt_demo", },
    {},
};


static struct platform_driver int_demo_driver = {
    .driver        = {
        .name    = "interrupt_demo",
        .of_match_table    = int_demo_dt_ids,
    },
    .probe        = int_demo_probe,
    .remove        = int_demo_remove,
};

static int  int_demo_init(void)
{
     platform_driver_register(&int_demo_driver);
    return 0;
}
static void __exit int_demo_exit(void)
{
    platform_driver_unregister(&int_demo_driver);
}

module_init(int_demo_init);
module_exit(int_demo_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("WU");

 

编写驱动程序的Makefile,编译,加载模块

root@wu:/mnt/driver_test/irq_test# [  377.666140] int_demo_isr enter, gpio:9, irq: 71
[  377.743009] int_demo_isr enter, gpio:9, irq: 71
[  377.927100] int_demo_isr enter, gpio:9, irq: 71
[  378.000418] int_demo_isr enter, gpio:9, irq: 71
[  480.665685] int_demo_isr enter, gpio:9, irq: 71


root@wu:/mnt/driver_test/irq_test# cat /proc/interrupts
 71:          0          0          0          0  sunxi_pio_edge   9 Edge      key-gpio

 

 

 

 

 

 

 

 


版权声明:本文为qq_18737805原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。