Documentation:Linux/GPIO,应用层写/sys/class/gpio/export文件,创建gpio107 gpio108等
Contents[hide]1 Interfacesexplained2 gpio-dev3 gpio-sysfs3.1 Filestructure3.2 GPIONumbers3.3 Gettingaccess to a GPIO3.4 Gettingand Setting Direction3.5 Gettingand Setting S
Contents[hide] |
Interfaces explained
There are 2 main ways which can be used to talk to gpio pins on an AVR32 from userspace:
- gpio-dev is an AVR32-specific interface, shipped only in .atmel kernels. You can change the state of a number of GPIOs at one time and you can receive pin change notifications by means of a blocking read. It can only deal with gpio inside the AVR32, not on an I/O expander.
- gpio-sysfs is a user interface to the in kernel gpio framework. As such you have the same interface no matter what platform you're developing for. It deals with pins strictly one at a time. It is available in all mainline kernels from 2.6.27 onwards. At the time of writing it does not have support for pin change notification but patches to implement this exist, just message Squidgit and he'll get them to you. gpio-sysfs also doesn't care whether the gpios are built in to the AVR32 or whether they're on an external gpio expander, they're all interfaced the same way.
If you're inside the kernel then you've got one option:
- gpio framework. This is the name of the framework through which gpios are accessed from within the kernel. gpio-sysfs is built on top of this for userspace access.
gpio-dev
NOTE: This method of I/O is depriciated and not suggested to use for new code. Use the gpio-sysfs instead.UPDATE: gpio-dev has been completely removed from Atmel kernels and Buildroot version 2.3.0 and newer. Use of sysfs is now mandatory for new systems.
Many others have shown how to use gpio-dev, I won't repeat their work here.
- GPIO device and sample C code to access GPIO (external link)
- LED's
- Reading a Switched Input
- Newbie Project 4 Push Buttons turns LED on/off
gpio-sysfs
gpio-sysfs is the preferred method of gpio interfacing from userspace. Use this unless you absolutely need to update multiple gpios simultaniously or you must use a kernel version before 2.6.27. The full documentation is alongside the gpio-framework documentation, here.
File structure
The control files are all contained in
#: ls/sys/class/gpio export gpiochip0 gpiochip32 gpiochip96 gpiochip128 gpiochip64 unexport
Initially all that is in this folder are gpiochipN folders. There is one of these for each chip which provides gpio pins. On an AT32AP7000 for example, you have 4 gpiochipN folders corresponding to Ports A, B, C, D and E. Note that inside the kernel, Porta A through E and actually called pio0 through pio4 respectively. You can find out which gpiochip folder is which by examinging the "label" file in each one of those folders. For example gpiochip32 corresponds to pio1/PortB:
#: cat /sys/class/gpio/gpiochip32/label pio1
For any gpios which have been exported for userspace access, you'll also see a gpioN folder where N is the number of the gpio. More on this shortly.
GPIO Numbers
To get access to a gpio, you must find the gpio number. This is done by finding the base number of the chip to which that gpio belongs then adding the number of the pin on that chip. For example, PC8 is the Port C base plus 8.
Each base can be found by looking in the "base" file of the corresponding gpiochipN folder. It's also the number at the end of the folder name. So in this example, we're looking for Port C, called pio2. This label is found in the gpiochip64 folder and as such the base number is 64. We want pin 8 so 8 + 64 is 72, this is our gpio number.
NOTE: This may sound complex but for chips which are always attached, like ones built in to the AVR32 chip, the numbers stay the same. You can find the gpio number once and use it for all time.
If you have any I/O expanders connected to, eg, the SPI bus, they'll have their own gpiochip folders here. The base numbers for these detachable expanders may change so you should find the base number and recalculate the gpio number each time the board starts up or the adapter is plugged in.
[edit] Getting access to a GPIO
Some times the kernel has already given you access to a gpio. If so you'll see gpioN folders in /sys/class/gpio where N is the gpio number. If you don't have this folder already, you need to create it. Once you've got the GPIO number, you request it from the kernel. Do this by writing the gpio number to the export file like
#: echo 72 > /sys/class/gpio/export
Once you've done this you'll see a folder, /sys/class/gpio/gpio72. In this folder you'll see the attributes needed to control the gpio.
#: ls /sys/class/gpio/gpio72 device power uevent direction subsystem value
Out of all of these, you only need to pay attention to "value" and "direction".
If you don't need control of the gpio anymore, you can unexport it
#: echo 72 > /sys/class/gpio/unexport
Getting and Setting Direction
To set the direction, write one of "in", "out", "high" or "low" to your gpio's direction attribute. "low" and "out" have the same effect, to change the pin to an output which is initially low. "high" changes the pin to an output which is initially high. "in" changes the pin to an input.
This file will read as "in" or "out" so you can tell the direction.
#: echo "high" > /sys/class/gpio/gpio72/direction #: cat /sys/class/gpio/gpio72/direction out
Please note on a custom built 2.6.27 kernel using Buildroot, Dingo_aus found he needed to use
#: echo out > /sys/class/gpio/gpio72/direction instead of #: echo "high" > /sys/class/gpio/gpio72/direction
Getting and Setting State
To set an output high or low, write a '1' or '0' to the value attribute. To read the value, just read this file.
Putting it all together
Right, lets put it all together and get access to PB2, set it to an initially high output, check that it has worked, set the output low then change it to an input and read the state.
#: cat /sys/class/gpio/gpiochip0/label pio0 #: cat /sys/class/gpio/gpiochip32/label pio1 #: cat /sys/class/gpio/gpiochip32/base 32So we've found that Port B (pio1) is gpiochip32, the base is 32. We want pin 2 of this so our gpio number is 34
#: echo 34 > /sys/class/gpio/export #: echo "high" > /sys/class/gpio/gpio34/direction #: cat /sys/class/gpio/gpio34/direction out #: cat /sys/class/gpio/gpio34/value 1 #: echo 0 > /sys/class/gpio/gpio34/value #: cat /sys/class/gpio/gpio34/value 0 #: echo "in" > /sys/class/gpio/gpio34/direction #: cat /sys/class/gpio/gpio34/value [some value]
Done!
Example of GPIO access from within a C program
The following a sample C program to blink PB3 at 1Hz on the AP7000.
// Blink pin 3 on port B at 1 Hz // Just add an LED and see the light! ;) // //Created by Dingo_aus, 7 January 2009 //email: dingo_aus [at] internode <dot> on /dot/ net // //Created in AVR32 Studio (version 2.0.2) running on Ubuntu 8.04 #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> FILE *fp; int main(int argc, char** argv) { printf("\n**********************************\n" "* Welcome to PIN Blink program *\n" "* ....blinking pin 3 on port B *\n" "* ....rate of 1 Hz............ *\n" "**********************************\n"); //create a variable to store whether we are sending a '1' or a '0' char set_value[4]; //Integer to keep track of whether we want on or off int toggle = 0; //Using sysfs we need to write "37" to /sys/class/gpio/export //This will create the folder /sys/class/gpio/gpio37 if ((fp = fopen("/sys/class/gpio/export", "ab")) == NULL) { printf("Cannot open export file.\n"); exit(1); } //Set pointer to begining of the file rewind(fp); //Write our value of "37" to the file strcpy(set_value,"37"); fwrite(&set_value, sizeof(char), 2, fp); fclose(fp); printf("...export file accessed, new pin now accessible\n"); //SET DIRECTION //Open the LED's sysfs file in binary for reading and writing, store file pointer in fp if ((fp = fopen("/sys/class/gpio/gpio37/direction", "rb+")) == NULL) { printf("Cannot open direction file.\n"); exit(1); } //Set pointer to begining of the file rewind(fp); //Write our value of "out" to the file strcpy(set_value,"out"); fwrite(&set_value, sizeof(char), 3, fp); fclose(fp); printf("...direction set to output\n"); //SET VALUE //Open the LED's sysfs file in binary for reading and writing, store file pointer in fp if ((fp = fopen("/sys/class/gpio/gpio37/value", "rb+")) == NULL) { printf("Cannot open value file.\n"); exit(1); } //Set pointer to begining of the file rewind(fp); //Write our value of "1" to the file strcpy(set_value,"1"); fwrite(&set_value, sizeof(char), 1, fp); fclose(fp); printf("...value set to 1...\n"); //Run an infinite loop - will require Ctrl-C to exit this program while(1) { //Set it so we know the starting value in case something above doesn't leave it as 1 strcpy(set_value,"1"); if ((fp = fopen("/sys/class/gpio/gpio37/value", "rb+")) == NULL) { printf("Cannot open value file.\n"); exit(1); } toggle = !toggle; if(toggle) { //Set pointer to begining of the file rewind(fp); //Write our value of "1" to the file strcpy(set_value,"1"); fwrite(&set_value, sizeof(char), 1, fp); fclose(fp); printf("...value set to 1...\n"); } else { //Set pointer to begining of the file rewind(fp); //Write our value of "0" to the file strcpy(set_value,"0"); fwrite(&set_value, sizeof(char), 1, fp); fclose(fp); printf("...value set to 0...\n"); } //Pause for one second sleep(1); } return 0; }
When executed on your board the expected output will be similar to the following:
/home/dingo # ./first_pin_blink.elf ********************************** * Welcome to PIN Blink program * * ....blinking pin 3 on port B * * ....rate of 1 Hz............ * ********************************** ...export file accessed, new pin now accessible ...direction set to output ...value set to 1... ...value set to 1... ...value set to 0... ...value set to 1... ^C /home/dingo #
更多推荐
所有评论(0)