//=====内核源码为ADI官方关于AD9361的内核,编译工具为petalinux2015.2,开发板为ZYNQXC7Z100=========
一、修改设备树:
1.打开petalinux项目下的./project-spec/meta-user/recipes-dt/device-tree/files/system-top.dts
2.找到gpio@e000a000节点,在interrupts属性后面添加自己的GPIO。
注:GPIO管脚号加32等于中断号。
例:添加61.62.63号的中断,0x14是他原本的中断。interrupts = <0x0 0x14 0x4>,<0x0 0x1d 0x1>, <0x0 0x1e 0x1>, <0x0
0x1f 0x1>;
二、修改驱动,添加中断程序:
1.打开内核目录下./drivers/gpio/gpio-zynq.c GPIO驱动文件。
2.找到驱动探测函数static int zynq_gpio_probe(struct platform_device *pdev)添加代码。
在zynq_gpio_probe函数内添加platform_get_resource与request_irq中断处理。(下面是源码范例)
在zynq_gpio_probe函数外添加中断发生后的处理函数。函数名需与request_irq的第四个参数相同。
例:irqreturn_t test_interrupt_61(int irqno, void *devid)
{
printk("......test61..........irqno = %d\n", irqno);
return IRQ_HANDLED;
}
3.有时需要添加头文件: #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/interrupt.h>
4.有时需要添加中断属性(部分):
#define IRQF_DISABLED 0x00000020 //调用中断处理程序时禁用IRQ
#define IRQF_TRIGGER_HIGH 0x00000004 //高电平触发
#define IRQF_TRIGGER_RISING 0x00000001 //上升沿触发
#define IRQF_SHARED 0x00000080 //共享中断
三、编译内核->运行程序:
1.cat /proc/interrupts能够看到挂载的GPIO中断
2.通过按键或其他方式触发中断,内核打印中断处理程序的内容。(我是通过vivado触发的)
四、完成。
源码范例:
static int zynq_gpio_probe(struct platform_device *pdev)
{
.........................
struct resource *res;
int ret1;
res=platform_get_resource(pdev,IORESOURCE_IRQ,1);
if(res == NULL ){
printk("platform_get_resource key1_res fail\n");
return -1;
}
ret = request_irq(res->start, test_interrupt_61, IRQF_TRIGGER_RISING, "int_test61", NULL);
if (ret1 < 0)
printk("....test61........failed request irq: irqno = irq_res->start\n");
res=platform_get_resource(pdev,IORESOURCE_IRQ,2);
if(res == NULL ){
printk("platform_get_resource key1_res fail\n");
return -1;
}
ret1 = request_irq(res->start, test_interrupt_62, IRQF_TRIGGER_RISING, "int_test62", NULL);
if (ret1 < 0)
printk("....test61........failed request irq: irqno = irq_res->start\n");
res =platform_get_resource(pdev,IORESOURCE_IRQ,3);
if(res == NULL ){
printk("platform_get_resource key1_res fail\n");
return -1;
}
ret1 = request_irq(res->start, test_interrupt_63, IRQF_TRIGGER_RISING, "int_test63", NULL);
if (ret1 < 0)
printk("....test61........failed request irq: irqno = irq_res->start\n");
...............................
}
心得:
1.request_irq函数中的第一个属性不能直接手动填中断号,必须通过设备树获取,进行映射之后才能使用,否者不能触发中断。
2.platform_get_resource函数的第三个属性,与设备树GPIO中断排列的排列顺序有关,从0开始数字几就表示第几个中断。
例:
3.其他的平台设备都可以添加中断,不仅仅是GPIO,但探测时传参要是platform_device。
4.struct resource *res;如果没有需要手动添加。