I've implemented this example to familiarize myself with basic GPIO programming in C. The code demonstrates how to write to GPIO pins but does not explicitly state how to read the state of pins. I suspect that WiringPi will ultimately be a better solution since I'll want to read the state of an output pin eventually, but meanwhile I'd like to complete my trek through Dom and Gert's code. How then, could I read the value of a pin?
That example from elinux uses memory-mapped IO. The kernel also exports a user space interface via
/sys/class/gpio,1 which is also documented on elinux. Working in C you would use low level
write() instead of
echo, obviously. Don't use higher level stream based functions.
Some programmers become a bit upset when told to use a file interface for things that they believe should be done with system calls. This is purely a matter of style -- they amount to the exact same thing. There is no "additional I/O overhead", etc., accessing a file in this case because it's not a real file, it's a kernel interface. Exactly like any other system ABI you've ever used, only different. The use of
/sys nodes has been long preferred by the kernel developers, but I still see people determined to use system calls where they can -- e.g.,
sysfs(), despite the fact that
man 2 sysfs says clearly:
This System-V derived system call is obsolete; don't use it. On systems with /proc, the same information can be obtained via /proc/filesystems; use that interface instead.
That's a C library man page telling you to use the
/proc interface. If that's not good enough to convince you, nothing is.
/sys is the same kind of thing. Point being: just because you are using a file node instead of some C specific API doesn't mean you aren't doing real programming, or that performance will suffer, etc. etc. Some people might say it's actually a nice feature. It's also the method recommended by the people who wrote the OS kernel.
A quick introduction to the GPIO interface can be found in
GPIOs are only made available to userspace by an explicit "export" operation. If a given GPIO is not claimed for use by kernel code, it may be exported by userspace (and unexported later). Kernel code may export it for complete or partial access. GPIOs are identified as they are inside the kernel, using integers in the range 0..INT_MAX. See Documentation/gpio.txt for more information. /sys/class/gpio /export ... asks the kernel to export a GPIO to userspace /unexport ... to return a GPIO to the kernel /gpioN ... for each exported GPIO #N /value ... always readable, writes fail for input GPIOs /direction ... r/w as: in, out (default low); write: high, low /edge ... r/w as: none, falling, rising, both /gpiochipN ... for each gpiochip; #N is its first GPIO /base ... (r/o) same as N /label ... (r/o) descriptive, not necessarily unique /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1)
There seem to various tutorials and such online in addition to the elinux one. I've only been using I2C, otherwise I'd give you a more direct answer.
If you are interested in writing kernel space code accessing GPIO, you can have a look here, although I think that is really only useful if you want to write a driver for a specific device and create your own user space API.
1. Since mem-mapped IO must also use read/write, I'm not sure if one method provides a significant advantage over the other here. Using the
/sys interface will certainly be more portable, if you are looking for code that will run on things other than a raspberry pi.