linux gpio驱动输出模式控制led

一:驱动源码:提供读写方法,用于测试
/led_drv.c*******/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/gpio.h>
 
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/uaccess.h>
#include <linux/delay.h>

#define on 1
#define off 0
#define BUFFER_SIZE 20

struct hi3559av100_led
{
	int dev_major ;
	struct class *cls;
	struct device *dev;
	int value;
};
struct hi3559av100_led *led_dev;
volatile unsigned long *gpio1_1_conf;
volatile unsigned char *gpio1_1_data;
int led_drv_open(struct inode *inode, struct file *filp)
{ 
	printk("%s\n", __FUNCTION__);
	*gpio1_1_conf |= (0x1<<1); //set pin out 
	*gpio1_1_data &= ~(0x1<<1); //set low off		 
	return 0;
}
int led_drv_close(struct inode *inode, struct file *filp)
{
	printk("%s\n", __FUNCTION__);
	//*gpio1_1_data &= ~(0x1<<1); // close led
	return 0;
}
ssize_t led_drv_write(struct file *filp, const char __user *buf, size_t count, loff_t *fpos)
{
	printk("%s\n", __FUNCTION__);
	char *led_buf;
	int ret = -1;
	led_buf = kmalloc(min_t(size_t, count+1, BUFFER_SIZE), GFP_KERNEL);
	if(led_buf == NULL) {	
		printk("%s kmalloc error\n",__FUNCTION__);
		return -EFAULT;	
	} else {
		printk("%s kmalloc  %d byte success\n",__FUNCTION__,count+1);
	}
	// copy data from app
	ret = copy_from_user(led_buf, buf, count);
	if(ret != 0) {
		printk("%s copy_from_user error\n",__FUNCTION__);
		kfree(led_buf);
		return -EFAULT;
	} else if(ret == 0) {
		printk("%s copy %d byte success   value:%s\n",__FUNCTION__,count,led_buf);
 	}
	// parse data
	if(*led_buf == '1')    //led on
	{		
		*gpio1_1_data |= (0x1<<1); 
		printk("%s led on\n",__FUNCTION__);
	}
	else if(*led_buf == '0')  //led off
	{		
		*gpio1_1_data &= ~(0x1<<1); 
		printk("%s led off\n",__FUNCTION__);	
	}
	else
	{
		printk("%s unknow data\n",__FUNCTION__);
		printk("%s\n",led_buf);
		return -EFAULT;
	}

	kfree(led_buf);
	return count;
}
long led_drv_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	switch(cmd)
	{
		case on :
			//led on
			printk("%s led on\n",__FUNCTION__);
			*gpio1_1_data |= (0x1<<1);
			break;	
		case off :
			//led off
			printk("%s led off\n",__FUNCTION__);
			*gpio1_1_data &= ~(0x1<<1); 
			break;
		default : 
			printk("%s unkown cmd\n",__FUNCTION__);
			return -EINVAL;		
	}	
	return 0;
}
const struct file_operations red_led_fops = {
	.open = led_drv_open,
	.write = led_drv_write,
	.release = led_drv_close,
	.unlocked_ioctl = led_drv_ioctl,
};
static int __init led_drv_init(void)
{	
	int ret;
 	printk("%s\n", __FUNCTION__);
	led_dev = kzalloc(sizeof(struct hi3559av100_led), GFP_KERNEL);
	if(led_dev == NULL)
	{
		printk(KERN_ERR,"kzalloc error\n");
		return -ENOMEM;
	}
		
	// 1,  申请主设备号
	led_dev->dev_major = 0;
	led_dev->dev_major = register_chrdev(led_dev->dev_major, "led_red",  &red_led_fops);
	if(led_dev->dev_major < 0)
	{
		printk("register_chrdev error\n");
		ret = -EINVAL;
		goto err_free;
	}
 
	// 2 ---自动创建设备节点
	led_dev->cls = class_create(THIS_MODULE,"led_red");
	if(IS_ERR(led_dev->cls))
	{
		printk("class_create error\n");
		ret = PTR_ERR(led_dev->cls);
		goto err_unregister;		
	}
 
	//创建一个设备节点
	led_dev->dev = device_create(led_dev->cls, NULL,MKDEV(led_dev->dev_major, 0), NULL, "led_red");
	if(IS_ERR(led_dev->dev))
	{
		printk("device_create error\n");
		ret = PTR_ERR(led_dev->dev);
		goto err_class_destroy;		
	}
 
	//返回值--映射之后的虚拟地址
	gpio1_1_conf = ioremap(0x12141400,16);
	gpio1_1_data = ioremap(0x12141008,8);

	*gpio1_1_conf |= (0x1<<1); //set pin out 
	*gpio1_1_data &= ~(0x1<<1); //set low off

	return 0;
 
err_class_destroy:
	class_destroy(led_dev->cls);
 
err_unregister:
	unregister_chrdev(led_dev->dev_major, "led_red");
 
err_free:
	kfree(led_dev);
	return ret;
}
static void __exit led_drv_exit(void)
{
	printk("%s\n", __FUNCTION__);
	*gpio1_1_data &= ~(0x1<<1); // close led
	iounmap(gpio1_1_conf);
	iounmap(gpio1_1_data);
	device_destroy(led_dev->cls, MKDEV(led_dev->dev_major, 0));	
	class_destroy(led_dev->cls);	
	unregister_chrdev(led_dev->dev_major, "led_red"); 
	kfree(led_dev);
}
module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");

二:app测试源码

1:可以在终端控制台输入:

echo 1 > /dev/led_red
echo 0 > /dev/led_red

2:app测试:提供三种方法
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/fs.h>
#include <linux/gpio.h>

#if 0

int main(int argc, char **argv)
{
    	int fd;
    	char* filename=NULL;
    	unsigned long arg;
	int ret = -1;

    	filename = argv[1];   
    	fd = open(filename, O_RDWR);
   	if (fd < 0)
    	{
        	printf("app open %s fail!\n", filename);
        	return 0;
    	}
   	else
    	{
		printf("app open led success %s!\r\n",filename);
    	}
	
    	if(!strcmp(argv[2], "on"))
	{
        	arg = 1;
		ret = ioctl(fd, 1, arg);
		if(ret < 0 )
        	printf("app oprate led on fail\r\n");
		else
		printf("app oprate led on success\r\n");
	}
	else if(!strcmp(argv[2], "off"))
	{
		arg = 1;
		ret = ioctl(fd, 0, arg);
		if(ret < 0 )
        	printf("app oprate led off fail\r\n");
		else
		printf("app oprate led off success\r\n");
	}
	close(fd);
   	return 0;
}

#elif 1

int main()
{
    	int fd0 = -1;
	int fd1 = -1;
    	char *filename0 = NULL;
	char *filename1 = NULL;
    	char buf[100]={0};
	int ret = -1;

    	filename0 = "/dev/led_green";
	filename1 = "/dev/led_red";   

	//led0
    	fd0 = open(filename0, O_RDWR);
   	if (fd0 < 0)
    	{
        	printf("app open %s fail\n", filename0);
        	return 0;
    	}
   	else
    	{
		printf("app open led success %s\r\n",filename0);
    	}
	//led1
	fd1 = open(filename1, O_RDWR);
   	if (fd1 < 0)
    	{
        	printf("app open %s fail\n", filename1);
        	return 0;
    	}
   	else
    	{
		printf("app open led success %s\r\n",filename1);
    	}
//led0 on
	memset(buf,0,sizeof(buf));
	buf[0]= '1';
    	ret = write(fd0,buf,1); 
	if(ret <= 0 )
        	printf("app write led fail\n");
    	sleep(1);
//led0 off
	memset(buf,0,sizeof(buf));
	buf[0]= '0';
	write(fd0,buf,1);   
	if(ret <= 0 )
        	printf("app write led fail\n");
	sleep(1);
//led0 on
	memset(buf,0,sizeof(buf));
	buf[0]= '1';
    	write(fd0,buf,1);  
	if(ret <= 0 )
        	printf("app write led fail\n");
	sleep(1);
//led0 off
	memset(buf,0,sizeof(buf));
	buf[0]= '0';
	write(fd0,buf,1);   
	if(ret <= 0 )
        	printf("app write led fail\n");
//sleep wait
	sleep(2);

//led1 on
	memset(buf,0,sizeof(buf));
	buf[0]= '1';
	write(fd1,buf,1);
	if(ret <= 0 )
        	printf("app write led fail\n");
	sleep(1);
//led1 off
	memset(buf,0,sizeof(buf));
	buf[0]= '0';
	write(fd1,buf,1);
	if(ret <= 0 )
        	printf("app write led fail\n");
	sleep(1);
//led1 on
	memset(buf,0,sizeof(buf));
	buf[0]= '1';
	write(fd1,buf,1);
	if(ret <= 0 )
        	printf("app write led fail\n");
	sleep(1);
//led1 off
	memset(buf,0,sizeof(buf));
	buf[0]= '0';
	write(fd1,buf,1);
	if(ret <= 0 )
        	printf("app write led fail\n");
//sleep wait
	sleep(2);

//led1 and led0 on
	write(fd1,"1",1);
    	write(fd0,"1",1);  
	sleep(2);

//led1 and led0 off
	write(fd1,"0",1);
    	write(fd0,"0",1);
	sleep(2);

//led1 and led0 on
	write(fd1,"on",2);
    	write(fd0,"on",2);  
	sleep(2);

//led1 and led0 off
	write(fd1,"off",3);
    	write(fd0,"off",3);  

	close(fd0);
	close(fd1);
   	return 0;
}

#elif 0

int main(int argc, char **argv)
{
    	int fd;
    	char* filename=NULL;
    	unsigned char buf[10]={0};
	int ret = -1;
	int i = 0;
    	filename = argv[1];   
    	fd = open(filename, O_RDWR);
   	if (fd < 0)
    	{
        	printf("app open %s fail\n", filename);
        	return 0;
    	}
   	else
    	{
		printf("app open led success %s\n",filename);
    	}
	
	while (1)
	{
		memset(buf, 0 , sizeof(buf));
		printf("请输入 on | off | quit \n");
		scanf("%s", buf);
		if (!strcmp(buf, "on"))
		{
			write(fd, "1", 1);
		}
		else if (!strcmp(buf, "off"))
		{
			write(fd, "0", 1);
		}
		else if (!strcmp(buf, "flash"))
		{
			for (i=0; i<3; i++)
			{
				write(fd, "1", 1);
				sleep(1);
				write(fd, "0", 1);
				sleep(1);
			}
		}	
		else if (!strcmp(buf, "quit"))
		{
			break;
		}
	}

	close(fd);
   	return 0;
}

#endif

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值