在基于 Linux 的 OS 中管理中断
Managing interrupt in Linux-based OS
上下文
我有一个设备树,其中一个节点是:
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
问题
一旦内核是运行,它是否应该自动识别并更新文件/proc/interrupt
中的数据?
但是我写了一个.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 */
}
在内核中插入模块时,我从 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不一样。正如指出 ,我将 platform_get_irq(pdev, 0);
更改为 irq_of_parse_and_map(pdev->dev.of_node, 0);
但结果是一样的。
Once the kernel is running, should it recognize, automatically, and
update the data in the file /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
What am I doing wrong? Why I cannot perform a correct request_irq?
共享中断(IRQF_SHARED
)必须传递dev_id(你在request_irq()
中传递NULL),如果NULL
,-EINVAL
是已返回,因此请确保您传递了一个非空的有效 dev_id
上下文
我有一个设备树,其中一个节点是:
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
问题
一旦内核是运行,它是否应该自动识别并更新文件
/proc/interrupt
中的数据?但是我写了一个
.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 */ }
在内核中插入模块时,我从 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不一样。正如指出 platform_get_irq(pdev, 0);
更改为 irq_of_parse_and_map(pdev->dev.of_node, 0);
但结果是一样的。
Once the kernel is running, should it recognize, automatically, and update the data in the file /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
What am I doing wrong? Why I cannot perform a correct request_irq?
共享中断(IRQF_SHARED
)必须传递dev_id(你在request_irq()
中传递NULL),如果NULL
,-EINVAL
是已返回,因此请确保您传递了一个非空的有效 dev_id