GPIO (LED) access using mmap

Hello,

My self given task was to get a LED blinking on the Beagleboard.

After getting bored from "echo 0 > brightness" and puzzling together
some pieces of code that I found on the net, I finally got a piece of
plain C code that I can cross compile on a Linux machine and play on
the Beagleboard. The two user LEDs as well as one pin of the extension
connect flash in a 1sec clock with it.

No guarantee for completeness, no guarantee for functionality, but
here it works.

Enjoy!

Günter (dl4mea)

/* Blinking of user LEDs USR0 and USR1 and gpio_157 on Expansion
Connector P2
   NOTE: gpio_157 is 1.8V IO, possibly not sufficient for a LED

disconnect user LEDs from Linux
echo none > /sys/class/leds/beagleboard::usr0/trigger; echo none > /
sys/class/leds/beagleboard::usr1/trigger;

compile using
<path_to_cross>/arm-armv6-linux-gnueabi-g++ -static blink.c -o blink

References: OMAP35x Applications Processor, Technical Reference Manual
            spruf98u.pdf
*/

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

int main(void)
{

    printf ("open file descriptor for PADCONFIG\n");
    int fd = open("/dev/mem", O_RDWR | O_SYNC); //O_SYNC makes the
memory uncacheable
    if (fd < 0) {
      printf("Could not open PADCONFIG memory fd\n");
      return 0;
    }

    // Pad configuration
    printf ("map PINCONFIG\n");
    volatile ulong *pinconf;
    pinconf = (ulong*) mmap(NULL, 0x10000, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0x48000000);
    if (pinconf == MAP_FAILED) {
      printf("Pinconf Mapping failed\n");
      close(fd);
      return 0;
    }

    printf ("set pinconfig GPIO\n");
    pinconf[0x217c/4] = pinconf[0x217c/4] & 0x0000ffff |
0x00040000; // gpio_149
    pinconf[0x2180/4] = pinconf[0x2180/4] & 0xffff0000 |
0x00000004; // gpio_150
    pinconf[0x218c/4] = pinconf[0x218c/4] & 0x0000ffff |
0x00040000; // gpio_157
    close(fd);

    /* -------------------------------------- */

    printf ("open file descriptor for GPIO\n");
    int gpio_fd = open("/dev/mem", O_RDWR | O_SYNC);
    if (gpio_fd < 0) {
      printf("Could not open GPIO memory fd\n");
      return 0;
    }

    // GPIO configuration
    printf ("map GPIO\n");
    volatile ulong *gpio;
    gpio = (ulong*) mmap(NULL, 0x10000, PROT_READ | PROT_WRITE,
MAP_SHARED, gpio_fd, 0x49050000);
    if (gpio == MAP_FAILED) {
      printf ("GPIO Mapping failed\n");
      close(gpio_fd);
      return 0;
    }

    printf ("set GPIO config\n");

    // Configure GPIO pins on bank 5 as output.
    // GPIO 5 is at physical address 0x49056000 = 0x49050000+0x6000
    gpio[0x6034/4] &= ~0x20600000; // set low for output
    // Also disable the wakeupenable and irqenable intertupts
    // GPIO clear_Wakeupenable is offset by 0x80 for each bank
    gpio[0x6080/4] = 0x20600000; // 0x1: Clear the corresponding
bit in the GPIO_WAKEUPENABLE register
    // GPIO clear_irqenable1 is offset by 0x60 for each bank
    gpio[0x6060/4] = 0x20600000; // 0x1: Clear the corresponding
bit in the GPIO_IRQENABLE1 register
    // GPIO clear_irqenable2 is offset by 0x70 for each bank
    gpio[0x6070/4] = 0x20600000; // 0x1: Clear the corresponding
bit in the GPIO_IRQENABLE2 register

    /* -------------------------------------- */

    printf ("Toggle Pins\n");

    int j=0;
    for (j=0; j<10; j++)
    {
       printf ("j=%u\n", j);
       //clear_data_out has offset 0x90
       gpio[0x6090/4]=0x20600000;
       usleep(500000);
       //set_data_out has offset 0x94
       gpio[0x6094/4]=0x20600000;
       usleep(500000);
    }

    close(gpio_fd);
}

I am new to beagle baord. I have a doubt here. Please help.

In the following line

`
pinconf[0x217c/4] = pinconf[0x217c/4] & 0x0000ffff | 0x00040000; // gpio_149

`

Why do you need the division inside the pinconf array for indexing?

The address is in bytes and pinconf is an array of integers, which are
4 bytes long.

j.

Thanks. In the following line it has been chosen 0x00040000 to write in to the configuration register.
`
pinconf[0x217c/4] = pinconf[0x217c/4] & 0x0000ffff | 0x00040000; // gpio_149

`

How to select that value?

The processor's TRM has full description of the bits in the control registers.

j.