?
- 外部IO中斷介紹
本篇文章以萬象奧科HD-RK3568-IOT評估板中GPIO30為例,介紹Linux內核中斷的注冊方法,使用中斷的方式檢測GPIO30是否出現上升沿信號。中斷在linux、設備驅動開發里使用的都非常多,可以更加實時的檢測GPIO30的狀態。
Linux內核提供了中斷的注冊接口:
- 注冊中斷
頭文件 include\linux\interrupt.h
定義文件 include\linux\interrupt.h
函數原型 int request_irq(unsigned int irq, /* 做實參傳遞給中斷服務函數第1個參數 */
Irq_handler_t handler, /* 中斷服務函數指針 */
unsigned long flags,
const char *name,
void *dev_id); /* 做實參傳遞給中斷服務函數第2個參數 */
函數功能: 向內核注冊一個中斷服務函數;
當發生中斷號為irq的中斷時,會執行handler指針函數。
函數參數:
irq: 中斷編號(每個中斷有唯一的編號)。
handler: 中斷服務函數指針。
原型 typedef irqreturn_t(*irq_handler_t)(int, void *)。
flag: 中斷的標志,用來描述本中斷的基本特征的。
有固定的值,由中斷源的特征決定;
比如外中斷有: 上升沿,下降沿觸發中斷這類標志。
name: 中斷名字,注冊后會出現cat /proc/interrupts
dev_id: 這個參數是傳遞給中斷服務函數。
對共享中斷來說,這個參數一定有要;
當注銷共享中斷中的其中一個時,用這個標識要注銷哪一個。
對于有唯一入口的中斷,可以傳遞NULL;
但是一般來說都會傳遞一個有意義指針,在中斷程序中使用,以方便編程。
返回值 0 標識成功
-EINVAL (無效參數22) 表示中斷號無效。
-EBUSY (設備或者資源忙16) 表示中斷已經被占用。
2) 注銷中斷
void free_irq(unsigned int irq, void *dev_id)
irq: 要注銷的中斷號
dev_id: 其實就是注冊時需要使用的dev參數,在共享中斷必不可少,不能傳遞NULL。
注意:為防止在注銷時同時發生中斷,調用時候,先禁掉中斷。
3) 中斷開啟與關閉
禁止中斷:
void disable_irq_nosync(unsigned int irq);
void disable_irq(unsigned int irq);
參數: irq,要禁止的中斷對應的編號。
注意:在中斷服務程序中不能使用disable_irq這個函數,否則內核崩潰,可以使用disable_irq_nosync,
disable_irq: 函數調用后,函數不會馬上返回,而等待中斷程序執行完成才返回,在中斷調用會導致死鎖。
使能中斷:
void enable_irq(unsigned int irq);
參數: irq, 要使能的中斷對應的編號。
4) 獲取irq中斷號
Int gpio_to_irq(unsigned int irq);
參數: irq,要使能的中斷對應的編號
- 外部IO中斷驅動編寫
- IO原理圖
![](https://file1.elecfans.com/web2/M00/AC/53/wKgaomVEi3OADDxNAAIwq7CXJew124.png)
![wKgZomVEizqAAaH_AAFy1JumMiQ719.png](https://file1.elecfans.com/web2/M00/AE/1C/wKgZomVEizqAAaH_AAFy1JumMiQ719.png)
圖 2.1 GPIO0_D6
GPIO0_D6=0*32+(4-1)-8+6=30
- 驅動示例代碼
#include
#include
#include
#include
#include
#define GPIO_PIN 30 // 替換為你的GPIO引腳
static unsigned int irq_number;
// GPIO中斷處理函數
static irqreturn_t gpio_irq_handler(int irq, void *dev_id) {
printk("GPIO中斷觸發!\n");
return IRQ_HANDLED;
}
static int __init mymodule_init(void) {
int ret;
// 請求GPIO
ret = gpio_request(GPIO_PIN, "my_gpio");
if (ret) {
printk("無法請求GPIO %d\n", GPIO_PIN);
return ret;
}
// 配置GPIO引腳為輸入
ret = gpio_direction_input(GPIO_PIN);
if (ret) {
printk("無法配置GPIO %d 為輸入\n", GPIO_PIN);
gpio_free(GPIO_PIN);
return ret;
}
// 請求GPIO中斷
irq_number = gpio_to_irq(GPIO_PIN);
ret = request_irq(irq_number, gpio_irq_handler, IRQF_TRIGGER_RISING, "my_gpio_irq", NULL);
/* IRQF_TRIGGER_RISING 上升沿有效 */
if (ret) {
printk("無法請求GPIO中斷 %d\n", irq_number);
gpio_free(GPIO_PIN);
return ret;
}
printk("模塊加載成功\n");
return 0;
}
static void __exit mymodule_exit(void) {
// 釋放GPIO中斷
free_irq(irq_number, NULL);
// 釋放GPIO
gpio_free(GPIO_PIN);
printk("模塊卸載成功\n");
}
module_init(mymodule_init);
module_exit(mymodule_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zou");
MODULE_DESCRIPTION("Sample GPIO and Timer Interrupt Kernel Module");
- 外部IO中斷驗證
將驅動編譯成模塊,insmod加載模塊后。 由于驅動檢測GPIO0_D6上升沿有效,當給該引腳提供高電平時,會觸發中斷執行中斷處理函數。
![](https://file1.elecfans.com/web2/M00/AC/53/wKgaomVEi3OAUPgcAACVy3nRBtg010.png)
![wKgaomVEi0uAQ_CwAAA8UPgHinc576.png](https://file1.elecfans.com/web2/M00/AC/53/wKgaomVEi0uAQ_CwAAA8UPgHinc576.png)
圖3.1 觸發IO中斷
?
-
GPIO
+關注
關注
16文章
1213瀏覽量
52210 -
評估板
+關注
關注
1文章
552瀏覽量
29370 -
LINUX內核
+關注
關注
1文章
316瀏覽量
21686 -
RK3568
+關注
關注
4文章
520瀏覽量
5128
發布評論請先 登錄
相關推薦
RK3568內置MCU開發介紹之一
![<b class='flag-5'>RK3568</b>內置MCU開發介紹之一](https://file1.elecfans.com/web3/M00/00/A2/wKgZPGdLMg-AFkS0AAA5BGKqG3E264.png)
基于HD-RK3568-CORE設計的HD-RK3568-OPS主板上新!
![基于HD-<b class='flag-5'>RK3568</b>-CORE設計的HD-<b class='flag-5'>RK3568</b>-OPS主板上新!](https://file1.elecfans.com/web2/M00/D0/F0/wKgaomYiQwSAOur3AAAcESs8JdU178.jpg)
評論