首页 > 其他 > 详细

第6课.定时器

时间:2020-03-16 17:05:50      阅读:66      评论:0      收藏:0      [点我收藏+]

1.简介

内核通过定时器中断来跟踪时间流。
定时器中断的中断间隔由内核根据HZ的值设定,HZ是一个与体系结构有关的常数默认HZ值范围为50~1200,而对软件仿真器的HZ值是24.大多数平台每秒有100或1000次时钟中断。
每次当时钟中断发生时,内核内部计数器的值就增加一。这个计数器的值在系统引导时,被初始化为0,因此,它的值就是自上次操作系统引导以来的时钟滴答数。这个计数器是一个64位的变量(即使在32位架构上也是64位),称为"jiffies_64",但是,驱动程序开发者通常访问的是jiffies变量,它是unsigned long型的变量,要么和"jiffies_64"相同,要么仅仅是jiffes_64的低32位。通常首先使用jiffies,因为对它的访问很快,从而对64位jiffes_64值的访问并不需要在所有架构上都是原子的

2.使用jiffes计数器

该计数器和读取计数器的工具函数包含在<linux/jiffies.h>中,但是通常只需要包含<linux/sched.h>文件,后者会自动放入jiffies.h。还需要说明的是,jiffies和jiffies_64均应该被看成只读变量。包含param.h时,HZ宏始终被扩展为100。

3.常用函数

// timer_list的数据结构
struct timer_list timer;        

// 初始化timer_list结构体
void init_timer(struct timer_list * timer) 

// 注册定时器结构,以在当前CPU上运行
void add_timer(struct timer_list *timer)

// 修改一个已经调度的定时器结构的到期时间。它也可以替代add_timer函数使用
int mod_timer(struct timer_list *timer, unsigned long expires)

4.代码解析

Makefile

KERN_DIR = /work/system/linux-2.6.22.6

all:
    make -C $(KERN_DIR) M=`pwd` modules 

clean:
    make -C $(KERN_DIR) M=`pwd` modules clean
    rm -rf modules.order

obj-m   += buttons.o

buttons.c

static struct timer_list buttons_timer;

static irqreturn_t buttons_irq(int irq, void *dev_id)
{
    /* 10ms后启动定时器 */
    irq_pd = (struct pin_desc *)dev_id;
    mod_timer(&buttons_timer, jiffies+HZ/100);
    return IRQ_RETVAL(IRQ_HANDLED);
}

static void buttons_timer_function(unsigned long data)
{
    struct pin_desc * pindesc = irq_pd;
    unsigned int pinval;

    if (!pindesc)
        return;
    
    pinval = s3c2410_gpio_getpin(pindesc->pin);

    if (pinval)
    {
        /* 松开 */
        key_val = 0x80 | pindesc->key_val;
    }
    else
    {
        /* 按下 */
        key_val = pindesc->key_val;
    }

    ev_press = 1;                  /* 表示中断发生了 */
    wake_up_interruptible(&button_waitq);   /* 唤醒休眠的进程 */
    
    kill_fasync (&button_async, SIGIO, POLL_IN);
}

static int sixth_drv_init(void)
{
    init_timer(&buttons_timer);
    buttons_timer.function = buttons_timer_function;
    //buttons_timer.expires  = 0;
    add_timer(&buttons_timer); 

    major = register_chrdev(0, "sixth_drv", &sencod_drv_fops);

    sixthdrv_class = class_create(THIS_MODULE, "sixth_drv");

    sixthdrv_class_dev = class_device_create(sixthdrv_class, NULL, MKDEV(major, 0), NULL, "buttons"); /* /dev/buttons */

//  gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);
//  gpfdat = gpfcon + 1;

    return 0;
}

解析:    HZ:表示1s
    HZ / 1000 = 1 / 100 = 10ms

buttons_test.c

int fd;

void my_signal_fun(int signum)
{
    unsigned char key_val;
    read(fd, &key_val, 1);
    printf("key_val: 0x%x\n", key_val);
}

int main(int argc, char **argv)
{
    unsigned char key_val;
    int ret;
    int Oflags;

    //signal(SIGIO, my_signal_fun);
    
    fd = open("/dev/buttons", O_RDWR);
    if (fd < 0)
    {
        printf("can't open!\n");
        return -1;
    }

    //fcntl(fd, F_SETOWN, getpid());
    
    //Oflags = fcntl(fd, F_GETFL); 
    
    //fcntl(fd, F_SETFL, Oflags | FASYNC);


    while (1)
    {
        ret = read(fd, &key_val, 1);
        printf("key_val: 0x%x, ret = %d\n", key_val, ret);
        //sleep(5);
    }
    
    return 0;
}

第6课.定时器

原文:https://www.cnblogs.com/huangdengtao/p/12504793.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!