LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Hardware > Linux - Embedded & Single-board computer
User Name
Password
Linux - Embedded & Single-board computer This forum is for the discussion of Linux on both embedded devices and single-board computers (such as the Raspberry Pi, BeagleBoard and PandaBoard). Discussions involving Arduino, plug computers and other micro-controller like devices are also welcome.

Notices

Reply
 
Search this Thread
Old 07-19-2008, 06:46 AM   #1
ra2008
LQ Newbie
 
Registered: Jul 2008
Posts: 23

Rep: Reputation: 15
GPIO access from users pace?


Hi, is it possible to access ARM's GPIOs (EP93xx) runnning 2.6.21 Linux, from user space?
if yes how? what are the system call? any tutorials?
thanks

Last edited by ra2008; 07-19-2008 at 06:51 AM.
 
Old 07-19-2008, 06:50 AM   #2
pinniped
Senior Member
 
Registered: May 2008
Location: planet earth
Distribution: Debian
Posts: 1,732

Rep: Reputation: 50
You can always write a driver to be able to do it. The manufacturer of your board may already provide a reference driver.
 
Old 07-19-2008, 12:58 PM   #3
raedbenz
Member
 
Registered: Dec 2007
Posts: 93

Rep: Reputation: 15
Yes u can.
try to look for "Low level I/O API", like read(), write(), also mmap()..
 
Old 07-19-2008, 10:49 PM   #4
estabroo
Senior Member
 
Registered: Jun 2008
Distribution: debian, ubuntu, sidux
Posts: 1,094
Blog Entries: 2

Rep: Reputation: 111Reputation: 111
mmap is the answer you are looking for, if you look at the ep9301 user guide (or one more appropriate to the chip you are using) you can see where it maps pins to memory.

- snippet of code for ep9302 memory mapping of gpio pins -
Code:
#define GPIO_BASE 0x80840000
/* GPIO memory mapped registers */

volatile unsigned int *PBDR;  /* for unit select, lowest 3 bits */
volatile unsigned int *PBDDR;
volatile unsigned int *PEDR;
volatile unsigned int *PEDDR;

int memory_map_open(unsigned char **gpio) {
  int fd;

  fd = open("/dev/mem", O_RDWR);
  if (fd < 0) {
    perror("Failed to open /dev/mem");
    return fd;
  }
  *gpio = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);

  PBDR = (unsigned int *)(*gpio + 0x04);
  PBDDR = (unsigned int *)(*gpio + 0x14);
  PEDR = (unsigned int *)(*gpio + 0x20);
  PEDDR = (unsigned int *)(*gpio + 0x24);

  return fd;
}
Then where you want to use the data registers that control the pins just assign the appropriate value to them

*PBDDR = 0xff; /* data direction register, 0xff makes all the pins outputs iirc, been a while since I've read the user guide */
*PBDR = 0x01; /* drive the lowest pin that it controls high */

Last edited by estabroo; 07-19-2008 at 10:51 PM. Reason: put in code tags
 
Old 07-20-2008, 02:09 PM   #5
ra2008
LQ Newbie
 
Registered: Jul 2008
Posts: 23

Original Poster
Rep: Reputation: 15
Hi estabroo
thanks for the helpful reply,
i have tested the code (after rewriting it by adding main function,etc.. )and i get this error on Olimex CS-e9302 board
Code:
Segmentation fault
any hints?
 
Old 07-20-2008, 03:08 PM   #6
jiml8
Senior Member
 
Registered: Sep 2003
Posts: 3,171

Rep: Reputation: 114Reputation: 114
Segmentation fault means a wild pointer.
 
Old 07-20-2008, 05:08 PM   #7
estabroo
Senior Member
 
Registered: Jun 2008
Distribution: debian, ubuntu, sidux
Posts: 1,094
Blog Entries: 2

Rep: Reputation: 111Reputation: 111
Can you run it in a debugger and find out where the segfault occurred? If not you might have to put in fprintf to stderr messages to narrow it down, does it have a console (serial, vga, ...)? You should also check the value you get back from mmap to make sure it didn't fail. Can you post your code?
 
Old 07-21-2008, 03:02 AM   #8
ra2008
LQ Newbie
 
Registered: Jul 2008
Posts: 23

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by estabroo View Post
does it have a console (serial, vga, ...)?
Hi,
if u mean someting like hyperterminal, then yes i am using cutecom. here is the code:

Code:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define GPIO_BASE 0x80840000
/* GPIO memory mapped registers */
volatile unsigned int *PEDR;
volatile unsigned int *PEDDR;
	
int main (void)
	{	
  	//long delay=128000, delay2=100;
  	unsigned char **gpio;
  	int fd;
  	fd = open("/dev/mem", O_RDWR);
  	if (fd < 0) 
  		{
   	perror("Failed to open /dev/mem");
   	return fd;
  		}
  	*gpio = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);

  	PEDR = (unsigned int *)(*gpio + 0x20);
  	PEDDR = (unsigned int *)(*gpio + 0x24);
	
	*PEDDR = 0xff;//set output
	*PEDR = 0x02;// turn ON Red LED (port E1)
		
  	return 0;
	}
 
Old 07-21-2008, 12:08 PM   #9
estabroo
Senior Member
 
Registered: Jun 2008
Distribution: debian, ubuntu, sidux
Posts: 1,094
Blog Entries: 2

Rep: Reputation: 111Reputation: 111
Okay the problem is your declaration of gpio. It was ** in the function I posted because it was being passed in by reference, since you have it in the main program you should do this instead
Code:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define GPIO_BASE 0x80840000
/* GPIO memory mapped registers */
volatile unsigned int *PEDR;
volatile unsigned int *PEDDR;
	
int main (void)
	{	
  	//long delay=128000, delay2=100;
  	unsigned char *gpio;
  	int fd;
  	fd = open("/dev/mem", O_RDWR);
  	if (fd < 0) 
  		{
   	perror("Failed to open /dev/mem");
   	return fd;
  		}
  	gpio = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);

  	PEDR = (unsigned int *)(gpio + 0x20);
  	PEDDR = (unsigned int *)(gpio + 0x24);
	
	*PEDDR = 0xff;//set output
	*PEDR = 0x02;// turn ON Red LED (port E1)
		
  	return 0;
	}
 
Old 07-21-2008, 01:31 PM   #10
ra2008
LQ Newbie
 
Registered: Jul 2008
Posts: 23

Original Poster
Rep: Reputation: 15
thanks very much,,it works now
 
Old 08-01-2008, 03:07 PM   #11
maicho
LQ Newbie
 
Registered: Aug 2008
Posts: 2

Rep: Reputation: 0
interruption

Hi, Your code was very very usefull to me, but I would like know how I can set an interruption in GIOPORT, for example:

if the pin x from portA or B detect a low level (0) then execute a function (eg, increase a counter)

thanks
 
Old 08-01-2008, 05:29 PM   #12
estabroo
Senior Member
 
Registered: Jun 2008
Distribution: debian, ubuntu, sidux
Posts: 1,094
Blog Entries: 2

Rep: Reputation: 111Reputation: 111
I would imagine you'd need to write a kernel module that setup an irq handler function and requested interrupts generated by that gpio be sent to it. Take a look at the set_irq_type and request_irq functions in the kernel.
 
Old 08-01-2008, 09:37 PM   #13
raedbenz
Member
 
Registered: Dec 2007
Posts: 93

Rep: Reputation: 15
Hi,
dealing with interrupts can be done only in Kernel space not user space.
just use as estabroo said, "request_irq" to register ur irq number and device name, etc..
then write the handler (ISR).. at the exit of the module just free the irq.
http://www.xml.com/ldd/chapter/book/ch09.html
cheers
 
Old 08-05-2008, 08:48 AM   #14
maicho
LQ Newbie
 
Registered: Aug 2008
Posts: 2

Rep: Reputation: 0
interruption

Thanks estabroo and raedbenz. I will tray write a module in kernel that let me manage an IO interruption. When I finish I will write here the code.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
LXer: Linux picks up pace on cellphones LXer Syndicated Linux News 0 09-19-2007 10:40 PM
LXer: Antiphishing efforts try to keep pace LXer Syndicated Linux News 0 10-09-2006 02:21 PM
pace dsl4000 set top box berrance General 0 03-23-2006 05:52 AM
Samba access by Windows users locking out directory access with Konqueror harry_fine Suse/Novell 1 12-18-2004 05:33 AM
Gpio Twiddling In Embedded Linux? or How to access PCI memory space regs? jds-linux Programming 1 07-11-2004 02:17 AM


All times are GMT -5. The time now is 10:29 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration