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