Skip to content
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

Optional async support #230

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Optional async support #230

wants to merge 1 commit into from

Conversation

XLPhere
Copy link

@XLPhere XLPhere commented Jan 19, 2025

This is an attempt to build upon PR #175 by @vhdirk with the idea by @avsaase of using the maybe_async.

The async feature will do the following:

  • Switch all the relevant functions from sync to async.
  • Swap DelayNs and SpiDevice from embedded_hal to their embedded_hal_async counterparts.

The actual implementation code is written in async, but will be converted to sync code by maybe_async if the async feature is not defined, so this should not result in any runtime overhead and code duplication should be minimal.

Notes:

  • This solution uses a modified version of the maybe_async crate to make the async feature opt in and not opt-out, see: feat: add default_sync and is_async feature gate fMeow/maybe-async-rs#26
  • #[maybe_async::maybe_async(AFIT)] currently doesn't have a possibility make returned version Send, possible solutions to this might be:
    1. Ignore the compiler warning with #[allow(async_fn_in_trait)] and not guarantee the presence of the Send trait. (current solution used in this draft)
    2. Use #[maybe_async::maybe_async(Send)], which will use #[async_trait] (in its current version) - would be an additional dependency added.
    3. Define sync and async version of crates manually (would duplicate trait definition).
  • The slowdown from SINGLE_BYTE_WRITE = true is significantly higher on async (for the RP2040 I'm testing on at least, it slows down to 40s) - a feature to disable this behavior would possibly be beneficial (or setting this to false entirely).

Comments and improvement ideas are appreciated!

@XLPhere XLPhere changed the title Async support that can be enabled with a feature flag Optional Async Support Jan 19, 2025
@XLPhere XLPhere changed the title Optional Async Support Optional async support Jan 19, 2025
@XLPhere XLPhere force-pushed the async branch 6 times, most recently from 84fb9ed to fc465e6 Compare January 26, 2025 15:04
@XLPhere XLPhere marked this pull request as ready for review January 26, 2025 15:04
@auto-assign auto-assign bot requested a review from caemor January 26, 2025 15:04
@XLPhere
Copy link
Author

XLPhere commented Jan 26, 2025

This should now be ready for testing!
Feedback on the async version as well as the sync version (which should work exactly the same as before) is very much appreciated!

@XLPhere XLPhere force-pushed the async branch 2 times, most recently from 9b60f05 to d0019cd Compare January 26, 2025 15:43
Optional async api that can be switched to with the "async" feature flag
@vhdirk
Copy link
Contributor

vhdirk commented Jan 26, 2025

Hi @XLPhere .
While it may not look like it, my async fork of this project does work. Or did work, I can't remember where I left off trying to go for embedded hal 1.0 :) I have a number of other projects queued before I can invest time in this again, so I'm glad you are taking the time getting async merged.

Maybe_async is cool. It keeps API changes (for sync) to a minimum, if needed at all. My idea was to work on an async version first and then see how that could be merged into main again.

Specifically, I wanted to get rid of all polling that exists in epd-waveshare since embedded_hal_async has a Wait trait. Even if rusts async is all polling, I felt that using the built-in Wait would perhaps be beneficial to battery life. But that's just an assumption.

As for delays; I saw that spi has a 'delay' transaction. I am assuming it to be more optimized than just a regular delay, but that's not really based on anything.

Since those 2 things caused a lot of API changes, I tried to improve error handling at the same time.

And as these things go, it ultimately became too much work to chop it in bite-sized chunks for merging...

I hope this clears up what my fork is trying to achieve :)

@XLPhere
Copy link
Author

XLPhere commented Feb 2, 2025

Hey @vhdirk

Thank you for your comments and previous work on this that very much influenced this solution!

The idea of this PR is to introduce no API and essentially also no implementation changes at all for the sync version, so the existing users won't run in any trouble from upgrading to a version with these changes.

The idea of the Wait trait is a good one, I have seen that some implementations use interrupts to facilitate that instead of polling, so it might make a difference. I will look into a solution that will use the wait trait when it is available and no delay_us has been set by the user.

The idea of SPI having a delay transaction could be useful to simplify the API (by no longer needing to pass the delay object), but this would API changes or at least could introduce behavioral changes for the sync version, so i would consider this out of scope for this PR. If seen beneficial it can be added by a separate PR later, i would suggest.

Either way, thanks for your input!

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