linux 驅動中的中斷處理程序:
當發生中斷的時候,無論是裸機程序還是Linux系統都會有一個統一的入口.
裸機中的中斷入口是代碼:ldr pc,_irq;
linux 系統中的統一入口:irq_svc
向Linux系統注冊中斷處理程序想:
requst_irq(unsigned int irq ,void(*handler)(int ,void *,struct pt_regs*),unsigned long flags,const char *devname ,void *dev_id )
參數分析:
unsigned long flags:參數還是一個宏,用於決定是快速中斷還是慢速中斷,或者表明該中斷是多少個設備共享。
unsigned int irq:
向Linux系統注銷中斷處理程序:
void free_irq(unsigned int irq ,void *dev_id)
參數分析:
int irq:中斷號,注意這里的中斷號和裸機中的中斷號有一定的不同,因為系統預留了16個的軟中斷號,所以硬件中斷號需要加上16,系統通過中斷號找到相應的描述符表,在描述符表中找到相應個處理函數。
dev_id:對於共享中斷號的設備,需要提供相應的中斷號才能准確的注銷掉。
中斷嵌套:
為了解決中斷處理速度,Linux中將硬件處理函數和非硬件處理函數進行了分開,將非硬件操作放到工作隊列中。
注意:工作隊列中的結構體數組名都是使用一個struct 在后面
定義和描述中斷隊列:
struct workqueue_struct {
struct cpu_workqueue_struct *cpu_wq;
struct list_head list;
const char *name; /*workqueue name*/
int singlethread;
int freezeable; /* Freeze threads during suspend */
int rt;
}
定義和描述一個工作:
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func;
};
創建一個工作隊列:
srtuct workqueue_struct * =create_workqueue(“workqueue_name”)
初始化工作:
INIT_WORK(struct work_struct *,func)
注意:創建工作實質是將創建的工作和相應的操作函數關聯起來
向Linux系統提交工作
queue_work(struct workqueue_struct , func)
在大多數情況下,並把需要定義工作隊列,Linux內核中已經有一個默認的工作隊列keventd_wq,所以只需要創建工作,並初始化工作。
提交默認工作隊列:
schedule_work()
按鍵去抖之內核定時器:
定義並描述定時器:
struct timer_list {
struct list_head entry;
unsigned long expires;
void (*function)(unsigned long);
unsigned long data;
struct tvec_base *base;
};
初始化定時器:
init_timer(struct list_timer * keytimer)
keytimer.function = key_timerfunc()
找一個地方定義timerfunc()
想Linux注冊定時器:
add_timer(struct timer_list *)
啟動定時器:
mod_timer(struct list_timer * ,jiffes+Hz/2)
阻塞型驅動:
背景:
當計算機驅動訪問一個硬件的時候發現訪問條件不滿足,稱之為阻塞,這時就需要將該驅動放入到等待隊列中。
定義等待隊列:
wait_queue_head_t my_queue
初始化等待隊列:
init_waitqueue_head( wai_queue_head_t* )
備注:定義並初始化等待隊列
DECLARE_WAIT_QUEUE_HEAD(wait_queue_head_t my_queue)
進入等待隊列:
wait_event(queue,condition) //TASK_UNINTERRUPT 模式
wait_event_interrupt(queue,condition)//TASK_INTERRUPT 模式
int wait_event_killable(queue,condition) //TASK_KILLABLE 模式
函數分析:
以上兩個函數,在條件滿足時,直接返回,並繼續執行相應的下面的程序,當條件不滿足時則掛載到等待隊列中,知道被喚醒。
喚醒等待隊列:
wake_up(wait_queue_t *q) //從等待隊列中喚醒,所有TASK_UNINTERRUPT ,TASK_INTERRUPT ,TASK_KILLABLE 狀態的所有進程。
wake_up_intterruptible(wait_queue_t *q)//從等待隊列q中喚醒狀態僅為INTERRUPTIBLE 狀態的隊列。
設備驅動在內存中開辟內存:
kmalloc()
注意:該函數返回的是物理地址
釋放內存:
kfree()