linux中斷處理程序
一、中斷處理流程
在linux內核代碼中進入entry-armv.S目錄:
linux統一的入口:__irq svc.
進入了統一的入口之后,程序跳到irq_handler標號(在同一個文件上面有說明):
而irq_handler實際上是調用上面的arch_irq_handler_defualt.該代碼在entry-macro-multi.S里面。
在這個中斷處理程序中。最重要的是get_irqnr_and_base獲取產生中斷的中斷源,搜索這個宏。這里以2410的為例(竟然沒有找到6410):
從上面的程序看到。他主要是獲取產生中斷的中斷號。獲得中斷號后,會跳轉到:arch_irq_handler_defualt里的asm_do_IRQ去處理中斷:
跳轉到這個函數之后,又會去調用generic_handle_irq(irq)這個函數:
這個函數又會去調用generic_handle_irq_desc這個函數:
在這個函數里又會去調用desc這個結構,這里的handle_irq是個函數指針
總結:在linux里:當產生中斷的時候,會有一個統一的入口,irq_svc.進來之后,第一步是拿到產生中斷源的編號,然后根據這個中斷號去找到irq_desc這個結構。然后在這個結構里取出事先准備好的注冊處理函數。
我們的驅動要支持中斷處理,首先必須去實現中斷處理程序。第二是要注冊中斷處理函數。
二、中斷處理程序設計
2.1中斷注冊
request_irq函數用於注冊中斷。
int request_irq(unsigned int irq, void(*handler)(int, void*, struct pt_regs *), unsigned long flags, const char*devname, void*dev_id)
返回0表示成功,或者返回一個錯誤碼
unsigned int irq中斷號。
void (*handler)(int,void *)中斷處理函數。
unsigned long flags與中斷管理有關的各種選項
在flags參數中,可以選擇一些與中斷管理有關的選項,如:
IRQF_DISABLED(SA_INTERRUPT)
如果設置該位,表示是一個“快速”中斷處理程序;
如果沒有設置這位,那么是一個“慢速”中斷處理程序。
IRQF_SHARED(SA_SHIRQ)
該位表明該中斷號是多個設備共享的。
const char * devname 設備名
void*dev_id共享中斷時使用。
快/慢速中斷的主要區別在於:快速中斷保證中斷處理的原子性(不被打斷),而慢速中斷則不保證。換句話說,也就是“開啟中斷”標志位(處理器IF)在運行快速斷處理程序時是關閉的,因此在服務該中斷時,不會被其他類型的中斷打斷;而調用慢速中斷處理時,其它類型的中斷仍可以得到服務。
2.2中斷處理程序
中斷處理程序的特別之處是在中斷上下文中運行的,它的行為受到某些限制:
1.不能使用可能引起阻塞的函數
2.不能使用可能引起調度的函數
3.3中斷注銷
當設備不再需要使用中斷時(通常在驅動卸載時), 應當把它們注銷, 使用函數:
void free_irq(unsigned int irq, void*dev_id)
Dev_id是指中斷里的第幾個函數,要注銷的。