内核里gpiolib可以操作gpio口,但基本只能作输入或输出功能。而全志的gpio控制器除这两种功能外,还提供了其它功能,如配置gpio的上下拉,输出电流等级大小等。所以全志提供了类似gpiolib但可以有更多功能的驱动(但现版本的驱动也只实现输入和输出功能).

首先确认内核里是否已选择上gpio-sunxi功能(默认是已选择上的)

make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-Device Drivers  --->*- GPIO Support  ---><M>   SUNXI GPIO USER INTERFACE

编译内核模块后,需要通过make modules_install安装模块到文件系统.


gpio-sunxi会像gpiolib一样提供gpio口操作的属性文件, 但无需提供gpio口的序号。只需要把要操作的gpio口列在script.bin里的gpio_para部分即可,gpio-sunxi驱动会在初始化时会给这些gpio口提供相应的属性文件.
如我的script.bin关于gpio_para部分的内容:

221 [gpio_para]
222 gpio_used = 1
223 gpio_num = 20
224 gpio_pin_1 = port:PA06<1><default><default><0>
225 gpio_pin_2 = port:PA13<1><default><default><0>
226 gpio_pin_3 = port:PA14<1><default><default><0>
227 gpio_pin_4 = port:PA01<1><default><default><0>
228 gpio_pin_5 = port:PD14<1><default><default><0>
229 gpio_pin_6 = port:PA00<1><default><default><0>
230 gpio_pin_7 = port:PA03<1><default><default><0>
231 gpio_pin_8 = port:PC04<1><default><default><0>
232 gpio_pin_9 = port:PC07<1><default><default><0>
233 gpio_pin_10 = port:PA02<1><default><default><0>
234 gpio_pin_11 = port:PA21<1><default><default><0>
235 gpio_pin_12 = port:PA07<1><1><3><0>
236 gpio_pin_13 = port:PA08<1><1><3><0>
237 gpio_pin_14 = port:PG08<1><default><default><0>
238 gpio_pin_15 = port:PA09<1><1><3><0>
239 gpio_pin_16 = port:PA10<1><1><3><0>
240 gpio_pin_17 = port:PG09<1><default><default><0>
241 gpio_pin_18 = port:PG06<1><default><default><0>
242 gpio_pin_19 = port:PG07<1><default><default><0>
243 gpio_pin_20 = port:PA15<1><default><default><0>
244
245 [leds_para]
246 leds_used = 0
247 green_led = port:PL10<1><default><default><1>
248 green_led_active_low = 0
249 red_led = port:PA15<1><default><default><0>
250 red_led_active_low = 0//需要注意的地方, gpio_para里列出的gpio口会作gpio_request操作的,不可复用,所以leds_para的leds_used设0.


操作:1 加载gpio-sunxi.ko驱动模块:modprobe gpio-sunxi.ko2 加载驱动模块后, 在/sys/class/gpio_sw目录下会看到上面所列的gpio口子目录:/ # ls /sys/class/gpio_sw/PPA0/   PA10/  PA14/  PA2/   PA3/   PA7/   PA9/   PC7/   PG6/   PG8/PA1/   PA13/  PA15/  PA21/  PA6/   PA8/   PC4/   PD14/  PG7/   PG9/3 每个gpio口子目录下又提供了属性文件:cfg   ,  data ,  pull,  drv// cfg属性文件是用于指定和获取gpio口的功能// data属性文件用于提定和获取gpio口的电平作用// pull属性文件用于设置gpio口的上下拉功能(现只有接口,没有实现此功能)// pull属性文件用于设置gpio口的输出电流等级(现只有接口,没有实现此功能)以上属性文件具体的可用值,应是根据datasheet来设置,如P15的配置信息:
功能分配(PA15):   000:输入,  001:输出, 010:SPI1_MOSI  011:UART3_RTS ,  110:PA_EINT15,  111:IO Disable默认值:7内部电阻状态(PA15): 00: Pull-up/down disable  , 01: Pull-up10: Pull-down,      11: Reserved默认值:0驱动能力(指输出的电流大小,等级越高,电流越大):00: Level 0 ,  01: Level 110: Level 2 ,  11: Level 3默认值: 1输出电平状态:   当功能选择输出时,1表示输出高电平, 0表示输出低电平
/////////////////////////
如操作PA15引脚(status-led用的gpio口)echo 1 > /sys/class/gpio_sw/PA15/cfg   //作输出功能echo 1 > /sys/class/gpio_sw/PA15/data  //输出高电平(灯亮)echo 0 > /sys/class/gpio_sw/PA15/data  //输出低电平(灯灭)



驱动源码在drivers/gpio/gpio-sunxi.c里
工作原理分析:

//已声明好4个属性文件, 每个属性文件都指定好读写操作的函数
279 static struct device_attribute gpio_sw_class_attrs[] = {
280     __ATTR(cfg,  0664, cfg_sel_show, cfg_sel_store),
281     __ATTR(pull, 0664, pull_show, pull_store),
282     __ATTR(drv,  0664, drv_level_show, drv_level_store),
283     __ATTR(data, 0664, data_show, data_store),
284     __ATTR_NULL,
285 };653 module_init(gpio_sw_init); //驱动模块的初始化函数为gpio_sw_init515 static int __init gpio_sw_init(void)
516 {...
525     gpio_sw_class = class_create(THIS_MODULE, "gpio_sw"); //创建class成功后会在/sys/class/目录下生成一个gpio_sw子目录...
531     gpio_sw_class->dev_attrs    = gpio_sw_class_attrs; //指定了gpio_sw的子目录属性文件(cfg,pull,data,drv)...
545     cnt = script_get_pio_list("gpio_para", &list); //获取script.bin里gpio_para里指定的所有gpio口563     for(i=0;i<cnt;i++){ //遍历gpio_para里的gpio口,进行gpio_request操作和给每个gpio口生成一个platform_device对象,初始化platform_device对象及注册.
564         printk("gpio_pin_%d(%d) gpio_request\n",i+1, list[i].gpio.gpio);
565         if(gpio_request(list[i].gpio.gpio, NULL)){  //请求操作
566             printk("gpio_pin_%d(%d) gpio_request fail \n",i+1, list[i].gpio.gpio);
567             continue;
568         }
569         sw_pdata[i] = kzalloc(sizeof(struct sw_gpio_pd), GFP_KERNEL); //准备platform_data空间
570         if(!sw_pdata[i]){
571             printk(KERN_ERR "kzalloc fail for sw_pdata[%d]\n",i);
572             return -1;
573         }
574
575         gpio_sw_dev[i] = kzalloc(sizeof(struct platform_device), GFP_KERNEL); //创建platform_device对象
576         if(!gpio_sw_dev[i]){
577             printk(KERN_ERR "kzalloc fail for gpio_sw_dev[%d]\n",i);
578             return -1;
579         }
580
581         sprintf(sw_pdata[i]->name,"gpio_pin_%d",i+1);
582         if (normal_led_pin.str && !strcmp(sw_pdata[i]->name, normal_led_pin.str)) {
583             sprintf(sw_pdata[i]->link,"%s", "normal_led");
584         } else if (standby_led_pin.str && !strcmp(sw_pdata[i]->name, standby_led_pin.str)) {
585             sprintf(sw_pdata[i]->link,"%s", "standby_led");
586         }
587 //初始化platform_device对象
588         gpio_sw_dev[i]->name = "gpio_sw";
589         gpio_sw_dev[i]->id   = i;
590         gpio_sw_dev[i]->dev.platform_data   = sw_pdata[i];
591         gpio_sw_dev[i]->dev.release         = gpio_sw_release;
592
593         if(platform_device_register(gpio_sw_dev[i])){ //注册platform_device对象
594             printk(KERN_ERR "%s platform_device_register fail\n",sw_pdata[i]->name);
595             goto INIT_ERR_FREE;
596         }
597     }
598     if(platform_driver_register(&gpio_sw_driver)){ //注册platform_driver对象
599         printk(KERN_ERR "gpio user platform_driver_register  fail\n");
600         for(i=0;i<cnt;i++)
601             platform_device_unregister(gpio_sw_dev[i]);
602         goto INIT_ERR_FREE;
603     }gpio_sw_driver对象:
504 static struct platform_driver gpio_sw_driver = {
505     .probe      = gpio_sw_probe,
506     .remove     = gpio_sw_remove,
507     .suspend    = gpio_suspend,
508     .resume     = gpio_resume,
509     .driver     = {
510         .name       = "gpio_sw",  //按此名字进行匹配
511         .owner      = THIS_MODULE,
512     },
513 };416 static int __devinit gpio_sw_probe(struct platform_device *dev)
417 {
418     struct sw_gpio              *sw_gpio_entry;
419     struct sw_gpio_pd           *pdata = dev->dev.platform_data;
420     int                         ret;
421     unsigned long               flags;
422     script_item_value_type_e    type;
423     char io_area[16];
424
425     sw_gpio_entry = kzalloc(sizeof(struct sw_gpio), GFP_KERNEL); //驱动给每个设备准备的数据
426     if(!sw_gpio_entry)
427         return -ENOMEM;
428     sw_gpio_entry->class.item = \
429         kzalloc(sizeof(script_item_u), GFP_KERNEL);
430     if(!sw_gpio_entry->class.item) {
431         kfree(sw_gpio_entry);
432         return -ENOMEM;
433     }
434     //在script.bin的gpio_para里获取"port:PA15<1><default><default><0>"指定的配置功能,上下拉功能,输出电流等级等
435     type = script_get_item("gpio_para", pdata->name, sw_gpio_entry->class.item);
436     if(SCIRPT_ITEM_VALUE_TYPE_PIO != type){
437         printk(KERN_ERR "get config err!\n");
438         kfree(sw_gpio_entry->class.item);
439         kfree(sw_gpio_entry);
440         return -ENOMEM;
441     }
442
443     ret = mapGpioToName(io_area,sw_gpio_entry->class.item->gpio.gpio);
444     printk("gpio name is %s, ret = %d\n",io_area, ret); //获取名称: PA15
445
446     platform_set_drvdata(dev,sw_gpio_entry); //把给设备准备的数据绑定到设备...//初始化里的操作函数,在上面的属性文件操作函数里会调用这些gpio_sw_xxx_xxx函数来完成实际功能.
457     sw_gpio_entry->class.gpio_sw_cfg_set = gpio_sw_cfg_set;
458     sw_gpio_entry->class.gpio_sw_cfg_get = gpio_sw_cfg_get;
459     sw_gpio_entry->class.gpio_sw_pull_set = gpio_sw_pull_set;
460     sw_gpio_entry->class.gpio_sw_pull_get = gpio_sw_pull_get;
461     sw_gpio_entry->class.gpio_sw_drv_set = gpio_sw_drv_set;
462     sw_gpio_entry->class.gpio_sw_drv_get = gpio_sw_drv_get;
463     sw_gpio_entry->class.gpio_sw_data_set = gpio_sw_data_set;
464     sw_gpio_entry->class.gpio_sw_data_get = gpio_sw_data_get;...// gpio_sw_classdev_register其实就是在/sys/class/gpio_sw目录下创建子目录,并在每个子目录都会生成cfg,pull,drv,data等属性文件
472     ret = gpio_sw_classdev_register(&dev->dev, &sw_gpio_entry->class);...
486     return 0;
487 }如对cfg进行写操作时,则触发调用cfg_sel_store函数
188 static ssize_t cfg_sel_store(struct device *dev,
189         struct device_attribute *attr, const char *buf, size_t size)
190 {
191     struct gpio_sw_classdev *gpio_sw_cdev = dev_get_drvdata(dev); //获取驱动里给设备准备的数据
192     ssize_t ret = -EINVAL;
193     char *after;
194     int cfg = simple_strtoul(buf, &after, 10);
195     size_t count = after - buf;
196
197     if (isspace(*after))
198         count++;
199
200     if (count == size){
201         ret = count;
202         gpio_sw_cdev->gpio_sw_cfg_set(gpio_sw_cdev, cfg); //调用457行初始化的函数
203     }
204
205     return ret;
206 }//然后通过阅读以下代码就可以发现有pull, drv接口,但根本没有实现实际功能.79 static int80 gpio_sw_cfg_set(struct gpio_sw_classdev *gpio_sw_cdev,int  mul_cfg){81 82     if (mul_cfg==0)83         gpio_direction_input(gpio_sw_cdev->item->gpio.gpio);84     else85         gpio_direction_output(gpio_sw_cdev->item->gpio.gpio, 0);86 87     return 0;88 }89 90 static int91 gpio_sw_cfg_get(struct gpio_sw_classdev *gpio_sw_cdev){92 93     return 0;94 }95 96 static int97 gpio_sw_pull_set(struct gpio_sw_classdev *gpio_sw_cdev,int  pull){98 99     return 0;
100 }
101
102 static int
103 gpio_sw_pull_get(struct gpio_sw_classdev *gpio_sw_cdev){
104
105     return 0;
106 }
107
108 static int
109 gpio_sw_drv_set(struct gpio_sw_classdev *gpio_sw_cdev,int  drv){
110
111     return 0;
112 }
113
114 static int
115 gpio_sw_drv_get(struct gpio_sw_classdev *gpio_sw_cdev){
116
117     return 0;
118 }
119
120 static int
121 gpio_sw_data_set(struct gpio_sw_classdev *gpio_sw_cdev,int  data){
122     __gpio_set_value(gpio_sw_cdev->item->gpio.gpio,data);
123     return 0;
124 }
125
126 static int
127 gpio_sw_data_get(struct gpio_sw_classdev *gpio_sw_cdev){
128     return __gpio_get_value(gpio_sw_cdev->item->gpio.gpio);
129 }

gpio-sunxi驱动应用gpio口终端操作相关推荐

  1. linux下的gpio转串口驱动,X-026-KERNEL-Linux gpio driver的移植之gpio range

    X-026-KERNEL-Linux gpio driver的移植之gpio range 作者:wowo 发布于:2017-9-27 22:27 分类:X Project 1. 前言 我们在[1][2 ...

  2. RT-Thread对GPIO操作两种方式的区别:1)通过设备操作接口2)直接通过通用GPIO设备驱动

    在学习RT-Thread设备驱动框架时,看到潘多拉开发板的RT-Thread例程资料中的文档<AN0002-RT-Thread-通用 GPIO 设备应用笔记>有如下描述,因此产生使用文档中 ...

  3. Linux GPIO键盘驱动开发记录_OMAPL138

    Linux GPIO键盘驱动开发记录_OMAPL138 Linux基本配置完毕了,这几天开始着手Linux驱动的开发,从一个最简单的键盘驱动开始,逐步的了解开发驱动的过程有哪些.看了一下Linux3. ...

  4. 树莓派开发笔记(五):GPIO引脚介绍和GPIO的输入输出使用(驱动LED灯、检测按键)

    若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/ ...

  5. rk3568 | 瑞芯微平台GPIO引脚驱动编写

    最近在玩瑞芯微平台的产品,移植了几个设备的驱动,遇到了一些问题,总结后发现大部分问题都出在了GPIO配置的问题上,写下本篇文章,用来分享一下调试的心得. 有喜欢瑞芯微的朋友,可以加我好友,拉你进群,一 ...

  6. AM335x(TQ335x)学习笔记——GPIO关键驱动移植

    或按照S5PV210学习秩序.我们首先解决的关键问题.TQ335x有六个用户按钮,每个上.下.剩下.对.Enter和ESC. 我想开始学习S5PV210当同一,写输入子系统驱动器的关键问题要解决,但浏 ...

  7. 飞思卡尔 p1010 gpio linux驱动开发

    gpio 开发文档 文章目录 gpio 开发文档 简述 centec gpio功能选择 gpio模式配置为开漏方向配置为输出模式 gpio的数据的读写 gpio操作上层应用程序的调用 简述 对于gpi ...

  8. ZYNQ-利用PS引脚实现EMIO GPIO的驱动

    学习内容 使用SDK和提供的API进行初始化GPIO,并驱动led和btn进行操作,实现led呼吸灯效果,串口读取btn的值. 开发环境 vivado 18.3 && SDK 开发板 ...

  9. GPIO驱动分析 GPIO使用方法--S5PC110和S5PC210

    参考文件:arch/arm/mach-s5pv210/include/mach/gpio.h , /drivers/gpio/gpiolib.c , arch/arm/plat-s3c/include ...

最新文章

  1. Dorado用法与示例
  2. 如何入门Go语言?这个开源项目赶紧收藏!
  3. Java 必会的 9 大技能,我请部门大神给你讲讲
  4. AC66U-B1) 刷梅林固件教程
  5. 15 JS应用-todolist任务
  6. HTML引入第三方类库项目需要授权解决方案
  7. 洛谷P2587 [ZJOI2008] 泡泡堂
  8. config userc.php,框架内置Config.php配置
  9. Python用format格式化字符串
  10. java方法前面加上x_@Autowired 写在构造方法上
  11. 可靠性计算python库
  12. oracle错误1327,问题简述:在oracle linux下安装oracle10g,多个文件报“Permission denied”错误...
  13. h5获取视频的第一帧
  14. 【Linux认证考试分数线多少】
  15. android 单位pt,Android APPUI设计师必知:pt sp dp之间的关系
  16. 华为麦芒6支持鸿蒙吗,华为麦芒6支持电信吗_华为麦芒6支持电信卡吗-太平洋IT百科...
  17. vscode配置php开发环境
  18. wpf 仿QQ音乐歌词卡拉OK
  19. Leetcode 483. Smallest Good Base [Python]
  20. 达内培训php怎么样,深圳达内php培训到底怎么样 说说亲身经历感受

热门文章

  1. 关于Object.defineProperty的几个坑
  2. 抽象代数 04.08 自由幺半群与自由群
  3. 最美的公式之一— —欧拉公式
  4. 用ALTER TABLE语句来创建索引
  5. [MFC] 几种子控件半透明效果的实现办法
  6. Linux学习笔记---VI编辑器常用快捷键
  7. 2022年全球及中国抑菌卫生巾行业头部企业市场占有率及排名调研报告
  8. 零拷贝机制(Zero Copy)
  9. 什么是电子秤称重模块?它具有哪些功能?
  10. 空调负荷需求响应matlab