在基于Linux的操作系统中管理中断

时间:2018-02-11 11:04:20

标签: linux-kernel linux-device-driver interrupt platform device-tree

上下文

我有一个设备树,其中一个节点是:

    gpio@41210000 {
        #gpio-cells = <0x2>;
        #interrupt-cells = <0x2>;
        compatible = "xlnx,xps-gpio-1.00.a,generic-uio,BTandSW";
        gpio-controller;
        interrupt-controller;
        interrupt-parent = <0x4>;
        //interrupt-parent =<&gic>;
        interrupts = <0x0 0x1d 0x4>;
        reg = <0x41210000 0x10000>;
        xlnx,all-inputs = <0x1>;
        xlnx,all-inputs-2 = <0x1>;
        xlnx,all-outputs = <0x0>;
        xlnx,all-outputs-2 = <0x0>;
        xlnx,dout-default = <0x0>;
        xlnx,dout-default-2 = <0x0>;
        xlnx,gpio-width = <0x4>;
        xlnx,gpio2-width = <0x2>;
        xlnx,interrupt-present = <0x1>;
        xlnx,is-dual = <0x1>;
        xlnx,tri-default = <0xffffffff>;
        xlnx,tri-default-2 = <0xffffffff>;
    };

内核运行后,执行

cat /proc/interrupts

结果是:

root@linaro-developer:~# cat /proc/interrupts
           CPU0       CPU1
 16:          0          0     GIC-0  27 Edge      gt
 17:          0          0     GIC-0  43 Level     ttc_clockevent
 18:       1588       1064     GIC-0  29 Edge      twd
 21:         43          0     GIC-0  39 Level     f8007100.adc
 24:          0          0     GIC-0  35 Level     f800c000.ocmc
 25:        506          0     GIC-0  59 Level     xuartps
 26:          0          0     GIC-0  51 Level     e000d000.spi
 27:          0          0     GIC-0  54 Level     eth5
 28:       4444          0     GIC-0  56 Level     mmc0
 29:          0          0     GIC-0  45 Level     f8003000.dmac
 30:          0          0     GIC-0  46 Level     f8003000.dmac
 31:          0          0     GIC-0  47 Level     f8003000.dmac
 32:          0          0     GIC-0  48 Level     f8003000.dmac
 33:          0          0     GIC-0  49 Level     f8003000.dmac
 34:          0          0     GIC-0  72 Level     f8003000.dmac
 35:          0          0     GIC-0  73 Level     f8003000.dmac
 36:          0          0     GIC-0  74 Level     f8003000.dmac
 37:          0          0     GIC-0  75 Level     f8003000.dmac
 38:          0          0     GIC-0  40 Level     f8007000.devcfg
 45:          0          0     GIC-0  41 Edge      f8005000.watchdog
IPI1:          0          0  Timer broadcast interrupts
IPI2:       1731       2206  Rescheduling interrupts
IPI3:         29         36  Function call interrupts
IPI4:          0          0  CPU stop interrupts
IPI5:          0          0  IRQ work interrupts
IPI6:          0          0  completion interrupts
Err:          0

问题

  1. 内核运行后,是否应该识别,自动并更新文件/proc/interrupt中的数据?

  2. 但是,我用这种方式编写了.probe函数:

     static int SWITCH_of_probe(struct platform_device *pdev)
    {
        int ret=0;
        struct irq_data data_tmp;
        SWITCH_01_devices->temp_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!(SWITCH_01_devices->temp_res)) {
            dev_err(&pdev->dev, "TRY could not get IO memory\n");
            return -ENXIO;
        }
    
     PDEBUG("resource : regs.start=%#x,regs.end=%#x\n",SWITCH_01_devices->temp_res->start,SWITCH_01_devices->temp_res->end);
    
     //SWITCH_01_devices->irq_line = platform_get_irq(pdev, 0);
     SWITCH_01_devices->irq_line = irq_of_parse_and_map(pdev->dev.of_node, 0);
       if (SWITCH_01_devices->irq_line < 0) {
           dev_err(&pdev->dev, "could not get IRQ\n");
         printk(KERN_ALERT "could not get IRQ\n");
           return SWITCH_01_devices->irq_line;
       }
    
     PDEBUG(" resource VIRTUAL IRQ NUMBER : irq=%#x\n",SWITCH_01_devices->irq_line);
     ret = request_irq((SWITCH_01_devices->irq_line), SWITCH_01_interrupt, IRQF_SHARED  , DRIVER_NAME, NULL);
     if (ret) {
        printk(KERN_ALERT "NEW SWITCH_01: can't get assigned irq, ret= %d\n", SWITCH_01_devices->irq_line, ret);
        SWITCH_01_devices->irq_line = -1;
    }
    
    
     SWITCH_01_devices->mem_region_requested = request_mem_region((SWITCH_01_devices->temp_res->start),resource_size(SWITCH_01_devices->temp_res),"SWITCH_01");
     if(SWITCH_01_devices->mem_region_requested == NULL){
         printk(KERN_WARNING "[LEO] SWITCH: FaiSWITCH request_mem_region(res.start,resource_size(&(SWITCH_01_devices->res)),...);\n");
     }
     else
         PDEBUG(" [+] request_mem_region\n");
    
     return 0; /* Success */
     }
    
  3. 在内核中插入模块时,我有来自dmesg的输出:

    [ 1249.777189] SWITCH_01: loading out-of-tree module taints kernel.
    [ 1249.777787] [LEO] SWITCH_01: dinamic allocation of major number
    [ 1249.777801] [LEO]  cdev initialized
    [ 1249.777988] [LEO] resource : regs.start=0x41210000,regs.end=0x4121ffff
    [ 1249.777994] [LEO]  resource : irq=0x2e
    [ 1249.778000] NEW SWITCH_01: can't get assigned irq, ret= -22
    [ 1249.782531] [LEO]  [+] request_mem_region
    

    我做错了什么?为什么我无法执行正确的request_irq?

    注意:设备树的interrupts = <0x0 0x1d 0x4>字段和检测到的irq_number不同。由于有人指出here,我使用platform_get_irq(pdev, 0);更改了irq_of_parse_and_map(pdev->dev.of_node, 0);,但结果是相同的。

1 个答案:

答案 0 :(得分:1)

  

内核运行后,它应该自动识别和   更新文件/ proc / interrupt中的数据?

是的,一旦注册了中断,它就会更新。

[ 1249.777189] SWITCH_01: loading out-of-tree module taints kernel.
[ 1249.777787] [LEO] SWITCH_01: dinamic allocation of major number
[ 1249.777801] [LEO]  cdev initialized
[ 1249.777988] [LEO] resource : regs.start=0x41210000,regs.end=0x4121ffff
[ 1249.777994] [LEO]  resource : irq=0x2e
[ 1249.778000] NEW SWITCH_01: can't get assigned irq, ret= -22
[ 1249.782531] [LEO]  [+] request_mem_region
  

我做错了什么?为什么我无法执行正确的request_irq?

共享中断(IRQF_SHARED)必须传递dev_id(您在request_irq()中传递NULL),如果返回NULL-EINVAL,请确保你传递一个非null的有效dev_id