linux下之定時器timer執行個體

來源:互聯網
上載者:User
最近工作中涉及到在一定的時間之後對特定的動作進行處理。比如按鍵,按鍵需要在按下至少4S之後,重新啟動系統之類、此時使用定時器,可以確保準確的計時。下面的實現可以通用。struct timer_list os_timer_t; //定義定時器#define OS_TIMER_FUNC(_fn)\void _fn(unsigned long timer_arg)#define OS_GET_TIMER_ARG(_arg, _type)\(_arg) = (_type)(timer_arg)#define OS_INIT_TIMER(_osdev, _timer, _fn, _arg)\do {\init_timer(_timer);\(_timer)->function = (_fn);\(_timer)->data = (unsigned long)(_arg);\} while (0)#define OS_SET_TIMER(_timer, _ms)\mod_timer(_timer, jiffies + ((_ms)*HZ)/1000)#define OS_CANCEL_TIMER(_timer)del_timer(_timer)1:初始化定時器//初始化,其處理函數為:wps_led_blinkOS_INIT_TIMER(NULL, &os_timer_t, wps_led_blink, &os_timer_t); 2:啟動定時器/設定定時器OS_SET_TIMER(&os_timer_t, 1000);//設定表示,在1000ms之後啟動定時器。3:取消定時器: OS_CANCEL_TIMER(&os_timer_t);4:定時器的處理函數定義如下:static OS_TIMER_FUNC(wps_led_blink){   static int WPSled = WPS_LED_ON,sec = 0;   ar7242_gpio_out_val(WPS_LED_GPIO,WPSled);   WPSled=!WPSled;     OS_SET_TIMER(&os_timer_t, 1000);   /*   sec++ ;   if(sec < 130)    {OS_SET_TIMER(&os_timer_t, 1000);   }   else    {sec = 0;wps_led_blinking = 0 ;OS_CANCEL_TIMER(&os_timer_t);ar7242_gpio_out_val (WPS_LED_GPIO, WPS_LED_OFF);   }*/}上面的處理函數可知:每隔1000ms即1S對WPS_LED_GPIO輸出高低電平。使其周期性的閃爍。完整的測試代碼如下:#include <linux/kernel.h>#include <linux/module.h>#include <linux/signal.h>#include <linux/interrupt.h>#include <linux/irq.h>#include <linux/init.h>#include <linux/resource.h>#include <linux/proc_fs.h>#include <linux/miscdevice.h>#include <asm/types.h>#include <asm/irq.h>#include <asm/delay.h>#include <asm/system.h>//Ar7240.h (e:\sdk_wlan_db12x\sdk\wlan-ap\linux\kernels\mips-linux-2.6.31\arch\mips\include\asm\mach-ar7240)407732011-12-1#include <asm/mach-ar7240/ar7240.h>#include <asm/mach-atheros/724x.h>#define WPS_LED_GPIO 0#define WPS_LED_OFF 1#define WPS_LED_ON  0#define SIMPLE_CONFIG_OFF     1#define SIMPLE_CONFIG_ON      2     #define SIMPLE_CONFIG_BLINK   3typedef enum {        LED_STATE_OFF   =       1,        LED_STATE_ON    =       2,        LED_STATE_BLINKING =    3,} led_state_e;#define OS_TIMER_FUNC(_fn)                      \    void _fn(unsigned long timer_arg)#define OS_GET_TIMER_ARG(_arg, _type)           \    (_arg) = (_type)(timer_arg)#define OS_INIT_TIMER(_osdev, _timer, _fn, _arg) \do {                                             \        init_timer(_timer);                      \        (_timer)->function = (_fn);              \        (_timer)->data = (unsigned long)(_arg);  \} while (0)#define OS_SET_TIMER(_timer, _ms)       mod_timer(_timer, jiffies + ((_ms)*HZ)/1000)#define OS_CANCEL_TIMER(_timer)         del_timer(_timer)static struct proc_dir_entry *simple_config_entry = NULL;static struct proc_dir_entry *simple_config_led_entry = NULL;static int wps_led_blinking = 0;struct timer_list  os_timer_t;static led_state_e simple_config_led_state = LED_STATE_BLINKING;void ar7242_gpio_config_output(int gpio){#ifdef CONFIG_WASP_SUPPORT    ar7240_reg_rmw_clear(AR7240_GPIO_OE, (1 << gpio));#else    ar7240_reg_rmw_set(AR7240_GPIO_OE, (1 << gpio));#endif}void ar7242_gpio_config_input(int gpio){#ifdef CONFIG_WASP_SUPPORT    ar7240_reg_rmw_set(AR7240_GPIO_OE, (1 << gpio));#else    ar7240_reg_rmw_clear(AR7240_GPIO_OE, (1 << gpio));#endif}void ar7242_gpio_out_val(int gpio, int val){    if (val & 0x1) {        ar7240_reg_rmw_set(AR7240_GPIO_OUT, (1 << gpio));    }    else {        ar7240_reg_rmw_clear(AR7240_GPIO_OUT, (1 << gpio));    }}int ar7242_gpio_in_val(int gpio){    return((1 << gpio) & (ar7240_reg_rd(AR7240_GPIO_IN)));}static OS_TIMER_FUNC(wps_led_blink){   static int WPSled = WPS_LED_ON,sec = 0;   ar7242_gpio_out_val(WPS_LED_GPIO,WPSled);   WPSled=!WPSled;     OS_SET_TIMER(&os_timer_t, 1000);   /*   sec++ ;   if(sec < 130)    {OS_SET_TIMER(&os_timer_t, 1000);   }   else    {sec = 0;wps_led_blinking = 0 ;OS_CANCEL_TIMER(&os_timer_t);ar7242_gpio_out_val (WPS_LED_GPIO, WPS_LED_OFF);   }*/}static int gpio_simple_config_led_read (char *page, char **start, off_t off,               int count, int *eof, void *data){    return sprintf (page, "%d\n", simple_config_led_state);}static int gpio_simple_config_led_write (struct file *file, const char *buf,unsigned long count, void *data){u_int32_t val = 0;  if(sscanf(buf, "%d", &val) != 1){return -EINVAL;}if ((val == SIMPLE_CONFIG_BLINK) && !wps_led_blinking)  /* wps LED blinking */{wps_led_blinking = 1 ;simple_config_led_state = SIMPLE_CONFIG_BLINK ;ar7242_gpio_out_val (WPS_LED_GPIO, WPS_LED_ON);//OS_INIT_TIMER(NULL, &os_timer_t, wps_led_blink, &os_timer_t);OS_SET_TIMER(&os_timer_t, 1000);}else if (val == SIMPLE_CONFIG_ON) /* WPS Success  */{wps_led_blinking = 0 ;simple_config_led_state = SIMPLE_CONFIG_ON ;OS_CANCEL_TIMER(&os_timer_t);ar7242_gpio_out_val (WPS_LED_GPIO, WPS_LED_ON);}else if (val == SIMPLE_CONFIG_OFF)  /* WPS failed */{wps_led_blinking = 0 ;simple_config_led_state = SIMPLE_CONFIG_OFF ;OS_CANCEL_TIMER(&os_timer_t);ar7242_gpio_out_val (WPS_LED_GPIO, WPS_LED_OFF);}   return count;}static int create_simple_config_led_proc_entry (void){    if (simple_config_entry != NULL) {        printk ("Already have a proc entry for /proc/simple_config!\n");        return -ENOENT;    }    simple_config_entry = proc_mkdir("simple_config", NULL);    if (!simple_config_entry)        return -ENOENT;    simple_config_led_entry = create_proc_entry ("simple_config_led", 0644,                                            simple_config_entry);    if (!simple_config_led_entry)        return -ENOENT;    simple_config_led_entry->write_proc = gpio_simple_config_led_write;    simple_config_led_entry->read_proc = gpio_simple_config_led_read;    /* configure gpio as outputs */    ar7242_gpio_config_output (WPS_LED_GPIO);     /* switch off the led */    ar7242_gpio_out_val(WPS_LED_GPIO, WPS_LED_OFF);    OS_INIT_TIMER(NULL, &os_timer_t, wps_led_blink, &os_timer_t);OS_SET_TIMER(&os_timer_t, 1000);//此處啟動定時器。    return 0;}//ar7240_reg_rd(AR7240_GPIO_IN_ETH_SWITCH_LED)=480fa //ar7240_reg_rd(AR7240_GPIO_IN_ETH_SWITCH_LED)=4800a static int __init init_ar7242_gpio_module(void){unsigned int rddata;  rddata = ar7240_reg_rd(AR7240_GPIO_IN_ETH_SWITCH_LED);  printk("first:reg 0x18040028=%x\n",rddata);     rddata = rddata & (~(0xf0));      ar7240_reg_wr(AR7240_GPIO_IN_ETH_SWITCH_LED, rddata);    rddata = ar7240_reg_rd(AR7240_GPIO_IN_ETH_SWITCH_LED);  printk("second:reg 0x18040028=%x\n",rddata);   create_simple_config_led_proc_entry();printk("***  init_ar7242_gpio_module success *** \n");return 0;}static void __exit cleanup_ar7242_gpio_module(void){  printk("%s (%s) line: %d\n", __FILE__, __func__,__LINE__);}module_init(init_ar7242_gpio_module);module_exit(cleanup_ar7242_gpio_module);MODULE_LICENSE("GPL");MODULE_AUTHOR("suiyuan from test"); MODULE_DESCRIPTION("Led driver for Atheros 7242  platform");--------------------------測試代碼二----------------------------------------#include <linux/kernel.h>#include <linux/module.h>#include <linux/signal.h>#include <linux/interrupt.h>#include <linux/irq.h>#include <linux/init.h>#include <linux/resource.h>#include <linux/proc_fs.h>#include <linux/miscdevice.h>\#include <linux/delay.h>#include <linux/types.h>#include <asm/types.h>#include <asm/irq.h>#include <asm/delay.h>#include <asm/system.h>#include <asm/mach-atheros/724x.h>#include <asm/mach-ar7240/ar7240.h>#define ATH_FACTORY_RESET0x89ABCDEF#define BUTTON_GPIO 11#define UDELAY_COUNT 8000000#define BUTTON_MINOR 189//#define ATH_WDT_TEST_CODE#ifdef ATH_WDT_TEST_CODE#define btdbg printk#else#define btdbg(junk, ...)#endif /* ATH_WDT_TEST_CODE 8 */typedef enum {    INT_TYPE_EDGE,    INT_TYPE_LEVEL,}ar7240_gpio_int_type_t;typedef enum {    INT_POL_ACTIVE_LOW,    INT_POL_ACTIVE_HIGH,}ar7240_gpio_int_pol_t;typedef struct   {wait_queue_head_t buttons_waitqueue; /* 等待隊列,當沒有按鍵被按下時,如果有進程調用s3c24xx_buttons_read函數,它將休眠 */volatile int ev_press;               /* 中斷事件標誌, 中斷服務程式將它置1,s3c24xx_buttons_read將它清0 */volatile unsigned int press_cnt; /* 4個按鍵被按下的次數(準確地說,是發生中斷的次數) */struct timer_list button_timers;     /* buttons delay timer */int ar7242_ButtonOpened;int button_short_time;int is_interrupt_finished;} buttons_dev_t;/*extern void ar7240_gpio_config_int(int gpio, ar7240_gpio_int_type_t type,ar7240_gpio_int_pol_t polarity);extern void ar7240_gpio_config_output(int gpio);extern void ar7240_gpio_config_input(int gpio);extern void ar7240_gpio_out_val(int gpio, int val);extern int ar7240_gpio_in_val(int gpio);*/void ar7240_gpio_config_int(int gpio, ar7240_gpio_int_type_t type,ar7240_gpio_int_pol_t polarity){    u32 val;    /*     * allow edge sensitive/rising edge too     */    if (type == INT_TYPE_LEVEL) {        /* level sensitive */        ar7240_reg_rmw_set(AR7240_GPIO_INT_TYPE, (1 << gpio));    }    else {       /* edge triggered */       val = ar7240_reg_rd(AR7240_GPIO_INT_TYPE);       val &= ~(1 << gpio);       ar7240_reg_wr(AR7240_GPIO_INT_TYPE, val);    }    if (polarity == INT_POL_ACTIVE_HIGH) {        ar7240_reg_rmw_set (AR7240_GPIO_INT_POLARITY, (1 << gpio));    }    else {       val = ar7240_reg_rd(AR7240_GPIO_INT_POLARITY);       val &= ~(1 << gpio);       ar7240_reg_wr(AR7240_GPIO_INT_POLARITY, val);    }    ar7240_reg_rmw_set(AR7240_GPIO_INT_ENABLE, (1 << gpio));}voidar7240_gpio_config_output(int gpio){#ifdef CONFIG_WASP_SUPPORT    ar7240_reg_rmw_clear(AR7240_GPIO_OE, (1 << gpio));#else    ar7240_reg_rmw_set(AR7240_GPIO_OE, (1 << gpio));#endif}voidar7240_gpio_config_input(int gpio){#ifdef CONFIG_WASP_SUPPORT    ar7240_reg_rmw_set(AR7240_GPIO_OE, (1 << gpio));#else    ar7240_reg_rmw_clear(AR7240_GPIO_OE, (1 << gpio));#endif}voidar7240_gpio_out_val(int gpio, int val){    if (val & 0x1) {        ar7240_reg_rmw_set(AR7240_GPIO_OUT, (1 << gpio));    }    else {        ar7240_reg_rmw_clear(AR7240_GPIO_OUT, (1 << gpio));    }}intar7240_gpio_in_val(int gpio){    return((1 << gpio) & (ar7240_reg_rd(AR7240_GPIO_IN)));}static  buttons_dev_t buttons_dev ={.ev_press   = 0,.press_cnt  = 0,.button_short_time =0, .is_interrupt_finished=1,};struct timer_list os_timer_t;#define OS_TIMER_FUNC(_fn)\void _fn(unsigned long timer_arg)#define OS_GET_TIMER_ARG(_arg, _type)\(_arg) = (_type)(timer_arg)#define OS_INIT_TIMER(_osdev, _timer, _fn, _arg)\do {\init_timer(_timer);\(_timer)->function = (_fn);\(_timer)->data = (unsigned long)(_arg);\} while (0)#define OS_SET_TIMER(_timer, _ms)\mod_timer(_timer, jiffies + ((_ms)*HZ)/1000)#define OS_CANCEL_TIMER(_timer)del_timer(_timer)static OS_TIMER_FUNC(wps_led_blink){static int sec = 0;sec++;if(sec < 40) {//printk("sec:%d\n",sec);{if(ar7240_gpio_in_val(BUTTON_GPIO)==0) {OS_SET_TIMER(&os_timer_t, 100);  //printk("01_ar7240_gpio_in_val(BUTTON_GPIO):%d\n",ar7240_gpio_in_val(BUTTON_GPIO));}else{buttons_dev.button_short_time=0;OS_CANCEL_TIMER(&os_timer_t);buttons_dev.is_interrupt_finished =1;printk("按鍵時間少於4秒,您按鍵已:%d 秒\n",(sec/10));sec =0;enable_irq(AR7240_GPIO_IRQn(BUTTON_GPIO));//printk("02_ar7240_gpio_in_val(BUTTON_GPIO):%d\n",ar7240_gpio_in_val(BUTTON_GPIO));}}} else{OS_SET_TIMER(&os_timer_t, 100);if(ar7240_gpio_in_val(BUTTON_GPIO)){printk("按鍵時間大於4秒,您按鍵已:%d 秒,系統設定將複位。\n",(sec/10));OS_CANCEL_TIMER(&os_timer_t);sec =0;buttons_dev.button_short_time=1;  buttons_dev.is_interrupt_finished=1;enable_irq(AR7240_GPIO_IRQn(BUTTON_GPIO));}}if(buttons_dev.button_short_time==1){buttons_dev.press_cnt = 1; /* 按鍵計數加1    */buttons_dev.ev_press = 1; buttons_dev.button_short_time = 0;sec =0;printk("buttons_dev.press_cnt:%d\n",buttons_dev.press_cnt);//wake_up_interruptible(&(buttons_dev.buttons_waitqueue));   /* 喚醒休眠的進程 */}}//中斷響應函數,到這裡表明已經發生了中斷,進入了中斷處理函數。static irqreturn_t ar7242buttons_interrupt(int irq, void *dev_id){disable_irq(AR7240_GPIO_IRQn(BUTTON_GPIO));//此處關閉中斷,之後,系統不會再次響應中斷。OS_SET_TIMER(&os_timer_t, 0);//printk("您請求按鍵中斷一次,系統為您做出按鍵響應,請等待.................\n");return IRQ_HANDLED;}static int ar7242Button_open(struct inode *inode, struct file *file){int ret =0;if (MINOR(inode->i_rdev) != BUTTON_MINOR) {return -ENODEV;}if (buttons_dev.ar7242_ButtonOpened) {return -EBUSY;}buttons_dev.ar7242_ButtonOpened = 1;ret = request_irq(AR7240_GPIO_IRQn(BUTTON_GPIO), ar7242buttons_interrupt, 0,"ar7242 button", NULL);if (ret != 0) {printk("request_irq for button  (error %d)\n", ret);}return ret;}static int ar7242Button_close(struct inode *inode, struct file *file){if (MINOR(inode->i_rdev) != BUTTON_MINOR) {return -ENODEV;}buttons_dev.ar7242_ButtonOpened = 0;free_irq(ATH_GPIO_IRQn(BUTTON_GPIO), NULL);return 0;}static ssize_t ar7242Button_read(struct file *file, char *buff, size_t count, loff_t * ppos){unsigned long err;int retval = 0;/* 如果ev_press等於0,休眠 *///應用程式需要讀取按鍵的狀態,故將這句屏蔽,不然應用程式會阻塞到這裡。//即讀不到資料的時候直接返回(-EFAULT)//wait_event_interruptible(buttons_dev.buttons_waitqueue, (buttons_dev.ev_press != 0));/* 執行到這裡時,ev_press等於1,將它清0 */buttons_dev.ev_press = 0;/* 將按鍵狀態複製給使用者,並清0 */err = copy_to_user(buff,(const void *)&buttons_dev.press_cnt,sizeof(buttons_dev.press_cnt));  if ((err < 0)) {//printk("\ncopy_to_user error ret: %d\n",err);retval = -EFAULT;}else{retval = sizeof(buttons_dev.press_cnt);}  // buttons_dev.press_cnt =0;   //當應用程式讀到按鍵的次數>1後,表示按鍵已經按下。可以根據此值,做出下一步的判斷。//printk("\nretval:%d  buttons_dev.press_cnt: %d: buttons_dev.ev_press:%d\n",retval,buttons_dev.press_cnt ,buttons_dev.ev_press);return retval;}static ssize_t ar7242Button_write(struct file *file, const char *buf, size_t count, loff_t * ppos){unsigned  int cnt =0;int ret ;int __user *ptr = (int __user *)buf;ret = get_user(cnt, ptr);if(ret){ret= -EFAULT;}else{ret = count;}buttons_dev.press_cnt = 0;//printk("\rret: %d  buttons_dev.press_cnt: %d: cnt:%d  count;%d\n",ret,buttons_dev.press_cnt ,cnt,count);return ret;}static int ar7242Button_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg){int ret = 0;return ret;}static struct file_operations ar7242Button_fops = {read:    ar7242Button_read,write:ar7242Button_write,ioctl:ar7242Button_ioctl,open:ar7242Button_open,release:ar7242Button_close};static struct miscdevice athfr_miscdev = {BUTTON_MINOR,"ar7242_button",&ar7242Button_fops};static int __init ar7242_button_init(void){int ret;ret = misc_register(&athfr_miscdev);if (ret < 0)     {printk("*** insmod ar7242_button.ko failed %d *** \n", ret);return -1;}OS_INIT_TIMER(NULL, &os_timer_t, wps_led_blink, &os_timer_t);init_waitqueue_head(&(buttons_dev.buttons_waitqueue));ar7240_gpio_config_input(BUTTON_GPIO);ar7240_gpio_config_int(BUTTON_GPIO, INT_TYPE_LEVEL,INT_POL_ACTIVE_LOW);    printk("*** insmod ar7242_button.ko success *** \n");return ret;}static void __exit ar7242_buttons_exit(void){         misc_deregister(&athfr_miscdev);// ath_gpio_intr_shutdown(ATH_GPIO_IRQn(BUTTON_GPIO));  printk("%s (%s) line: %d\n", __FILE__, __func__,__LINE__);}module_init(ar7242_button_init);module_exit(ar7242_buttons_exit);MODULE_AUTHOR("cctv from test");                // 驅動程式的作者MODULE_DESCRIPTION("button driver for Atheros 7242  platform");         // 一些描述資訊MODULE_LICENSE("GPL");                              // 遵循的協議

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.