Linux中斷

前言:

一.問:CPU爲什麼有中斷機制? (本質:外設的處理速度要遠遠慢於CPU的處理速度)


明確:計算機系統除了CPU,還有各種外設;

明確:外設的處理速度要遠遠慢於CPU的處理速度;

以CPU讀取串口爲例,假如沒有中斷機制,CPU爲了避免串口數據的丟失,只能採用輪詢方式(CPU原地空轉),
等待串口數據的到來;採用這種方式,CPU只能做一件事情,大大降低了CPU的利用率;
如果採用中斷機制,CPU如果發現串口數據不可用(數據沒有到來),CPU去做別的事情,一旦串口來數,
串口給CPU發送一箇中斷信號 (嗨,CPU,我數據準備就緒,請來處理),CPU一旦接受到了中斷信號,CPU停止手頭的工
作轉去處理串口數據,處理完畢,接着執行原先被打斷的工作,此時CPU至少2件事情,大大提高了CPU的利用率!


問: CPU和外設的中斷信號的硬件處理過程
明確:外設產生的中斷電信號不會直接到達CPU,首先要經過中斷控制器,經過中斷控制器的處理以後,最終中斷控制器決定是否再給CPU產生一箇中斷電信號;

中斷控制器所作的內容:
1.能夠使能或者屏蔽某個外設中斷信號;
2.能夠指定外設中斷的優先級;
3.能夠獲取中斷的狀態;

注意:以上操作都是中斷硬件操作,沒有軟件參與;
一旦CPU接受到了中斷信號,CPU開始處理中斷,此時會進入軟件處理中斷的過程;

問:中斷的軟件處理過程

如下圖所示:


問:中斷的編程實現步驟
答:

1.編寫建立異常向量表的代碼
2.編寫保護現場的代碼
3.編寫中斷處理程序
4.編寫恢復現場的代碼

切記:不管是裸板程序還是基於某個操作系統,中斷編程四個步驟固定不變;

問:linux系統中斷編程步驟
linux系統已將中斷編程的第1,2,4三個步驟已經幫你實現,對於驅動開發者只需完成第3步即可,完成中斷處理函數即可!

明確:中斷的處理過程都是在內核中完成,中斷編程的四步驟代碼都在內核中!

Linux中斷編程

問:如何在linux內核中編寫一個硬件中斷對應的中斷處理函數呢?
答:
如果要向內核添加某個外設中斷的中斷處理函數,只需要利用以下兩個函數即可完成工作:
*************************************************

static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)


函數功能:
1.首先向內核申請硬件中斷資源,CPU的硬件中斷對於內核來說是一種寶貴的資源,
如果要使用,必須向內核中去申請

2.一旦硬件中斷資源申請成功,最後註冊這個硬件對應的中斷處理
函數到內核,將來這個硬件中斷一般被觸發,內核就會執行對應的中斷處理
函數

參數說明:
irq:傳遞硬件中斷在內核中的一個軟件編號,這個軟件編號統稱中斷號,一
個硬件中斷有唯一的一箇中斷號,
例如:
XEINT0(CPU的第一個硬件中斷管腳) ,
它對應的內核中斷號爲IRQ_EINT(0) ,
XEINT1(CPU的第二個硬件中斷管腳) ,
它對應的內核中斷號爲IRQ_EINT(1)

handler:中斷處理函數,將來硬件中斷處理,內核執行此函數

flags:中斷標誌,常見的中斷標誌如下:
如果此中斷爲外部中斷(中斷線能看到),中斷標誌如用以下即可:
IRQF_TRIGGER_FALLING; //下降沿觸發
IRQF_TRIGGER_RISING; //上升沿觸發
IRQF_TRIGGER_LOW; //低電平觸發
IRQF_TRIGGER_HIGH; //高電平觸發
以上屬性給中斷控制器使用;
如果此中斷爲內部中斷,中斷標誌給0

name:中斷名稱,將來出現在 cat /proc/interrupts

dev:給中斷處理函數傳遞的參數,如果不傳遞參數給NULL
 *************************************************
void free_irq(unsigned int irq, void *dev);
作用:
如果中斷資源不使用,記得要釋放和刪除中斷處理函數
irq:硬件中斷對應的中斷號
dev:給中斷處理函數傳遞的參數,
切記,此參數一定要和註冊中斷時傳遞的參數要一樣!否則內核崩潰!

中斷處理函數的原型:
*************************************************
irqreturn_t 中斷處理函數名(int irq, void *dev)
{
...
return IRQ_HANDLED; //中斷處理完畢
或者
return IRQ_NONE; //中斷不做處理
}

irq:保存硬件中斷對應的中斷號
dev:保存註冊中斷時傳遞來的參數

案例:

編寫XEINT0中斷驅動程序
#include <linux/init.h>
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/interrupt.h>

//中斷處理函數
static irqreturn_t button_isr(int irq, void *dev)
{
    printk("%s\n", __func__);
    return IRQ_HANDLED;
}

static int btn_init(void)
{
    //申請中斷和註冊中斷處理函數
    request_irq(IRQ_EINT(0),
                button_isr,
        IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
                "KEY_UP",
                NULL);
    return 0;
}

static void btn_exit(void)
{
    //釋放中斷
    free_irq(IRQ_EINT(0), NULL);
}
module_init(btn_init);
module_exit(btn_exit);
MODULE_LICENSE("GPL");
***去除官方的按鍵驅動
cd /opt/kernel
make menuconfig
Device Drivers->
Input device support --->
[*] Keyboards --->
[*]S3C gpio keypad support //去掉
make zImage
cp arch/arm/boot/zImage /tftpboot
重啓開發板

ARM執行:
1.insmod btn_drv.ko
2.操作按鍵,觀察打印信息      

  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章