Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1222226
  • 博文数量: 105
  • 博客积分: 127
  • 博客等级: 入伍新兵
  • 技术积分: 962
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-29 15:22
文章分类

全部博文(105)

文章存档

2021年(1)

2019年(3)

2018年(1)

2017年(11)

2016年(47)

2015年(32)

2014年(4)

2012年(6)

我的朋友

分类: 嵌入式

2015-09-21 10:19:42

   在工业控制中,GPIO口用作DO,DI的情况非常多,所以常常不|厌其烦的改写DO,DI的字符设备驱动。虽然改起来很快,但是感觉很多时候都是重复的工作。
最近把它整理成了一个模板,最后在我所使用的这种厂家的
ARM体系架构下的芯片只需要填写一个数组就OK,想想这些也是没有办法更简单了。

  由于以前的GPIO口相关的驱动,我都是采用的Platform 平台的。driver device分开的思想还是很不错的,但是对GPIO这种简单的驱动来说,就整得有点复
杂了。我想这也是
MISC 设备驱动模型存在的原因,以前有简单分析过MISC 驱动模型,如下链接:

http://blog.chinaunix.net/uid-20768928-id-3423500.html

  整理过程我最后还是选择采用MISC模型,因为能在一个文件中搞定,这样改起来也方便。
  MISC 的优点就是设备节点创建简单,主次设备号申请简单,driverdevice在同一个文件中就可以搞定。

 
 
整理后的GPIO DODI驱动源码demo如下:linux_dodi_misc_model.rar

点击(此处)折叠或打开

  1. #include <linux/gpio.h>
  2. #include <linux/io.h>
  3. #include <linux/ioport.h>
  4. #include <linux/module.h>
  5. #include <linux/slab.h>
  6. #include <linux/delay.h>
  7. #include <linux/fcntl.h>
  8. #include <linux/cdev.h>
  9. #include <asm/uaccess.h>
  10. #include <asm/system.h>
  11. #include <asm/io.h>
  12. #include <linux/kernel.h>
  13. #include <linux/fs.h>
  14. #include <linux/init.h>
  15. #include <linux/device.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/ioctl.h>

  18. #include <linux/miscdevice.h>
  19. #include <asm/uaccess.h>


  20. /*********************************************/
  21. #include <mach/pinctrl.h>
  22. #include "mach/mx28_pins.h"
  23. /*********************************************/


  24. //#define xxx_DEBUG
  25. #undef PDEBUG /* undef it, just in case */
  26. #ifdef xxx_DEBUG
  27. #ifdef __KERNEL__
  28.      /* This one if debugging is on, and kernel space */
  29. #define PDEBUG(fmt, args...) printk( KERN_EMERG "xxx: " fmt, ## args)
  30. #else
  31.      /* This one for user space */
  32. #define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
  33. #endif
  34. #else
  35. #define PDEBUG(fmt, args...) /* not debugging: nothing */
  36. #endif


  37. #define MCU_DIDO_IOC_MAGIC 'd'

  38. #define         IO_GPIO_SET_OUTPUT _IO(MCU_DIDO_IOC_MAGIC,0)
  39. #define         IO_GPIO_RSEET_OUTPUT _IO(MCU_DIDO_IOC_MAGIC,1)
  40. #define     IO_GPIO_GET_INPUT _IOR(MCU_DIDO_IOC_MAGIC,2,int)

  41. #define PINID_PCM_SYNC MXS_PIN_ENCODE(3,21)
  42. #define PINID_PCM_DOUT MXS_PIN_ENCODE(3,26)
  43. #define PINID_PCM_DIN MXS_PIN_ENCODE(3,23)
  44. #define PINID_PCM_CLK MXS_PIN_ENCODE(3,22)

  45. #define PINID_LCD_08 MXS_PIN_ENCODE(1,8)


  46. #define DI_GPIO_0 MXS_PIN_TO_GPIO(PINID_PCM_SYNC)
  47. #define DI_GPIO_1 MXS_PIN_TO_GPIO(PINID_PCM_CLK)
  48. #define DI_GPIO_2 MXS_PIN_TO_GPIO(PINID_PCM_DIN)
  49. #define DI_GPIO_3 MXS_PIN_TO_GPIO(PINID_PCM_DOUT)

  50. #define DO_GPIO_0 MXS_PIN_TO_GPIO(PINID_LCD_08)      //以上为体系结构相关的部分

  51. //do 不超过256 , di 不超过32
  52. static unsigned int uI_Input[] = {DI_GPIO_0,DI_GPIO_1,DI_GPIO_2,DI_GPIO_3};
  53. static unsigned int uI_Output[] = {DO_GPIO_0};
  54. unsigned char ucOutputNum = 0;
  55. unsigned char ucInputNum = 0 ;

  56. static int xxx_open(struct inode *inode,struct file *filp)
  57. {
  58.     PDEBUG("---> %s \n",__FUNCTION__);
  59.     return 0;
  60. }

  61. static int xxx_close(struct inode *inode,struct file *filp)
  62. {
  63.     PDEBUG("---> %s \n",__FUNCTION__);
  64.     return 0;
  65. }

  66. static int xxx_read(struct file *filp,char __user *buff,size_t count,loff_t *offp)
  67. {
  68.     int err = 0;
  69.     PDEBUG("---> %s \n",__FUNCTION__);
  70.     return err;
  71. }


  72. static int xxx_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
  73. {
  74.     int ret = 0;
  75.     unsigned char i ;
  76.     unsigned int temp = 0 ;
  77.     unsigned int input_value = 0 ;
  78.     PDEBUG("---> %s, cmd=%d,arg=%ld \n",__FUNCTION__,cmd,arg);
  79.     switch(cmd)
  80.     {    
  81.         case IO_GPIO_SET_OUTPUT:
  82.          PDEBUG("%s: case xxx_ON \n",__FUNCTION__);
  83.          if(arg >= ucOutputNum)
  84.                 return -EINVAL;
  85.          gpio_direction_output(uI_Output[arg],1);
  86.             break;
  87.         case IO_GPIO_RSEET_OUTPUT:
  88.          PDEBUG("%s: case xxx_OFF \n",__FUNCTION__);
  89.          if(arg >= ucOutputNum)
  90.                 return -EINVAL;
  91.          gpio_direction_output(uI_Output[arg],0);
  92.          break;
  93.         case IO_GPIO_GET_INPUT:
  94.             for(i = 0 ; i < ucInputNum ; i++)
  95.             {
  96.                 temp = gpio_get_value(uI_Input[i]);
  97.                 if(temp)
  98.                     input_value |= (1<<i);
  99.             }        
  100.          PDEBUG("%s: %d \n",__FUNCTION__,input_value);
  101.                  
  102.          copy_to_user((void *)arg,&input_value,4);
  103.          break;            
  104.         default :
  105.             return -EINVAL;
  106.     }
  107.         
  108.     return ret;
  109. }


  110. static int xxx_write(struct file *filp,const char __user *buf,size_t size,loff_t *ppos)
  111. {
  112.     PDEBUG("---> %s \n",__FUNCTION__);
  113.     return 0;
  114. }

  115. /************************************************************
  116.                       important struct
  117. ************************************************************/
  118. static struct file_operations xxx_fops=
  119. {
  120.     .owner = THIS_MODULE,
  121.     .open = xxx_open,
  122.     .release =xxx_close,
  123.     .read = xxx_read,
  124.     .ioctl = xxx_ioctl,
  125.     .write = xxx_write
  126. };



  127. static int __devinit xxx_probe(void)
  128. {
  129.     int ret ;
  130.     char i = 0 ;

  131.     
  132.     ucOutputNum = sizeof(uI_Output) / sizeof(unsigned int);  //输出数量
  133.     ucInputNum = sizeof(uI_Input) / sizeof(unsigned int);  // 输入数量
  134.     
  135.     for(i = 0 ; i < ucInputNum ; i++)
  136.     {
  137.         ret = gpio_request(uI_Input[i],"input_di");
  138.         if (ret)
  139.             {
  140.                 goto err_free_inputs;
  141.             }
  142.     }
  143.     
  144.     for(i = 0 ; i < ucOutputNum ; i++)
  145.     {
  146.         ret = gpio_request(uI_Output[i],"output_do");
  147.         if (ret)
  148.             {
  149.                 goto err_free_outputs;
  150.             }
  151.     }

  152. //    gpio_direction_output(uI_Output[0],1);
  153. //    gpio_direction_input(uI_Input[0]);

  154.     printk(KERN_INFO "xxx driver probe OK \n");
  155.     return 0;

  156. err_free_outputs:
  157.     i = ucOutputNum;
  158.     while(--i >= 0)
  159.         gpio_free(uI_Output[i]);
  160.         
  161. err_free_inputs:
  162.     i = ucInputNum;        
  163.     while(--i >= 0)
  164.         gpio_free(uI_Input[i]);            
  165.                                             
  166.     return ret;
  167. }


  168. static struct miscdevice xxx = {
  169.     .minor = MISC_DYNAMIC_MINOR,
  170.     .name = "xxx",
  171.     .fops = &xxx_fops,
  172. };



  173. static int __init xxx_init(void)
  174. {
  175.     int ret = 0;
  176.     int i;
  177.     ret = xxx_probe();
  178.     if(ret)
  179.     {
  180.         printk("xxx gpio reques fail \n");
  181.         return ret ;
  182.     }
  183.     ret = misc_register(&xxx);
  184.     if(ret<0)
  185.     {
  186.         printk("xxx misc devices register fail \n");
  187.     }
  188.     
  189.     return ret;
  190. }

  191. static int __exit xxx_exit(void)
  192. {
  193.     char i ;
  194.     misc_deregister(&xxx);
  195.     
  196.     i = ucInputNum;        
  197.     while(--i >= 0)
  198.         gpio_free(uI_Input[i]);    
  199.         
  200.     i = ucOutputNum;
  201.     while(--i >= 0)
  202.         gpio_free(uI_Output[i]);
  203.                 
  204.     return 0;
  205. }


  206. module_init(xxx_init);
  207. module_exit(xxx_exit);

xxx是设备名,全部替换就OK了。

uI_Input 是输入GPIO数组。有就填写,没有可以留空数组。

uI_Output 是输出GPIO数组。有就填写,没有可以留空数组。


在这种体系结构下,需要换GPIO口,只需要更换uI_Input , uI_Output 两个数组。然后用你想要的设备名替换xxx。
misc 的次设备采用MISC_DYNAMIC_MINOR动态分配。





阅读(4823) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~