跟着小狂玩RicoBoard之三种方法玩转GPIO第二篇
上一篇帖子已经把官方提供的历程解释了一遍,这一篇帖子我们直接调用公用的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文档。
我们在注册模块的时候应该注册IO,看下图
然后在移除模块的时候应该释放IO
这里我们事先在控制台的输出控制,不需要ioctl,先不实现,当我们往设备节点中写字符1的时候,io设置为0,开灯,同时打印信息,写0的时候关灯,同时打印信息,只需要事先写函数就行。
驱动程序,实现后,我们应该在内核中编译,makefile文件如下图所示,这个make文件只适合一个.c文档的编译,不适合多个.c,下一篇帖子会说多个.c的makefile,其中KERNELDIR指定你的内核主Makefile所在的目录。
在虚拟机中进入到你的make所在目录,然后执行make,编译完成如下图所示
然后我们把程序下载到开发板中,导入模块
查看我们的驱动有没有导入到内核
可以看到我们的主设备号为233,然后在驱动文件中建立设备节点
查看一下设备节点有没有成功建立
然后我们点亮LED
在这里就不上实物图啦,结果跟上一篇帖子一样
然后,我们让灯关了
总结
到这里,我们在驱动层控制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 ok\n");
- 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 ok\n");
- if(copy_from_user(&(dev->value),buf,1))
- return -EFAULT;
- if(dev->value=='0'){
- gpio_set_value(57,1);
- printk(KERN_NOTICE "gpio off %c\n",*buf);
- } else if(dev->value == '1') {
- gpio_set_value(57,0);
- printk(KERN_NOTICE "gpio on %c\n",*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 cdev);
- kfree(gpio_devp);
- unregister_chrdev_region(MKDEV(gpio_major,0),1);
- gpio_free(57);
- printk(KERN_NOTICE "exit ok\n");
- }
- module_init(gpio_init);
- module_exit(gpio_clean_up);
小狂出品,必须精品
小编真会玩
哈哈,小狂的口号啊,必须的,哈哈,谢谢支持
玩就玩点不一样的吗,这才对得起玩啊
高手!
谢谢分享!
兜纳K1
谢谢支持
论坛的原创担当啊~
谢谢小编大人夸奖,哈哈
小编我问个问题 我照着你的Makefile写的 我把pwm-ehrpwm.c 复制过去了 然后make报了好几篇的错误 是怎么内核目录的Makefile不一样吗 我的也是自带的 不应该啊
对,要指向你的内核的目录,另外,你的内核要编译一下
谢谢小编 我的Makefile写的不对 改了就好了
再问一下 我是3.12内核 PWM用不了 该设备树没效果 用.ko文件insmod不了 你的能用吗
我的板子被收回了,嘿嘿,就没有玩,嘻嘻,应该只是支持的,insmod肯定可以的