zoukankan      html  css  js  c++  java
  • GPIO设备虚拟文件结点的创建【转】

    本文转载自:http://blog.csdn.net/dwyane_zhang/article/details/6742066

    所谓GPIO设备虚拟文件结点,就是方便用户在应用程序直接操纵GPIO的值。

    1.首先必须了解static DEVICE_ATTR(GPS_nRST, 0644, gps_reset_show, gps_reset_store); 这个函数的意思。

    “GPS_nRST“是要操纵的引脚,“0644”创建文件结点的权限,“gps_reset_show”结点的读状态,“gps_reset_store”结点的写状态。

    通过这个函数既是填充文件结点。

    2.最终注册是通过 device_create_file(&pdev->dev, &dev_attr_GPS_nRST); 注册上的。注意参数pdev->dev必须是在板载信息里要初始化的。

    参数&dev_attr_GPS_nRST即是引脚GPS_nRST,只不过前面加一个dev_attr_是格式上的要求。

    下面贴上自己写的代码以供参考。

    #include <Linux/module.h>
    #include <linux/mman.h>
    #include <linux/init.h>
    #include <linux/kernel.h>
    #include <linux/spinlock.h>
    #include <linux/delay.h>
    #include <linux/sysdev.h>
    #include <linux/errno.h>
    #include <linux/io.h>
    #include <linux/device.h>
    #include <mach/gpio.h>
    #include <linux/platform_device.h>
    #include "gpio_gps.h"

    #include <asm/uaccess.h>
    #include <mach/hardware.h>
    #include <linux/device.h>

    #define nRST  85 
    #define PWON  87


    static ssize_t gps_standby_show(struct device *dev,
      struct device_attribute *attr, char *buf)
    {
     int len = 0;
     struct gps_gpio_platform_data *pdata = dev->platform_data;

     len += sprintf(buf + len, "%u ", pdata->standby_state);
     printk("======== %s len = %d ",__func__,len);
     return len;
    }

    static ssize_t gps_standby_store(struct device *dev,
      struct device_attribute *attr, const char *buf, size_t size)
    {

     unsigned long state = simple_strtoul(buf, NULL, 10);
     struct gps_gpio_platform_data *pdata = dev->platform_data;

     pdata->standby_state = (int)state;
     printk(" ****** standby_state = %d ",pdata->standby_state);

     if(state)         //如果读的到数据,就拉高电平
      gpio_direction_output(PWON, 1); //standby on
     else
      gpio_direction_output(PWON, 0); //standby off

     return size;
    }

    static ssize_t gps_reset_show(struct device *dev,
      struct device_attribute *attr, char *buf)
    {
     int len = 0;
     struct gps_gpio_platform_data *pdata = dev->platform_data;

     len += sprintf(buf + len, "%u ", pdata->reset_state);
     printk("======== %s len = %d ",__func__,len);

     return len;
    }

    static ssize_t gps_reset_store(struct device *dev,
      struct device_attribute *attr, const char *buf, size_t size)
    {

     unsigned long state = simple_strtoul(buf, NULL, 10);
     struct gps_gpio_platform_data *pdata = dev->platform_data;
     printk(" ******%s  %s  line = %d ",__func__,__FILE__,__LINE__);

     pdata->reset_state = (int)state;
     printk(" ****** reset_state = %d ",pdata->reset_state);

     if(state)
      gpio_direction_output(nRST, 1); //reset on
     else
      gpio_direction_output(nRST, 0); //reset off

     return size;
    }

    static DEVICE_ATTR(GPS_nRST, 0644, gps_reset_show, gps_reset_store);
    static DEVICE_ATTR(GPS_PWR_EN, 0644, gps_standby_show, gps_standby_store);

    #if 0
    static struct device_attribute GPS_nRST = {
     .attr = {
      .name = "gps_reset",
      .mode = 0644,
     },
     .show = gps_reset_show,
     .store = gps_reset_store,
    };

    static struct device_attribute GPS_PWR_EN = {
     .attr = {
      .name = "gps_poweron",
      .mode = 0644,
     },
     .show = gps_standby_show,
     .store = gps_standby_store,
    };
    #endif
    #if 0
    static struct msm_gpio msm_gps_cfg_data[] = {
     {GPIO_CFG(85, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), "gps_reset"},
     {GPIO_CFG(87, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), "gps_poweron"},
    };
    #endif
    static int gps_gpio_probe(struct platform_device *pdev)
    {
        int ret;
        struct gps_gpio_platform_data *pdata = pdev->dev.platform_data;

        // 这里的gps_gpio_platform_data *pdata要注意,其中struct gps_gpio_platform_data 结构体在板载信息board-msm7630.c中也要声明,并与此函数保持一致,

        // 而pdata也要填充。
    #if 0
        msm_gpios_request_enable(msm_gps_cfg_data,
                             ARRAY_SIZE(msm_gps_cfg_data));
    #endif
        gpio_request(PWON, "gps_poweron");  //standby
        gpio_request(nRST, "gps_reset");  //reset

        pdata->standby_state = 0;       // 初始化的状态
        pdata->reset_state = 1;
        //    mv_gpio_set_out_data(2, 1);//32kHz clk_en
    #if 0
        gpio_direction_output(nRST, 0); //reset off
        mdelay(200);
        gpio_direction_output(nRST, 1); //reset on
        mdelay(200);
        gpio_direction_output(PWON, 1); //standby on
    #endif
        ret = device_create_file(&pdev->dev, &dev_attr_GPS_nRST);
    //    ret = device_create_file(&pdev->dev, &GPS_PWR_EN);
        printk("//////   ret  = %d ",ret);
        if(ret)
            return ret;
        else
            return device_create_file(&pdev->dev, &dev_attr_GPS_PWR_EN);
            //return device_create_file(&pdev->dev, &GPS_nRST);
    }

    static int gps_gpio_remove(struct platform_device *pdev)
    {
    //    struct gps_gpio_platform_data *pdata = pdev->dev.platform_data;
        gpio_direction_output(PWON, 0);
        gpio_direction_output(nRST, 0);
        return 0;
    }

    struct platform_driver gps_gpio_driver = {
        .probe = gps_gpio_probe,
        .remove = gps_gpio_remove,
        .driver = {
            .name   = "gps_gpio",
            .owner  = THIS_MODULE,
        },
    };

    static int __init gps_gpio_init(void)
    {
        return platform_driver_register(&gps_gpio_driver);
    }

    static void __exit  gps_gpio_exit(void)
    {
        platform_driver_unregister(&gps_gpio_driver);
    }

    late_initcall(gps_gpio_init);
    module_exit(gps_gpio_exit);

    MODULE_AUTHOR("zhangmin");
    MODULE_LICENSE("GPL v2");

    红色的部分是另外一种注册GPIO结点的写法。

    上面就是我加设备结点的全过程,建立完后会在/sys/devices/platform/gps-gpio.0/GPS_nRST、/sys/devices/platform/gps-gpio.0/GPS_PWR_EN 会有两个结点。

    我们可以在adb shell中自由的控制电平的引脚。如 echo 1 > /sys/devices/platform/gps-gpio.0/GPS_nRST 即是把GPS_nRST 引脚拉高 ,

    echo 0 > /sys/devices/platform/gps-gpio.0/GPS_nRST 即是把GPS_nRST 引脚拉低。

    在应用程序用这个结点的时候要注意是否操作权限一致的问题,比如都要是root权限即可操作了。

  • 相关阅读:
    IT痴汉的工作现状24-Just for fun
    &quot;duplicate symbol for architecture i386&quot; 解决的方法
    如何将visual studio 2010编辑模式改为插入???
    教学平台服务器安装环境说明
    Microsoft SQL Server 2008 基本安装说明
    WEB安全测试的类型
    IBM Rational Appscan使用之扫描结果分析
    IBM Rational AppScan使用详细说明
    Security Testing Basics
    ZAP介绍
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/6757153.html
Copyright © 2011-2022 走看看