//=====核心源碼為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>;
二、修改驅動,添加中斷程式:
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;如果沒有需要手動添加。