linux内核中断和定时器

来源:互联网 发布:assert java 断言 编辑:程序博客网 时间:2024/05/17 21:54

1.对于学过单片机的我对于中断是有一个很清楚的认识,就是当程序执行的时候,突然发生了一件很重要的事情,将cpu打断,进而cpu去执行中断的事情,在嵌入式中,都是通过读取硬件寄存器来判断是什么中断发生。
2.在linux内核中提供了读取中断寄存器的函数
int int_scs = read_int_status();
3.申请和释放中断
int request _ irq(unsigned int irq,void (*handler)(int irq, void *dev _ id, struct pt _ regs
regs),unsigned long irqflags,const char devname,
void *dev _ id);
irq是要申请的硬件中断号,handler是中断处理函数,irqflags是中断属性,返回值是0代表成功
void free _ irq(unsigned int irq,void *dev _ id);释放中断

4.屏蔽中断函数
void disable _ irq(int irq);
void disable _ irq _ nosync(int irq);
void enable _ irq(int irq);

区别就是第一个是立刻进行屏蔽,第二个是等当前中断程序执行完成后在屏蔽。

    void local_irq_save(unsigned long flags);    void local_irq_disable(void);

屏蔽CPU内所有中断程序,与他对应的是恢复程序
void local _ irq _ restore(unsigned long flags);
void local _ irq _ enable(void);

下面是实时时钟的驱动代码

/*这open函数*/static int my_rtc_open(void){    int ret;    ret=request_irq(s3c2410_rtc_alarmno,myrtc_alarmno,SA_INTERRUPT,"myrtc",NULL);    if(ret)    {        prink("this is error);    }    ret = request_irq(s3c2410_rtc_tickno, my_tickirq,SA_INTERRUPT,14 "s3c2410-rtc tick", NULL);    if(ret)    {        printk("this is rtc is error\n");        goto errorrtc;        return -1;    }           return ret; errorrtc:    free_irq(s3c2410_rtc_alarmno,NULL);                                                                 return -1;}/*这是release函数对应的ops中close*/static void s3c2410_rtc_release(void){    s3c2410_rtc_setpie(0);    free_irq(s3c2410_rtc_alarmno,NULL);    free_irq(s3c2410_rtc_tickno, NULL);}static irqreturn_t myrtc_alarmno(int irq, void *id, struct pt _ regs *r){     rtc_update(1, RTC_AF | RTC_IRQF);     return IRQ_HANDLED;}static irqreturn_t my_tickirq(int irq, void *id, struct pt _ regs *r){     rtc_update(1, RTC_PF | RTC_IRQF);     return IRQ_HANDLED;}

整型原子操作
1.设置原子变量的值
void atomic _ set(atomic _ t *v, int i); //设置原子变量的值为 i
atomic _ t v = ATOMIC _ INIT(0); //定义原子变量 v 并初始化为 0
2.获取原子变量的值
atomic _ read(atomic _ t *v); //返回原子变量的值
3.原子变量加/减
void atomic _ add(int i, atomic _ t *v); //原子变量增加 i
void atomic _ sub(int i, atomic _ t *v); //原子变量减少 i
4.原子变量自增/自减
void atomic _ inc(atomic _ t *v); //原子变量增加 1
void atomic _ dec(atomic _ t *v); //原子变量减少 1
5.操作并测试
int atomic _ inc _ and _ test(atomic _ t *v);
int atomic _ dec _ and _ test(atomic _ t *v);
int atomic _ sub _ and _ test(int i, atomic _ t *v);
上述操作对原子变量执行自增、自减和减操作后(注意没有加)测试其是否为 0,
为 0 则返回 true,否则返回 false。
6.操作并返回
int atomic _ add _ return(int i, atomic _ t *v);
int atomic _ sub _ return(int i, atomic _ t *v);
int atomic _ inc _ return(atomic _ t *v);
int atomic _ dec _ return(atomic _ t *v);
上述操作对原子变量进行加/减和自增/自减操作,并返回新的值。

位原子操作
1.设置位
void set _ bit(nr, void *addr);
上述操作设置 addr 地址的第 nr 位,所谓设置位即将位写为 1。
2.清除位
void clear _ bit(nr, void *addr);
上述操作清除 addr 地址的第 nr 位,所谓清除位即将位写为 0。
3.改变位
void change _ bit(nr, void *addr);
上述操作对 addr 地址的第 nr 位进行反置。
4.测试位
test _ bit(nr, void *addr);
上述操作返回 addr 地址的第 nr 位。
5.测试并操作位
int test _ and _ set _ bit(nr, void *addr);
int test _ and _ clear _ bit(nr, void *addr);
int test _ and _ change _ bit(nr, void *addr);
上述 test_and_xxx_bit (nr, void *addr)操作等同于执行 test_bit (nr, void *addr) 后
再执行 xxx_bit(nr, void *addr)。

定时器:
在linux内核中每一个定时器对应这timer_list的实例
struct timer _ list {
struct list _ head entry; //定时器列表
unsigned long expires; //定时器到期时间
void (*function)(unsigned long); //定时器处理函数
unsigned long data; //作为参数被传入定时器处理函数
struct timer _ base _ s *base;
};
1.初始化定时器
void init _ timer(struct timer _ list * timer);
2.DEFINE_TIMER(_name, _function, _expires, _data)宏是定义并初始化定
时器成员的.
3.增加定时器
void add _ timer(struct timer _ list * timer);
上述函数用于注册内核定时器,将定时器加入到内核动态定时器链表中。
4.删除定时器
int del _ timer(struct timer _ list * timer);
上述函数用于删除定时器。
5.修改定时器的 expire
int mod _ timer(struct timer _ list *timer, unsigned long expires);
上述函数用于修改定时器的到期时间,在新的被传入的 expires 到来后才会执行定时器函数。

写一个秒的设备驱动,他是一个字符驱动设备:

#include ......#define SECOND _ MAJOR 252 /*预设的 second 的主设备号*/static int second_major = SECOND _ MAJOR;/*second 设备结构体*/struct second_dev{    struct cdev cdev; /*cdev 结构体*/    atomic_t counter;/* 一共经历了多少秒?*/    struct timer_list s_timer; /*设备要使用的定时器*/};struct second_dev *second_devp; /*设备结构体指针*/static void second_timer_handler(unsigned long arg){    mod_timer(second_devp->s_timer,jiffies+HZ);    atomic_inc(second_devp->counter);    printk(KERN _ NOTICE "current jiffies is %ld\n", jiffies);}static int second_open(struct inode *inode, struct file *filp){    /*     * 1. 初始化2.添加3.计数器清零     */     init_timer(second_devp->s_timer);     second_devp->s_timer.function = second_timer_handler; //定时器函数     second_devp->s_timer.expires = jiffies+HZ;   //添加预存储寄存器值     add_timer(&second_devp->s_timer);   //添加定时器设备     atomic_set(&second_devp->counter,0);//计数器清零}/*文件释放函数*/int second _ release(struct inode *inode, struct file *filp){    del_timer(&second_devp->s_timer);    return 0;}static ssize_t second_read(struct file *filp,char  __user *buf,size_t count,loff_t *ppos){   int counter;   counter = atomic_read(&second_devp->counter);   if(put_user(counter, (int*)buf))       return -EFAULT;   else       return sizeof(unsigned int);}static const struct file_operations second_fops ={    .owner = THIS_MODULE,    .open = second_open,    .release = second_release,    .read = second_read,};static void second_setup_cdev(struct second_dev *dev,int index){    int err, devno = MKDEV(second_major, index);    cdev_init(&dev->cdev,&second_fops);    dev->cdev.owner = THIS_MODULE;    dev->cdev.ops = &second_fops;    err = cdev_add(&dev->cdev,devno,1);    if(err)    {        prink("error\n");    }}static int second_init(void){    dev_t inode = MKDEV(second_major, 0);    if(second_major)    {        ret = register_chrdev_region(inode,1,"dev_no");    }    else    {        ret = alloc_chrdev_region(&inode,0,1,"dev_no");        second_major = MAJOR(inode);    }    if(ret<0)    {        printk("error\n");        return ret;    }    second_devp = kmalloc(sizeof(struct second_dev), GFP_KERNEL);    if(second_devp == NULL)    {        printk("kmalloc is error\n");        goto Failkmalloc;    }    memset(second_devp ,0,sizeof(struct second_dev));    second_setup_cdev(second_devp, 0);Failkmalloc:        unregister_chrdev_region(inode, 1);    return 0;}static void second_exit(void){    return 0;}MODULE _ AUTHOR("Song Baohua");MODULE _ LICENSE("Dual BSD/GPL");module _ param(second _ major, int, S _ IRUGO);module_init(second_init);module_exit(second_exit);
原创粉丝点击