zoukankan      html  css  js  c++  java
  • [gpio]Linux GPIO简单使用方式1-sysfs

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

    1.1.References

    1.2.GPIO Usage from a Linux Application

         1.2.1Overview

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

    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.

    StepActionDescription
    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
    MeaningNotes
    /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.

    Leopardboard365-gpio0-haywire.jpg

    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 "
    gpio.sh <gpio pin number> [in|out [<value>]]
    "
    }
    
    if [ ( $# -eq 0 ) -o ( $# -gt 3 ) ] ; then
        show_usage
        printf "
    
    ERROR: incorrect number of parameters
    "
        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 "
    
    ERROR: second parameter must be 'in' or 'out'
    "
        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>
    
    ");  
            printf("Waits for a change in the GPIO pin voltage level or input on stdin
    ");  
            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("
    poll() failed!
    ");  
                return -1;  
            }  
            
            if (rc == 0) {  
                printf(".");  
            }  
                  
            if (fdset[1].revents & POLLPRI) {  
                len = read(fdset[1].fd, buf, MAX_BUF);  
                printf("
    poll() GPIO %d interrupt occurred
    ", gpio);  
            }  
      
            if (fdset[0].revents & POLLIN) {  
                (void)read(fdset[0].fd, buf, 1);  
                printf("
    poll() stdin read 0x%2.2X
    ", (unsigned int) buf[0]);  
            }  
      
            fflush(stdout);  
        }  
      
        gpio_fd_close(gpio_fd);  
        return 0;  
    }  
  • 相关阅读:
    关于神奇的MD5算法21
    【转】C# 轻松实现对窗体(Form)换肤
    个人代码库のXML操作演练
    个人代码库の自定义后缀名
    个人代码库の自定义不规则窗体和控件
    个人代码库の创建快捷方式
    jquery 实现省市级联动
    分析器错误消息: 无法识别的属性“targetFramework”。请注意属性名称区分大小写
    EXTJS 面板控件panel应用
    HTTP 错误 500.21 Internal Server Error处理程序
  • 原文地址:https://www.cnblogs.com/aaronLinux/p/6684260.html
Copyright © 2011-2022 走看看