

Zynqの割り込みに悩んでいます。

システムの主要構成  
Microzed, petalinux2016.2, CentOS7

GPIO割り込みは使用しません。  
ドライバのCodingにUIOは使用しません。

IPの構成は簡単です:

  * Zynq7
  * Axi Interconnect
  * Processor System Reset
  * my_ip (ilc_ip_0)
  * 4 IPのみ

my_ipの割り込み要求端子intrはZYNQのIRQ_F2P [0,0]に直接接続されています。

Myproject はvivadoから生成されるdesign_1_wrapper.hdfファイルが基礎になっています。  
buildして4つのファイルが得られ、1個を追加しました。

  * image.ub
  * system.dtb (不要？)
  * ilcproc
  * ilcdev.ko
  * mystartup.sh

これらをSDCARDに格納、Resetします。  
割り込み以外の機能は正常です。

以下に割り込み関連事項を抜き出しています。

### 1\. irqNo

次のファイルが取得でき

[code]

    ilc(myprg)/subsystems/linux/hw-description/xparameters.h
    
[/code]

これから

[code]

    #define XPAR_FABRIC_ILC_IP_0_INTR_INTR 61
    
[/code]

の記述を抜き出して  
irqNo は61に確定しました。

### 2\. device tree

以下のDevice=treeが得られました：

[code]

    ilc/subsystems/linux/device-tree/pl.dtsi
    
[/code]

内容

[code]

     / {
     amba_pl: amba_pl {
     # address-cells = <1>;
     # size-cells = <1>;
     compatible = "simple-bus";
     ranges;
     ilc_ip_0: ilc_ip @ 43c00000 {
     compatible = "xlnx, ilc-ip-189.4";
     interrupt-parent = <& intc>;
     interrupts = <0 29 4>;
     reg = <0x43c00000 0x10000>;
     xlnx, s00-axi-ilc-ip-addr-width = <0x4>;
     xlnx, s00-axi-ilc-ip-data-width = <0x20>;
     };
     };
    
[/code]

`interrupts = <0 29 4>;?` は何を意味するのでしょう？  
以下のように推量しました：

[code]

      0: SPI
     29: 61-32 = 29 29 はGICがもたらすOffset？。しかし GICは使わないつもりです。
      4: Level interrupt. これはSPIなのだから0が正しいのではないか？
    
[/code]

### 3.

割り込み要求信号"intr" はedge信号が間違いなく出ていることをオッシロで確認しました。 Interruptは発生しません。

### 4.

次に `/proc/interrupts` をチェックしてみました。

[code]

     21: 43 0 GIC       39 Level f8007100.adc
     61:  0 0 zynq-gpio 38 Edge  ilcdev
    142:  0 0 GIC       35 Level f800c000.ocmc
    
[/code]

zynq-gpio、これは何でしょう？  
GPIO は構成に含まず全く関係ありません。  
これはintrがGICを介さCPUに直接つながっていることを表していると考えました。  
それともGICに代わるI/Fの仕様なのでしょうか？  
いずれにしろGICの設定は全く行っていません。

ご示唆いただける方がいると助かります。

### 5.

Linuxの関係programを一括して掲載します。  
Xilinx社のTemplateそのままです。

[code]

    static int ilcdev_probe(struct platform_device *pdev)
    {
        struct resource *r_irq; /* Interrupt resources */
        struct resource *r_mem; /* IO mem resources */
        struct device *dev = &pdev->dev;
        struct ilcdev_local *lp = NULL;
    
        int rc = 0;
    
        dev_info(dev, "Device Tree Probing\n");
    
        /* Get iospace for the device */
        r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!r_mem) {
            dev_err(dev, "invalid address\n");
            return -ENODEV;
        }
    
        lp = (struct ilcdev_local *) kmalloc(sizeof(struct ilcdev_local), GFP_KERNEL);
        if (!lp) {
            dev_err(dev, "Cound not allocate ilcdev device\n");
            return -ENOMEM;
        }
    
        dev_set_drvdata(dev, lp);
    
        lp->mem_start = r_mem->start;
        lp->mem_end = r_mem->end;
    
        if (!request_mem_region(lp->mem_start,
                    lp->mem_end - lp->mem_start + 1,
                    DRIVER_NAME)) {
            dev_err(dev, "Couldn't lock memory region at %p\n",
                (void *)lp->mem_start);
            rc = -EBUSY;
            goto error1;
        }
    
        lp->base_addr = ioremap(lp->mem_start, lp->mem_end - lp->mem_start + 1);
        if (!lp->base_addr) {
            dev_err(dev, "ilcdev: Could not allocate iomem\n");
            rc = -EIO;
            goto error2;
        }
    
        /* Get IRQ for the device */
        r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!r_irq) {
            dev_info(dev, "no IRQ found\n");
            dev_info(dev, "ilcdev at 0x%08x mapped to 0x%08x\n",
                (unsigned int __force)lp->mem_start,
                (unsigned int __force)lp->base_addr);
            return 0;
        }
        lp->irq = r_irq->start;
    
        rc = request_irq(lp->irq, &ilcdev_irq, 0, DRIVER_NAME, lp);
        if (rc) {
            dev_err(dev, "testmodule: Could not allocate interrupt %d.\n",
                lp->irq);
            goto error3;
        }
    
        dev_info(dev,"ilcdev at 0x%08x mapped to 0x%08x, irq=%d\n",
            (unsigned int __force)lp->mem_start,
            (unsigned int __force)lp->base_addr,
            lp->irq);
    
        enable_irq(lp->irq);                // 2019/10/19 Added
    
        return 0;
    error3:
        free_irq(lp->irq, lp);
    error2:
        release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1);
    error1:
        kfree(lp);
        dev_set_drvdata(dev, NULL);
        return rc;
    }
    
    
    static int __init ilcdev_init(void)
    {
        int ret;
    
        printk("<1>Hello module world.\n");
        printk("<1>Module parameters were (0x%08x) and \"%s\"\n", myint, mystr);
    
        static struct resource foomatic_resources[] = {
            {
                .start  = 0x43c00000,
                .end    = 0x43c0ffff,
                .flags  = IORESOURCE_MEM,
                .name   = "io-memory"
            },
            {
                .start  = XPAR_FABRIC_ILC_IP_0_INTR_INTR,
                .end    = 20,
                .flags  = IORESOURCE_IRQ,
                .name   = "irq",
            }
        };
    
        pdev = platform_device_register_simple(DRIVER_NAME, 0, foomatic_resources,
            ARRAY_SIZE(foomatic_resources));              
        printk("ARRAY_SIZE(foomatic_resources) %x\n", ARRAY_SIZE(foomatic_resources));
    
        if (pdev == NULL)                       {                                                     
            printk("Adding platform device pdev\"%x\" failed\n", pdev);
            kfree(pdev);                                                             
            return -ENODEV;                                                          
        }
        else{
            printk("Adding platform device pdev\"%x\" successfull\n", pdev);
        }
    
        return platform_driver_register(&ilcdev_driver);
    }
    
[/code]


CC BY-SA 4.0
2019-10-29T12:39:29.760
60086
2019-10-29T14:42:02.707
2019-10-29T14:42:02.707
19110
36330
question
linux centos zynq
Zynqで割り込みが不調