TODOs to research/implement before gpio is ready for a 0.10.0 release
golemparts opened this issue · 2 comments
golemparts commented
-
InputPin
s created using different instances ofGpio
won't share the sameEventLoop
, which means they'll be added to the wrongEventLoop
instance byInputPin::set_interrupt()
when a user tries to poll multiple sync interrupts usingGpio::poll_interrupts()
. Either share a single staticEventLoop
instance, or combine add/poll/remove into a single method. - Running
InputPin::poll_interrupt()
for different pins on multiple threads simultaneously will block all but one due to the requiredMutex
lock.Find a better solution.Update documentation. - 32-bit reads/writes to 32-bit aligned memory locations are atomic on ARMv6/v7/v8 (see ARM Architecture Reference Manuals). Verify
GpioMem
's mmap configuration (O_SYNC, MAP_SHARED) doesn't negate atomicity and doesn't cause any caching-related issues, and then remove the locking mechanism for single reads/writes. Locks are still needed when multiple operations need to be synchronized (set_mode, set_pullupdown). - Consider the consequences of removing the single instance limitation on
Gpio
, now thatPin
s survive aGpio
instance going out of scope. - Consider moving the contents of
Gpio
to a static variable, and haveGpio::new()
either clone the static variable if it has been created already, or initialize it and return any relevant errors. (This also meansGPIO_MEM_LOCKS
can be moved back to a local struct field) - Give each
Pin
a clonedGpioState
. - Use a weak reference for the shared static
GpioState
, so it'll automatically get dropped when allGpio
andPin
instances go out of scope. - Move the static
PINS_TAKEN
to a localGpioState
struct field. -
ConsiderGpio::take()
versusGpio::get()
.Option::take()
andHashSet::take()
similarly remove the returned value from where it was taken. However,Pin
can be taken again after it goes out of scope, so that makes the expected functionality different.get()
methods usually return a temporary reference instead of an owned value, but after the returned reference goes out of scope it can be retrieved again, similar to what happens when aPin
is dropped. - Disable pull-up/pull-down when InputPin is dropped and clear_on_drop==true.
- Expand pin documentation in the main section of the gpio module.
- Add a section on interrupts to the gpio module documentation.
-
Investigate if we can lock a pin throughSee comment below./dev/gpiochipN
to prevent other processes from gaining access simultaneously, while still using/dev/gpiomem
for fast register access. - Using the gpio module for charlieplexing or bitbanging I2C requires switching a pin between input and output mode. This should be easier to do than dropping the derived pin and calling
Gpio::get()
again for each mode switch. Possible solutions:Addinto_
methods toInputPin
andOutputPin
to switch pin types.- Add a new pin type (
IoPin
?) that allows users to switch between input and output mode. The new pin type could allow users to set any mode, replacingAltPin
. Add a set of methods to eitherPin
orInputPin
andOutputPin
that either return a temporary reference, or take a closure that is called with a reference to a pin of the appropriate type.
- Change
Gpio::get()
to return aResult
rather than anOption
for uniform error handling. Return anError::PinNotAvailable
when a pin is already in use, or when the pin number isn't supported on the current Pi model. -
Consider removingReconsider for 0.11.0.Gpio::new()
, and instantiate/cloneGpioState
from withinGpio::get()
.Gpio::poll_interrupts()
would need some tweaks as well. Pro: Single method that can return any applicable errors. Con: Need to lock a mutex for each call. No uniform API for all peripherals.
golemparts commented
golemparts commented
After doing some research/testing on using /dev/gpiochipN
to lock pins for exclusive access, I've come to the conclusion the interface just isn't mature enough for this yet.
/dev/gpiochipN
must be re-opened through a new fd each time we want to request a handle to lock a pin for exclusive access. If we continue to use an already open/dev/gpiochipN
after another process takes and then releases a handle, our handle request's fd will be 0 (indicating an error).- Requesting a handle requires providing a pin mode (if flags is kept 0, the pin mode will still be changed to Input). Since the ioctl interface doesn't yet provide a way to set (or read) any of the ALT function modes, that means requesting a handle will always overwrite those modes unless we subsequently reset them through the registers, which ends up requiring a messy workaround at a point where we don't want to mess with the pin's mode (read the current mode through
/dev/gpiomem
, open/dev/gpiochipN
, request a handle (which briefly changes the pin mode to Input), reset the mode through/dev/gpiomem
, create a Pin instance).
I'll revisit this idea at some future point, after additional Raspberry Pi-specific features are added to /dev/gpiochipN
(support for setting pull-ups/pull-downs would be nice to have as well).