微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 跟着小狂玩RicoBoard之三种方法玩转GPIO第二篇

跟着小狂玩RicoBoard之三种方法玩转GPIO第二篇

时间:10-02 整理:3721RD 点击:

上一篇帖子已经把官方提供的历程解释了一遍,这一篇帖子我们直接调用公用的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啊,分别对应就行了。下一篇我们讲怎么在驱动中使用物理地址映射。

附代码如下

  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. #include
  10. #define GPIO_SIZE 0X1000
  11. #define GPIO_MAJOR 233

  12. static int gpio_major=GPIO_MAJOR;
  13. struct gpio_dev{
  14.         struct cdev cdev;
  15.         uint8_t value;
  16. };
  17. struct gpio_dev *gpio_devp;
  18. MODULE_AUTHOR("Xiaokuang ");
  19. MODULE_LICENSE("GPL v2");
  20. static int gpio_open(struct inode *inode,struct file *filp)
  21. {
  22.         struct gpio_dev *dev;
  23.         dev=container_of(inode->i_cdev,struct gpio_dev,cdev);
  24.         filp->private_data=dev;
  25. //        filp->private_data=gpio_devp;
  26.         printk(KERN_NOTICE "open ok\n");        
  27.         return 0;
  28. }
  29. int gpio_release(struct inode *inode , struct file *filp)
  30. {
  31.         return 0;
  32. }
  33. ssize_t gpio_write(struct file *filp,const char __user *buf ,size_t count,loff_t *f_pos)
  34. {
  35.         struct gpio_dev *dev=filp->private_data;
  36. //        printk(KERN_NOTICE "write ok\n");
  37.         if(copy_from_user(&(dev->value),buf,1))
  38.                 return -EFAULT;
  39.         if(dev->value=='0'){
  40.                 gpio_set_value(57,1);
  41.                 printk(KERN_NOTICE "gpio off %c\n",*buf);
  42.         } else if(dev->value == '1') {
  43.                 gpio_set_value(57,0);
  44.                 printk(KERN_NOTICE "gpio on %c\n",*buf);
  45.         }
  46.         return 1;
  47. }
  48. ssize_t gpio_read(struct file *filp,char __user *buf ,size_t count,loff_t *f_pos)
  49. {
  50.         struct gpio_dev *dev=filp->private_data;
  51.         if(copy_to_user(buf,&(dev->cdev),1))
  52.                 return -EFAULT;
  53.         return 1;
  54. }
  55. //int gpio_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
  56. //{
  57. //        struct gpio_dev *dev=filp->private_data;
  58. //        return 0;
  59. //}
  60. //
  61. struct file_operations gpio_fops = {
  62.         .owner=THIS_MODULE,
  63.         .open=gpio_open,
  64.         .release=gpio_release,
  65.         .write=gpio_write,
  66.         .read=gpio_read,
  67. };
  68. void gpio_setup_cdev(struct gpio_dev *dev ,int index)
  69. {
  70.         int err;
  71.         dev_t devno=MKDEV(gpio_major,index);
  72.         cdev_init(&dev->cdev,&gpio_fops);
  73.         dev->cdev.owner=THIS_MODULE;
  74.         dev->cdev.ops=&gpio_fops;
  75.         err=cdev_add(&dev->cdev,devno,1);
  76.         if(err)
  77.               printk(KERN_NOTICE "Error %d adding GPIO %d",err,index);
  78. }
  79. static int __init gpio_init(void)
  80. {
  81.         int result;
  82.         int a=0;
  83.         dev_t dev=MKDEV(gpio_major,0);
  84.         if(gpio_major)
  85.                result=register_chrdev_region(dev,1,"led");
  86.         else {
  87.                 result=alloc_chrdev_region(&dev,0,1,"led");
  88.                 gpio_major=MAJOR(dev);
  89.         }
  90.         if(result cdev);
  91.         kfree(gpio_devp);
  92.         unregister_chrdev_region(MKDEV(gpio_major,0),1);
  93.         gpio_free(57);
  94.         printk(KERN_NOTICE "exit ok\n");
  95. }
  96. module_init(gpio_init);
  97. module_exit(gpio_clean_up);

复制代码


小狂出品,必须精品

小编真会玩

哈哈,小狂的口号啊,必须的,哈哈,谢谢支持

玩就玩点不一样的吗,这才对得起玩啊

高手!
谢谢分享!

兜纳K1

谢谢支持

论坛的原创担当啊~

谢谢小编大人夸奖,哈哈

小编我问个问题 我照着你的Makefile写的 我把pwm-ehrpwm.c 复制过去了  然后make报了好几篇的错误 是怎么内核目录的Makefile不一样吗 我的也是自带的 不应该啊

对,要指向你的内核的目录,另外,你的内核要编译一下

谢谢小编 我的Makefile写的不对 改了就好了
再问一下 我是3.12内核 PWM用不了 该设备树没效果 用.ko文件insmod不了 你的能用吗

我的板子被收回了,嘿嘿,就没有玩,嘻嘻,应该只是支持的,insmod肯定可以的

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top