linux下之定时器timer实例

来源:互联网 发布:淘宝二手店铺怎么开 编辑:程序博客网 时间:2024/06/06 05:52
最近工作中涉及到在一定的时间之后对特定的动作进行处理。比如按键,按键需要在按下至少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");                              // 遵循的协议

原创粉丝点击