[arm驱动]linux内核中断编程
第一部分獲取中斷(開啟硬件中斷)
一、中斷的申請注銷:
1)中斷的申請
| 1 2 | int?request_irq(unsigned?int?irq, irq_handler_t handler, ?????????????????????????unsigned?long?irqflags,?const?char?*devname,?void?*dev_id) |
2)中斷的注銷
| 1 | void?free_irq(unsigned?int?irq,?void?*dev_id) |
3)中斷處理函數
| 1 | static?irqreturn_t irq_handle(int?irq,?void?*dev__id); |
? ?參數:irq:表示中斷號,這個參數還保留由于歷史遺留問題,往后可能越來越沒用了。由于第二個參數信息更強大
dev__id:就是request_irq()中void *dev_id參數。
二、中斷申請函數參數
| 1 2 | int?request_irq(unsigned?int?irq, irq_handler_t handler, ?????????????????????????unsigned?long?irqflags,?const?char?*devname,?void?*dev_id) |
? ?1)參數:
? ?irq:是要申請的硬件中斷號。
handler:是向系統注冊的中斷處理函數,是一個回調函數,中斷發生時,系統調用這個函數,dev_id參數將被傳遞給它。
? ? irqflags:是中斷處理的屬性,
? ? ? ?a)若設置了IRQF_DISABLED,則表示中斷處理程序是快速處理程序,快速處理程序被調用時屏蔽所有中斷,慢速處理程序不屏蔽;
? ? ? ?b)若設置了 ? ?IRQF_SHARED,則表示多個設備共享中斷;//在另一篇文章會提到
? ? ? ?c)若設置了IRQF_SAMPLE_RANDOM,表示對系統熵有貢獻,對系統獲取隨機數有好處。
? ? ? ? ? ?Tip:(flag是可以通過或的方式同時使用的)
? ?devname:設置中斷名稱,通常是設備驅動程序的名稱 ?在cat /proc/interrupts中可以看到此名稱。
? ?dev_id:在中斷共享時會用到,一般設置為這個設備的設備結構體或者不使用時為NULL。因為在共享中斷中同一個中斷線(或可以說同一個中斷號)可能掛載好幾個設備,當使用void free_irq(unsigned int irq, void *dev_id)時,根據irq和dev_id可以找到中斷線為irq上的標識為dev_id的某個具體設備。dev_id也經常在不是共享中斷中的驅動傳遞數據
? ?2)返回值:
? ?a)request_irq()返回0表示成功;
? ?b)返回-EINVAL表示無效的參數,如果返回這個值,應該看看傳遞給request_irq()的參數是否正確;
? ?c)返回-EBUSY表示中斷已經被占用且不能共享;
? ?d)返回ENOMEM表示內存不足。嵌入式系統由于內存資源有限,經常會發生這樣的錯誤。
? ?3)擴展---unsigned long irqflags值
? ?在include\linux\interrupt.h中
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /* ?* These correspond to the IORESOURCE_IRQ_* defines in ?* linux/ioport.h to select the interrupt line behaviour.? When ?* requesting an interrupt without specifying a IRQF_TRIGGER, the ?* setting should be assumed to be "as already configured", which ?* may be as per machine or firmware initialisation. ?*/ #define IRQF_TRIGGER_NONE??? 0x00000000 #define IRQF_TRIGGER_RISING??? 0x00000001 #define IRQF_TRIGGER_FALLING??? 0x00000002 #define IRQF_TRIGGER_HIGH??? 0x00000004 #define IRQF_TRIGGER_LOW??? 0x00000008 #define IRQF_TRIGGER_MASK??? (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW | \ ?????????????????IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING) #define IRQF_TRIGGER_PROBE??? 0x00000010 /* ?* These flags used only by the kernel as part of the ?* irq handling routines. ?* ?* IRQF_DISABLED - keep irqs disabled when calling the action handler ?* IRQF_SAMPLE_RANDOM - irq is used to feed the random generator ?* IRQF_SHARED - allow sharing the irq among several devices ?* IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur ?* IRQF_TIMER - Flag to mark this interrupt as timer interrupt ?* IRQF_PERCPU - Interrupt is per cpu ?* IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing ?* IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is ?*??????????????? registered first in an shared interrupt is considered for ?*??????????????? performance reasons) ?*/ #define IRQF_DISABLED??????? 0x00000020 #define IRQF_SAMPLE_RANDOM??? 0x00000040 #define IRQF_SHARED??????? 0x00000080 #define IRQF_PROBE_SHARED??? 0x00000100 #define IRQF_TIMER??????? 0x00000200 #define IRQF_PERCPU??????? 0x00000400 #define IRQF_NOBALANCING??? 0x00000800 #define IRQF_IRQPOLL??????? 0x00001000 |
? ?Tip:下面是老版本(2.4內核irqflags的值),不要在新版本使用。(2.6 內核及2.6以上內核都為新內核)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ?* Migration helpers. Scheduled for removal in 9/2007 ?* Do not use for new code !//不要的新版本使用,2.6 內核及2.6以上內核都為新內核 ?*/ static?inline unsigned?long?__deprecated deprecated_irq_flag(unsigned?long?flag) { ????return?flag; } #define SA_INTERRUPT??????? deprecated_irq_flag(IRQF_DISABLED) #define SA_SAMPLE_RANDOM??? deprecated_irq_flag(IRQF_SAMPLE_RANDOM) #define SA_SHIRQ??????? deprecated_irq_flag(IRQF_SHARED) #define SA_PROBEIRQ??????? deprecated_irq_flag(IRQF_PROBE_SHARED) #define SA_PERCPU??????? deprecated_irq_flag(IRQF_PERCPU) #define SA_TRIGGER_LOW??????? deprecated_irq_flag(IRQF_TRIGGER_LOW) #define SA_TRIGGER_HIGH??????? deprecated_irq_flag(IRQF_TRIGGER_HIGH) #define SA_TRIGGER_FALLING??? deprecated_irq_flag(IRQF_TRIGGER_FALLING) #define SA_TRIGGER_RISING??? deprecated_irq_flag(IRQF_TRIGGER_RISING) #define SA_TRIGGER_MASK??????? deprecated_irq_flag(IRQF_TRIGGER_MASK) |
三、使用模板
? ?使用步驟:以外部中斷為例
a)定義結構體,相當于定義(void *dev_id)中的(void *)
| 1 2 3 4 5 | struct pin_desc{//聲明一個引腳描述的結構體pin_desc ???????unsigned?int?pin;//引腳值,參考數據手冊及板子電路原理圖 ???????unsigned?int?key_val;//值自已隨便定義;看自己的項目需要 ???????//................... ???}; |
b)實例化結構體,相當于(void *dev_id)中的 dev_id
| 1 2 3 4 5 | struct?pin_desc pins_desc[3] = {//實例化結構體,以jz2440按鍵為列 ???????{S3C2410_GPF0, 0x01},//S3C2410_GPFn在內核中定義好了 ???????{S3C2410_GPF2, 0x02}, ???????{S3C2410_GPG3, 0x03}, ???}; |
c)定義中斷處理函數
| 1 2 3 4 5 | static?irqreturn_t irq_handle(int?irq,?void?*dev__id){ ????struct pin_desc *pindesc = (struct pin_desc *)dev__id; ????//................ ????return?IRQ_RETVAL(IRQ_HANDLED);//返回IRQ_HANDLED表示中斷已經處理 ????} |
d)申請中斷
| 1 2 3 | request_irq(IRQ_EINT0, irq_handle, IRQ_TYPE_EDGE_BOTH,?"s2", &pins_desc[0]);//IRQ_EINTn在內核中定義好了 ???request_irq(IRQ_EINT2, irq_handle, IRQ_TYPE_EDGE_BOTH,?"s3", &pins_desc[1]); ???request_irq(IRQ_EINT11, irq_handle, IRQ_TYPE_EDGE_BOTH,?"s4", &pins_desc[2]); |
e)釋放內存
| 1 2 3 | free_irq(IRQ_EINT0, &pins_desc[0]); ????free_irq(IRQ_EINT2, &pins_desc[1]); ????free_irq(IRQ_EINT11, &pins_desc[2]); |
Tip:可以直接將IRQ_EINTn也在pins_desc定義,然后
| 1 2 3 4 | int?i =?0; ???for(i =?0; i <?3; i++){ ???free_irq(pins_desc[i].irqnum, &pins_desc[i]); ???} |
? ?實例見[arm驅動]Linux內核開發之阻塞非阻塞IO----輪詢操作?中的實例(按鍵中斷雙邊沿觸發)
本文轉自lilin9105 51CTO博客,原文鏈接:http://blog.51cto.com/7071976/1392439,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的[arm驱动]linux内核中断编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到手机没电了这代表什么
- 下一篇: Linux下安全审计工具 lynis 使