应用层写程序控制6盏灯亮灭,要求使用GPIO子系统
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/cdev.h>
#include "led.h"
#define CNAME "myled"
/* myleds{
myled1=<&gpioe 10 0>;
myled2=<&gpiof 10 0>;
myled3=<&gpioe 8 0>;
myled4=<&gpioz 5 0>;
myled5=<&gpioz 6 0>;
myled6=<&gpioz 7 0>;
};
*/
char kbuf[128]={0};
//定义指向获取的设备树节点信息空间
struct device_node *node;
struct gpio_desc* gpiono1;//用于接收gpio编号
struct gpio_desc* gpiono2;
struct gpio_desc* gpiono3;
struct gpio_desc* gpiono4;
struct gpio_desc* gpiono5;
struct gpio_desc* gpiono6;
int ret;
struct cdev* cdev;
struct class *cls;
struct device* dev;
#if 1
unsigned int major=0;
#else
unsigned int majo=500;
#endif
int minor=0;
const int count=6;
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)
{
int whitch;
int ret;
switch(cmd)
{
case LED_ON:
ret=copy_from_user(&whitch,(void*)arg,sizeof(int));
if(ret)
{
printk("copy from user led on!!!!\n");
}
switch(whitch)
{
case LED1:
gpiod_set_value(gpiono1,1);
break;
case LED2:
gpiod_set_value(gpiono2,1);
break;
case LED3:
gpiod_set_value(gpiono3,1);
break;
case LED4:
gpiod_set_value(gpiono4,1);
break;
case LED5:
gpiod_set_value(gpiono5,1);
break;
case LED6:
gpiod_set_value(gpiono6,1);
break;
}
break;
case LED_OFF:
ret=copy_from_user(&whitch,(void*)arg,sizeof(int));
if(ret)
{
printk("copy from user led off!!!!\n");
}
switch(whitch)
{
case LED1:
gpiod_set_value(gpiono1,0);
break;
case LED2:
gpiod_set_value(gpiono2,0);
break;
case LED3:
gpiod_set_value(gpiono3,0);
break;
case LED4:
gpiod_set_value(gpiono4,0);
break;
case LED5:
gpiod_set_value(gpiono5,0);
break;
case LED6:
gpiod_set_value(gpiono6,0);
break;
}
break;
}
return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
const struct file_operations fops={
.open=mycdev_open,
.unlocked_ioctl = mycdev_ioctl,
.release=mycdev_close,
};
static int __init mycdev_init(void)
{
dev_t devno;
int i;
//通过路径获取设备树节点信息
node=of_find_node_by_path("/myleds");
if(node==NULL)
{
printk("通过路径解析设备树节点失败\n");
return -EFAULT;
}
printk("成功解析设备树节点\n");
//获取申请gpio编号
gpiono1=gpiod_get_from_of_node(node,"myled1",0,GPIOD_OUT_LOW,NULL);
if(IS_ERR(gpiono1))
{
printk("获取gpio1编号失败\n");
return PTR_ERR(gpiono1);
}
gpiono2=gpiod_get_from_of_node(node,"myled2",0,GPIOD_OUT_LOW,NULL);
if(IS_ERR(gpiono2))
{
printk("获取gpio2编号失败\n");
return PTR_ERR(gpiono2);
}
gpiono3=gpiod_get_from_of_node(node,"myled3",0,GPIOD_OUT_LOW,NULL);
if(IS_ERR(gpiono3))
{
printk("获取gpio3编号失败\n");
return PTR_ERR(gpiono3);
}
gpiono4=gpiod_get_from_of_node(node,"myled4",0,GPIOD_OUT_LOW,NULL);
if(IS_ERR(gpiono4))
{
printk("获取gpio4编号失败\n");
return PTR_ERR(gpiono4);
}
gpiono5=gpiod_get_from_of_node(node,"myled5",0,GPIOD_OUT_LOW,NULL);
if(IS_ERR(gpiono5))
{
printk("获取gpio5编号失败\n");
return PTR_ERR(gpiono5);
}
gpiono6=gpiod_get_from_of_node(node,"myled6",0,GPIOD_OUT_LOW,NULL);
if(IS_ERR(gpiono6))
{
printk("获取gpio编号失败\n");
return PTR_ERR(gpiono6);
}
printk("获取gpio编号成功\n");
//设置管脚为输出
gpiod_direction_output(gpiono1,0);
gpiod_direction_output(gpiono2,0);
gpiod_direction_output(gpiono3,0);
gpiod_direction_output(gpiono4,0);
gpiod_direction_output(gpiono5,0);
gpiod_direction_output(gpiono6,0);
//点亮led
//gpiod_set_value(gpiono,1);
//1.分配cdev结构体
cdev=cdev_alloc();
if(NULL==cdev)
{
printk("cdev alloc is error\n");
ret=-EIO;
goto ERR1;
}
//2.初始化结构体
cdev_init(cdev,&fops);
//3.申请设备号
if(major>0)
{
//静态指定设备号
ret=register_chrdev_region(MKDEV(major,minor),count,CNAME);
if(ret)
{
printk("register chrdev region is error\n");
ret = -ENOMEM;
goto ERR2;
}
}
else{
//动态申请设备号
ret=alloc_chrdev_region(&devno,0,count,CNAME);
if(ret)
{
printk("alloc chrdev region is error\n");
ret = -ENOMEM;
goto ERR2;
}
//获取主设备号
major=MAJOR(devno);
//获取次设备号
minor=MINOR(devno);
}
//4.驱动的注册
ret=cdev_add(cdev,MKDEV(major,minor),count);
if(ret)
{
printk("cdev add is error\n");
ret = -EIO;
goto ERR3;
}
//5.自动创建设备节点
//向上层提交目录信息
cls=class_create(THIS_MODULE,CNAME);
if(IS_ERR(cls))
{
printk("class create is error\n");
ret=PTR_ERR(cls);
goto ERR4;
}
//向上层提交设备节点信息
for(i=0;i<count;i++)
{
dev=device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);
if(IS_ERR(dev))
{
printk("device create is error\n");
ret=PTR_ERR(dev);
goto ERR5;
}
}
return 0;
ERR5:
for(--i;i>=0;i--)
{
device_destroy(cls,MKDEV(major,i));
}
class_destroy(cls);
ERR4:
cdev_del(cdev);
ERR3:
unregister_chrdev_region(MKDEV(major,minor),count);
ERR2:
kfree(cdev);
ERR1:
return -EIO;
}
static void __exit mycdev_exit(void)
{
int i;
//1.销毁设备节点信息
for(i=0;i<count;i++)
{
device_destroy(cls,MKDEV(major,i));
}
//2.销毁目录信息
class_destroy(cls);
//3.驱动的注销
cdev_del(cdev);
//4.销毁设备号
unregister_chrdev_region(MKDEV(major,minor),count);
//5.释放cdev结构体
kfree(cdev);
gpiod_set_value(gpiono1,0);
gpiod_set_value(gpiono2,0);
gpiod_set_value(gpiono3,0);
gpiod_set_value(gpiono4,0);
gpiod_set_value(gpiono5,0);
gpiod_set_value(gpiono6,0);
//释放
gpiod_put(gpiono1);
gpiod_put(gpiono2);
gpiod_put(gpiono3);
gpiod_put(gpiono4);
gpiod_put(gpiono5);
gpiod_put(gpiono6);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
#ifndef __LED_H__
#define __LED_H__
typedef enum{
LED1,
LED2,
LED3,
LED4,
LED5,
LED6
}led_t;
#define LED_ON _IOW('a',1,int)
#define LED_OFF _IOW('a',0,int)
#endif
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include "led.h"
char buf[128]="";
int main(int argc, char const *argv[])
{
int fd1=-1;
int fd2=-1;
int fd3=-1;
int fd4=-1;
int fd5=-1;
int fd6=-1;
int whitch;
fd1=open("/dev/myled0",O_RDWR);
fd2=open("/dev/myled1",O_RDWR);
fd3=open("/dev/myled2",O_RDWR);
fd4=open("/dev/myled3",O_RDWR);
fd5=open("/dev/myled4",O_RDWR);
fd6=open("/dev/myled5",O_RDWR);
if(-1==fd1)
{
perror("open is error");
exit(1);
}
while(1)
{
whitch =LED1;
ioctl(fd1,LED_ON,&whitch);
sleep(1);
ioctl(fd1,LED_OFF,&whitch);
sleep(1);
whitch = LED2;
ioctl(fd2,LED_ON,&whitch);
sleep(1);
ioctl(fd2,LED_OFF,&whitch);
sleep(1);
whitch = LED3;
ioctl(fd3,LED_ON,&whitch);
sleep(1);
ioctl(fd3,LED_OFF,&whitch);
sleep(1);
whitch =LED4;
ioctl(fd4,LED_ON,&whitch);
sleep(1);
ioctl(fd4,LED_OFF,&whitch);
sleep(1);
whitch = LED5;
ioctl(fd5,LED_ON,&whitch);
sleep(1);
ioctl(fd5,LED_OFF,&whitch);
sleep(1);
whitch = LED6;
ioctl(fd6,LED_ON,&whitch);
sleep(1);
ioctl(fd6,LED_OFF,&whitch);
sleep(1);
}
return 0;
}