2013-10-07 实验之按键中断控制Led

实验描述:编写按键中断,K1控制Led1,K2控制Led2 .......K4控制Led4,并且将每次按键 的结果返回到用户态

注意事项:驱动层,中断程序编写,指针地址,唤醒与睡眠,地址映射解绑

  应用层,指针,内存置0,格式化输出

内核版本: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> 
/*
      Kernel Version: Linux 2.6.38
      Arm Version: Mini 6410
*/

#define MyPrintk  printk

struct button_irq_desc {
	int irq;
	unsigned long flags;
	char *name;
	unsigned long count;
};

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 DECLARE_WAIT_QUEUE_HEAD(buttons_waitq);
static volatile int buttons_press = 0;
static dev_t  Leds_Major ;
static char * DEVICE_NAME = "ButtonsLeds";
static int current_press;
volatile unsigned long *gpkcon0 = NULL;
volatile unsigned long *gpkdat    = NULL;
volatile unsigned long *gpncon   = NULL;
volatile unsigned long *gpndat    = NULL;
static struct class *leds_class;

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;
		}
	}
	MyPrintk (KERN_EMERG "gpkndata: %lu\n", *gpndat);  
	*gpkdat |= (1<<4) | (1<<5) | (1<<6) | (1<<7) ;  
	*gpkdat &= ledsvalue[i];
	MyPrintk (KERN_EMERG "gpkkdata: %lu %d\n", *gpkdat, i);  
	buttons_press = 1;
	volatile int *count = (volatile int *)dev;
	*count = *count + 1;
	current_press  = i ;
	wake_up_interruptible(&buttons_waitq);
	return IRQ_RETVAL(IRQ_HANDLED);
}

static int   buttons_leds_init (struct inode *inode, struct file *file)
{
	*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) ;  
	/*
		set the interrupt pin

	*gpncon &= ~((0x3<<0*2) | (0x3<<1*2) | (0x3<<2*2) | (0x3<<3*2)); 
	*gpncon |= (0x2<<0*2) | (0x2<<1*2) | (0x2<<2*2) | (0x2<<3*2);
		register the interrupt
	*/
	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");
	}
	return 0;
}

static ssize_t buttons_leds_read(struct file *file, const char __user *buffer, size_t count, loff_t * ppos)
{
	printk("\nwait............. \n");
	wait_event_interruptible(buttons_waitq, buttons_press);
	printk("\nwake............. \n");
	buttons_press = 0;
	int err;
	printk("%d\n", sizeof(button_irqs[current_press]));
	printk("interrupt irq: %d, flags: %lu, name: %s, count: %lu\n",button_irqs[current_press].irq,
		button_irqs[current_press].flags, button_irqs[current_press].name, button_irqs[current_press].count);
	err = copy_to_user( (void * )buffer, (const void * )(button_irqs[current_press].name), sizeof( button_irqs[current_press].name));
	if(err){
		printk("Sorry, copy to user failure!");
	}
	return 0;
}

int buttons_leds_close (struct inode * inode, struct file *file)
{
	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,
	.read = buttons_leds_read,
	.open = buttons_leds_init,
	.release = buttons_leds_close,
};

static int myleds_init(void)  
{   
	Leds_Major = register_chrdev(Leds_Major,DEVICE_NAME , &s3c64XX_leds_fops);
	if(Leds_Major < 0){
   	  	 MyPrintk (KERN_EMERG "Sorry, Can not register the leds device!\n");  
   	} 
	MyPrintk (KERN_EMERG " Register the interrupt leds device\n");   
	leds_class = class_create(THIS_MODULE, "InterruptLeds"); 
	device_create(leds_class, NULL , MKDEV(Leds_Major, 0), NULL, "ButtonsLeds");
	gpkcon0 = (volatile unsigned long *)ioremap(0x7F008800,12);
	gpkdat = gpkcon0 + 2; 
	gpncon = (volatile unsigned long *)ioremap(0x7F008830,8);
	gpndat = gpncon + 1; 
	return 0;  
}  

static int myleds_exit(void)  
{   
	unregister_chrdev(Leds_Major, DEVICE_NAME);
  	device_destroy(leds_class,  MKDEV(Leds_Major, 0));	
	class_destroy(leds_class);
	iounmap(gpkcon0);
	iounmap(gpncon);
  	MyPrintk (KERN_EMERG "Buttons Leds Linux Byebye\n");  
  	return 0;  
}  
  
module_init(myleds_init);  
module_exit(myleds_exit);
MODULE_LICENSE("GPL");  

应用程序:

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>

int main(int argc, char **argv)
{
	int fd;
	int val = 1;
	int ret;
	fd = open("/dev/ButtonsLeds", O_RDWR);
	if (fd < 0){
		printf("Sorry, can't open!\n");
	}
	char *name = (char *)malloc(10);

	while(1){
		ret = read(fd, name, sizeof(name));
		if(ret < 0){
			printf("Sorry, read error!\n");
		}
		printf("name: %s\n", name);
		memset(name, 0, sizeof(name));
		printf("memset  name: %s\n", name);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值