linux:/sys/xxx 读写节点使用方法

公众号

欢迎扫码关注本人微信公众号:公众号上分享更多嵌入式知识和资料,分享个人学习嵌入式的心得体会。欢迎大家一起来玩呀。
在这里插入图片描述

/sys/xxx读写节点

在 /sys 中生成节点,用于应用层从驱动中获取数据,或者将数据写到驱动层中,比如点亮LED灯或者获取GPIO的值的高低电平。

#include <linux/init.h>                        
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>

#include <linux/delay.h>
#include <linux/err.h>

#include <linux/of_gpio.h>
#include <linux/gpio.h>

#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/io.h>

#include <linux/delay.h>

#include <dt-bindings/gpio/gpio.h>

#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#endif

struct taishan_gpio_dev{
     struct platform_device *pdev;

     int power_switch_gpio;           //电源关断器控制IO
     int power_switch_gpio_direction;
     
     int out_switch_gpio;            //输出短路器控制IO
     int out_switch_gpio_direction; 
     
     int relays1_gpio;               //继电器输出控制IO
     int relays1_gpio_direction;
     int relays2_gpio;
     int relays2_gpio_direction;
     int relays3_gpio;
     int relays3_gpio_direction;
     int relays4_gpio;
     int relays4_gpio_direction;

     int flame_sensor_gpio;
     int smoke_sensor_gpio;
};

static struct taishan_gpio_dev *ptaishan_dev = NULL;

static ssize_t power_switch_gpio_store(struct device *dev, struct device_attribute *attr,
              const char *buf, size_t count) {
              
    struct taishan_gpio_dev *pdata = ptaishan_dev;            
    if (buf[0] == '0') {
        pdata->power_switch_gpio_direction = 0;
        gpio_direction_output(pdata->power_switch_gpio, pdata->power_switch_gpio_direction);
    }else if (buf[0] == '1') {
        pdata->power_switch_gpio_direction = 1;
        gpio_direction_output(pdata->power_switch_gpio, pdata->power_switch_gpio_direction);
    }    

    printk(KERN_ERR "power_switch_gpio_store %d \n",pdata->power_switch_gpio_direction);   
    return count;
}

static ssize_t out_switch_gpio_store(struct device *dev, struct device_attribute *attr,
            const char *buf, size_t count) {
            
    struct taishan_gpio_dev *pdata = ptaishan_dev;            
    if (buf[0] == '0') {
        pdata->out_switch_gpio_direction = 0;
        gpio_direction_output(pdata->out_switch_gpio, pdata->out_switch_gpio_direction);
    }else if (buf[0] == '1') {
        pdata->out_switch_gpio_direction = 1;
        gpio_direction_output(pdata->out_switch_gpio, pdata->out_switch_gpio_direction);
    }    

    printk(KERN_ERR "out_switch_gpio_store %d \n",pdata->out_switch_gpio_direction);   
    return count;
}

static ssize_t relays1_gpio_store(struct device *dev, struct device_attribute *attr,
              const char *buf, size_t count) {
              
    struct taishan_gpio_dev *pdata = ptaishan_dev;            
    if (buf[0] == '0') {
        pdata->relays1_gpio_direction = 0;
        gpio_direction_output(pdata->relays1_gpio, pdata->relays1_gpio_direction);
    }else if (buf[0] == '1') {
        pdata->relays1_gpio_direction = 1;
        gpio_direction_output(pdata->relays1_gpio, pdata->relays1_gpio_direction);
    }    

    printk(KERN_ERR "relays1_gpio_store %d \n",pdata->relays1_gpio_direction);   
    return count;
}

static ssize_t relays2_gpio_store(struct device *dev, struct device_attribute *attr,
            const char *buf, size_t count) {
            
    struct taishan_gpio_dev *pdata = ptaishan_dev;            
    if (buf[0] == '0') {
        pdata->relays2_gpio_direction = 0;
        gpio_direction_output(pdata->relays2_gpio, pdata->relays2_gpio_direction);
    }else if (buf[0] == '1') {
        pdata->relays2_gpio_direction = 1;
        gpio_direction_output(pdata->relays2_gpio, pdata->relays2_gpio_direction);
    }    

    printk(KERN_ERR "relays2_gpio_store %d \n",pdata->out_switch_gpio_direction);   
    return count;
}


static ssize_t relays3_gpio_store(struct device *dev, struct device_attribute *attr,
             const char *buf, size_t count) {
             
    struct taishan_gpio_dev *pdata = ptaishan_dev;            
    if (buf[0] == '0') {
        pdata->relays3_gpio_direction = 0;
        gpio_direction_output(pdata->relays3_gpio, pdata->relays3_gpio_direction);
    }else if (buf[0] == '1') {
        pdata->relays3_gpio_direction = 1;
        gpio_direction_output(pdata->relays3_gpio, pdata->relays3_gpio_direction);
    }    

    printk(KERN_ERR "relays3_gpio_store %d \n",pdata->relays3_gpio_direction);   
    return count;
}


static ssize_t relays4_gpio_store(struct device *dev, struct device_attribute *attr,
             const char *buf, size_t count) {
             
    struct taishan_gpio_dev *pdata = ptaishan_dev;            
    if (buf[0] == '0') {
        pdata->relays4_gpio_direction = 0;
        gpio_direction_output(pdata->relays4_gpio, pdata->relays4_gpio_direction);
    }else if (buf[0] == '1') {
        pdata->relays4_gpio_direction = 1;
        gpio_direction_output(pdata->relays4_gpio, pdata->relays4_gpio_direction);
    }    

    printk(KERN_ERR "relays4_gpio_store %d \n",pdata->relays4_gpio_direction);   
    return count;
}

static ssize_t flame_sensor_gpio_show(struct device *dev, struct device_attribute *attr, char *buf) {
    struct taishan_gpio_dev *pdata = ptaishan_dev; 
    int gpio_value = 0;

    gpio_value = gpio_get_value(pdata->flame_sensor_gpio);
    
    return snprintf(buf, PAGE_SIZE, "%d\n",
			gpio_value);
}

static ssize_t smoke_sensor_gpio_show(struct device *dev, struct device_attribute *attr, char *buf) {
    struct taishan_gpio_dev *pdata = ptaishan_dev; 
    int gpio_value = 0;

    gpio_value = gpio_get_value(pdata->smoke_sensor_gpio);
    
    return snprintf(buf, PAGE_SIZE, "%d\n",
			gpio_value);
}



static struct device_attribute taishan_gpio1_attr[] = {
    __ATTR(power_switch_gpio, 0664, NULL, power_switch_gpio_store),
    
	__ATTR(out_switch_gpio, 0664, NULL,   out_switch_gpio_store),
	
	__ATTR(relays1_gpio, 0664, NULL,      relays1_gpio_store),
	__ATTR(relays2_gpio, 0664, NULL,      relays2_gpio_store),
	__ATTR(relays3_gpio, 0664, NULL,      relays3_gpio_store),
	__ATTR(relays4_gpio, 0664, NULL,      relays4_gpio_store),
	
	__ATTR(flame_sensor_gpio, 0664, flame_sensor_gpio_show,NULL),
	__ATTR(smoke_sensor_gpio, 0664, smoke_sensor_gpio_show,NULL),
};

static void taishan_gpio_init_sysfs(struct device *dev)
{
	int i, ret;
	for (i = 0; i < ARRAY_SIZE(taishan_gpio1_attr); i++) {
		ret = sysfs_create_file(&dev->kobj,
					&taishan_gpio1_attr[i].attr);
		if (ret)
			dev_err(dev, "create charger node(%s) error\n",
				taishan_gpio1_attr[i].attr.name);
	}
}

static int taishan_gpio_dt(struct taishan_gpio_dev *pdata) {
    int gpio;
    int ret;
    enum of_gpio_flags flags;
    struct device *dev = &pdata->pdev->dev;
    struct device_node *node = dev->of_node;
    
    gpio = of_get_named_gpio_flags(node, "power_switch_gpio", 0, &flags);
	if (gpio_is_valid(gpio))
	{
	    pdata->power_switch_gpio           = gpio;
	    pdata->power_switch_gpio_direction = (flags == GPIO_ACTIVE_HIGH)? 1:0;	    
	    printk(KERN_ERR"power_switch_gpio: %d\n", pdata->power_switch_gpio);
	    
	    ret = devm_gpio_request(dev,gpio, "power_switch_gpio");
	    if (ret) {
			printk("Failed to get power_switch_gpio gpio.\n");
		}
    }

    gpio = of_get_named_gpio_flags(node, "out_switch_gpio", 0, &flags);
	if (gpio_is_valid(gpio))
	{
	    pdata->out_switch_gpio           = gpio;
	    pdata->out_switch_gpio_direction = (flags == GPIO_ACTIVE_HIGH)? 1:0;	    
	    printk(KERN_ERR"out_switch_gpio: %d\n", pdata->out_switch_gpio);
	    
	    ret = devm_gpio_request(dev,gpio, "out_switch_gpio");
	    if (ret) {
			printk("Failed to get out_switch_gpio gpio.\n");
		}
    }

    gpio = of_get_named_gpio_flags(node, "relays1_gpio", 0, &flags);
	if (gpio_is_valid(gpio))
	{
	    pdata->relays1_gpio           = gpio;
	    pdata->relays1_gpio_direction = (flags == GPIO_ACTIVE_HIGH)? 1:0;	    
	    printk(KERN_ERR"relays1_gpio: %d\n", pdata->relays1_gpio);
	    
	    ret = devm_gpio_request(dev,gpio, "relays1_gpio");
	    if (ret) {
			printk("Failed to get relays1_gpio gpio.\n");
		}
    }


    gpio = of_get_named_gpio_flags(node, "relays2_gpio", 0, &flags);
	if (gpio_is_valid(gpio))
	{
	    pdata->relays2_gpio           = gpio;
	    pdata->relays2_gpio_direction = (flags == GPIO_ACTIVE_HIGH)? 1:0;	    
	    printk(KERN_ERR"relays2_gpio: %d\n", pdata->relays2_gpio);
	    
	    ret = devm_gpio_request(dev,gpio, "relays2_gpio");
	    if (ret) {
			printk("Failed to get relays2_gpio gpio.\n");
		}
    }

    gpio = of_get_named_gpio_flags(node, "relays3_gpio", 0, &flags);
	if (gpio_is_valid(gpio))
	{
	    pdata->relays3_gpio           = gpio;
	    pdata->relays3_gpio_direction = (flags == GPIO_ACTIVE_HIGH)? 1:0;	    
	    printk(KERN_ERR"relays3_gpio: %d\n", pdata->relays3_gpio);
	    
	    ret = devm_gpio_request(dev,gpio, "relays3_gpio");
	    if (ret) {
			printk("Failed to get relays3_gpio gpio.\n");
		}
    }


    gpio = of_get_named_gpio_flags(node, "relays4_gpio", 0, &flags);
	if (gpio_is_valid(gpio))
	{
	    pdata->relays4_gpio           = gpio;
	    pdata->relays4_gpio_direction = (flags == GPIO_ACTIVE_HIGH)? 1:0;	    
	    printk(KERN_ERR"relays4_gpio: %d\n", pdata->relays4_gpio);
	    
	    ret = devm_gpio_request(dev,gpio, "relays4_gpio");
	    if (ret) {
			printk("Failed to get relays4_gpio gpio.\n");
		}
    }


    gpio = of_get_named_gpio_flags(node, "flame_sensor_gpio", 0, &flags);
	if (gpio_is_valid(gpio))
	{
	    pdata->flame_sensor_gpio        = gpio;
	    printk(KERN_ERR"flame_sensor_gpio: %d\n", pdata->flame_sensor_gpio);
	    
	    ret = devm_gpio_request(dev,gpio, "flame_sensor_gpio");
	    if (ret) {
			printk("Failed to get flame_sensor_gpio gpio.\n");
		}

		ret = gpio_direction_input(gpio);
		if (ret) {
			printk("Failed to set flame_sensor_gpio gpio.\n");
		}
    }

    gpio = of_get_named_gpio_flags(node, "smoke_sensor_gpio", 0, &flags);
	if (gpio_is_valid(gpio))
	{
	    pdata->smoke_sensor_gpio        = gpio;
	    printk(KERN_ERR"smoke_sensor_gpio: %d\n", pdata->smoke_sensor_gpio);
	    
	    ret = devm_gpio_request(dev,gpio, "smoke_sensor_gpio");
	    if (ret) {
			printk("Failed to get smoke_sensor_gpio gpio.\n");
		}

		ret = gpio_direction_input(gpio);
		if (ret) {
			printk("Failed to set flame_sensor_gpio gpio.\n");
		}
    }

    return 0;
}

static void taishan_gpio_set_default(struct taishan_gpio_dev *pdata) {

    if (pdata->power_switch_gpio) {
        gpio_direction_output(pdata->power_switch_gpio, pdata->power_switch_gpio_direction);
    }

    if (pdata->out_switch_gpio) {
        gpio_direction_output(pdata->out_switch_gpio, pdata->out_switch_gpio_direction);
    }

    if (pdata->relays1_gpio) {
        gpio_direction_output(pdata->relays1_gpio, pdata->relays1_gpio_direction);
    }

    if (pdata->relays2_gpio) {
        gpio_direction_output(pdata->relays2_gpio, pdata->relays2_gpio_direction);
    }

    if (pdata->relays3_gpio) {
        gpio_direction_output(pdata->relays3_gpio, pdata->relays3_gpio_direction);
    }

    if (pdata->relays4_gpio) {
        gpio_direction_output(pdata->relays4_gpio, pdata->relays4_gpio_direction);
    }
}


static int taishan_gpio_probe(struct platform_device *pdev) {
     printk(KERN_ALERT "%s \n",__func__);      
     ptaishan_dev = kmalloc(sizeof(struct taishan_gpio_dev), GFP_KERNEL);
     if (ptaishan_dev == NULL) {
        printk(KERN_ERR"kmalloc struct taishan_gpio_dev err \n");
        return -ENOMEM;
     }

     memset(ptaishan_dev, 0, sizeof(struct taishan_gpio_dev));

     ptaishan_dev->pdev = pdev;

     taishan_gpio_dt(ptaishan_dev);
     taishan_gpio_set_default(ptaishan_dev);
     taishan_gpio_init_sysfs(&ptaishan_dev->pdev->dev);
     
     printk(KERN_ALERT "%s end !!!!!\n",__func__);
     return 0;
}



static struct of_device_id taishan_gpio_of_match[] = {
	{ .compatible = "taishan_gpio" },
	{ }
};


static struct platform_driver taishan_gpio_driver = {
	.driver		= {
		.name		= "taishan_gpio",
		.of_match_table	= of_match_ptr(taishan_gpio_of_match),
	},
	.probe		= taishan_gpio_probe,
};


module_platform_driver(taishan_gpio_driver);

MODULE_AUTHOR("FenDa Ltd System Application Group");
MODULE_DESCRIPTION("taishan gpio driver");
MODULE_LICENSE("GPL");


应用层节点生成sys/xxxxx

在/sys/devices/platform/taishan-gpio 路径下可以看到会生成如下的节点:
power_switch_gpio
out_switch_gpio
relays1_gpio
relays2_gpio
relays3_gpio
relays4_gpio
flame_sensor_gpio
smoke_sensor_gpio
每一个节点代表一个GPIO引脚

rk3399:/sys/devices/platform/taishan-gpio # ls -la
total 0
drwxr-xr-x   3 root root    0 2013-01-18 08:50 .
drwxr-xr-x 142 root root    0 2013-01-18 08:50 ..
lrwxrwxrwx   1 root root    0 2021-10-26 06:57 driver -> ../../../bus/platform/drivers/taishan_gpio
-rw-r--r--   1 root root 4096 2021-10-26 06:57 driver_override
-rw-rw-r--   1 root root 4096 2021-10-26 06:57 flame_sensor_gpio
-r--r--r--   1 root root 4096 2021-10-26 06:57 modalias
lrwxrwxrwx   1 root root    0 2021-10-26 06:57 of_node -> ../../../firmware/devicetree/base/taishan-gpio
-rw-rw-r--   1 root root 4096 2021-10-26 06:57 out_switch_gpio
drwxr-xr-x   2 root root    0 2013-01-18 08:50 power
-rw-rw-r--   1 root root 4096 2021-10-26 06:57 power_switch_gpio
-rw-rw-r--   1 root root 4096 2021-10-26 06:57 relays1_gpio
-rw-rw-r--   1 root root 4096 2021-10-26 06:57 relays2_gpio
-rw-rw-r--   1 root root 4096 2021-10-26 06:57 relays3_gpio
-rw-rw-r--   1 root root 4096 2021-10-26 06:57 relays4_gpio
-rw-rw-r--   1 root root 4096 2021-10-26 06:57 smoke_sensor_gpio
lrwxrwxrwx   1 root root    0 2021-10-26 06:57 subsystem -> ../../../bus/platform
-rw-r--r--   1 root root 4096 2013-01-18 08:50 uevent

应用层使用方法

使用cat命令 cat节点可以获取GPIO的值,下面的例子中获取到1,表示高电平
rk3399:/sys/devices/platform/taishan-gpio # cat smoke_sensor_gpio
1
使用echo命令给节点写入1,让relays1_gpio这个gpio输出高电平
rk3399:/sys/devices/platform/taishan-gpio # echo 1 > relays1_gpio

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值