linux平台设备驱动程序的写法之操作led灯

        很晚了,不多说了,还是在以前的led灯中断控制的基础上写的,以下直接附程序:

        1、led_device.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
//#include <linux/ioport.h>
static struct resource led_rsrc[] = {
	{
		.start = 0xE0200060,
		.end   = 0xE0200067,
		.flags = IORESOURCE_MEM,
	},
	
	{
		.start = 0xE0200060+0xc00-0x60,
		.end   = 0xE0200060+0xc00-0x60+0x07,
		.flags = IORESOURCE_MEM,
	},
	{
		.start = IRQ_EINT(1),
		.end   = IRQ_EINT(4),
		.flags = IORESOURCE_IRQ,
	}
};

static void led_device_release(struct device * dev)
{
}

static struct platform_device led_keys_device = {
	.name           = "led-keys",
	.num_resources  = ARRAY_SIZE(led_rsrc),
	.resource       = led_rsrc,
	.dev = { 
    	.release = led_device_release, 
	},
};

static int __init led_keys_init(void)
{
	return platform_device_register(&led_keys_device);
}

static void __exit led_keys_exit(void)
{
	platform_device_unregister(&led_keys_device);
}

module_init(led_keys_init);
module_exit(led_keys_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ethyn Blog:blog.csdn.net/humanspider1");
MODULE_DESCRIPTION("Keys device for led test");

2、led_driver.c

#include <linux/module.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/io.h>
#include <asm/uaccess.h>

#define led_keys_of_match NULL
static unsigned char KeyFlag;
wait_queue_head_t my_waitqueue;
struct s5pv210_resource {
	struct platform_device		*pdev;
	u64				cur_format;
	unsigned int			cur_rate;
	unsigned long			flags;
	int				playback_period, capture_period;
	/* Serialize access to opened variable */
	spinlock_t			lock;
	void __iomem			*regs;
	int				irq;
	int				opened;
	int				reset_pin;
};

static int major;
static volatile int press = 0; 
static struct class *led_class;
volatile unsigned long *gpcxcon, *gpcxdat,*gpchcon;//用与存放两个个寄存器的地址
static unsigned char witch_key = 0;



static void led1_on(void)
{
	*gpcxdat |= 1 << 3;
	*gpcxdat &= ~(0x01 << 4);
}

static void led2_on(void)
{
	*gpcxdat |= 1 << 4;
	*gpcxdat &= ~(0x01 << 3);
}

static void all_leds_on(void)
{
		*gpcxdat |= 1 << 3;		// 点亮LED1
		*gpcxdat |= 1 << 4;		// 点亮LED2
}
static void all_leds_off(void)
{

	*gpcxdat &= ~(0x3 << 3);		// 熄灭LED1和LED2
	printk("all leds off\n");
}

static void led_config(void)
{
	*gpcxcon &= ~(0xFF << 12);
	*gpcxcon |= 0x11 << 12;			// 配置GPC0_3和GPC0_4为输出
	*gpchcon &= ~0x0F; //配置为输入
	all_leds_off();
}



static ssize_t led_device_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
	int ret = -1;
	unsigned char from[1]={0};
	wait_event_interruptible(my_waitqueue,press);
	press = 0;
	if(KeyFlag)
	{
	   led1_on();		
	}
	else
	{
		led2_on();
	}
	from[0] = witch_key;
	if(witch_key>0)
	{
		ret = copy_to_user(buf,from,sizeof(from));
		if(ret)
		{
			 printk("copy to user failed\n");	
		}
		witch_key = 0;
	}


	return 0;
}



static irqreturn_t led_keys_interrupt(int irq, void *dev)
{
		 printk("led-keys-interrupt just happened\n");
		 press = 1;
		wake_up_interruptible(&my_waitqueue); 
		KeyFlag = !KeyFlag;
		printk("KERNEL:irq == %d  witch_key= %d\n",irq,witch_key);
	  return  IRQ_RETVAL(IRQ_HANDLED);
}

static struct file_operations led_fops = {
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .read   =   led_device_read,     

};


static int __devinit led_keys_probe(struct platform_device *pdev)
{

	 	struct s5pv210_resource		*chip= NULL;
		struct resource			*regs = NULL;
		int i;
		unsigned int				irq =0;
		unsigned long regs_data = 0;
		int				retval=0;
		
		printk("find led-keys module success\n");
		printk("excute 12221\n");
		regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
		regs_data = (unsigned long)ioremap(regs->start, regs->end - regs->start + 1);
		if (!regs_data) {
		dev_dbg(&pdev->dev, "could not remap register memory\n");
		goto err_ioremap;
		}
		printk("excute 444\n");
		gpcxcon = (unsigned long *)regs_data;
		gpcxdat = (unsigned long *)(regs_data + 0x04);
		
		regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
		if (!regs) {
		dev_dbg(&pdev->dev, "no memory resource\n");
		return -ENXIO;
		}
		regs_data = (unsigned long)ioremap(regs->start, regs->end - regs->start + 1);
		if (!regs_data) {
		dev_dbg(&pdev->dev, "could not remap register memory\n");
		goto err_ioremap;
		}
		gpchcon = (unsigned long *)regs_data;
		led_config();
		irq = platform_get_irq(pdev, 0);
		if (irq < 0) {
		dev_dbg(&pdev->dev, "could not get irq\n");
		return -ENXIO;
		}
		for(i=0;i<4;i++)
		{

				retval = request_irq(irq+i, led_keys_interrupt, IRQ_TYPE_EDGE_FALLING, "led-irq", chip);
				if (retval) {
				dev_dbg(&pdev->dev, "unable to request irq %d\n",irq+i );
				goto err_request_irq;
				}
		}
		init_waitqueue_head(&my_waitqueue);
	major = register_chrdev(0, "myled", &led_fops);

	led_class = class_create(THIS_MODULE, "myled");

	device_create(led_class, NULL, MKDEV(major, 0), NULL, "led");
	 	return 0;
err_ioremap:
	free_irq(irq, chip);
err_request_irq:
	return retval;
}

static  int led_keys_remove(struct platform_device *pdev)
{
		device_destroy(led_class, MKDEV(major, 0));
		class_destroy(led_class);
		unregister_chrdev(major, "myled");

	
	   return 0;
}


static struct platform_driver led_keys_driver = {
	.probe		= led_keys_probe,
	.remove		= led_keys_remove,
	.driver		= {
		.name	= "led-keys",
		.owner	= THIS_MODULE,
		.of_match_table = led_keys_of_match,
	}
};



static int __init led_keys_init(void)
{
	return platform_driver_register(&led_keys_driver);
}

static void __exit led_keys_exit(void)
{
	platform_driver_unregister(&led_keys_driver);
}

module_init(led_keys_init);
module_exit(led_keys_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ethyn Blog:blog.csdn.net/humanspider1");
MODULE_DESCRIPTION("Keys driver for led test");

3测试程序apptest.c

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <unistd.h>

int main(int argc,char **argv)
{
    int fd = -1;
    char val = 0;
    char buf[10]={0};
    char temp= 0;
    char *s = malloc(100);
    unsigned char key[1];
    fd = open("/dev/led",O_RDWR);
    if(fd<0)
                        printf("can't open \n");
                while(1)
                {
                                val++;
                          read(fd,key,sizeof(key));
                                //temp =key[0]?1:(key[1]?2:(key[2]?3:(key[3]?4:0)));
                                temp = key[0];
                                if(temp)
                                         printf("pressed key is key[%x]\n",temp);
                                temp = 0;

                }
                free(s);
    return 0;

}

以上程序适用于s5pv210,如果其它的开发板稍微改下io口和中断号就可以了




猜你喜欢

转载自blog.csdn.net/humanspider1/article/details/41103801