一:驱动源码:提供读写方法,用于测试
/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