Why use C/C++ file I/O to access GPIO pins?

Greetings all,
I’ve been playing with software and hardware for 30+ years, but I’m new to Linux and embedded Linux systems. The code snippets I’ve been able to find for GPIO access all seem use file I/O functions. I’ve never seen this approach before – I’m accustomed to reading and writing processor registers. The file I/O approach seems strange to me, but I’m new here, and there’s a lot that seems strange.

So, can someone explain why the file I/O approach is used? Is this a typical technique for Linux systems, or something particular to ARM processors? I suppose it doesn’t really matter, but I prefer to understand why things are done as they are.

Thanks very much, folks.

Yours in newness,
Tim

I think…

It’s one of UNIX system base, that everything is a file.
It is a common way of doing things in different platforms. For example: gpio registers in 8051 are different from PIC, and different from AVR, and so on. On a Linux (at least at user space), there is a common interface to access gpio. Gives you much more portability. You can run the same code in different processors.

Jerônimo Lopes

So, I’m guessing it’s a case of sacrificing performance for portability and robustness. My first reaction is that it seems odd, but then again — make it work before you make it faster.
Thanks!

If you have something that just needs to switch something on / off once in a while( less than 200 Hz ) why would you need to complicate things ?

If you need fast though, a PRU + mmap can achieve fairly “insane” speeds. 10Mhz or better should not be a problem.

I've been playing with software and hardware for 30+ years,
but I'm new to Linux and embedded Linux systems. The code
snippets I've been able to find for GPIO access all seem use
file I/O functions. I've never seen this approach before --
I'm accustomed to reading and writing processor registers.
The file I/O approach seems strange to me, but I'm new here,
and there's a /lot /that seems strange.

You may be more comfortable using the GPMC bus for memory-mapped byte I/O, rather than the bit-wise GPIO interface. It's much faster too.

- Mike

<Sigh!> I do tend to think in terms of basic microcontrollers where you have to make every clock cycle count. It looks like BBB is going to give me the luxury of clock cycles to spare.

From what I can gather, though, part of the problem in accessing the processor registers directly is that you’d have to run as root. Wouldn’t you have the same problem with PRU access?

Having to be root to access certain directories is really a non issue. It is like this of course for security reasons. But in the context of getting things done there are a few ways to deal with this.

http://en.wikipedia.org/wiki/Setuid is one such way( which the ping command I believe uses to send “bad” packets ).

http://en.wikipedia.org/wiki/Inter-process_communication would be another different approach. But is more complex and requires a bit of thought.

Of course, you could always add a regular user to a group that has read, write, and / or execute permissions for various files / directories. But this could be just as bad as running an internet facing process as root( assuming access is somehow available through the internet ).

Here is a fairly decent read concerning the PRU’s if you have interest. http://www.element14.com/community/community/designcenter/single-board-computers/next-gen_beaglebone//blog/2013/05/22/bbb–working-with-the-pru-icssprussv2 To be sure, there are many similar blog posts on the internet.

Greetings all,
I’ve been playing with software and hardware for 30+ years, but I’m new to Linux and embedded Linux systems. The code snippets I’ve been able to find for GPIO access all seem use file I/O functions. I’ve never seen this approach before – I’m accustomed to reading and writing processor registers. The file I/O approach seems strange to me, but I’m new here, and there’s a lot that seems strange.

So, can someone explain why the file I/O approach is used? Is this a typical technique for Linux systems, or something particular to ARM processors? I suppose it doesn’t really matter, but I prefer to understand why things are done as they are.

Well, that is because you are trying to access the GPIO from user space. If you wanted to access the GPIO from kernel space, you would use a similar approach to what you did on your smaller processors. The only difference would be that each pin supports several functions which are defined by Mode 0 through 7. To use a pin for GPIO, you would use Mode 7. Also, the processor has a set register and a clear register so that you don’t have to disable interrupts during a real/modify/write. One other approach is to use mmap so that you can access the processor registers in user space for GPIO operations or as others have proposed, use the PRU to control GPIO.

Regards,
John

An other approach would be to drop Linux OS completely and to have your own (StarterWare-based) firmware running on the board. With it’s standard timers you can have a output frequency of up to 2 MHz (when doing it out of an ISR with some bit-banging code) or up to 100 MHz (when bit-banging using PRU-code).

Or you can always access them with /dev/mem mmap without dumping Linux.