2013-10-17 实验之中断后推之tasklet
2013-10-17 14:01
246 查看
实验描述:tasklet
注意事项:tasklet的使用
内核版本:Linux 2.6.38
开发板: Mini 6410
驱动程序:
测试程序:
注意事项:tasklet的使用
内核版本:Linux 2.6.38
开发板: Mini 6410
驱动程序:
#include <linux/init.h> #include <linux/module.h> #include <linux/device.h> #include <linux/kdev_t.h> #include <linux/fs.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <linux/delay.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/cdev.h> /* Kernel Version: Linux 2.6.38 Arm Version: Mini 6410 */ #define MyPrintk printk struct button_irq_desc { int irq; unsigned long flags; char name[20]; unsigned long count; }; static struct cdev first_cdev; static struct button_irq_desc button_irqs [] = { {IRQ_EINT(0), IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "K1", 0}, {IRQ_EINT(1), IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "K2", 0}, {IRQ_EINT(2), IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "K3", 0}, {IRQ_EINT(3), IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "K4", 0}, }; static unsigned int ledsvalue []= { ~ ((1<<4) | (0<<5) | (0<<6) | (0<<7)) , ~ ((0<<4) | (1<<5) | (0<<6) | (0<<7)), ~ ((0<<4) | (0<<5) | (1<<6) | (0<<7)), ~ ((0<<4) | (0<<5) | (0<<6) | (1<<7)) }; static dev_t Leds_Major ; volatile unsigned long *gpkcon0 = NULL; volatile unsigned long *gpkdat = NULL; static struct class *leds_class; static struct tasklet_struct my_tasklet; void my_tasklet_handler(unsigned long data) { printk("tasklet_statrt: %lu\n", data); } static irqreturn_t buttons_hander(int irq, void * dev) { int i; for (i=0; i < sizeof(button_irqs) /sizeof(button_irqs[0]); i++) { if(irq == button_irqs[i].irq){ break; } } *gpkdat |= (1<<4) | (1<<5) | (1<<6) | (1<<7) ; *gpkdat &= ledsvalue[i]; volatile int *count = (volatile int *)dev; *count = *count + 1; printk("interrupt irq: %d, flags: %lu, name: %s, count: %lu\n",button_irqs[i].irq, button_irqs[i].flags, button_irqs[i].name, button_irqs[i].count); tasklet_schedule(&my_tasklet); return IRQ_RETVAL(IRQ_HANDLED); } static int data_open(struct file *file, struct node *nodes) { int i; int err; for (i=0; i < sizeof(button_irqs) /sizeof(button_irqs[0]); i++) { err = request_irq(button_irqs[i].irq, buttons_hander, button_irqs[i].flags, button_irqs[i].name, (void *)&button_irqs[i].count); if(err){ break; } printk("register this interrupt %d \n", button_irqs[i].irq); } if(err){ i--; for(; i >= 0; i--) { free_irq(button_irqs[i].irq, (void *)&button_irqs[i].count); } printk("Sorry, can not register these interrupts"); } *gpkcon0 &= ~( (0xF<<4*4) | (0xF<<5*4) | (0xF<<6*4) | (0xF<<7*4)); *gpkcon0 |= ( (0x1<<4*4) |(0x1<<5*4) | (0x1<<6*4) | (0x1<<7*4)); *gpkdat |= (1<<4) | (1<<5) | (1<<6) | (1<<7) ; unsigned long data = 1000; tasklet_init(&my_tasklet, my_tasklet_handler, data); return 0; } static int data_release(struct file *file, struct node *nodes) { int i; for (i=0; i < sizeof(button_irqs) /sizeof(button_irqs[0]); i++) { free_irq(button_irqs[i].irq, (void *)&button_irqs[i].count); } return 0; } static struct file_operations s3c64XX_leds_fops = { .owner = THIS_MODULE, .open = data_open, .release = data_release, }; int major; static int myleds_init(void) { alloc_chrdev_region(&Leds_Major,2, 3, "mycdev"); major = MAJOR(Leds_Major); if(Leds_Major < 0){ MyPrintk (KERN_EMERG "Sorry, Can not register the cdev leds device!\n"); } MyPrintk (KERN_EMERG " Register the cdev leds device\n"); cdev_init(&first_cdev, &s3c64XX_leds_fops); cdev_add(&first_cdev, Leds_Major, 3); leds_class = class_create(THIS_MODULE, "mycdev"); device_create(leds_class, NULL , MKDEV(major, 2), NULL, "mycdev2"); device_create(leds_class, NULL , MKDEV(major, 3), NULL, "mycdev3"); device_create(leds_class, NULL , MKDEV(major, 4), NULL, "mycdev4"); gpkcon0 = (volatile unsigned long *)ioremap(0x7F008800,12); gpkdat = gpkcon0 + 2; return 0; } static int myleds_exit(void) { device_destroy(leds_class, MKDEV(major, 2)); device_destroy(leds_class, MKDEV(major, 3)); device_destroy(leds_class, MKDEV(major, 4)); class_destroy(leds_class); iounmap(gpkcon0); cdev_del(&first_cdev); unregister_chrdev_region( MKDEV(major, 2), 3); MyPrintk (KERN_EMERG "cdev Leds Linux Byebye\n"); return 0; } module_init(myleds_init); module_exit(myleds_exit); MODULE_LICENSE("GPL");
测试程序:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main(){ int fd; fd = open( "/dev/mycdev2", O_RDWR); if (-1 == fd){ perror(" open 1 error"); } sleep(20); close(fd); fd = open( "/dev/mycdev3", O_RDWR); if (-1 == fd){ perror(" open 2 error"); } sleep(20); close(fd); }
相关文章推荐
- jQuery 2.0.3 源码分析Sizzle引擎 - 编译函数(大篇幅)
- ie6 png透明
- C++ vector容器使用 排序
- jQuery 2.0.3 源码分析Sizzle引擎 - 解析原理
- VM下 NAT网络配置虚拟机上网
- 人搜笔试编程题——树的层序遍历
- 交换机端口安全 port-security配置详解
- wikioi 1017 乘积最大 (2000年NOIP全国联赛普及组NOIP全国联赛提高组)
- python confingparser与optparser
- ABAP 供应商主数据比较常用的表
- jQuery 2.0.3 源码分析Sizzle引擎 - 词法解析
- c、c++排序函数qsort、stable_sort
- linux 下长命令的简化(命令别名)
- 如何解读游戏运维工程师这一职位
- mysql如何将一个表导出为excel表格
- cPanel虚拟主机上运行Python的方法
- java导出csv用excel打开后数字不用科学计数法显示
- linux基础(二)----linux常用命令积累
- linux基础(二)----linux常用命令积累
- python中if __name__ == '__main__': 的解析