zynq添加GPIO中断程序

//=====内核源码为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;如果没有需要手动添加。

猜你喜欢

转载自blog.csdn.net/qq_41133610/article/details/81564076