From GumstixDocsWiki
/****************************************************************************/
/* */
/* Copyright (c) 2006 Tim Crawford <timcrawford@comcast.net> */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License version 2 as */
/* published by the Free Software Foundation. */
/* */
/* Alternatively, this software may be distributed under the terms of BSD */
/* license. */
/* */
/* See README and COPYING for more details. */
/* */
/****************************************************************************/
/* Use this Makefile as an example on how to build: */
/* http://svn.gumstix.org/wikifiles/hello-world/Makefile */
/* This program demonstrates how to program the GPIO */
/* */
/* gpio(u32 direction, u32 set_clear, u32 gpio_bit) */
/* example: */
/* gpio(OUT, SET, 59); //This will program GPIO(59) as a GPIO function */
/* // set the direction as output, and set the bit */
/* */
/* gpio_function(u32 gpio_bit, u32 function); */
/* example: */
/* gpio_function(59, GPIO); //This will program GPIO(59) as a GPIO funct*/
/* */
/* gpio_direction(u32 gpio_bit, u32 direction) */
/* example: */
/* gpio_direction(59, OUT); //This will program GPIO(59) as an output */
/* */
/* gpio_set(u32 gpio_bit) */
/* example: */
/* gpio_set(59); //This will program GPIO(59) to a logic 1 */
/* */
/* gpio_clear(u32 gpio_bit) */
/* example: */
/* gpio_clear(59); //This will program GPIO(59) to a logic 0 */
/* */
/* gpio_status(u32 gpio_bit) */
/* example: */
/* i = gpio_status(59); //i is set to the logic level of GPIO(59) */
/* */
/****************************************************************************/
#include <stdio.h>
#include <time.h>
#include <stdio.h> // Why is this need twice?
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#define MAP_SIZE 4096
#define MAP_MASK ( MAP_SIZE - 1 )
#define GPLR0 0x40E00000
#define GPLR1 0x40E00004
#define GPLR2 0x40E00008
#define GPDR0 0x40E0000C
#define GPDR1 0x40E00010
#define GPDR2 0x40E00014
#define GPSR0 0x40E00018
#define GPSR1 0x40E0001C
#define GPSR2 0x40E00020
#define GPCR0 0x40E00024
#define GPCR1 0x40E00028
#define GPCR2 0x40E0002C
#define GAFR0_L 0x40E00054
#define GAFR0_U 0x40E00058
#define GAFR1_L 0x40E0005C
#define GAFR1_U 0x40E00060
#define GAFR2_L 0x40E00064
#define GAFR2_U 0x40E00068
#define IN 250
#define OUT 251
#define GPIO 0
#define AF0 0
#define AF1 1
#define AF2 2
#define AF3 3
#define SET 252
#define CLEAR 253
typedef unsigned int u32;
void *map, *regaddr;
static void putmem(u32 addr, u32 val)
{
regaddr = (void*)((u32)map + (addr & MAP_MASK));
*(u32*) regaddr = val;
}
static int getmem(u32 addr)
{
u32 val;
regaddr = (void*)((u32)map + (addr & MAP_MASK));
val = *(u32*) regaddr;
return val;
}
void gpio_set(u32 gpio)
{
u32 pos;
u32 bit = 1;
pos = gpio / 32;
bit <<= gpio % 32;
putmem(GPSR0 + (pos * 4), bit);
}
void gpio_clear(u32 gpio)
{
u32 pos;
u32 bit = 1;
pos = gpio / 32;
bit <<= gpio % 32;
putmem(GPCR0 + (pos * 4), bit);
}
u32 gpio_status(u32 gpio)
{
u32 pos;
u32 bit = 1;
u32 data;
pos = gpio / 32;
bit <<= gpio % 32;
data = getmem(GPLR0 + (pos * 4));
data &= bit;
if (data == 0)
return(0);
else
return(1);
}
void gpio_direction(u32 gpio, u32 dir)
{
u32 pos;
u32 bit = 1;
u32 data;
pos = gpio / 32;
bit <<= gpio % 32;
data = getmem(GPDR0 + (pos * 4));
data &= ~bit;
if (dir == OUT)
data |= bit;
putmem(GPDR0 + (pos * 4), data);
}
void gpio_function(u32 gpio, u32 fun)
{
u32 pos;
u32 bit = 3;
u32 data;
pos = gpio / 16;
bit <<= (gpio % 16) * 2;
fun <<= (gpio % 16) * 2;
data = getmem(GAFR0_L + (pos * 4));
data &= ~bit;
data |= fun;
putmem(GAFR0_L + (pos * 4), data);
}
u32 gpio(u32 dir, u32 set, u32 reg)
{
if ((dir != IN) & (dir != OUT)){
printf("ERROR: must specify a valid direction\n");
return(1);
}
if ((set != SET) & (set != CLEAR)){
printf("ERROR: must specify a valid level\n");
return(1);
}
if (reg > 84){
printf("ERROR: not a valid register -->%d\n", reg);
return(1);
}
gpio_function(reg, GPIO);
gpio_direction(reg, dir);
if (dir == OUT){
if (set == SET)
gpio_set(reg);
else
gpio_clear(reg);
}
return(0);
}
int main( int argc, char **argv )
{
unsigned int i, ii, rval, speed, count, tmp;
int fd;
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd<0) {
perror("open(\"/dev/mem\")");
exit(1);
}
map = mmap(0,
MAP_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
// The following was only needed for certain broken revisions of uClibc
//#ifdef __ARM_EABI__
// 0x40E00000 / MAP_SIZE
//#else
0x40E00000 & ~MAP_MASK
//#endif
);
if (map == (void*)-1 ) {
perror("mmap()");
exit(1);
}
/* Set GPIO functions first */
gpio_function(59, GPIO);
gpio_function(60, GPIO);
gpio_function(84, GPIO);
/* Then set the direction */
gpio_direction(59, IN);
gpio_direction(60, OUT);
gpio_direction(84, OUT);
/* Now set/clear/read GPIO bits */
gpio_set(84);
i = gpio_status(59);
printf("GPIO(59) = %d\n", i);
if (i)
gpio_set(60);
else
gpio_clear(60);
/* This is another way to program gpio */
gpio(IN, SET, 59);
i = gpio_status(59);
printf("GPIO(59) = %d\n", i);
if (i)
gpio(OUT, SET, 60);
else
gpio(OUT, CLEAR, 60);
munmap(0,MAP_SIZE);
return 0;
}