Zynqで割り込みが不調
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
次のファイルが取得でき
ilc(myprg)/subsystems/linux/hw-description/xparameters.h
これから
#define XPAR_FABRIC_ILC_IP_0_INTR_INTR 61
の記述を抜き出して
irqNo は61に確定しました。
2. device tree
以下のDevice=treeが得られました:
ilc/subsystems/linux/device-tree/pl.dtsi
内容
/ {
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>;
};
};
interrupts = <0 29 4>;?
は何を意味するのでしょう?
以下のように推量しました:
0: SPI
29: 61-32 = 29 29 はGICがもたらすOffset?。しかし GICは使わないつもりです。
4: Level interrupt. これはSPIなのだから0が正しいのではないか?
3.
割り込み要求信号"intr" はedge信号が間違いなく出ていることをオッシロで確認しました。 Interruptは発生しません。
4.
次に /proc/interrupts
をチェックしてみました。
21: 43 0 GIC 39 Level f8007100.adc
61: 0 0 zynq-gpio 38 Edge ilcdev
142: 0 0 GIC 35 Level f800c000.ocmc
zynq-gpio、これは何でしょう?
GPIO は構成に含まず全く関係ありません。
これはintrがGICを介さCPUに直接つながっていることを表していると考えました。
それともGICに代わるI/Fの仕様なのでしょうか?
いずれにしろGICの設定は全く行っていません。
ご示唆いただける方がいると助かります。
5.
Linuxの関係programを一括して掲載します。
Xilinx社のTemplateそのままです。
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);
}