上一篇帖子已经把官方提供的历程解释了一遍,这一篇帖子我们直接调用公用的GPIO接口库gpiolib.c,实现我们的控制功能。米尔科技提供的内核已经吧RicoBoard的GPIO操作和gpiolib连接起来啦,具体怎么连接,在这篇帖子里小狂就不做详细的描述了,这是一个非常复杂的过程,看的我也是头晕脑胀各种赋值操作,各种跳转。有兴趣的童鞋可以参考一下这篇帖子, http://weimenlove.blog.163.com/blog/static/1777547320139251031924/ 讲的非常之详细,能让你更加清晰内核的调用过程。我们要做的就是在我们的驱动程序中,调用gpiolib.c库中的内容,然后实现IO的拉高和拉低操作。其实米尔提供的内核文件也是基于ti的,我们从TI的官网上,可以直接找到他们GPIO的调用过程。
上一篇帖子我们直接用到的就是User Layer层来控制我们的GPIO ,这一节小狂主要就是带大家在GPIO 的字符驱动层调用gpiolib.c中的函数来实现IO的控制。 static inline int gpio_request(unsignedgpio, const char *label); 其中gpio为请求的io号在内核中的表达形式,跟上一节的计算方式一致GPIO5_9=5*32+9=169,GPIO1_25=1*32+25=57。Lable是你为申请的GPIO起一个名字。 static inline void gpio_free(unsigned gpio); 有申请就要有释放,这个在驱动编程中应该要养成的一个好习惯,这个函数的作用就是释放你刚才申请的IO号。 int gpio_direction_input(unsigned gpio); int gpio_direction_output(unsigned gpio,int value); 这两个函数是设置GPIO为输入还是输出状态,当设置为输出的时候,可以指定初始时为高电平还是低电平。 static inline void gpio_set_value(unsignedint gpio, int value); 设置当前GPIO的输出状态,这次驱动中对GPIO的控制主要为输出控制,小狂在这里只介绍输出。如果还想了解更多的gpiolib中函数的使用方法,可以查看documentat文件夹里gpio.txt文档。
这里我们事先在控制台的输出控制,不需要ioctl,先不实现,当我们往设备节点中写字符1的时候,io设置为0,开灯,同时打印信息,写0的时候关灯,同时打印信息,只需要事先写函数就行。
驱动程序,实现后,我们应该在内核中编译,makefile文件如下图所示,这个make文件只适合一个.c文档的编译,不适合多个.c,下一篇帖子会说多个.c的makefile,其中KERNELDIR指定你的内核主Makefile所在的目录。
在虚拟机中进入到你的make所在目录,然后执行make,编译完成如下图所示
可以看到我们的主设备号为233,然后在驱动文件中建立设备节点
到这里,我们在驱动层控制LED的想法已经实现,其实吧,这种控制方式,是我们自己调用内核中GPIO驱动,就是上边说的那些函数,上一节是在系统中往文件中写内容,其实也是调用的那些函数,什么export啊,direction啊,分别对应就行了。下一篇我们讲怎么在驱动中使用物理地址映射。 附代码如下
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define GPIO_SIZE 0X1000
- #define GPIO_MAJOR 233
- static int gpio_major=GPIO_MAJOR;
- struct gpio_dev{
- struct cdev cdev;
- uint8_t value;
- };
- struct gpio_dev *gpio_devp;
- MODULE_AUTHOR("Xiaokuang ");
- MODULE_LICENSE("GPL v2");
- static int gpio_open(struct inode *inode,struct file *filp)
- {
- struct gpio_dev *dev;
- dev=container_of(inode->i_cdev,struct gpio_dev,cdev);
- filp->private_data=dev;
- // filp->private_data=gpio_devp;
- printk(KERN_NOTICE "open okn");
- return 0;
- }
- int gpio_release(struct inode *inode , struct file *filp)
- {
- return 0;
- }
- ssize_t gpio_write(struct file *filp,const char __user *buf ,size_t count,loff_t *f_pos)
- {
- struct gpio_dev *dev=filp->private_data;
- // printk(KERN_NOTICE "write okn");
- if(copy_from_user(&(dev->value),buf,1))
- return -EFAULT;
- if(dev->value=='0'){
- gpio_set_value(57,1);
- printk(KERN_NOTICE "gpio off %cn",*buf);
- } else if(dev->value == '1') {
- gpio_set_value(57,0);
- printk(KERN_NOTICE "gpio on %cn",*buf);
- }
- return 1;
- }
- ssize_t gpio_read(struct file *filp,char __user *buf ,size_t count,loff_t *f_pos)
- {
- struct gpio_dev *dev=filp->private_data;
- if(copy_to_user(buf,&(dev->cdev),1))
- return -EFAULT;
- return 1;
- }
- //int gpio_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
- //{
- // struct gpio_dev *dev=filp->private_data;
- // return 0;
- //}
- //
- struct file_operations gpio_fops = {
- .owner=THIS_MODULE,
- .open=gpio_open,
- .release=gpio_release,
- .write=gpio_write,
- .read=gpio_read,
- };
- void gpio_setup_cdev(struct gpio_dev *dev ,int index)
- {
- int err;
- dev_t devno=MKDEV(gpio_major,index);
- cdev_init(&dev->cdev,&gpio_fops);
- dev->cdev.owner=THIS_MODULE;
- dev->cdev.ops=&gpio_fops;
- err=cdev_add(&dev->cdev,devno,1);
- if(err)
- printk(KERN_NOTICE "Error %d adding GPIO %d",err,index);
- }
- static int __init gpio_init(void)
- {
- int result;
- int a=0;
- dev_t dev=MKDEV(gpio_major,0);
- if(gpio_major)
- result=register_chrdev_region(dev,1,"led");
- else {
- result=alloc_chrdev_region(&dev,0,1,"led");
- gpio_major=MAJOR(dev);
- }
- if(result<0)
- return result;
- gpio_devp=kmalloc(sizeof(struct gpio_dev),GFP_KERNEL);
- if(!gpio_devp){
- result= -ENOMEM;
- goto failmalloc;
- }
- memset(gpio_devp,0,sizeof(struct gpio_dev));
- gpio_setup_cdev(gpio_devp,0);
- printk(KERN_NOTICE "init okn");
- //gpio ini
- a=gpio_request(57,"test_led");
- if(a)
- printk(KERN_NOTICE "gpio request failed %dn",a);
- else {
- gpio_direction_output(57,1);
- }
- return 0;
- failmalloc:
- unregister_chrdev_region(MKDEV(gpio_major,0),1);
- return result;
- }
- static void __exit gpio_clean_up(void)
- {
- cdev_del(&gpio_devp->cdev);
- kfree(gpio_devp);
- unregister_chrdev_region(MKDEV(gpio_major,0),1);
- gpio_free(57);
- printk(KERN_NOTICE "exit okn");
- }
- module_init(gpio_init);
- module_exit(gpio_clean_up);
复制代码
1
|
|
|
|