Fixed headers, added docs

This commit is contained in:
Chris 2014-06-12 14:22:37 +02:00
parent 0d16700511
commit 551b9529cc
8 changed files with 383 additions and 5 deletions

View File

@ -3,22 +3,41 @@ Linux Userspace GPIO Library
* Export and Unexport GPIO pins
* Interrupt support (*)
* Rewrite of NoccyLabs RaspIO
* Hardware-neutral rewrite of NoccyLabs RaspIO
* Compatible with psr/logs LoggerInterface for logging
## Interrupts
*NOTE: Not implemented!*
For interrupts to work, you need to first bind the interrupt handler, and then
make sure to call on `Gpio#refresh()` every cycle to poll the interrupt flag on
the selected pins.
the selected pins. This is because the `select()` function is used.
$gpio = new Gpio();
$gpio->onInterrupt(Gpio::get(0), "rising", function($e) { ... });
// Set the handler on the Gpio object
$gpio->setInterruptHandler($gpio[4], function() { ... });
// Or like this on the GpioPin.
$gpio[4]
->setEdge("rising")
->setHandler(function() { ... });
while (..) {
..
$gpio->refresh();
}
##
You can also be risky and use php ticks and timerfuncs (although that might not
be portable/supported/efficient/a good idea):
declare(ticks=5);
$gpio = new Gpio();
$gpiotick = new GpioTickHandler();
$gpiotick->registerGpio($gpio);
// The interrupts will now be polled approx every 5th php vm "tick"

119
docs/gpio.txt Normal file
View File

@ -0,0 +1,119 @@
GPIO Interfaces
===============
The documents in this directory give detailed instructions on how to access
GPIOs in drivers, and how to write a driver for a device that provides GPIOs
itself.
Due to the history of GPIO interfaces in the kernel, there are two different
ways to obtain and use GPIOs:
- The descriptor-based interface is the preferred way to manipulate GPIOs,
and is described by all the files in this directory excepted gpio-legacy.txt.
- The legacy integer-based interface which is considered deprecated (but still
usable for compatibility reasons) is documented in gpio-legacy.txt.
The remainder of this document applies to the new descriptor-based interface.
gpio-legacy.txt contains the same information applied to the legacy
integer-based interface.
What is a GPIO?
===============
A "General Purpose Input/Output" (GPIO) is a flexible software-controlled
digital signal. They are provided from many kinds of chip, and are familiar
to Linux developers working with embedded and custom hardware. Each GPIO
represents a bit connected to a particular pin, or "ball" on Ball Grid Array
(BGA) packages. Board schematics show which external hardware connects to
which GPIOs. Drivers can be written generically, so that board setup code
passes such pin configuration data to drivers.
System-on-Chip (SOC) processors heavily rely on GPIOs. In some cases, every
non-dedicated pin can be configured as a GPIO; and most chips have at least
several dozen of them. Programmable logic devices (like FPGAs) can easily
provide GPIOs; multifunction chips like power managers, and audio codecs
often have a few such pins to help with pin scarcity on SOCs; and there are
also "GPIO Expander" chips that connect using the I2C or SPI serial buses.
Most PC southbridges have a few dozen GPIO-capable pins (with only the BIOS
firmware knowing how they're used).
The exact capabilities of GPIOs vary between systems. Common options:
- Output values are writable (high=1, low=0). Some chips also have
options about how that value is driven, so that for example only one
value might be driven, supporting "wire-OR" and similar schemes for the
other value (notably, "open drain" signaling).
- Input values are likewise readable (1, 0). Some chips support readback
of pins configured as "output", which is very useful in such "wire-OR"
cases (to support bidirectional signaling). GPIO controllers may have
input de-glitch/debounce logic, sometimes with software controls.
- Inputs can often be used as IRQ signals, often edge triggered but
sometimes level triggered. Such IRQs may be configurable as system
wakeup events, to wake the system from a low power state.
- Usually a GPIO will be configurable as either input or output, as needed
by different product boards; single direction ones exist too.
- Most GPIOs can be accessed while holding spinlocks, but those accessed
through a serial bus normally can't. Some systems support both types.
On a given board each GPIO is used for one specific purpose like monitoring
MMC/SD card insertion/removal, detecting card write-protect status, driving
a LED, configuring a transceiver, bit-banging a serial bus, poking a hardware
watchdog, sensing a switch, and so on.
Common GPIO Properties
======================
These properties are met through all the other documents of the GPIO interface
and it is useful to understand them, especially if you need to define GPIO
mappings.
Active-High and Active-Low
--------------------------
It is natural to assume that a GPIO is "active" when its output signal is 1
("high"), and inactive when it is 0 ("low"). However in practice the signal of a
GPIO may be inverted before is reaches its destination, or a device could decide
to have different conventions about what "active" means. Such decisions should
be transparent to device drivers, therefore it is possible to define a GPIO as
being either active-high ("1" means "active", the default) or active-low ("0"
means "active") so that drivers only need to worry about the logical signal and
not about what happens at the line level.
Open Drain and Open Source
--------------------------
Sometimes shared signals need to use "open drain" (where only the low signal
level is actually driven), or "open source" (where only the high signal level is
driven) signaling. That term applies to CMOS transistors; "open collector" is
used for TTL. A pullup or pulldown resistor causes the high or low signal level.
This is sometimes called a "wire-AND"; or more practically, from the negative
logic (low=true) perspective this is a "wire-OR".
One common example of an open drain signal is a shared active-low IRQ line.
Also, bidirectional data bus signals sometimes use open drain signals.
Some GPIO controllers directly support open drain and open source outputs; many
don't. When you need open drain signaling but your hardware doesn't directly
support it, there's a common idiom you can use to emulate it with any GPIO pin
that can be used as either an input or an output:
LOW: gpiod_direction_output(gpio, 0) ... this drives the signal and overrides
the pullup.
HIGH: gpiod_direction_input(gpio) ... this turns off the output, so the pullup
(or some other device) controls the signal.
The same logic can be applied to emulate open source signaling, by driving the
high signal and configuring the GPIO as input for low. This open drain/open
source emulation can be handled transparently by the GPIO framework.
If you are "driving" the signal high but gpiod_get_value(gpio) reports a low
value (after the appropriate rise time passes), you know some other component is
driving the shared signal low. That's not necessarily an error. As one common
example, that's how I2C clocks are stretched: a slave that needs a slower clock
delays the rising edge of SCK, and the I2C master adjusts its signaling rate
accordingly.

155
docs/sysfs.txt Normal file
View File

@ -0,0 +1,155 @@
GPIO Sysfs Interface for Userspace
==================================
Platforms which use the "gpiolib" implementors framework may choose to
configure a sysfs user interface to GPIOs. This is different from the
debugfs interface, since it provides control over GPIO direction and
value instead of just showing a gpio state summary. Plus, it could be
present on production systems without debugging support.
Given appropriate hardware documentation for the system, userspace could
know for example that GPIO #23 controls the write protect line used to
protect boot loader segments in flash memory. System upgrade procedures
may need to temporarily remove that protection, first importing a GPIO,
then changing its output state, then updating the code before re-enabling
the write protection. In normal use, GPIO #23 would never be touched,
and the kernel would have no need to know about it.
Again depending on appropriate hardware documentation, on some systems
userspace GPIO can be used to determine system configuration data that
standard kernels won't know about. And for some tasks, simple userspace
GPIO drivers could be all that the system really needs.
Note that standard kernel drivers exist for common "LEDs and Buttons"
GPIO tasks: "leds-gpio" and "gpio_keys", respectively. Use those
instead of talking directly to the GPIOs; they integrate with kernel
frameworks better than your userspace code could.
Paths in Sysfs
--------------
There are three kinds of entry in /sys/class/gpio:
- Control interfaces used to get userspace control over GPIOs;
- GPIOs themselves; and
- GPIO controllers ("gpio_chip" instances).
That's in addition to standard files including the "device" symlink.
The control interfaces are write-only:
/sys/class/gpio/
"export" ... Userspace may ask the kernel to export control of
a GPIO to userspace by writing its number to this file.
Example: "echo 19 > export" will create a "gpio19" node
for GPIO #19, if that's not requested by kernel code.
"unexport" ... Reverses the effect of exporting to userspace.
Example: "echo 19 > unexport" will remove a "gpio19"
node exported using the "export" file.
GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
and have the following read/write attributes:
/sys/class/gpio/gpioN/
"direction" ... reads as either "in" or "out". This value may
normally be written. Writing as "out" defaults to
initializing the value as low. To ensure glitch free
operation, values "low" and "high" may be written to
configure the GPIO as an output with that initial value.
Note that this attribute *will not exist* if the kernel
doesn't support changing the direction of a GPIO, or
it was exported by kernel code that didn't explicitly
allow userspace to reconfigure this GPIO's direction.
"value" ... reads as either 0 (low) or 1 (high). If the GPIO
is configured as an output, this value may be written;
any nonzero value is treated as high.
If the pin can be configured as interrupt-generating interrupt
and if it has been configured to generate interrupts (see the
description of "edge"), you can poll(2) on that file and
poll(2) will return whenever the interrupt was triggered. If
you use poll(2), set the events POLLPRI and POLLERR. If you
use select(2), set the file descriptor in exceptfds. After
poll(2) returns, either lseek(2) to the beginning of the sysfs
file and read the new value or close the file and re-open it
to read the value.
"edge" ... reads as either "none", "rising", "falling", or
"both". Write these strings to select the signal edge(s)
that will make poll(2) on the "value" file return.
This file exists only if the pin can be configured as an
interrupt generating input pin.
"active_low" ... reads as either 0 (false) or 1 (true). Write
any nonzero value to invert the value attribute both
for reading and writing. Existing and subsequent
poll(2) support configuration via the edge attribute
for "rising" and "falling" edges will follow this
setting.
GPIO controllers have paths like /sys/class/gpio/gpiochip42/ (for the
controller implementing GPIOs starting at #42) and have the following
read-only attributes:
/sys/class/gpio/gpiochipN/
"base" ... same as N, the first GPIO managed by this chip
"label" ... provided for diagnostics (not always unique)
"ngpio" ... how many GPIOs this manges (N to N + ngpio - 1)
Board documentation should in most cases cover what GPIOs are used for
what purposes. However, those numbers are not always stable; GPIOs on
a daughtercard might be different depending on the base board being used,
or other cards in the stack. In such cases, you may need to use the
gpiochip nodes (possibly in conjunction with schematics) to determine
the correct GPIO number to use for a given signal.
Exporting from Kernel code
--------------------------
Kernel code can explicitly manage exports of GPIOs which have already been
requested using gpio_request():
/* export the GPIO to userspace */
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
/* reverse gpio_export() */
void gpiod_unexport(struct gpio_desc *desc);
/* create a sysfs link to an exported GPIO node */
int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc);
/* change the polarity of a GPIO node in sysfs */
int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);
After a kernel driver requests a GPIO, it may only be made available in
the sysfs interface by gpiod_export(). The driver can control whether the
signal direction may change. This helps drivers prevent userspace code
from accidentally clobbering important system state.
This explicit exporting can help with debugging (by making some kinds
of experiments easier), or can provide an always-there interface that's
suitable for documenting as part of a board support package.
After the GPIO has been exported, gpiod_export_link() allows creating
symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can
use this to provide the interface under their own device in sysfs with
a descriptive name.
Drivers can use gpiod_sysfs_set_active_low() to hide GPIO line polarity
differences between boards from user space. Polarity change can be done both
before and after gpiod_export(), and previously enabled poll(2) support for
either rising or falling edge will be reconfigured to follow this setting.

View File

@ -1,5 +1,22 @@
<?php
/*
* Copyright (C) 2014, NoccyLabs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
namespace NoccyLabs\Gpio\Device;
abstract class Device implements GpioAwareInterface

View File

@ -1,5 +1,22 @@
<?php
/*
* Copyright (C) 2014, NoccyLabs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
namespace NoccyLabs\Gpio\Device\Display;
use NoccyLabs\Gpio\Device\Device;

View File

@ -1,5 +1,22 @@
<?php
/*
* Copyright (C) 2014, NoccyLabs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
namespace NoccyLabs\Gpio\Exception;
use NoccyLabs\Gpio\GpioPin;

View File

@ -1,5 +1,22 @@
<?php
/*
* Copyright (C) 2014, NoccyLabs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
namespace NoccyLabs\Gpio\Exception\Handler;
use NoccyLabs\Gpio\Exception\GpioException;

View File

@ -1,5 +1,22 @@
<?php
/*
* Copyright (C) 2014, NoccyLabs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
namespace NoccyLabs\Gpio\Exception;
use NoccyLabs\Gpio\GpioPin;