I used as my reference
To access the necessary registers from user space, they use memory mapping. They then set up the Beagleboard expansion header pins to map to GPIO Bank 5, set the appropriate pullup registers, and enable input. They then set up Bank 5 as an input, and read from it.
I first tried to mirror that setup, but doing output instead. This didn't exactly work for me. One /huge/ problem is that I am communicating with my beagleboard over a USB network adaptor. For some reason (that I have yet to figure out), toggling some of the bits on GPIO5 clobbers the USB interface. I don't know why, but I do know that only happens with the high bits, so I settled for using the low bits.
Here's the relevant C code for output, based on the aforementioned post:
includes:
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
Setting the pin configuration:
//O_SYNC makes the memory uncacheable
int fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0) {
sprintf(stderr,"Could not open memory\n");
return 0;
}
// Pad configuration
volatile ulong *pinconf;
pinconf = (ulong*) mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x48000000);
if (pinconf == MAP_FAILED) {
sprintf(stderr,"Pinconf Mapping failed\n");
close(fd);
return 0;
}
// set lower 16 pins to GPIO bank5
pinconf[0x2158/4] = 0x00040004;
pinconf[0x215C/4] = 0x00040004;
pinconf[0x2160/4] = 0x00040004;
pinconf[0x2164/4] = 0x00040004;
/* pinconf[0x2168/4] = 0x00040004; */
/* pinconf[0x216C/4] = 0x00040004; */
/* pinconf[0x2170/4] = 0x00040004; */
/* pinconf[0x2188/4] = 0x00040004; */
close(fd);
GPIO Bank 5 configuration:
volatile ulong * gpio_fd = open("/dev/mem", O_RDWR | O_SYNC);
if (gpio_fd < 0) {
sprintf(stderr,"Could not open memory\n");
return 0;
}
// First set all output on bank5 to high
// (set_data_out has offset 0x94)
gpio[0x6094/4]=0xFFFFFFFF;
// Configure low 16 GPIO pins on bank 5 as output.
// GPIO 5 is at physical address 0x49056000 = 0x49050000+0x6000
// GPIO Output enable (GPIO_OE) is offset by 0x34 for each bank
// (set low for output)
gpio[0x6034/4] = 0x00000000;
// Also disable the wakeupenable and irqenable intertupts
// GPIO clear_Wakeupenable is offset by 0x80 for each bank
gpio[0x6080/4] = 0x0000FFFF;
// GPIO clear_irqenable1 is offset by 0x60 for each bank
gpio[0x6060/4] = 0x0000FFFF;
// GPIO clear_irqenable2 is offset by 0x70 for each bank
gpio[0x6070/4] = 0x0000FFFF;
Toggling the pins from high to low, waste some time, then toggle pin back to high:
//clear_data_out has offset 0x90
gpio[0x6090/4]=0x0000FFFF;
usleep(500);
for (i=0;i<25000;i++);
//set_data_out has offset 0x94
gpio[0x6094/4]=0x0000FFFF;
usleep(500);
I do not know if the "usleep" commands are absolutely necessary, but I couldn't get this to work without them.
This comment has been removed by the author.
ReplyDeleteHi Alex - I'm interested in adapting this for the overo as well. Would you mind letting me know what parts of the code had to be modified to get it to work?
ReplyDeleteEnded up using a sys call with devmem2
ReplyDeleteand using sysfs
system("devmem2 0x480021E0 h 0x10");
eg
(fp = fopen("/sys/class/gpio/gpio10/direction", "rb+")
fp = fopen("/sys/class/gpio/export", "ab")
(fp = fopen("/sys/class/gpio/gpio10/value", "rb+")
then fwrite and fread
original code from
http://groups.google.com/group/beagleboard/browse_thread/thread/db4accfabf02d986/c623a16637625685?pli=1
Trying to keep it simple as its for examples for students to use and build on.
Thanks very much for posting this back! Really helpful.
ReplyDeletesee gpio2.c code example at
ReplyDeletehttp://alexthegeek.com/omap/overo/code/
I've just added some adc code to the gumstix wiki
ReplyDeleteat http://wiki.gumstix.org/index.php?title=Category:How_to_-_adc
on reading adc's via both system calls and sysfs via fopen and fread
Hi,
ReplyDeleteI'm trying to design a home automatic system using begaleboard XM, hence I need to access those GPIO. Here are my questions:
1) I believe in order to use the GPIO I need to use user-space to do it, so is user-space code (your sample code) embedded with my application code?
2) How did you get those values and what does it mean?
pinconf[0x2158/4] = 0x00040004;
pinconf[0x215C/4] = 0x00040004;
pinconf[0x2160/4] = 0x00040004;
pinconf[0x2164/4] = 0x00040004;
3) Is using a text editor and native toolchain good enough to control the GPIO?
Sorry if I asked too many questions, coz I'm really new to these stuff. And I really need your helps = )
Thank You very much.
Regards,
Fiona
Hi Fiona,
ReplyDeleteSo normally one can't use GPIO from userspace. It requires getting to the GPIO configuration registers, which are normally in a memory location that userspace doesn't have access to. Parts of the code above "remap" the memory so that it can be accessed from userspace.
More info on that in this blog post here:
http://41j.com/blog/2011/09/beagleboard-gpio-input-driverless/
2) The point of this code is to set the physical pins on the OMAP 3530 as output pins (rather than input, or some other state). I think you can find more in the TI documentation here: http://focus.ti.com/lit/ug/sprufd5a/sprufd5a.pdf
3) Yes, that's all I use too.