[][src]Crate apigpio

Raspberry PI GPIO access library based on pigpiod.

This library a pure-Rust analogue to the C pigpio_if2 library, providing an async interface to talk to pigpiod. apigpio uses the Rust async framework Tokio.

Currently we provide only a subset of pigpio's functionality: raw GPIO access and notifications, and waveform generation. Contributions are of course welcome.

You will want to read the pigpio_if2 documentation from the pigpio project.

Consider rppal instead!

You should consider whether you wish to use this library, or instead use the excellent rppal library.

Advantages of apigpo:

  • Access to pigpiod's DMA-based wavefile generation.

  • Interface is very similar to pigpio's own interface: this could ease porting existing rpi code to Rust, and may make it easier to make use of existing online information based on C or Python pigpio access.

  • You can port-forward your pigpiod to a faster or more convenient computer, and run your program there (during development, for example).

  • Correct, race-free, operation when multiple processes are changing modes of GPIO pins concurrently, provided everything is using pigpiod. (Concurrent multiprocess changes to GPIO levels are fine with any library, including rppal.)

Advantages of rppal:

  • I2C, PWM, SPI, UART support. RPI model information, etc.

  • Much more Rust-ish interface, with better type safety etc. For example, you can't forget to set the gpio pin mode.

  • Less overhead because GPIO access is done directly within your Rust program without any syscalls, rather than by talking to a separate daemon.

  • GPIO change notification based on interrupts rather than pigpiod's polling.

  • No need to deal with async Rust.

  • No need to arrange for a daemon to be running, override pigpiod's default so it's not open to the global Internet (!), make sure your system startup order is correct, etc.

It is entirely possible to use both libraries in a single project. I have done so myself. But see the following note:

Concurrent setting of RPI GPIO pin modes

The Broadcom SOC provides a way to raise, or lower, individual GPIO pin outputs (or sets of outputs) in a way that does not interfere with other similar operations performed concurrently.

However, this interface is only provided for setting the level of an output pin. For modes, pullup/pulldown, etc., there are only mmio registers containing information about multiple pins where changes are made by reading the register, adjusting the bits which control a particular pin, and writing the information back.

If multiple actors on the rpi do this at once, even for different pins, they can accidentally undo each others' changes.

For this purpose, pigpiod is a single actor: it will serialise the updates itself. So if all your programs use pigpiod (via apigpio, or via libraries in other programming languages which talk to pigpiod) you are fine.

Even combining rppal and apigpio within one Rust program involves multiple actors, because apigpiod's work is all done by pigpiod.

If you want to mix and match, the easiest way to ensure correctness is to have a single task at startup set all the gpio modes. Then all subsequent updates will be harmless no-ops. (This is not suitable, of course, if you need to change modes at runtime.)

But the easiest way to avoid this problem is to have only a single program using a single (thread-safe, if applicable) library - for example, rppal.

Safety and correctness

apigpio is entirely in safe Rust. So you should not experience memory corruption within your Rust program.

However, there can be some surprises because of the way pigpiod itself works.

Firstly: pigpiod resources are global. There is no isolation between different programs all speaking to pigpiod and there is no automatic cleanup. For example, in particular:

Only one program can conveniently make use of wave_* functions at once, because pigpiod has only one currently-building waveform, and one currently-transmitting waveform. Waveforms are not deleted when your program quits - but it is conventional to use wave_clear at startup so your next run will clean everything up.

Secondly: pigpiod itself has some hazardous features. These are generally discussed in the pigpio documentation. The only such feature currently available via apigpio is the *SYNC* waveform chaining function combined with the ability to delete waveforms. These kind of features are made available by apigpiod only to unsafe callers (even though they are implemented in safe Rust).

Modules

constants

Constants from C pigpio.h, converted into Rust consts.

errors

pigpiod error codes, as values of type PigpiodError.

trackbuf

Utility module for async command/response stream tracking

Structs

Connection

The main struct which owns a connection to pigpiod. Start by creating one of these.

ConnectionCore

Most of the Connection methods, mirroring pigpiod_if2, are actually provided here.

GpioChange

Represents a change to a gpio pin, as requested by notify_subscribe.

PigpiodError

Wraps up a pigpiod error code

Pulse

Represents a waveform element. Pure data. See the pigpio docs.

Subscription

Subscription to a GPIO pin.

WaveId

Refers to a Wave stored in pigpiod.

Enums

Error
GpioMode
Level

Constants

PI_DEFAULT_SOCKET_ADDR

Default pigpiod address.

PI_DEFAULT_SOCKET_PORT

Default pigpiod port.

PI_ENVADDR

Env var name to override pigpiod address to connect to.

PI_ENVPORT

Env var name to override pigpiod port to connect to.

TICK_KEEPALIVE_US

Keepalive interval for notify_subscribe tick_keepalives

Type Definitions

MessageBuf

Used only for reporting an unexpected reply from pigpiod.

Pin

BCM GPIO pin number.

PullUpDown

Specifies whether there should be a weak pullup or pulldown.

Result
Tick

pigpiod tick ([us])

Word

pigpiod likes to think about most things as 32-bit words.