linux中斷處理(1)上半部機(jī)制
應(yīng)用程序通過/dev/目錄中的設(shè)備結(jié)點(diǎn)操作設(shè)備,通過/sys目錄中的收集設(shè)備信息.
查看中斷:
cat /proc/interrupts
查看中斷統(tǒng)計(jì):
cat /proc/stat
1、頭文件
#include <linux/interrupt.h>
#include <asm/arch/irqs.h>
2、申明中斷處理程序
static spinlock_t wiegand_lock; // 使用之前必須初始化,spin_lock_init(&wiegand_lock);
static irqreturn_t wiegand_minus1_interrupt(int irq, void *dev_id)
{
spin_lock(&wiegand_lock);
//do something
//wiegand_minus_interrupt();
spin_unlock(&wiegand_lock);
return IRQ_HANDLED;
}
3.注冊(cè)中斷 request_irq()
2.6 內(nèi)核 函數(shù)原型如下:
extern int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev_id);
第1個(gè)參數(shù):中斷號(hào),是要申請(qǐng)的中斷號(hào)
第2個(gè)參數(shù):中斷處理函數(shù)
第3個(gè)參數(shù):中斷觸發(fā)標(biāo)志
IRQF_DISABLED 快中斷(禁止其他中斷)
IRQF_TRIGGER_RISING 設(shè)備在中斷線上產(chǎn)生一個(gè)上升沿時(shí),發(fā)出中斷.(說明在中斷之前,設(shè)備一直將中斷線保持在一個(gè)電平上)
IRQF_TRIGGER_FALLING 下降沿觸發(fā)
IRQF_TRIGGER_HIGH 高電平觸發(fā)中斷
IRQF_TRIGGER_LOW 低電平觸發(fā)中斷
IRQF_TRIGGER_RANDOM 為系統(tǒng)隨機(jī)發(fā)生器提供支持
IRQF_TRIGGER_SHARED (表示共享相同的中斷號(hào),多個(gè)設(shè)備共享)
/*
* linux/interrupt.h
* 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
typedef irqreturn_t (*irq_handler_t)(int, void *);
第4個(gè)參數(shù):中斷的標(biāo)識(shí),中斷的標(biāo)識(shí)與/proc/interrupts對(duì)應(yīng)
第5個(gè)參數(shù):傳入中斷處理程序的參數(shù),可以為NULL,在注冊(cè)共享中斷時(shí),此參數(shù)不能為NULL,作為共享中斷時(shí)的中斷區(qū)別參數(shù)。
返回值:如果中斷處理成功,返回IREQ_HANDLED,否則,返回IRQ_NONE
/* irqreturn.h */
typedef int irqreturn_t;
#define IRQ_NONE (0)
#define IRQ_HANDLED (1)
#define IRQ_RETVAL(x) ((x) != 0)
中斷上下文
中斷上下文注意事項(xiàng):
1)中斷上下文代碼絕不可以停止運(yùn)行。不能做任何可能發(fā)生休眠的操作,在從中斷處理函數(shù)中調(diào)用一個(gè)內(nèi)核API之前,應(yīng)該仔細(xì)分手它,以確保其內(nèi)部不會(huì)觸發(fā)阻塞等待!
2)為了在中斷處理函數(shù)中保護(hù)臨界區(qū),不能使用互斥體,因?yàn)樗鼈円苍S導(dǎo)致睡眠,應(yīng)該使用自旋鎖代替互斥體.
3)中斷處理函數(shù)不能與用戶空間直接交互數(shù)據(jù).
調(diào)度器工作于進(jìn)程之間,如果中斷處理函數(shù)睡眠并被調(diào)度出去.無法調(diào)度回來!
4)中斷處理函數(shù)一方面需要快速地為其他進(jìn)程讓出處理器,另一方面又需要完成它的工作,為了規(guī)避這種沖突,中斷處理函數(shù)通常將工作分成兩個(gè)部分.頂半部設(shè)一個(gè)標(biāo)志以宣稱它已經(jīng)服務(wù)了該中斷,而重大的工作負(fù)載都被丟給了底半部,底半部的執(zhí)行被延后.在其執(zhí)行環(huán)境中,所有的中斷都是使能的.
4.釋放中斷
extern void free_irq(int irq,void *dev_id)
5、啟動(dòng)用禁用中斷
extern void disable_irq_nosync(unsigned int irq);
extern void disable_irq(unsigned int irq);
extern void enable_irq(unsigned int irq);