[sysfs]Linux GPIO简单使用方式

转自:http://blog.csdn.net/drivermonkey/article/details/20132241

1.1.References

1.2.GPIO Usage from a Linux Application

1.2.1Overview

1.2.2.Configure the kernel for GPIO support in sysfs

1.2.3.Enable GPIO access from user space

1.2.4.GPIO interrupts from user space

1.2.4.1.Reference

1.2.4.2.LeopoardBoard 365 GPIO 0 connection

1.2.4.3.Using poll to monitor for GPIO 0 change

2.Viewing GPIO Configuration

3.Example shell script making it easy to set GPIOs from the command line

4.Example of C/C++ code making it easier to set GPIOs

本文资料主要来自互联网,并通过本人亲测试正确性

1.1.References

1.2.GPIO Usage from a Linux Application

1.2.1.Overview

The following table summarizes the steps to configuring and using GPIO signals from a Linux application.

Step Action Description
1 Configure the kernel for GPIO support in sysfs Allow GPIO configuration and control from Linux applications (user space). The GPIO shoulw up in the system file system, sysfs, at /sys/class/gpio
2 Export GPIO to user space Each GPIO is are not accessible from user space until the GPIO has been exported. You can only export a GPIO that isn‘t owned by a Linux kernel driver
3 Configure GPIO for input or output To avoid hardware issues where two devices are driving the same signal, GPIOs default to be configured as an input. If you want to use the GPIO as an output, you need to change the configuration
4 Configure GPIO an an interrupt source If you have a GPIO that is an input, and you have an application you want to block waiting for the GPIO to change level, you can configure the GPIO as an interrupt source. You also need to configure if the interrupt occurs when the GPIO signal has a rising edge, a falling edge, or interrupts on both rising and falling edges. Once configured as an interrupt, your application can read the value file and the read will block until the interrupt occurs, then your application will return from the read system call and continue running.

The sysfs directory /sys/class/gpio contains subdirectories and files that are used for configuring and using GPIO signals from a Linux application.

File or
directory
Meaning Notes
/sys/class/gpio sysfs GPIO subdirectory Linux applications can configuration and use GPIO signals by accessing files in this subdirectory.
/sys/class/gpio/export Write-only file to expose a GPIO Before a Linux application can configuration and use a GPIO, the GPIO first has to beexported to user space by writing the GPIO number to this file.
/sys/class/gpio/gpio<<<number>>> Subdirectory for configuring and reading a specific GPIO signal Once a GPIO has been exported to user space, a new directory appears with a set of files that allow the GPIO to be configured and used by a Linux application
/sys/class/gpio/gpio<<<number>>>/direction Read-write supporting values of inand out  
/sys/class/gpio/gpio<<<number>>>/value Read-write supporting values of 0 and1  
/sys/class/gpio/gpio<<<number>>>/edge Read-write supporting values ofrisingfalling, and both Check your processor documentation. Not all GPIO pins support interrupts.

1.2.2.Configure the kernel for GPIO support in sysfs

Symbol: GPIO_SYSFS [=y]
  Prompt: /sys/class/gpio/... (sysfs interface)
    Defined at drivers/gpio/Kconfig:51
    Depends on: GPIOLIB && SYSFS && EXPERIMENTAL
     Location:
      -> Kernel configuration
        -> Device Drivers
         -> GPIO Support (GPIOLIB [=y])

1.2.3.Enable GPIO access from user space

GPIO=22

cd /sys/class/gpio
ls
echo $GPIO > export
ls

Notice on the first ls that gpio22 doesn‘t exist, but does after you export GPIO 22 to user space.

cd /sys/class/gpio/gpio$GPIO
ls

There are files to set the direction and retrieve the current value.

echo "in" > direction
cat value

You can configure the GPIO for output and set the value as well.

echo "out" > direction
echo 1 > value

1.2.4.PIO interrupts from user space

1.2.4.1.Reference

1.2.4.2.eopoardBoard 365 GPIO 0 connection

On the LeopardBoard 365, the only GPIO I could find that was usable for interrupt input is GPIO0, also called CMOS_TRIGGER in the schematics. In looking at the schematics resistor R12 is not loaded and one of the pads connects to CMOS_TRIGGER. This R12 pad is the one closest to R11. If you hold the leopardboard 365 with the SD card slot facing you and rotate the board until the SD card slot is on the bottom edge, the the R12 pads are to the right of J6 and to the left of the SD card slot upper left corner.

1.2.4.3.sing poll() to monitor for GPIO 0 change

The gpio-int-test.c program (or gpiopin.cpp for those who prefer C++) shows one way of using the sysfs file /sys/class/gpio/gpio0/value to block program execution using poll() until the input level on GPIO0 changes. The tricky part was figuring out to use POLLPRI instead of POLLIN as the event to monitor. You must have GPIO support in sysfs for this program to work (or you will not see the /sys/class/gpio directory).

The gpio-int-test.c program uses poll() to wake up every 3 seconds (using poll() timeout mechanism) at which time it prints a period. The poll() function is also watching for input from stdin and for an interrupt from GPIO 0.

Here is an example output. I started gpio-int to watch GPIO 0. I waited around 12 seconds (4 timeout periods), then pressed the letter ‘a‘ twice followed by enter key. Then I shorted the haywire to 3.3V that is accessible on pin 5 on the JTAG connector. JTAG pin 5 is across from the JTAG missing pin). I exited the program using cntl-C.

/root # gpio-int 0 

....aa

poll() stdin read 0xA61

poll() stdin read 0xA61

poll() stdin read 0xA0A
..
poll() GPIO 0 interrupt occurred (len 0)

poll() GPIO 0 interrupt occurred (len 0)

poll() GPIO 0 interrupt occurred (len 0)

poll() GPIO 0 interrupt occurred (len 0)
..^C

2.Viewing GPIO Configuration

You can use debugfs to videw the current GPIO configuration. You may also be able to use debugfs to see if the GPIO pin is multiplex as a GPIO or is dedicated to some other function.

Configure the kernel to enable debugfs:

Symbol: DEBUG_FS [=y]
   Prompt: Debug Filesystem
     Defined at lib/Kconfig.debug:77
     Depends on: SYSFS
     Location:
       -> Kernel configuration
         -> Kernel hacking     

Boot the target hardware and mount debugfs:

mount -t debugfs none /sys/kernel/debug

Dump the GPIO configuration.

cat /sys/kernel/debug/gpio

Dump the pin multiplexing configuration.

cat /sys/kernel/debug/omap_mux/board      # for OMAP
cat /sys/kernel/debug/dm365_mux           # for DM36x

3.Example shell script making it easy to set GPIOs from the command line

If you want to have a simple way to control a GPIO signal from the Linux command line, try the gpio.sh script below.

For examaple, if you want to read the value of GPIO 72 without setting its direction, try

gpio.sh 72

If you want to force GPIO 35 to be in input and read the current value, try

gpio.sh 35 in

If you want to configure GPIO 4 to be an output and set the value high, try

gpio.sh 4 out 1

For the script below to work, you need to first make sure you have build busybox with printf enabled.

#!bin/sh

show_usage()
{
    printf "\ngpio.sh <gpio pin number> [in|out [<value>]]\n"
}

if [ \( $# -eq 0 \) -o \( $# -gt 3 \) ] ; then
    show_usage
    printf "\n\nERROR: incorrect number of parameters\n"
    exit 255
fi

#doesn‘t hurt to export a gpio more than once
echo $1 > /sys/class/gpio/export

if [  $# -eq 1 ] ; then
   cat /sys/class/gpio/gpio$1/value
   exit 0
fi

if [ \( "$2" != "in" \) -a  \( "$2" != "out" \) ] ; then
    show_usage
    printf "\n\nERROR: second parameter must be ‘in‘ or ‘out‘\n"
    exit 255
fi

echo $2 > /sys/class/gpio/gpio$1/direction

if [  $# -eq 2 ] ; then
   cat /sys/class/gpio/gpio$1/value
   exit 0
fi

VAL=$3

if [ $VAL -ne 0 ] ; then
    VAL=1
fi

echo $VAL > /sys/class/gpio/gpio$1/value

4.Example of C/C++ code making it easier to set GPIOs

/* Copyright (c) 2011, RidgeRun
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by the RidgeRun.
 * 4. Neither the name of the RidgeRun nor the
 *    names of its contributors may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY RIDGERUN ‘‘AS IS‘‘ AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL RIDGERUN BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */  

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>  

 /****************************************************************
 * Constants
 ****************************************************************/  

#define SYSFS_GPIO_DIR "/sys/class/gpio"
#define POLL_TIMEOUT (3 * 1000) /* 3 seconds */
#define MAX_BUF 64  

/****************************************************************
 * gpio_export
 ****************************************************************/
int gpio_export(unsigned int gpio)
{
    int fd, len;
    char buf[MAX_BUF];  

    fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
    if (fd < 0) {
        perror("gpio/export");
        return fd;
    }  

    len = snprintf(buf, sizeof(buf), "%d", gpio);
    write(fd, buf, len);
    close(fd);  

    return 0;
}  

/****************************************************************
 * gpio_unexport
 ****************************************************************/
int gpio_unexport(unsigned int gpio)
{
    int fd, len;
    char buf[MAX_BUF];  

    fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY);
    if (fd < 0) {
        perror("gpio/export");
        return fd;
    }  

    len = snprintf(buf, sizeof(buf), "%d", gpio);
    write(fd, buf, len);
    close(fd);
    return 0;
}  

/****************************************************************
 * gpio_set_dir
 ****************************************************************/
int gpio_set_dir(unsigned int gpio, unsigned int out_flag)
{
    int fd, len;
    char buf[MAX_BUF];  

    len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR  "/gpio%d/direction", gpio);  

    fd = open(buf, O_WRONLY);
    if (fd < 0) {
        perror("gpio/direction");
        return fd;
    }  

    if (out_flag)
        write(fd, "out", 4);
    else
        write(fd, "in", 3);  

    close(fd);
    return 0;
}  

/****************************************************************
 * gpio_set_value
 ****************************************************************/
int gpio_set_value(unsigned int gpio, unsigned int value)
{
    int fd, len;
    char buf[MAX_BUF];  

    len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);  

    fd = open(buf, O_WRONLY);
    if (fd < 0) {
        perror("gpio/set-value");
        return fd;
    }  

    if (value)
        write(fd, "1", 2);
    else
        write(fd, "0", 2);  

    close(fd);
    return 0;
}  

/****************************************************************
 * gpio_get_value
 ****************************************************************/
int gpio_get_value(unsigned int gpio, unsigned int *value)
{
    int fd, len;
    char buf[MAX_BUF];
    char ch;  

    len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);  

    fd = open(buf, O_RDONLY);
    if (fd < 0) {
        perror("gpio/get-value");
        return fd;
    }  

    read(fd, &ch, 1);  

    if (ch != ‘0‘) {
        *value = 1;
    } else {
        *value = 0;
    }  

    close(fd);
    return 0;
}  

/****************************************************************
 * gpio_set_edge
 ****************************************************************/  

int gpio_set_edge(unsigned int gpio, char *edge)
{
    int fd, len;
    char buf[MAX_BUF];  

    len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio);  

    fd = open(buf, O_WRONLY);
    if (fd < 0) {
        perror("gpio/set-edge");
        return fd;
    }  

    write(fd, edge, strlen(edge) + 1);
    close(fd);
    return 0;
}  

/****************************************************************
 * gpio_fd_open
 ****************************************************************/  

int gpio_fd_open(unsigned int gpio)
{
    int fd, len;
    char buf[MAX_BUF];  

    len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);  

    fd = open(buf, O_RDONLY | O_NONBLOCK );
    if (fd < 0) {
        perror("gpio/fd_open");
    }
    return fd;
}  

/****************************************************************
 * gpio_fd_close
 ****************************************************************/  

int gpio_fd_close(int fd)
{
    return close(fd);
}  

/****************************************************************
 * Main
 ****************************************************************/
int main(int argc, char **argv, char **envp)
{
    struct pollfd fdset[2];
    int nfds = 2;
    int gpio_fd, timeout, rc;
    char *buf[MAX_BUF];
    unsigned int gpio;
    int len;  

    if (argc < 2) {
        printf("Usage: gpio-int <gpio-pin>\n\n");
        printf("Waits for a change in the GPIO pin voltage level or input on stdin\n");
        exit(-1);
    }  

    gpio = atoi(argv[1]);  

    gpio_export(gpio);
    gpio_set_dir(gpio, 0);
    gpio_set_edge(gpio, "rising");
    gpio_fd = gpio_fd_open(gpio);  

    timeout = POLL_TIMEOUT;  

    while (1) {
        memset((void*)fdset, 0, sizeof(fdset));  

        fdset[0].fd = STDIN_FILENO;
        fdset[0].events = POLLIN;  

        fdset[1].fd = gpio_fd;
        fdset[1].events = POLLPRI;  

        rc = poll(fdset, nfds, timeout);        

        if (rc < 0) {
            printf("\npoll() failed!\n");
            return -1;
        }  

        if (rc == 0) {
            printf(".");
        }  

        if (fdset[1].revents & POLLPRI) {
            len = read(fdset[1].fd, buf, MAX_BUF);
            printf("\npoll() GPIO %d interrupt occurred\n", gpio);
        }  

        if (fdset[0].revents & POLLIN) {
            (void)read(fdset[0].fd, buf, 1);
            printf("\npoll() stdin read 0x%2.2X\n", (unsigned int) buf[0]);
        }  

        fflush(stdout);
    }  

    gpio_fd_close(gpio_fd);
    return 0;
}  
时间: 2024-10-13 15:44:17

[sysfs]Linux GPIO简单使用方式的相关文章

Linux内核调试的方式以及工具集锦

CSDN GitHub Linux内核调试的方式以及工具集锦 LDD-LinuxDeviceDrivers/study/debug 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作 因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 也欢迎大家提供一些其他好的调试工具以供收录, 鄙人在此谢谢啦 "调试难度本来就是写代码的两倍. 因此, 如果你写代码的时候聪明用尽, 根据定义, 你就没有能耐去调试它了.&qu

Linux 进程间通讯方式 pipe()函数 (转载)

转自:http://blog.csdn.net/ta893115871/article/details/7478779 Linux 进程间通讯方式有以下几种: 1->管道(pipe)和有名管道(fifo). 2->消息队列 3->共享内存 4->信号量 5->信号(signal) 6->套接字(sicket) 在这里我们看一下第一种====管道(pipe).有名管道(fifo)见其它文章. eg :我们以前学的命令 cat  file | grep  "abc

Linux之简单命令之日期时间命令之date,cal,clock ,hwclock和tzselect

一.date命令: 在linux环境中,不管是编程还是其他维护,时间是必不可少的,也经常会用到时间的运算,熟练运用date命令来表示自己想要表示的时间,肯定可以给自己的工作带来诸多方便. 1.命令格式: date [参数]... [+格式] 2.命令功能: date 可以用来显示或设定系统的日期与时间. 3.命令参数: 必要参数: %H 小时(以00-23来表示).  %I 小时(以01-12来表示).  %K 小时(以0-23来表示).  %l 小时(以0-12来表示).  %M 分钟(以00

Thinkbox.Deadline.v8.0.4.1.Linux 1DVD简单易用的管理和渲染+Xpedition Enterprise VX.2.1

Allen Bradley RSLogix5 v8.0 Win32-ISO 1DVD 使用RSLogix 5000 软件可以完全实现对模块的设置和监视 通过I/O 实现ControlLogix 背板连接 所有模块相关数据都包含在一个处理器数据对象中,这便于配置,监视和连接模块参数.RSLogix 5000功能更加强大,更加方便实用.RsLogix 5000编程软件除了为顺序控制提供梯形图编程外,还可以为运动控制提供完整的编程及调试支持.RSLogix 5000可同时完成顺序控制与运动控制. Sy

Linux的简单介绍和常用命令的介绍

Linux的简单介绍和常用命令的介绍 本说明以Ubuntu系统为例 Ubuntu系统的安装自行百度,或者参考http://www.cnblogs.com/CoderJYF/p/6091068.html 自行安装 Linux简介及Ubuntu安装 Linux,免费开源,多用户多任务系统.基于Linux有多个版本的衍生.RedHat.Ubuntu.Debian 安装VMware或VirtualBox虚拟机.具体安装步骤,找百度. 再安装Ubuntu.具体安装步骤,找百度 常用指令 ls      

Linux的简单操作

du -h --max-depth=1 work/testing   查看文件的大小 df -h 查看硬盘的大小和使用情况 df   大概情况同上 rm -f 强制删除 rm -rf 强制递归删除 cp -rp ./top/* ./sharm/   递归复制 mysql -u 数据库名 -p 数据库名 >site.sql   复制数据库 chmod -R 777 添加权限 chown -R admin chgrp -R admin 用户及用户组管理命令 1.useradd命令 useradd l

Win7激活后添加grub引导Linux最简单方法

因为Win7(Vista同理)的激活方式是通过grub摸你OEM的Slic信息,所以主引导分区MBR被这个grub占用,以此才能激活WIn7.但是如果想同时安装Linux在别的分区,就会产生问题:grub不能往MBR添加,否则会破坏Win7的激活.网上有一些复杂的方法,但是要输入一大堆命令行.这里提供自己摸索的最简单的无需命令行的方法.而且重装win7或者linux都可以很容易修复.1.正常安装Win7到C盘,并激活.2.正常安装Linux到其他分区,最后要求写入grub时,选择Linux挂载点

Linux GPIO键盘驱动开发记录_OMAPL138

Linux GPIO键盘驱动开发记录_OMAPL138 Linux基本配置完毕了,这几天开始着手Linux驱动的开发,从一个最简单的键盘驱动开始,逐步的了解开发驱动的过程有哪些.看了一下Linux3.3内核文件下的driver目录,点开里面的C文件,感觉底层的Linux驱动机制还是很复杂的,还需要一段漫长时间的学习.现在开发的也不能说是叫做驱动,也只能说是驱动的应用,我们学习驱动也从应用逐步开始,往里面深入吧. 0.开发准备 内核源文件(当时我们编译内核时候的目录,很重要,编译驱动的时候需要依赖

一个linux下简单的纯C++实现Http请求类(GET,POST,上传,下载)

目录 一个linux下简单的纯C++实现Http请求类(GET,POST,上传,下载) Http协议简述 HttpRequest类设计 请求部分 接收部分 关于上传和下载 Cpp实现 关于源码中的Logger 使用示例 一个linux下简单的纯C++实现Http请求类(GET,POST,上传,下载) 最近写了点关于Http上传下载文件相关的,于是今天整理下代码. Http协议简述 HttpRequest类设计 使用示例 Http协议简述 协议:网络协议的简称,网络协议是通信计算机双方必须共同遵从