Sie sind hier

Now Generally Useful: OpenBSD's GPIO Subsystem

Gespeichert von Marc Balmer am Mi., 11/26/2008 - 16:59

OpenBSD has had support for General Purpose Input/Output devices since the 3.6 release. GPIO devices, or gpios for short, provide an easy way to interface electronic circuits which can be as simple as a LED or that provide more complex functionality like a OneWire or I2C bus. The GPIO implementation in OpenBSD 3.6 up to and including 4.4, however, has some problems and drawbacks which made me rework larger parts of this subsystem during the h2k8 hardware hackathon in Coimbra, Portugal.

gpios are either wired internally for a specific function or connected to a header on the system board where electronic devices can be connected. And on many embedded systems LEDs are found that are controlled by gpios, providing a simple user feedback mechanism. OpenBSD's GPIO subsystem is used to control individual pins of gpios, but also a device driver can make use of GPIO pins using the gpio framework. In this case a driver maps the pins it needs and they are no longer available to other uses. The gpio model found in OpenBSD 3.6 - 4.4 is weak in a few regards: A device driver that needs gpio pins must be configured in a kernel configuration file and a custom kernel needs to be built. Such device drivers therefore can not be attached to gpio(4) devices at runtime. Since only the user of a machine can know the exact layout of its gpio pins there is always the risk of damaging hardware. The use of gpios can be dangerous and making them generally available can be a bit of a risk. So the goal was to lock down gpio configuration to securelevel 0 and to make it possible to attach device drivers to gpio pins at runtime. All configuration of gpios is done at an early boot stage and once the securelevel is raised, it can not be changed. As a convenience to users, individual pins can be named for later reference. Pins that have been configured at securelevel 0 remain accessible at higher securelevels.

A New Syntax for gpioctl(8)

The changes to the kernel parts of course had to be reflected in the gpioctl(8) userland command, which got an all new and easier commandline syntax at the same time. A device driver that uses gpio pins can now be attached using the following command:

gpioctl gpio0 attach gpioow 4 1

In this example we attach a gpioow(4) device on pin 4 of the /dev/gpio0 device with a mask of 1 (the mask specifies how many and which pins are being used by the driver starting at a offset, which is the pin number.) If the device had to detached again, it could be done while still at securelevel 0 using the command

gpioctl gpio0 detach gpioow0

Notice how in the first example, only the driver name is given, but in the second example, the name of the driver instance is specified. Individual pins can now be configured using a relatively easy syntax and at the same name given a symbolic name. Once a pin has been named, it can be referenced either by pin number or symbolic name.

gpioctl gpio0  set [in|out|inout|od|pp|tri|pu|pd|iin|iout] []

One a pin has been configure this way, it will be accessible in the usual way even when the securelevel has been raised. While still at securelevel 0, a pin can be unconfigure using the unset command as follows:

gpioctl gpio0  unset

Access to gpio pins is done as follows:

gpioctl gpio0  [0|1|2]