gpio-sunxi驱动应用gpio口终端操作
内核里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口终端操作相关推荐
- 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 ...
- RT-Thread对GPIO操作两种方式的区别:1)通过设备操作接口2)直接通过通用GPIO设备驱动
在学习RT-Thread设备驱动框架时,看到潘多拉开发板的RT-Thread例程资料中的文档<AN0002-RT-Thread-通用 GPIO 设备应用笔记>有如下描述,因此产生使用文档中 ...
- Linux GPIO键盘驱动开发记录_OMAPL138
Linux GPIO键盘驱动开发记录_OMAPL138 Linux基本配置完毕了,这几天开始着手Linux驱动的开发,从一个最简单的键盘驱动开始,逐步的了解开发驱动的过程有哪些.看了一下Linux3. ...
- 树莓派开发笔记(五):GPIO引脚介绍和GPIO的输入输出使用(驱动LED灯、检测按键)
若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/ ...
- rk3568 | 瑞芯微平台GPIO引脚驱动编写
最近在玩瑞芯微平台的产品,移植了几个设备的驱动,遇到了一些问题,总结后发现大部分问题都出在了GPIO配置的问题上,写下本篇文章,用来分享一下调试的心得. 有喜欢瑞芯微的朋友,可以加我好友,拉你进群,一 ...
- AM335x(TQ335x)学习笔记——GPIO关键驱动移植
或按照S5PV210学习秩序.我们首先解决的关键问题.TQ335x有六个用户按钮,每个上.下.剩下.对.Enter和ESC. 我想开始学习S5PV210当同一,写输入子系统驱动器的关键问题要解决,但浏 ...
- 飞思卡尔 p1010 gpio linux驱动开发
gpio 开发文档 文章目录 gpio 开发文档 简述 centec gpio功能选择 gpio模式配置为开漏方向配置为输出模式 gpio的数据的读写 gpio操作上层应用程序的调用 简述 对于gpi ...
- ZYNQ-利用PS引脚实现EMIO GPIO的驱动
学习内容 使用SDK和提供的API进行初始化GPIO,并驱动led和btn进行操作,实现led呼吸灯效果,串口读取btn的值. 开发环境 vivado 18.3 && SDK 开发板 ...
- GPIO驱动分析 GPIO使用方法--S5PC110和S5PC210
参考文件:arch/arm/mach-s5pv210/include/mach/gpio.h , /drivers/gpio/gpiolib.c , arch/arm/plat-s3c/include ...
最新文章
- Dorado用法与示例
- 如何入门Go语言?这个开源项目赶紧收藏!
- Java 必会的 9 大技能,我请部门大神给你讲讲
- AC66U-B1) 刷梅林固件教程
- 15 JS应用-todolist任务
- HTML引入第三方类库项目需要授权解决方案
- 洛谷P2587 [ZJOI2008] 泡泡堂
- config userc.php,框架内置Config.php配置
- Python用format格式化字符串
- java方法前面加上x_@Autowired 写在构造方法上
- 可靠性计算python库
- oracle错误1327,问题简述:在oracle linux下安装oracle10g,多个文件报“Permission denied”错误...
- h5获取视频的第一帧
- 【Linux认证考试分数线多少】
- android 单位pt,Android APPUI设计师必知:pt sp dp之间的关系
- 华为麦芒6支持鸿蒙吗,华为麦芒6支持电信吗_华为麦芒6支持电信卡吗-太平洋IT百科...
- vscode配置php开发环境
- wpf 仿QQ音乐歌词卡拉OK
- Leetcode 483. Smallest Good Base [Python]
- 达内培训php怎么样,深圳达内php培训到底怎么样 说说亲身经历感受