Skip to content

Add async gpio support #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 7, 2025
Merged

Add async gpio support #64

merged 5 commits into from
Mar 7, 2025

Conversation

d3zd3z
Copy link
Collaborator

@d3zd3z d3zd3z commented Mar 5, 2025

This adds a cargo feature to the zephyr crate async-drivers, which enables support for async driver calls. These are built around standard Rust async, and should work with any executor (except for the kio one which is non-standard).

Currently, this adds wait_for_high and wait_for_low to the gpio driver (currently, only level triggering, not edge). The implementation both tries to avoid races as well as avoid excessive interrupts. However, as the Zephyr gpio API does not provide a way to read an individual interrupt status, this does require the IRQ to always fire. In the case where the pin is already at the desired level, the IRQ callback will happen between the enable, and the status check, which means the async task will not pend, but simply return, just with the overhead of an irq and the callback.

There is a single callback per gpio controller.

This includes a new mechanism in the devicetree mapping that allows static data to be associated with each instance. Static data is needed as the callback and the state cannot be moved.

@d3zd3z d3zd3z force-pushed the embassy branch 3 times, most recently from 37d825c to 15f1cb3 Compare March 5, 2025 20:27
d3zd3z added 5 commits March 6, 2025 09:19
Add methods for get and set of pin logical values.

Signed-off-by: David Brown <david.brown@linaro.org>
Allow the dt-rust.yaml file to specify a `static_type` value for device
nodes.  The generated code for the nodes will reserve a static value of
that type, and pass it into the constructor.  There is a NoStatic which
is the default.  As it is zero size, it will not cause any code to be
generated for the types that do not need static.

Fix the flash device to accept this argument, but the fix for gpio will
come in a subsequent patch.

Signed-off-by: David Brown <david.brown@linaro.org>
Implement a general async `wait_for_high` and `wait_for_low` to the
GpioPin interface.  The waiting is supported at the level of the gpio
driver. Each Gpio instance has an array of `AtomiWaker` to hold the
wakers that are waiting on the pins, as well as the callback handler
from using the pins in interrupt mode in Zephyr.

Although most of the examples of gpios in Zephyr use irq-gpios instead
of gpios in the custom properties, there isn't anything that happens
when this is done, and regular 'gpios' properties work just fine with
interrupts.

Signed-off-by: David Brown <david.brown@linaro.org>
This is a basic test to test for the waiting gpios.  Currently, this
test requires a specific hardware setup.  To test on the rpi-pico, it is
necessary to connect GPIO-0 to GPIO-6 with a button or switch.
Running should then print Pressed/Released on a debounced version of
that switch, with the code not polling the gpio while waiting.

Signed-off-by: David Brown <david.brown@linaro.org>
Enable the async functionality so it will be included in the generated
documentation.  This also requires enabling an additional KConfig needed
to be able to configure the state of interrupts on gpios.

Signed-off-by: David Brown <david.brown@linaro.org>
@d3zd3z d3zd3z merged commit 2790674 into main Mar 7, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants