天天看點

zynq添加GPIO中斷程式

//=====核心源碼為ADI官方關于AD9361的核心,編譯工具為petalinux2015.2,開發闆為ZYNQXC7Z100=========

一、修改裝置樹:

    1.打開petalinux項目下的./project-spec/meta-user/recipes-dt/device-tree/files/system-top.dts

    2.找到[email protected]節點,在interrupts屬性後面添加自己的GPIO。

注:GPIO管腳号加32等于中斷号。

例:添加61.62.63号的中斷,0x14是他原本的中斷。interrupts = <0x0 0x14 0x4>,<0x0 0x1d 0x1>, <0x0 0x1e 0x1>, <0x0

0x1f 0x1>;

zynq添加GPIO中斷程式

二、修改驅動,添加中斷程式:

    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; 

}

zynq添加GPIO中斷程式
zynq添加GPIO中斷程式

    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中斷

zynq添加GPIO中斷程式

    2.通過按鍵或其他方式觸發中斷,核心列印中斷處理程式的内容。(我是通過vivado觸發的)

zynq添加GPIO中斷程式
zynq添加GPIO中斷程式

四、完成。

源碼範例:

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開始數字幾就表示第幾個中斷。

例:

zynq添加GPIO中斷程式

3.其他的平台裝置都可以添加中斷,不僅僅是GPIO,但探測時傳參要是platform_device。

zynq添加GPIO中斷程式

4.struct resource *res;如果沒有需要手動添加。

繼續閱讀