實現一個簡單的定時器驅動代碼

屏亮無操作,按鍵燈5s 後自動熄滅
實現場景:
1)按下按鍵後檢測到按鍵中斷,在中斷函數中點亮按鍵燈並且啓動定時器定時五秒,時間到關閉按鍵燈。
2)當點亮屏幕後,點亮按鍵燈並且啓動定時器定時五秒,時間到關閉按鍵燈。
@ \kernel\drivers\input\keyboard\aw9523.c

#include <linux/jiffies.h>//jiffies調用頭文件
#include <linux/timer.h> //timer_list結構體

u32 bl_level_bakup = 0; // 備份bl_level (當前屏幕背光的亮度值),用於點亮按鍵燈的亮度,bl_level是一個局部變量
static bool is_btn_leds_timer_onoff = false; // 定時器開 flag

static struct timer_list btn_leds_ms_timer; //定義timer_list結構體
static void btn_leds_ms_timer_func_handler(unsigned long a); //聲時定時器函數
void aw9523_buttonleds_set_timer_on(u32 bl_level); //*********************

void aw9523_key_work()
{
    // 在按鍵處理函數中 調用封裝好的代碼
    //*********************
    aw9523_buttonleds_set_timer_on(bl_level_bakup)   //同理,panel.c 中也直接調用這個 
}

@ 點亮按鍵燈並且啓動定時器定時五秒,時間到關閉按鍵燈。
void aw9523_buttonleds_set_timer_on(u32 bl_level)
{
	if(bl_level == 0){    //*********************
		// 判斷當前定時器是否開啓了
		if (is_btn_leds_timer_onoff == true){
			del_timer(&btn_leds_ms_timer);  // 移除定時器
		}
		//如果是滅屏,則不啓動定時器,直接關燈
		aw9523_buttonleds_set(bl_level);    
		
	}else{
		// 如果是亮屏狀態
		//cancel timer 如果定時器已經開啓過了,說明此時按鍵燈已經是開啓狀態,則清除定時器
		if (is_btn_leds_timer_onoff == true)
		{
	        printk("hyl_timer [%s][%d] --start to restart timer-- ----- 333333-----\n",__func__,__LINE__);
			//如果之前已經有按過,則刪定時器,並重新啓動定時器
	        mod_timer(&btn_leds_ms_timer, jiffies+msecs_to_jiffies(1000 * 5));
		}
		else
		{
	        printk("hyl_timer [%s][%d] --start timer------- 222222----- \n",__func__,__LINE__);
			// 如果定時器沒有開啓過,則說明按鍵燈沒有開啓過,則開啓按鍵背光
			// light up button leds   hyl_leds +++
	        // ------------此處先註釋,看看log--------log 正常 後開啓
	
	        // 定義定時器中斷時間: 5s 後進入中斷                   
	        btn_leds_ms_timer.expires = jiffies + msecs_to_jiffies(1000 * 5);  
	        // 綁定定時器的計時到達時候的操作函數
	        btn_leds_ms_timer.function = btn_leds_ms_timer_func_handler;            
	        // 啓動定時器
	        add_timer(&btn_leds_ms_timer);   //增加註冊定時器,使定時器生效
		}
		aw9523_buttonleds_set(bl_level);     //*********************
		is_btn_leds_timer_onoff = true;
	}
}

// 定時器函數代碼,定義定時器處理函數
static void btn_leds_ms_timer_func_handler(unsigned long a)
{
    printk("hyl_timer [%s][%d] --timer end ,start turn off leds ----- 4444------- \n",__func__,__LINE__);

	// close button leds
    // ------------此處先註釋,看看log--------log 正常 後開啓
	//aw9523_buttonleds_set(0); 
	// 清楚定時器開關標誌位
	is_btn_leds_timer_onoff = false;  
}
static int aw9523_probe(struct i2c_client *client, const struct i2c_device_id *id)
{

    // 初始化定時器
    init_timer(&btn_leds_ms_timer);      
    // 定義定時器中斷時間: 5s 後進入中斷                   
    btn_leds_ms_timer.expires = jiffies + msecs_to_jiffies(1000 * 5);  
    // 綁定定時器的計時到達時候的操作函數
    btn_leds_ms_timer.function = btn_leds_ms_timer_func_handler;            

    printk("hyl_timer [%s][%d] add timer success ----- 111111-----\n",__func__,__LINE__);

    // 此時不啓動定時器
    // add_timer(&btn_leds_ms_timer);                           //增加註冊定時器,使定時器生效
}
static int aw9523_release(struct i2c_client *client, const struct i2c_device_id *id)
{
    // 刪除化定時器
    del_timer(&btn_leds_ms_timer);
}

增加工作隊列:

#include <linux/workqueue.h>
// 工作隊列定義
static struct work_struct leds_work;
//---> 把這個函數的代碼還原
void aw9523_buttonleds_set_timer_on(void)
{
	if(btn_leds_timer_onoff == true)
	{
		printk("---hyl---timer[%s][%d]--33333-start to restart timer\n",__func__,__LINE__);
		mod_timer(&btn_leds_ms_timer,jiffies+msecs_to_jiffies(1000*5));
	}
	else
	{
		printk("---hyl---timer[%s][%d]--------22222----------start timer\n",__func__,__LINE__);
		aw9523_buttonleds_set(0);
		btn_leds_ms_timer.expires = jiffies + msecs_to_jiffies(1000*5);
		btn_leds_ms_timer.function = btn_leds_ms_timer_func_handler;
		add_timer(&btn_leds_ms_timer);
	}
	btn_leds_timer_onoff = true;
} 
// 工作隊列運行函數 ,將之前定時器函數中的工作 ,全搬過來,在工作隊列中, 關閉燈
static void leds_work_handler(struct work_struct *data)
{
    printk("hyl_timer [%s][%d] --timer end ,start turn off leds ----- 5555------- \n",__func__,__LINE__);
	aw9523_buttonleds_set(0);  // close button leds
	
	// 清除定時器開關標誌位
	is_btn_leds_timer_onoff = false; 
}
// 定義定時器處理函數  , 定時器時間到達後只負表 讓CPU調度leds_work_handler()
static void btn_leds_ms_timer_func_handler(void)
{
    printk("hyl_timer [%s][%d] --timer end ,start turn off leds ----- 4444------- \n",__func__,__LINE__);
	schedule_work(&leds_work); // 讓CPU 調度工作隊列, cpu 會創建線程執行leds_work_handler()這個函數
}
void probe (){
	// 這個代碼,在初始化定時器後面增加
	INIT_WORK(&leds_work, leds_work_handler);  //初始化工作隊列,綁定  leds_work_handler() 這個函數
}

增加proc 調試節點:

#include <linux/proc_fs.h>

void xxxxx_aaa(void)
{
   printk("hyl_timer [%s][%d] ---- \n",__func__,__LINE__);
   //打開背光
   //啓動 5s 定時器
   ms_timer.expires=jiffies+msecs_to_jiffies(1000 * 5);
   ms_timer.function=ms_timer_handler;
   add_timer(&ms_timer);
}
static ssize_t igh_gfar_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *f_pos)
{
    xxxxx_aaa();  // 此處加上 ,打開背光,啓動 5s 定時器
	return count;
}
struct proc_dir_entry *leds_proc_dir = NULL;
static int32_t xxx_probe(void)
{
	struct proc_dir_entry* leds_file;
    leds_proc_dir = proc_mkdir("leds_back", NULL);
	leds_file = proc_create("leds_onoff", 0777, leds_proc_dir, &leds_proc_fops);
	
}	
static xxxx_release(void){

    del_timer(&ms_timer);
	remove_proc_entry("leds_onoff", leds_proc_dir);
	remove_proc_entry("leds_back", NULL);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章