- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我使用的是带有 Zynq XC72010 的定制开发板,用于运行 Linux 4.5 内核。我正在为我们正在内部测试的芯片开发设备驱动程序,我在尝试将 GPIO 线绑定(bind)到软件 IRQ 时遇到了很多问题。到目前为止,我已经尝试了几种方法并用尽了我能想到的任何谷歌搜索。我的设备树配置的相关部分:
/ {
compatible = "xlnx,zynq-7000";
amba {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
ranges;
intc: interrupt-controller@f8f01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
interrupt-controller;
reg = <0xF8F01000 0x1000>,
<0xF8F00100 0x100>;
};
i2c0: i2c@e0004000 {
compatible = "cdns,i2c-r1p10";
status = "disabled";
clocks = <&clkc 38>;
interrupt-parent = <&intc>;
interrupts = <0 25 4>;
reg = <0xe0004000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
// I WANT INTERRUPT TO TRIGGER
// ON THIS DEVICE (axi_gpio_0, pin 2)
device: device@48 {
compatible = "device,name";
reg = <0x48>;
reset-gpios = <&axi_gpio_0 1 0>;
interrupt-parent = <&axi_gpio_0>;
interrupt-gpios = <&axi_gpio_0 2 0>;
};
};
};
amba_pl {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges ;
axi_gpio_0: gpio@41200000 {
#gpio-cells = <2>;
compatible = "xlnx,xps-gpio-1.00.a";
gpio-controller;
interrupt-parent = <&intc>;
interrupts = <0 31 4>;
reg = <0x41200000 0x10000>;
xlnx,all-inputs = <0x0>;
xlnx,all-inputs-2 = <0x0>;
xlnx,all-outputs = <0x0>;
xlnx,all-outputs-2 = <0x0>;
xlnx,dout-default = <0x00000000>;
xlnx,dout-default-2 = <0x00000000>;
xlnx,gpio-width = <0x10>;
xlnx,gpio2-width = <0x20>;
xlnx,interrupt-present = <0x1>;
xlnx,is-dual = <0x0>;
xlnx,tri-default = <0xFFFFFFFF>;
xlnx,tri-default-2 = <0xFFFFFFFF>;
};
};
我正在尝试为“设备”内的“axi_gpio_0”的引脚 2 分配一个中断。
浏览 google 得到了 3 种在驱动程序代码中绑定(bind)中断的常用方法:
/* Method 1 */
device->interrupt_gpio = devm_gpiod_get_optional(&i2c_client->dev,
"interrupt", GPIOD_IN);
if(IS_ERR(device->interrupt_gpio))
return PTR_ERR(device->interrupt_gpio);
printk("device: Interrupt GPIO = %d\n",desc_to_gpio(device->interrupt_gpio));
irq = gpiod_to_irq(device->interrupt_gpio);
printk("device: IRQ = %d\n",irq);
ret = devm_request_threaded_irq(&i2c_client->dev, irq,
NULL, device_irq_thread, IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
"device", device);
if (ret != 0)
dev_err(&i2c_client->dev, "Failed to request IRQ: %d\n", ret);
/* Method 2 */
device->interrupt_gpio = devm_gpiod_get_optional(&i2c_client->dev,
"interrupt", GPIOD_ASIS);
if (IS_ERR(device->interrupt_gpio))
return PTR_ERR(device->interrupt_gpio);
if (device->interrupt_gpio) {
dev_info(&i2c_client->dev, "Found interrupt GPIO: %d\n",desc_to_gpio(device->interrupt_gpio));
dev_info(&i2c_client->dev, "IRQ Number: %d\n",gpiod_to_irq(device->interrupt_gpio));
gpio_request(desc_to_gpio(device->interrupt_gpio), "DEVICE_INT"); // Request a GPIO pin from the driver
gpio_direction_input(desc_to_gpio(device->interrupt_gpio)); // Set GPIO as input
gpio_set_debounce(desc_to_gpio(device->interrupt_gpio), 50); // Set a 50ms debounce, adjust to your needs
gpio_export(desc_to_gpio(device->interrupt_gpio), false); // The GPIO will appear in /sys/class/gpio
ret = request_irq(gpiod_to_irq(device->interrupt_gpio), // requested interrupt
(irq_handler_t) irqHandler, // pointer to handler function
IRQF_TRIGGER_RISING, // interrupt mode flag
"DEVICE_IRQ_HANDLER", // used in /proc/interrupts
NULL); // the *dev_id shared interrupt lines, NULL is okay
if (ret != 0) {
dev_err(&i2c_client->dev,
"Failed to request IRQ: %d\n", ret);
}
}
else {
dev_err(&i2c_client->dev, "Failed to get interrupt GPIO pin\n");
}
/* Method 3 */
dev_info(&i2c_client->dev, "IRQ requested: %d\n", i2c_client->irq);
ret = devm_request_threaded_irq(&i2c_client->dev, i2c_client->irq,
NULL, device_irq_thread, IRQF_ONESHOT | IRQF_TRIGGER_LOW,
"device", device);
if (ret != 0)
dev_err(&i2c_client->dev, "Failed to request IRQ: %d\n", ret);
我尝试了所有这些方法和各种设备树配置的组合,但它们都没有实现我需要的功能。
方法 1 的结果如下:
device: Interrupt GPIO = 892
device: IRQ = -6
device 0-0048: Failed to request IRQ: -22
方法 2 的结果如下:
device 0-0048: Found interrupt GPIO: 892
device 0-0048: IRQ Number: -6
device 0-0048: Failed to request IRQ: -22
因此,尝试使用描述符 GPIO 和旧的 GPIO api 都无法成功绑定(bind)中断。
为了尝试方法 3,我调整了设备树:
device: device@48 {
compatible = "device,name";
reg = <0x48>;
interrupt-parent = <&axi_gpio_0>; // or <&intc>?
interrupts = <0 2 0x02>; // trying to grab pin 2
};
方法 3 的结果如下:
genirq: Setting trigger mode 2 for irq 168 failed (gic_set_type+0x0/0x48)
device 0-0048: IRQ requested: 168
genirq: Setting trigger mode 8 for irq 168 failed (gic_set_type+0x0/0x48)
device 0-0048: Failed to request IRQ: -22
问题似乎是将软件中断分配给 Linux 中的特定 GPIO。我不明白我在这里错过了什么。任何建议表示赞赏。
编辑 1:
我发现 Linux 出于某种原因不喜欢低级中断。将方法 3 更改为:
device: device@48 {
compatible = "device,name";
reg = <0x48>;
interrupt-parent = <&axi_gpio_0>;
interrupts = <0 2 0x04>;
};
和驱动程序代码:
dev_info(&i2c_client->dev, "IRQ requested: %d\n", i2c_client->irq);
ret = devm_request_threaded_irq(&i2c_client->dev, i2c_client->irq,
NULL, device_irq_thread, IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
"device", device);
if (ret != 0)
dev_err(&i2c_client->dev, "Failed to request IRQ: %d\n", ret);
允许我成功请求 IRQ。但是,我的信号是低电平有效,所以这对我帮助不大。此外,我不确定此方法是否引用 axi_gpio_0
pin 2 作为中断信号。我可以同时使用 intc
和 axi_gpio_0
作为 interrupt-parent
并且它映射到相同的 IRQ 号(我从 cat/过程/中断
)。那么,忽略信号的极性,我如何确保根据 axi_gpio_0
引脚 2 的切换触发我注册的中断?
编辑 2:
我跟踪了向中断 Controller 的驱动程序请求低电平有效中断的问题:kernel/drivers/irqchip/irq-gic.c
。这部分代码是导致问题的原因:
static int gic_set_type(struct irq_data *d, unsigned int type)
{
void __iomem *base = gic_dist_base(d);
unsigned int gicirq = gic_irq(d);
/* Interrupt configuration for SGIs can't be changed */
if (gicirq < 16)
return -EINVAL;
/* SPIs have restrictions on the supported types */
if (gicirq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
type != IRQ_TYPE_EDGE_RISING)
return -EINVAL;
return gic_configure_irq(gicirq, type, base, NULL);
}
破解内核根本不是我想做的,而是注释掉:
/* SPIs have restrictions on the supported types */
/*if (gicirq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
type != IRQ_TYPE_EDGE_RISING)
return -EINVAL;*/
允许我请求低电平有效中断。出于测试目的,这应该暂时有效。
更新:
我已经成功地在 GPIO 引脚上创建了一个 IRQ。我的问题出在我使用的 GPIO Controller 上。 Controller 是 Zynq 可编程逻辑 block 内的 Xilinx IP block ,该 Controller 无法触发 GPIO 引脚上的中断(我不知道原因)。我将正在处理的电路板上的中断引脚焊接到另一个更通用的 Controller 上的 GPIO 引脚,现在 Linux 可以很好地配合我使用。
总而言之,匹配 compatible = "xlnx,xps-gpio-1.00.a";
的 GPIO Controller 无法绑定(bind)到 Linux 中的软件中断。如果您遇到此问题,请使用不同的 GPIO Controller 。
感谢大家的帮助。
最佳答案
使用方法 3 的设备树节点,您应该能够使用 irq_of_parse_and_map(i2c_client->dev.of_node, 0)
检索 IRQ。
然后可以像使用 devm_request_threaded_irq()
那样请求检索到的 IRQ。
关于c - Linux 4.5 GPIO 中断通过 Xilinx Zynq 平台上的 Devicetree,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39212771/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
Linux 管道可以缓冲多少数据?这是可配置的吗? 如果管道的两端在同一个进程中,但线程不同,这会有什么不同吗? 请注意:这个“同一个进程,两个线程”的问题是理论上的边栏,真正的问题是关于缓冲的。 最
我找到了here [最后一页] 一种有趣的通过 Linux 启动 Linux 的方法。不幸的是,它只是被提及,我在网上找不到任何有用的链接。那么有人听说过一种避免引导加载程序而使用 Linux 的方法
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我试图了解 ld-linux.so 如何在 Linux 上解析对版本化符号的引用。我有以下文件: 测试.c: void f(); int main() { f(); } a.c 和 b.c:
与 RetroPie 的工作原理类似,我可以使用 Linux 应用程序作为我的桌面环境吗?我实际上并不需要像实际桌面和安装应用程序这样的东西。我只需要一种干净简单的方法来在 RaspberryPi 上
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 10 年前。 Improve thi
有什么方法可以覆盖现有的源代码,我应该用 PyQt、PyGTK、Java 等从头开始构建吗? 最佳答案 如果您指的是软件本身而不是它所连接的存储库,那么自定义应用程序的方法就是 fork 项目。据我所
我的情况是:我在一个磁盘上安装了两个 linux。我将第一个安装在/dev/sda1 中,然后在/dev/sda2 中安装第二个然后我运行第一个系统,我写了一个脚本来在第一个系统运行时更新它。
我在 i2c-0 总线上使用地址为 0x3f 的系统监视器设备。该设备在设备树中配置有 pmbus 驱动程序。 问题是,加载 linux 内核时,这个“Sysmon”设备没有供电。因此,当我在总线 0
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 11 年前。 Improve thi
我正试图在 linux 模块中分配一大块内存,而 kalloc 做不到。 我知道唯一的方法是使用 alloc_bootmem(unsigned long size) 但我只能从 linux 内核而不是
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
我有 .sh 文件来运行应用程序。在该文件中,我想动态设置服务器名称,而不是每次都配置。 我尝试了以下方法,它在 CentOS 中运行良好。 nohup /voip/java/jdk1.8.0_71/
我是在 Linux 上开发嵌入式 C++ 程序的新手。我有我的 Debian 操作系统,我在其中开发和编译了我的 C++ 项目(一个简单的控制台进程)。 我想将我的应用程序放到另一个 Debian 操
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 4 年前。 Improve this ques
我使用4.19.78版本的稳定内核,我想找到带有企鹅二进制数据的C数组。系统启动时显示。我需要在哪里搜索该内容? 我在 include/linux/linux_logo.h 文件中只找到了一些 Log
我知道可以使用 gdb 的服务器模式远程调试代码,我知道可以调试针对另一种架构交叉编译的代码,但是是否可以更进一步,从远程调试 Linux 应用程序OS X 使用 gdbserver? 最佳答案 当然
是否有任何可能的方法来运行在另一个 Linux 上编译的二进制文件?我知道当然最简单的是在另一台机器上重建它,但假设我们唯一能得到的是一个二进制文件,那么这可能与否? (我知道这可能并不容易,但我只是
我是一名优秀的程序员,十分优秀!