Homepage Wiki Forum Buy

GPIO

From GNUBLIN

severity (level) requirement Gnublin family
Gnublin logo advanced.png Kernel compile, Toolchain All

Contents

Digital input and output

Digital inputs and outputs can be used by different purposes. It's possible that you only read the status of switches or impuls generators and serial devices.If you need one more UART, I2C or SPI interface you can simulate it by using the gpio interface.

Note: GPIO4 can only be used as input! All other ports can be used as input and output!

technical specification

  • -0,5V to 3,6 V
  • from approximately 2,31V = High (logical = 1)
  • typical 4 mA current per Pin

For beginners

To test the functionality of your GPIO pins you can run the following program:

gnublin-gpio

GPIO pin as output

You can set gpio3 (the red LED) as output with high level by executing the following command:

gnublin-gpio -o 1 -p 3

You can turn the LED off with the following command:

gnublin-gpio -o 0 -p 3


GPIO pin as output

You can read out the value or the level of a GPIO pin with the following command:

gnublin-gpio -i -p <pin>

<pin> should be a the number of your GPIO you want to read out. For example GPIO14 -> <pin> = 14

For advanced

GPIO over console

Under linux, the periphery of the processor can be easily accessed by the filesystem. Hereinafter it will be described how to access the red LED on the board.


GPIO assignment:

GPIO3...........LED1
GPIO11..........X4-2  J5-12
GPIO13..........
GPIO14..........X4-3  J5-11
GPIO15..........X4-4


GPIO3 stands for the red LED. About the sysfs you can get access to the LED.

Change to the directory

cd /sys/class/gpio

Activate the red LED wich is connected to an GPIO pin

root@gnublin:/sys/class/gpio# echo 3 > export

Change to the new directory for GPIO3

root@gnublin:/sys/class/gpio# cd gpio3/

Display the present direction of this I/O pin

root@gnublin:/sys/devices/virtual/gpio/gpio3# cat direction

Use pin as ouput

root@gnublin:/sys/devices/virtual/gpio/gpio3# echo out > direction

turn on the LED

root@gnublin:/sys/devices/virtual/gpio/gpio3# echo 1 > value

Turn of the LED

root@gnublin:/sys/devices/virtual/gpio/gpio3# echo 0 > value


If you want to use the GPIO pin as input, you have to do the following (GPIO11 on the connector):

The easiest way is to connect the switch like follows:

Taster-gpio11.jpg

The curcuit looks like the following:

Switch on GPIO11

      VCC 3.3V
         |
        10K
 __T__   |
 o   o---+------> GPIO11 (white/blue)
 |
===
GND (blue)
 


root@gnublin:/sys/class/gpio# echo 11 > export


In order to use the pin as input you have to set its direction:

root@gnublin:/sys/class/gpio# cd gpio11/
root@gnublin:/sys/devices/virtual/gpio/gpio11# echo in > direction

Getting the output of the value (1 = ca. 3.3V, 0 = ca. 0 V or GND) by make cat to the value file.

cat /sys/class/gpio/gpio11/value

It works so simply with linux!

Task: Let the LED blink on the board!

You can copy-and-paste your program directly into a opend file of Gnublin. Use the vi editor on Gnublin.

LED blink with Shell Skript

Apply file blink.sh:

# Blink the onboard LED
# http://blog.makezine.com/archive/2009/02/blinking-leds-with-the-beagle-board.html

GPIO=3

cleanup() { # Release the GPIO port
  echo $GPIO > /sys/class/gpio/unexport
  exit
}

# Open the GPIO port ('high' direction is output)
#
echo $GPIO > /sys/class/gpio/export
echo "high" > /sys/class/gpio/gpio$GPIO/direction

trap cleanup SIGINT # call cleanup on Ctrl-C

# Blink forever
while [ "1" = "1" ]; do
  echo 1 > /sys/class/gpio/gpio$GPIO/value
  sleep 1
  echo 0 > /sys/class/gpio/gpio$GPIO/value
  sleep 1
done

cleanup # call the cleanup routine
 

In order to start the script, type the following:

sh blink.sh

With STRG-c you can chancel the application.


Get switch status with a shell script

A switch can be easily analized with a bash script.

On GPIO 11:

Taster-gpio11.jpg

The curcuit looks like the following:

Switch on GPIO11

      VCC 3.3V
         |
        10K
 __T__   |
 o   o---+------> GPIO11 (white/blue)
 |
===
GND (blue)

 

Get the switch status:

#!/bin/sh

GPIO=11

cleanup() { # Release the GPIO port
  echo $GPIO > /sys/class/gpio/unexport
  exit
}

echo $GPIO > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio$GPIO/direction

trap cleanup SIGINT # call cleanup on Ctrl-C

while [ "1" = "1" ]; do
   cat /sys/class/gpio/gpio$GPIO/value
   sleep 1
done

cleanup # call the cleanup routine
 

GPIO with Lua Script

Start: lua blink.lua

-- blink.lua

GPIO = 3

function wait(n)
  os.execute("sleep " .. tonumber(n))
end

function cmd(c)
  print(c)
  os.execute(c)
end

cmd("echo " .. GPIO .. " > /sys/class/gpio/export")
cmd("echo out > /sys/class/gpio/gpio" .. GPIO .. "/direction")

n = 0
while n < 2 do
   cmd("echo 1 > /sys/class/gpio/gpio"..GPIO.."/value")
   wait(1)
   cmd("echo 0 > /sys/class/gpio/gpio" .. GPIO .. "/value")
   wait(1)
   n = n + 1
end

cmd("echo "..GPIO.." > /sys/class/gpio/unexport")
 


With os.path_exists() you can check, wether files and directories are existend:

-- blink2.lua
-- H. Hoegl, 21. Dec 2011

if os.path_exists("/sys/class/gpio/gpio11") == 1 then
   print("remove gpio pin")
   f = io.open("/sys/class/gpio/unexport", "w")
   f:write("11")
   f:close()
else
   print("create gpio pin")
   f = io.open("/sys/class/gpio/export", "w")
   f:write("11")
   f:close()
end
-- and so on...
 

GPIO in C access over memory address

Herinafter code can be used to directly access the GPIO-registers:

/*Gnublin User Space GPIO demo using mmap() H. Hoegl, 2012-06-22 Literature:

[1] The Kernel Hackers Guide, chapter "user space device drivers"
    http://tldp.org/LDP/khg/HyperNews/get/devices/fake.html 
[2] man mem
[3] man mmap

Create /dev/mem device (see [2])

   mknod -m 660 /dev/mem c 1 1
   chown root:kmem /dev/mem

Bit numbers in MODE0 and MODE1 registers - Warning: No GPIO4 available for Output!

  0 -> GPIO1  !!!
  1 -> GPIO0
  2 -> GPIO2
  3 -> GPIO3  (red LED)
  5 -> GPIO11 
  6 -> GPIO12 
  7 -> GPIO13 
  8 -> GPIO14
  9 -> GPIO15
  10 -> GPIO16
  11 -> GPIO17 
  12 -> GPIO18
  13 -> GPIO19
  14 -> GPIO20

M1/M0 combinations

  M1   M0    function
  0    0     input/output driver disabled
  0    1     output is controlled by the device 
  1    0     output is driven low 
  1    1     output is driven high*/


#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

/* LPC3131 UM chapter 15 */
#define IOCONFIG    0x13003000
#define FBLO_GPIO   0x1C0  /* GPIO functional block */

/* offset in GPIO functional block  */
#define PINS        0x00
#define MODE0       0x10  
#define MODE0_SET   0x14
#define MODE0_RESET 0x18
#define MODE1       0x20  
#define MODE1_SET   0x24
#define MODE1_RESET 0x28

/* !! Warning !!
 * GPIO4 (1 << 4) is only as INPUT available.
 * Setting the MODE0-Register for Pin 4 to 1 will cause a crash of the system!
 */
#define GPIO3   (1 << 3)

#define LED        GPIO3

void byebye(void);

char *mymem;

int main()
{
    int mem_fd;
    atexit(byebye);
    if ((mem_fd = open("/dev/mem", O_RDWR)) < 0) {
        printf("can't open /dev/mem \n");
        exit(-1);
    }
    printf("mem_fd = %d\n", mem_fd);
    printf("getpagesize() -> %d\n", getpagesize());
    mymem = mmap(0, 
                 getpagesize(), 
                 PROT_READ|PROT_WRITE, 
                 MAP_SHARED, 
                 mem_fd, 
                 IOCONFIG);
    if (mymem == MAP_FAILED) {
        printf("mmap error %d\n", errno);
        exit(-1);
    }
    else {
        printf("mymem = 0x%x\n", (unsigned int)mymem);
    }
    *(unsigned int *)(mymem + FBLO_GPIO + MODE1_SET) = LED;
    while (1) {
        printf("LED on\n");
        *(unsigned int *)(mymem + FBLO_GPIO + MODE0_SET) = LED;
        sleep(1);
        printf("LED off\n");
        *(unsigned int *)(mymem + FBLO_GPIO + MODE0_RESET) = LED;
        sleep(1);
    }
    return 0;
}

void byebye()
{
    printf("cleaning up\n");
    /* when not explicitly given, munmap() will automatically
       be called on exit (see 'man munmap') */
    munmap(mymem, getpagesize()); 
}

In other languages