Using BeagleBone Black GPIOs read by c

board/beaglebone Black 2013. 9. 5. 17:04

from : https://gist.github.com/ajmontag/4013192


C program that listens for button presses on a Beaglebone GPIO pin and reports the press duration.



gpio.c
C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
/**
* Title: gpio.c
*
* Author: Andrew Montag
* ajmontag@gmail.com
* sites.google.com/site/andrewmontag
*
* Licence: Boost Software Licence - Verison 1.0
* http://www.boost.org/users/license.html
*
* Purpose:
* Helpers for configuring and accessing GPIO pins.
*/
 
/**
* Original source from
* https://www.ridgerun.com/developer/wiki/index.php/Gpio-int-test.c
* as example code.
* Modularized by Andrew Montag, 10/30/2012
*
* 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 "gpio.h"
 
#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 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];
 
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;
}
 
gpio_get_value_fd(fd, value);
 
close(fd);
return 0;
}
 
int gpio_get_value_fd(int fd, unsigned int *value)
{
char ch;
 
read(fd, &ch, 1);
 
if (ch != '0') {
*value = 1;
} else {
*value = 0;
}
 
return 0;
}
 
/****************************************************************
* gpio_set_edge
****************************************************************/
 
int gpio_set_edge(unsigned int gpio, const 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);
}
gpio.h
C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
/**
* Title: gpio.h
*
* Author: Andrew Montag
* ajmontag@gmail.com
* sites.google.com/site/andrewmontag
*
* Licence: Boost Software Licence - Verison 1.0
* http://www.boost.org/users/license.html
*
* Purpose:
* Helpers for configuring and accessing GPIO pins.
*/
 
#ifndef _GPIO_H_
#define _GPIO_H_
 
/**
* @ return 0 on success
*
* @param gpio the gpio pin number.
* If the pin is GPIOm_n, then the pin number is
* m * 32 + n. Example: GPIO3_21 = 3*32+21 = 117
*/
 
/**
* gpio_export
* export a gpio pin for use in the user space.
* must be called before the pin can be used.
*/
int gpio_export(unsigned int gpio);
 
 
/**
* gpio_unexport
* undo the export action.
*/
int gpio_unexport(unsigned int gpio);
 
#define GPIO_DIR_INPUT (0)
#define GPIO_DIR_OUTPUT (1)
 
/**
* gpio_set_dir
* @param out_flag true=output, false=input
*/
int gpio_set_dir(unsigned int gpio, unsigned int out_flag);
 
 
/**
* gpio_set_value
* writes the boolean value to the pin.
*/
int gpio_set_value(unsigned int gpio, unsigned int value);
 
 
/**
* gpio_get_value
* reads the state of the pin.
* @param as return, 0 or 1
*/
int gpio_get_value(unsigned int gpio, unsigned int *value);
 
/** @param fd an fd opened using gpio_fd_open */
int gpio_get_value_fd(int fd, unsigned int *value);
 
 
static const char* kPollEdge_rising = "rising";
static const char* kPollEdge_falling = "falling";
static const char* kPollEdge_both = "both";
 
/**
* gpio_set_edge
* @param edge should be "rising", "falling", or "both"
*/
int gpio_set_edge(unsigned int gpio, const char *edge);
 
 
/**
* gpio_fd_open
* @return an open an fd for later use.
* useful when using poll().
*/
int gpio_fd_open(unsigned int gpio);
 
 
/**
* gpio_fd_close
* close an open fd.
*/
int gpio_fd_close(int fd);
 
#endif
press_duration.c
C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
/**
* Title: press_duration.c
*
* Author: Andrew Montag
* ajmontag@gmail.com
* sites.google.com/site/andrewmontag
*
* Licence: Boost Software Licence - Verison 1.0
* http://www.boost.org/users/license.html
*
* Purpose:
* A program which listens for button presses on a GPIO pin and reports the
* press duration.
*
*/
 
#include "gpio.h"
 
#include <sys/time.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
 
#define POLL_TIMEOUT_30_SEC (30 * 1000)
#define POLL_TIMEOUT_20_SEC (20 * 1000)
#define POLL_TIMEOUT_10_SEC (10 * 1000)
#define POLL_TIMEOUT_5_SEC (5 * 1000)
#define POLL_TIMEOUT_2_SEC (2 * 1000)
#define POLL_TIMEOUT_1_SEC (1 * 1000)
#define POLL_TIMEOUT_INF (-1)
 
#define MAX_BUF 64
 
void report_button_ms(int duration) {
printf("button pressed for %d ms.\n", duration);
}
 
int main(int argc, char **argv, char **envp)
{
struct pollfd pollfdset;
const int nfds = 1;
int timeout, rc;
char *buf[MAX_BUF];
unsigned int gpio;
int len;
 
// gpio pin number
if (argc < 2) {
printf("Usage: gpio-int <gpio-pin>\n\n");
printf("Reports button press duration on a gpio pin\n");
exit(-1);
}
 
gpio = atoi(argv[1]);
 
// export and configure the pin for our usage
gpio_export(gpio);
gpio_set_dir(gpio, GPIO_DIR_INPUT);
 
// stuff the poll structure
memset((void*) &pollfdset, 0, sizeof(pollfdset));
pollfdset.fd = gpio_fd_open(gpio);
pollfdset.events = POLLPRI;
 
// clear any backed up events
// XXX I'm not sure why we need this, but without it we get a false
// report of an edge from the first poll()
rc = poll(&pollfdset, nfds, 0);
len = read(pollfdset.fd, buf, MAX_BUF);
 
while (1) {
//printf("waiting for rising edge.\n");
 
// wait for rising edge, button press
pollfdset.revents = 0;
gpio_set_edge(gpio, kPollEdge_rising);
rc = poll(&pollfdset, nfds, POLL_TIMEOUT_INF);
len = read(pollfdset.fd, buf, MAX_BUF);
 
if (rc < 0) {
// TODO error
printf("\npoll() failed!\n");
return -1;
} /* else if (rc == 0) timeout */
 
if (pollfdset.revents & POLLPRI) {
// rising edge occurred
printf("rising edge!\n");
 
// make note of the time of the rising edge
struct timeval starttv;
gettimeofday(&starttv, NULL);
 
// now wait for the falling edge
gpio_set_edge(gpio, kPollEdge_falling);
 
// the button is currently being held down
int duration = -1;
while (duration < 0) {
//printf("waiting for falling edge\n");
pollfdset.revents = 0;
rc = poll(&pollfdset, nfds, POLL_TIMEOUT_5_SEC);
len = read(pollfdset.fd, buf, MAX_BUF);
 
if (rc < 0) {
printf("error!\n");
// TODO error
duration = 0;
} else if (0 == rc) {
// timeout, check the state of the button to make sure we didn't miss the edge
printf("timeout while waiting for falling edge\n");
 
unsigned int value = 0xFFFF;
rc = gpio_get_value_fd(pollfdset.fd, &value);
if (0 == value) {
// button is released, but we missed the falling edge
// report a very short duration
printf("Button falling edge missed!\n"); // debug only
duration = 1;
} else if (1 == value) {
// the button is still pressed, carry on
printf("Button still pressed\n");
}
 
if (rc < 0) {
printf("error2!");
// TODO error
duration = 0;
}
}
 
if (pollfdset.revents & POLLPRI) {
// falling edge occurred
printf("falling edge!\n");
 
// make note of the falling edge time
struct timeval endtv;
gettimeofday(&endtv, NULL);
 
// subtract the times and convert millisecond
struct timeval difftv;
timersub(&endtv, &starttv, &difftv);
duration = (difftv.tv_sec) * 1000 + (difftv.tv_usec) / 1000 ;
assert(duration >= 0); // XXX assert?
}
} // end while duration < 0
 
report_button_ms(duration);
 
}
 
}
 
// TODO unexport and put in the SIGTERM handler
gpio_fd_close(pollfdset.fd);
return 0;
}


일단 컴파일 혀서 타겟에다가 옮겨 놓습니다.


그러고

# ./filename 60 실행

P9의 12번 핀과 2번핀 사이에 스위치나 저항을 달아서 확인 합니다.


실행화면은 아래와 같이...


root@beaglebone:~# ./press 60

rising edge!

falling edge!

button pressed for 0 ms.

rising edge!

falling edge!

button pressed for 2320 ms.

rising edge!

falling edge!

button pressed for 0 ms.

rising edge!

falling edge!

button pressed for 1 ms.

rising edge!

falling edge!

button pressed for 2226 ms.

rising edge!

falling edge!

button pressed for 0 ms.

rising edge!

falling edge!

button pressed for 1 ms.

rising edge!

falling edge!

button pressed for 1 ms.

rising edge!

falling edge!

button pressed for 0 ms.

rising edge!

falling edge!

button pressed for 0 ms.

rising edge!

falling edge!

button pressed for 1 ms.

rising edge!

falling edge!

button pressed for 2937 ms.

rising edge!

timeout while waiting for falling edge

Button still pressed

timeout while waiting for falling edge

Button still pressed

timeout while waiting for falling edge

Button still pressed

timeout while waiting for falling edge

Button still pressed

timeout while waiting for falling edge

Button still pressed



일단 성공~~~~~~~ 분석은 나중에....

BeagleBone Black – Controlling user LEDs using C/C++

board/beaglebone Black 2013. 9. 5. 15:53

from : http://learnbuildshare.wordpress.com/2013/05/19/beaglebone-black-controlling-user-leds-using-c/

The $45 BeagleBone Black is here! With all its GPIO ports, it can be a great tool for robotics projects. It ships with javascript example code (in the Cloud9 IDE). There are many examples on the internet showing pin manipulation with javascript and python. There are lots of examples on pin manipulation from the terminal. Unfortunately for a new BBB owner, I could only find suggestions on how to do this on C/C++. I could not find a complete, short, and plain C/C++ example which I could just copy and use as a starting point…something like the traditional “blink” example. Some people have posted their own C++ libraries for pin manipulation, but I find that confusing without understanding the basic concepts.

After a lot of digging, ssh-ing, and g++-ing, I finally got a “blink” example up and running on C++. Here it is. Hopefully, for all the new BBB users out there, this can serve as a starting point in understanding how to use the GPIO ports through C/C++.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/*******************************************************
 * Example code for user LEDs on the new beaglebone
 * black running the Linux Angstrom distribution
 ********************************************************
 * Instructions:
 * -Compile and run from the root directory
 * -For the older (white) beaglebone, change
 *  "beaglebone:green:usr0" to "beaglebone::usr0"
 *
 * Code adapted from:
 * - Derek Molloy, "Beaglebone: C/C++ Programming
 * Introduction for ARM Embedded Linux Development
 * using Eclipse CDT" video tutorial,
 * (link: www.youtube.com/watch?v=vFv_-ykLppo)
 * -  Mark A. Yoder, EBC Exercise 10 Flashing an LED
 * (link: "elinux.org/EBC_Exercise_10_Flashing_an_LED)
 *******************************************************/
 
#include <stdio.h>
#include <unistd.h>
 
using namespace std;
 
int main(int argc, char** argv) {
 
  FILE *LEDHandle = NULL;
  char *LEDBrightness = "/sys/class/leds/beaglebone:green:usr0/brightness";
  printf("\nStarting simple LED blink program\n");
 
  while(1){
 
    if((LEDHandle = fopen(LEDBrightness, "r+")) != NULL){
      fwrite("1", sizeof(char), 1, LEDHandle);
      fclose(LEDHandle);
    }
 
    sleep(0.3);
 
    if((LEDHandle = fopen(LEDBrightness, "r+")) != NULL){
      fwrite("0", sizeof(char), 1, LEDHandle);
      fclose(LEDHandle);
    }
 
    sleep(0.8);
  }
  return 0;
 
}



# g++ led.cpp -o led


Using BeagleBone Black GPIOs by bash script

board/beaglebone Black 2013. 9. 5. 15:19

Using BeagleBone Black GPIOs

To control digital input / outputs for the BeagleBone Black, you can use the facilities exposed by the kernel in the/sys/class/gpio directory. Note that the BeagleBone White pinouts are different from the BeagleBone Black. Also note that the GPIOs available on the BBW have changed between revisions, so be certain to get the proper technical reference manual for your actual board revision.

After boot, nothing is exported for use, but we do see the four GPIO controllers (gpio0, gpio1, gpio2, andgpio3):

# ls -al /sys/class/gpio
total 0
drwxr-xr-x  2 root root    0 May 26 15:40 .
drwxr-xr-x 45 root root    0 Jan  1  2000 ..
--w-------  1 root root 4096 May 26 15:48 export
lrwxrwxrwx  1 root root    0 May 26 15:45 gpiochip0 -> ../../devices/virtual/gpio/gpiochip0
lrwxrwxrwx  1 root root    0 May 26 15:45 gpiochip32 -> ../../devices/virtual/gpio/gpiochip32
lrwxrwxrwx  1 root root    0 May 26 15:45 gpiochip64 -> ../../devices/virtual/gpio/gpiochip64
lrwxrwxrwx  1 root root    0 May 26 15:45 gpiochip96 -> ../../devices/virtual/gpio/gpiochip96
--w-------  1 root root 4096 May 26 15:45 unexport

Note that each GPIO controller is offset by 32 from the previous (0, 32, 64, 96) — more on this later.

Not all GPIO pins are available by default. A lot of frustration may come from not knowing this — sometimes when it appears that all should be working, it does not. The microcontroller needs to be reconfigured to enable some of the pin modes. To understand what may be available, you need to study table 10 on page 70 for the P8 header and table 11 on page 72 for the P9 header in the BeagleBone Black System Reference Manual. Pay close attention to which header is P8 and which is P9 (page 68) because they feel backwards to me.

In this example, I will export P9 header GPIO pins 12, 14, 15, 16. Referencing page 72 mode 7 column, it shows pin 12 to be gpio1[28], pin 14 to be gpio1[18], pin 15 to be gpio1[16], pin 16 to be gpio1[19]. All of these pins are on the gpio1 controller (gpiochip32). To get to the GPIO number that should be exported from the kernel, we must add on 32 to each GPIO (64 for gpio2, and 96 for gpio3). Therefore gpio1[28] = 32 + 28 = 60. I will just do all the math here and we will refer to them by the kernel nomenclature and stop with the gpio1[x] business as it gets confusing.

요건 조금 거시기 한데. 결론인 즉은

GPIO 0는 그대로 GPIO[몇번]이고, GPIO1은 32+GPIO[몇번]이라는 말씀. GPIO가 32개 단위로 짤리는듯.

GPIO1_28 : pin 12 --> gpio60 : 32+GPIO1[28]
EHRPWM1A : pin 14 --> gpio50 : 32+GPIO1[18]
EHRPWM1B: pin 15 --> gpio48 : 32+GPIO1[16]
GPIO1_14 : pin 16 --> gpio51 : 32+GPIO1[19]

Now that we have a relationship between the P9 header physical pins and what the kernel is calling them, we can begin configuration. To make this example easy to follow, I am just going to use bash scripts, but all of the same principles apply to the file manipulation APIs in your favorite language.

In this example, we will be configuring all four pins to be digital outputs. To do so, we need to copy the gpio number we want to export into the kernel gpiolib /sys/class/gpio/export file.

echo 48 > /sys/class/gpio/export
echo 50 > /sys/class/gpio/export
echo 51 > /sys/class/gpio/export
echo 60 > /sys/class/gpio/export

Afterward we can see there are four new subdirectories for each of the gpios:

# ls -al /sys/class/gpio
total 0
drwxr-xr-x 2 root root    0 May 26 15:40 ./
drwxr-xr-x 45 root root   0 Jan  1  2000 ../
--w------- 1 root root 4096 May 26 16:25 export
lrwxrwxrwx 1 root root    0 May 26 16:25 gpio48 -> ../../devices/virtual/gpio/gpio48/
lrwxrwxrwx 1 root root    0 May 26 16:25 gpio50 -> ../../devices/virtual/gpio/gpio50/
lrwxrwxrwx 1 root root    0 May 26 16:25 gpio51 -> ../../devices/virtual/gpio/gpio51/
lrwxrwxrwx 1 root root    0 May 26 16:25 gpio60 -> ../../devices/virtual/gpio/gpio60/
lrwxrwxrwx 1 root root    0 May 26 15:45 gpiochip0 -> ../../devices/virtual/gpio/gpiochip0/
lrwxrwxrwx 1 root root    0 May 26 15:45 gpiochip32 -> ../../devices/virtual/gpio/gpiochip32/
lrwxrwxrwx 1 root root    0 May 26 15:45 gpiochip64 -> ../../devices/virtual/gpio/gpiochip64/
lrwxrwxrwx 1 root root    0 May 26 15:45 gpiochip96 -> ../../devices/virtual/gpio/gpiochip96/
--w------- 1 root root 4096 May 26 15:45 unexport

And the contents of one of the gpio subdirectories:

# ls -alH /sys/class/gpio/gpio48
total 0
drwxr-xr-x  3 root root    0 May 26 16:25 .
drwxr-xr-x 10 root root    0 May 26 15:45 ..
-rw-r--r--  1 root root 4096 May 26 16:29 active_low
-rw-r--r--  1 root root 4096 May 26 16:29 direction
-rw-r--r--  1 root root 4096 May 26 16:29 edge
drwxr-xr-x  2 root root    0 May 26 16:29 power
lrwxrwxrwx  1 root root    0 May 26 16:25 subsystem -> ../../../../class/gpio
-rw-r--r--  1 root root 4096 May 26 16:25 uevent
-rw-r--r--  1 root root 4096 May 26 16:29 value

There are several configuration options available to each gpio. I suggest you read the Linux GPIO Interfaces manual for all of the details. I am only covering the basics here, and the Linux GPIO Interfaces manual is a very important read to understanding Linux gpio control.

Next we must specify if the exported gpio is input or output. It does not make sense to configure anything else ahead of this and as far as I know, the kernel doesn’t let you do anything else with it until you set the gpio as input or output.

To set a gpio as output, we set its direction as in or out. For outputs there is an alternative nomenclature where output direction can be set instead as high or low to help with glitch free operation. I’ll use this nomenclature:

echo high > /sys/class/gpio/gpio48/direction
echo high > /sys/class/gpio/gpio50/direction
echo high > /sys/class/gpio/gpio51/direction
echo high > /sys/class/gpio/gpio60/direction

Pins 12, 14, 15, 16 are now configured as outputs and are currently high — these pins will now be reading 3.3v. Do not use 5v TTL logic parts or you will damage the board.

Finally, we will set the pins low which will depower them:

echo 0 > /sys/class/gpio/gpio48/value
echo 0 > /sys/class/gpio/gpio50/value
echo 0 > /sys/class/gpio/gpio51/value
echo 0 > /sys/class/gpio/gpio60/value

Putting this all together, this script will configure and run a binary counter that will overflow and start at zero again. It is kind of cool to watch if you hook relays up to the board.

내용중에 빈칸 않해줘서 에러 작렬!!! 조심.

#!/bin/bash -e

if [ ! -d /sys/class/gpio/gpio48 ]; then echo 48 > /sys/class/gpio/export; fi
if [ ! -d /sys/class/gpio/gpio50 ]; then echo 50 > /sys/class/gpio/export; fi
if [ ! -d /sys/class/gpio/gpio51 ]; then echo 51 > /sys/class/gpio/export; fi
if [ ! -d /sys/class/gpio/gpio60 ]; then echo 60 > /sys/class/gpio/export; fi

echo low > /sys/class/gpio/gpio48/direction
echo low > /sys/class/gpio/gpio50/direction
echo low > /sys/class/gpio/gpio51/direction
echo low > /sys/class/gpio/gpio60/direction

for (( i=0 ; ; ++i ))
do
   if (( i > 0x0f )); then
      i=0
      printf '\n[press  + c to stop]\n\n'
   fi

   bit0=$(( (i & 0x01) > 0 ))
   bit1=$(( (i & 0x02) > 0 ))
   bit2=$(( (i & 0x04) > 0 ))
   bit3=$(( (i & 0x08) > 0 ))
   echo $bit3 $bit2 $bit1 $bit0

   echo $bit0 > /sys/class/gpio/gpio60/value
   echo $bit1 > /sys/class/gpio/gpio50/value
   echo $bit2 > /sys/class/gpio/gpio48/value
   echo $bit3 > /sys/class/gpio/gpio51/value

   sleep .2
done

#!/bin/bash -e는 shell의 종류를 나타냄. #은 주석이라도.

실행

#sh shellname.sh 

어째든 SYSFS를 이용하여 shell를 이용해서 io를 제어 해보았다...인자 첫걸음이니.....