Linux裝置註冊中斷服務request irq

2021-10-08 11:01:09 字數 3683 閱讀 4895

中斷處理程式是管理硬體的驅動程式的組成部分,

每一裝置都有相關的驅動程式,驅動程式可以通過request_irq()函式註冊乙個中斷處理程式,

並且啟用給定的中斷號,來處理指定的中斷. 同時需要晶元對應的io口支援中斷

#include #include #include #include #include //  建立該結構體用於把按鍵的相關資訊封裝起來傳遞到中斷服務函式中

struct gpio_button_data ;

// 建立結構體用於儲存資料 在解除安裝驅動模組的時候釋放相關的記憶體

struct gpio_keys_drvdata ;

static int gpio_get_value(unsigned long pin)

static int gpio_init(struct example_gpio_keys_button *button)

static irqreturn_t gpio_keys_isr(int irq, void *dev_id)

if (!gpio_level)

int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;

printk("%s[ev_key,%d,%d]\n", __func__, button->code, !!state);

return irq_handled;

}static struct example_gpio_keys_button exp_buttons = ,

};static int __devinit gpio_keys_probe(struct platform_device *pdev)

platform_set_drvdata(pdev, ddata);

input->name = pdev->name;

input->phys = "gpio-keys/input0";

input->dev.parent = &pdev->dev;

input->id.bustype = bus_host;

input->id.vendor = 0x0001;

input->id.product = 0x0001;

input->id.version = 0x0100;

ddata->input = input;

struct example_gpio_keys_button *button = &exp_buttons[0];

struct gpio_button_data *bdata = &ddata->data[0];

int irq;

bdata->input = input;

bdata->button = button;

error = gpio_init(button);

if (error < 0)

irq = exp_gpio_to_irq(button->gpio); // 獲取按鍵對應的中斷號

if (irq < 0)

void* dev_id = bdata;

error = request_irq(irq, gpio_keys_isr, irqf_trigger_high, "gpio_keys", dev_id);

if (error)

// 設定輸入裝置可以上報哪些輸入事件(按鍵/觸控/led/...)

input_set_capability(input, ev_key, button->code);

error = input_register_device(input);

if (error)

// 喚醒能力, 提供所有的wakeup資訊。

device_init_wakeup(&pdev->dev, 1);

return 0;

fail2:

while (--i >= 0)

platform_set_drvdata(pdev, null);

fail1:

input_free_device(input);

kfree(ddata);

return error;

}static int __devexit gpio_keys_remove(struct platform_device *pdev)

input_unregister_device(input);

return 0;

}static struct platform_driver gpio_keys_device_driver =

};static int __init gpio_keys_init(void)

static void __exit gpio_keys_exit(void)

module_init(gpio_keys_init);

module_exit(gpio_keys_exit);

module_license("gpl");

module_author("mr.linux.debug");

module_description("demo gpio-irq-key for kernel module");

相關函式說明

input_allocate_device

分配乙個裝置結構體,並初始化成員

作為input子系統的核心函式

request_irq

註冊中斷服務函式

(中斷號,中斷服務函式,高/低電平觸發,"gpio_keys",傳遞給中斷函式的引數)

input_set_capability

設定輸入裝置可以上報哪些輸入事件

(本例程上報的是按鍵事件ev_key, 還有ev_abs/ev_led等)

input_register_device

該函式將input_dev結構體註冊到輸入子系統

(輸入子系統核心[input core]提供的函式)

free_irq

對應request_irq

(釋放相關的中斷任務)

platform_set_drvdata

platform_get_drvdata

讀取 platform_set_drvdata 儲存到裝置資訊中的附加資料

platform_get_drvdata(struct platform_device *)

需要注意的地方

1 查詢晶元對應的io口是否具備中斷功能(是否有對應的中斷號)

2 需要在中斷服務函式中修改中斷條件(修改中斷電平),否則中斷服務函式會在滿足條件下一直呼叫

3 由於中斷處理程式需要占用cpu的時間,為了cpu盡快恢復中斷現場,有耗時操作,建議打包成任務,排到核心的工作佇列中進行處理

相應的一些巨集定義

ev_syn

表示裝置支援所有的事件

ev_key

鍵盤或者按鍵,表示乙個鍵碼

ev_rel

滑鼠裝置,表示乙個相對的游標位置結果

ev_abs

手寫板產生的值,其是乙個絕對整數值

ev_led

led燈裝置

ev_snd

蜂鳴器,輸入聲音

ev_rep

允許重複按鍵型別

irqf_shared

表示共享相同的中斷號,很多人可以占用這個中斷號

irqf_trigger_high

高電平中斷

Linux混雜裝置註冊方法

linux混雜裝置註冊,相對來說更加簡單,可以這樣做 static int init init fpga void 可以看到沒有字元裝置標準的那種什麼申請裝置號,初始化,新增等操作,只用乙個misc register 就可以了。static struct miscdevice ppc dpram m...

裝置註冊 驅動註冊以及雜項裝置註冊之間的關係

1.裝置宣告是在平台檔案 home leizi android itop4412 kernel 3.0 arch arm mach exynos mach itop4412.c中,如下圖,並且裝置名稱是led two.核心編譯之後,s3c device leds ctl被註冊到核心中,並不名稱是le...

linux字元裝置註冊相關函式

本文介紹linux字元裝置註冊相關的四個函式 cdev alloc cdev init cdev add和cdev del。這四個函式在檔案 fs char dev.c中定義,在標頭檔案include linux cdev.h中宣告。其中cdev alloc和cdev init是一對 互斥 函式,以...