基于迅为4412的一个GPIO输出高低电平的驱动

前言:

为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长。

基于迅为4412的一个GPIO输出高低电平的驱动_第1张图片


窗外的天空不再湛蓝,我知道北京的冬天快要来了,自己也即将走上一段新的旅途。过去的时光如民大秋天的银杏叶,静静的飘落,随风而来,随风而逝。

最近在实验室调试一个语音模块,就用GPIO做了一个数据接收的开关。参考网上的资料弄了一个输出高低电平的驱动。
驱动程序:

/*包含初始化宏定义的头文件,代码中的module_init和module_exit在此文件中*/
#include 
/*包含初始化加载模块的头文件,代码中的MODULE_LICENSE在此头文件中*/
#include 
/*三个字符设备函数*/
#include 
/*定义字符设备的结构体*/
#include 
/*分配内存空间函数头文件*/
#include 
/*定义module_param module_param_array中perm的头文件*/
#include 
/*MKDEV转换设备号数据类型的宏定义*/
#include 
/*字符定义*/
#include 
/*linux系统提供的申请端口函数和设置端口状态的函数*/
#include 
/*设置GPIO状态,上下拉,输入输出就,复用等等相关函数*/
#include 		
/*包含GPIO端口的宏定义*/
#include 
#include 
/*dev_t等的定义*/
#include 
/*包含copy_to_user和copy_from_user的头文件*/
#include 
/*包含寄存器操作函数的头文件*/
#include 
/*延时定义*/
#include 
/*包含函数device_create 结构体class等头文件*/
#include 
/*错误诊断和输出需要的头文件*/
#include 

#define PT (EXYNOS4_GPA0(7))/*4412开发板的gpio部分,gpio第13引脚,控制总线*/
#define PORT_MAJOR 245
#define PORT_MINOR 0
#define DEVICE_NAME "gpio_hl"
#define IO_WRITE  0
#define IO_READ   1

static int pt_major = PORT_MAJOR;
static int pt_minor = PORT_MINOR;
/*字符设备结构体*/
struct elec_cdev{
	struct cdev cdev;
};
struct elec_cdev *dev;

static struct class *pt_class;
static char gpio_devices[220];

static gpio_open(struct inode *inode,struct file *flip)
{
	int minor,ret;
	
	ret = gpio_request(PT, "PT_CTRL");
	if(ret<0){
		printk("gpio_request is failed!\n");
		return ret;
	}
	minor = MINOR(inode->i_rdev);
	s3c_gpio_cfgpin(PT,S3C_GPIO_OUTPUT);	/*设置为输出*/
	gpio_set_value(PT,0);
	gpio_devices[minor]++;
	return 0;
}

static int gpio_release(struct inode *inode,struct file *flip)
{
	int minor;
	
	minor = MINOR(inode->i_rdev);
	if(gpio_devices[minor])
		gpio_devices[minor]--;
	/*释放gpiio*/
	gpio_free(PT);
	printk("gpio_release is success!\n");
	return 0;
}

static long gpio_ioctl(struct inode *inode, struct file *flip,unsigned int cmd, unsigned long arg)
{
	switch(cmd){
		case IO_WRITE:
			gpio_set_value(PT,0);	/*输出低电平*/
			break;
		case IO_READ:
			gpio_set_value(PT,1);	/*输出高电平*/
			break;
	}
	return 0;
}

static struct file_operations gpio_fops = {
	.owner			= THIS_MODULE,
	.open			= gpio_open,
	.release	    = gpio_release,
	.unlocked_ioctl = gpio_ioctl,
};

static int __init gpio_init (void)
{
	int ret = 0;
	dev_t pt_dev;
	
	pt_dev = MKDEV(PORT_MAJOR,PORT_MINOR);
	ret = register_chrdev_region(pt_dev,1,DEVICE_NAME);
	dev = kmalloc(sizeof(struct elec_cdev),GFP_KERNEL);
	memset(dev,0,sizeof(struct elec_cdev));
	pt_class = class_create(THIS_MODULE,DEVICE_NAME);
	cdev_init(&dev->cdev,&gpio_fops);	/*字符设备注册三部曲*/
	dev->cdev.owner = THIS_MODULE;
	dev->cdev.ops   = &gpio_fops;
	ret = cdev_add(&dev->cdev,MKDEV(pt_major,pt_minor),1);
	device_create(pt_class,NULL,MKDEV(pt_major,pt_minor),NULL,DEVICE_NAME);	/*创建设备节点*/
	
	printk(KERN_EMERG "gpio init!\n");
	return 0;
}

static void __exit gpio_exit(void)
{
	/*摧毁设备节点*/
	device_destroy(pt_class,MKDEV(pt_major,pt_minor));
	/*注销设备*/
	cdev_del(&dev->cdev);
	/*释放总线*/
	class_destroy(pt_class);
	/*释放内存*/
	kfree(dev);
	/*注销设备号*/
	unregister_chrdev_region(MKDEV(pt_major,pt_minor),1);
	
	printk(KERN_EMERG "gpio exit!\n");
}

module_init(gpio_init);
module_exit(gpio_exit);

MODULE_AUTHOR("star sky");/*作者*/
MODULE_DESCRIPTION("ITOP4412 Gpio driver:high or low level");/*模块功能描述*/
MODULE_LICENSE("Dual BSD/GPL");/*开源声明*/
MODULE_VERSION("V1.0");/*代码修订版本*/

测试代码:

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

#define PATH "/dev/gpio_hl"
#define IO_WRITE  0
#define IO_READ   1

int main()
{
	int fd;
	int val = -1;
	
	if((fd = open(PATH,O_RDWR|O_NOCTTY|O_NDELAY|O_NONBLOCK))<0){
		perror("open gpio is failea!\n");
		exit(1);
	}
	else{
		printf("open gpio is success!\n");
		while(1){
			printf("0:low,1:high,2:quit:");
			scanf("%d",&val);
			if(val == 0)
				ioctl(fd,IO_READ,0);
			else if(val == 1)
				ioctl(fd,IO_WRITE,1);
			else if(val == 2){
				close(fd);
				exit(1);
			}
		}
	}
}

注:参考 [http://www.dzkf.cn/html/qianrushixitong/2008/0318/3043.html]

你可能感兴趣的:(Linux驱动学习)