2013-10-17 实验之中断后推之tasklet

实验描述:tasklet

注意事项: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);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值