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);
- linux内核中断和定时器
- Linux内核中断及定时器实现
- 内核驱动系列--中断和定时器
- 中断与内核定时器
- 中断与内核定时器
- 中断与内核定时器
- linux驱动开发学习--对中断和内核定时器的学习笔记
- Linux内核-中断-中断响应和返回
- linux内核-中断和异常
- LINUX内核之中断(5)--定时器与延迟执行
- 内核线程、软中断和定时器有何区别
- 中断机制与内核定时器
- linux中断与定时器
- linux-内核-内核定时器
- Linux内核时间管理和定时器
- Linux内核时钟系统和定时器实现
- 删除linux内核定时器和工作队列
- 中断和定时器实验
- Sql工作小记(1)
- 前端编码规范
- oh-my-zsh 配置目录路径,绝对路径配置成先对路径,配置主题
- a标签中href="#"和href="javascript:void(0);"href跳转使用详细说明
- 10.9-全栈Java笔记:装饰器模式构建IO流体系
- linux内核中断和定时器
- 测试--0630
- 成功的背后!(给所有IT人)
- Hash哈希算法
- FPGA入门笔记三 RTL schematic验证你的RTL级设计
- 算法导论 B树(附带节点高度)
- Samsung ARTIK 530 connect ARTIK Cloud by using Node-RED
- QTableWidget中限制输入整数、浮点数
- Nobody Loves You When You are Down and Out,微信展示面设计朋友圈打造方法