实例操作led驱动

/*the driver is for  led  writted by william in 2013.2.27 and the kernel 2.6.25*/

#include <linux/module.h>    //动态加载模块到内核,假如没有这个头文件,编译一切正常,但是安装驱动模块后,不会产生节点,即不成功。
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/arch/gpio.h>
#include <asm-arm/arch-pxa/mfp.h>

#include "led.h"
/*led.h 中的内容如下
#ifndef __LED_H__
#define __LED_H__

#define LED_ON	0
#define LED_OFF	1
#define Led_Count 	5

struct Led_dev{
	int Led_Num;
	unsigned char state;
	unsigned int timems;
	//unsigned int offtimems;	
};

#endif
*/

#define LED_DEVICE_NAME "william_led"            

struct Led_dev LED_DEV;

static unsigned long led_table[] = {
2,3,4,5,83,
};    //这是根据硬件电路图得出的gpio引脚

/*
int led_open(struct inode *inode,struct file *filp)
{
	return 0;
}

int led_release(struct inode *inode,struct file *filp)
{
	return 0;
}

static ssize_t led_read(struct file *filp,char *buf,size_t size,loff_t *ppos)    
{	
	if(copy_to_user(buf,&LED_DEV,sizeof(LED_DEV)))
	{
		printk("copy to user failed !\n");
		return -EFAULT;
	}
	return sizeof(LED_DEV);
}
*/
static ssize_t led_write(struct file *filp,const char *buf,size_t size,loff_t *ppos)
{
	
	unsigned int gpioID;
	int i,num;
	struct Led_dev NEW_LED_DEV = LED_DEV;
	
	if(copy_from_user(&NEW_LED_DEV,buf,sizeof(NEW_LED_DEV)))
	{
		printk("copy from user failed !\n");
		return -EFAULT;
	}
	
	if(NEW_LED_DEV.Led_Num < Led_Count)
	{
		num = NEW_LED_DEV.Led_Num;
		gpioID = mfp_to_gpio(led_table[num]);    //#define mfp_to_gpio(m)  ((m) % 128)
		gpio_direction_output(gpioID,NEW_LED_DEV.state);
	}
	else
	{	
		for(i=0;i<Led_Count;i++)
		{
			gpioID = mfp_to_gpio(led_table[i]);
			gpio_direction_output(gpioID,NEW_LED_DEV.state);
		}				
	}
	return 0;
}
/*
static int led_ioctl(struct inode *inodep,struct file *filp,unsigned int cmd,unsigned long arg)
{
	return 0;
}
*/
static struct file_operations led_fops = {
	.owner = THIS_MODULE,
	//.read = led_read,
	.write = led_write,
	//.ioctl = led_ioctl,
	//.open = led_open,        //有些函数我们用不到可以省去,看上去更简洁
	//.release = led_release,
};

static struct miscdevice led_dev = {
	.minor = 53,    //cat  /proc/misc 查看这个次设备号是否已被使用
	.name = LED_DEVICE_NAME,
	.fops = &led_fops,
};    //混杂设备必须的三个元素minor ,name,fops 。 

static int led_probe(struct platform_device *pdev)
{
	int ret;
	int i;
	unsigned int gpioID;
	ret = misc_register(&led_dev);

	for(i=0;i<ARRAY_SIZE(led_table);i++){
		gpioID = mfp_to_gpio(led_table[i]);
		ret = gpio_request(gpioID,"leds-request");
		if(ret){
			printk("Failed in gpio-%d",gpioID);
		}
		gpio_direction_output(gpioID,LED_OFF);
	}
	return 0;
}

static int led_remove(struct platform_device *pdev)
{
	int i;
	unsigned int gpioID;
	for(i=0;i<ARRAY_SIZE(led_table);i++){
		gpioID = mfp_to_gpio(led_table[i]);
		gpio_direction_output(gpioID,LED_OFF);
		gpio_free(gpioID);
	}
	misc_deregister(&led_dev);
	return 0;
}

#ifdef CONFIG_PM        //这里考虑能耗,添加了休眠模式
static int led_suspend(struct platform_device *pdev, pm_message_t state)
{	
	return 0;
}

static int led_resume(struct platform_device *pdev)
{	
	return 0;
}
#else
#define s3c24xx_led_suspend NULL
#define s3c24xx_led_resume NULL
#endif

static struct platform_driver led_driver = {
	.driver = {
		.name = "william_test_led",	    	
		},
	.probe = led_probe,
	.remove = led_remove,
	.suspend = led_suspend,
	.resume = led_resume,
};
#    这个需要在内核你所用板子的函数中添加
#    static struct platform_device led_device = {
#	    .name		= "william_test_led",
#	    .id 		= -1,
#    };
#    并在初始化函数中添加
#    platform_device_register(&led_device);

static int __init led_init(void)
{
	printk("hello led !\n");
	return platform_driver_register(&led_driver);
}

static void __exit led_exit(void)
{
	platform_driver_unregister(&led_driver);
	printk("bye led !\n");
}

module_init(led_init);  
module_exit(led_exit); 

MODULE_AUTHOR("William Wang");  
MODULE_LICENSE("GPL");

//注意:驱动要保持其简洁性,不要加led闪烁之类的附加功能,凡API易做的,尽量在API中做。

附加测试程序
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "led.h"

void delay(int n)
{
int i;
for(i=0;i<n;i++)
for(i=0;i<10000;i++);
}

int do_led(struct Led_dev testled)
{
	int fd;
	if((fd=open("/dev/william_led",O_RDWR)) == -1)
	{
		printf("open err !\n");
	}

	fd = write(fd,&testled,sizeof(testled));
	if(fd == -1)
	{
		printf("write err !\n");
	}
	
	close(fd);
	return 0;
}

int main(void)
{
	int i;
	struct Led_dev test_led ={
		2,
		LED_ON,
		10,
	};
	 
	for(i=0;i<5;i++){
		test_led.Led_Num = i;
		do_led(test_led);
		delay(test_led.timems);    //delay 作用不明显
		test_led.state = ~test_led.state;
		do_led(test_led);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值