Fixed headers, added docs
This commit is contained in:
parent
0d16700511
commit
551b9529cc
29
README.md
29
README.md
@ -3,22 +3,41 @@ Linux Userspace GPIO Library
|
|||||||
|
|
||||||
* Export and Unexport GPIO pins
|
* Export and Unexport GPIO pins
|
||||||
* Interrupt support (*)
|
* Interrupt support (*)
|
||||||
* Rewrite of NoccyLabs RaspIO
|
* Hardware-neutral rewrite of NoccyLabs RaspIO
|
||||||
|
* Compatible with psr/logs LoggerInterface for logging
|
||||||
|
|
||||||
## Interrupts
|
## Interrupts
|
||||||
|
|
||||||
|
*NOTE: Not implemented!*
|
||||||
|
|
||||||
For interrupts to work, you need to first bind the interrupt handler, and then
|
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
|
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 = 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 (..) {
|
while (..) {
|
||||||
..
|
..
|
||||||
$gpio->refresh();
|
$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
119
docs/gpio.txt
Normal 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
155
docs/sysfs.txt
Normal 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.
|
@ -1,5 +1,22 @@
|
|||||||
<?php
|
<?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;
|
namespace NoccyLabs\Gpio\Device;
|
||||||
|
|
||||||
abstract class Device implements GpioAwareInterface
|
abstract class Device implements GpioAwareInterface
|
||||||
|
@ -1,5 +1,22 @@
|
|||||||
<?php
|
<?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;
|
namespace NoccyLabs\Gpio\Device\Display;
|
||||||
|
|
||||||
use NoccyLabs\Gpio\Device\Device;
|
use NoccyLabs\Gpio\Device\Device;
|
||||||
|
@ -1,5 +1,22 @@
|
|||||||
<?php
|
<?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;
|
namespace NoccyLabs\Gpio\Exception;
|
||||||
|
|
||||||
use NoccyLabs\Gpio\GpioPin;
|
use NoccyLabs\Gpio\GpioPin;
|
||||||
|
@ -1,5 +1,22 @@
|
|||||||
<?php
|
<?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;
|
namespace NoccyLabs\Gpio\Exception\Handler;
|
||||||
|
|
||||||
use NoccyLabs\Gpio\Exception\GpioException;
|
use NoccyLabs\Gpio\Exception\GpioException;
|
||||||
|
@ -1,5 +1,22 @@
|
|||||||
<?php
|
<?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;
|
namespace NoccyLabs\Gpio\Exception;
|
||||||
|
|
||||||
use NoccyLabs\Gpio\GpioPin;
|
use NoccyLabs\Gpio\GpioPin;
|
||||||
|
Loading…
Reference in New Issue
Block a user