为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长。
窗外的天空不再湛蓝,我知道北京的冬天快要来了,自己也即将走上一段新的旅途。过去的时光如民大秋天的银杏叶,静静的飘落,随风而来,随风而逝。
最近在实验室调试一个语音模块,就用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]