基于gpio的子系统编写led的驱动和应用程序测试

myled.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define LED_ON   _IOW('l',1,int)
#define LED_OFF  _IOW('l',0,int)

int major;
struct class *cls;
struct device *dev;
struct device_node *dnode;
struct gpio_desc *gpiono0,*gpiono1,*gpiono2; 
char kbuf[128]={0};

int mycdev_open(struct inode *inode,struct file *file)
{
	printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
	return 0;
}

long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	
    switch (cmd)
    {
    case LED_ON: // 开灯
		gpiod_set_value(gpiono0,1);
		gpiod_set_value(gpiono1,1);
		gpiod_set_value(gpiono2,1);
		break;
    case LED_OFF: // 关灯
        gpiod_set_value(gpiono0,0);
		gpiod_set_value(gpiono1,0);
		gpiod_set_value(gpiono2,0);
        break;
    }
    return 0;
}

int mycdev_close(struct inode *inode,struct file *file)
{
	printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
	return 0;
}

//定义一个操作方法结构体对象并且初始化
struct file_operations fops = {
	.open=mycdev_open,
	.unlocked_ioctl = mycdev_ioctl,
	.release=mycdev_close,
};

static int __init mycdev_init(void)
{
	//字符设备驱动注册
	major = register_chrdev(0,"myled",&fops);
	if(major < 0)
	{
		printk("字符设备驱动注册失败\n");
		return major;
	}
	printk("字符设备驱动注册成功:major=%d\n",major);

	//向上提交目录
	cls = class_create(THIS_MODULE,"myled");
	if(IS_ERR(cls))
	{
		printk("向上提交目录失败\n");
		return -PTR_ERR(cls);
	}
	printk("向上提交目录成功\n");

	//向上提交设备节点的信息
	int i;
	for(i=0;i<3;i++)
	{
		dev=device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);
		if(IS_ERR(dev))
		{
			printk("向上提交设备节点的信息失败\n");
			return -PTR_ERR(dev);
		}
	}
	printk("向上提交设备节点信息成功\n");

    //解析LED的设备树节点
    dnode=of_find_node_by_path("/myled");
    if(dnode==NULL)
    {
        printk("解析设备树节点失败\n");
        return -ENXIO;
    }
    printk("解析GPIO信息成功\n");
    //申请gpio对象
    gpiono0=gpiod_get_from_of_node(dnode,"led1-gpio",0,GPIOD_OUT_LOW,NULL);
	gpiono1=gpiod_get_from_of_node(dnode,"led2-gpio",0,GPIOD_OUT_LOW,NULL);
	gpiono2=gpiod_get_from_of_node(dnode,"led3-gpio",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono0) || IS_ERR(gpiono1) ||IS_ERR(gpiono2))
    {
        printk("申请gpio对象失败\n");
        return -ENXIO;
    }
    printk("申请gpio信息对象成功\n");
    
	return 0;
}
static void __exit mycdev_exit(void)
{
	//销毁设备节点信息
	int i;
	for(i=0;i<3;i++)
	{
		device_destroy(cls,MKDEV(major,i));
	}
	//销毁目录信息
	class_destroy(cls);
	//注销字符设备驱动
	unregister_chrdev(major,"myled");
    //灭灯
    gpiod_set_value(gpiono0,0);
	gpiod_set_value(gpiono1,0);
	gpiod_set_value(gpiono2,0);
    //释放gpio编号
    gpiod_put(gpiono0);
	gpiod_put(gpiono2); 
	gpiod_put(gpiono1);

}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

app.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define LED_ON  _IOW('l',1,int)
#define LED_OFF _IOW('l',0,int)

int main(int argc, const char *argv[])
{
	int fd,a;
    char buf[128]={0};

    // 打开设备节点
    fd = open("/dev/myled0", O_RDWR);
    if (fd < 0) 
	{
        printf("设备文件打开失败\n");
		exit(-1);
    }
	while(1)
	{
    	printf("亲输入对LED灯的控制:1(开灯)0(关灯)\n");
		scanf("%d",&a);
		switch(a)
		{
			case 1:
				ioctl(fd,LED_ON);
				break;
			case 0:
				ioctl(fd,LED_OFF);

		}
	
	}
    close(fd);
	return 0;
}

你可能感兴趣的:(嵌入式,c语言)