Closed eldruin closed 10 months ago
Would it be worth cutting a 0.1.0-alpha (or just 0.1.0) release with the existing I2C, SPI etc async traits, while Serial is worked out?
Given the higher complexity I also expect CAN might take a while longer to figure out than the others, so at least getting the basic traits onto crates.io would let people start using them without git dependencies.
Could we have an alpha 1 release of this? I have a pending PR for embassy that depends on the new SPI transaction API in master. Cheers!
I've started trying to port some of my code over to embedded-hal-async
, and I'm wondering if you have any guidance for how device driver crates should be ported. It's not a great story if we tell everyone they have to maintain two copies of every function, where the ~only difference is async
and .await
sprinkled in one of them.
I'm wondering if there might be a procedural macro solution that would allow a single device driver to be compiled in both blocking and async modes. Has anyone explored that? Or is it more trouble than it's worth and we expect crates to quickly move over to the new traits? (Presumably that's blocked on the necessary features hitting stable.)
there's a blocking to "fake async" adapter that you can use to get an async impl out of any HAL with only a blocking impl. It's "fake async" because it will block and never "async yield", but for many use cases that's fine (spi/i2c register reads/writes are fast).
This allows maintaining just one version of the driver (async) but still using it with HALs that don't support async.
You still need an "executor", but since there's no yielding/waking going on a very dumb one like loop { fut.poll() }
is enough (roughly same idea as nb::block!()
), so it should still be very lightweight.
I saw that adapter, but I feel like you wouldn't want to do "async only" until both these traits are stable and they can be compiled with stable Rust, and probably an fut::block!()
macro that mirrors nb:block!()
exists for people who are not using async.
I'm wondering if there might be a procedural macro solution that would allow a single device driver to be compiled in both blocking and async modes. Has anyone explored that?
i've spent way more time than i should have trying to achieve this with traits with no real success (though radio
is kinda neat in that our higher-level blocking traits automagically become async)... definitely interested in whether we can do useful things with proc macros without too much magic (tm).
Or is it more trouble than it's worth and we expect crates to quickly move over to the new traits?
i don't think we can expect folks to all move to async (or vice versa), so the story for compatibility and combining the two seems fairly important!
I'm wondering if there might be a procedural macro solution that would allow a single device driver to be compiled in both blocking and async modes. Has anyone explored that?
i've spent way more time than i should have trying to achieve this with traits with no real success (though
radio
is kinda neat in that our higher-level blocking traits automagically become async)... definitely interested in whether we can do useful things with proc macros without too much magic (tm).
I started writing something like this and then I discovered the maybe-async-cfg
crate already does pretty much exactly what I was thinking of.
I was able to very easily adapt my async device driver into something that compiles both sync and async versions side-by-side. I don't quite love the user ergonomics (it generates types named FooSync
and FooAsync
to keep them separate; I think it would be better if they could just be generated in two different modules, so the user would only have to change a use
statement to swap between them, but then the problem is that async
is a reserved identifier and use device::r#async::Device
is not a great UX either.)
@ryankurte Maybe take a look at that crate and see what you think?
I was able to very easily adapt my async device driver into something that compiles both sync and async versions side-by-side. I don't quite love the user ergonomics (it generates types named
FooSync
andFooAsync
to keep them separate; I think it would be better if they could just be generated in two different modules, so the user would only have to change ause
statement to swap between them, but then the problem is thatasync
is a reserved identifier anduse device::r#async::Device
is not a great UX either.)
I think the accepted naming convention for async modules is asynch
:)
Hello everyone, I'm joining this conversation to see the progress of the issue. It seems that there are still a few things missing (to my understanding) in order to release a stable version of the async traits, however, there is one thing that can be done additionally:
Digital Pin (input, output, etc.) in the async hal should be added, until the traits get merged inside the embedded-hal
, until then we still have to rely on embedded-hal for the async versions when dealing with digital pins.
Discussion point from https://github.com/rust-embedded/embedded-hal/issues/177:
Should embedded-hal-async
be merged back into embedded-hal
, now that async fn
in traits are stable? And if so, how do we best do that?
Another thing: Is embedded-hal-nb
still useful, or should it be deprecated now that we can do async
things in stable?
my personal opionion is we should deprecate it (i.e never release embedded-hal-nb 1.0), but it's up to the HAL team as a whole to decide... It was discussed a while back and the conclusion was "don't deprecate, or at least not yet". Perhaps now that stable AFIT is here it's worth a second discussion?
For what it's worth, I never encountered a library that actually implements the embedded-hal-nb
traits in the wild. Most of the dependent packages are HALs, based on what's published at least.
embedded-hal-async
1.0.0 has now been released.
Thank you so much to everyone that was worked and helped through all this time to make this a reality.
🎉
We have started a project to develop a asynchronous versions of the
embedded-hal
traits, at the moment championed by @Dirbaio. This will be developed as a separate crate calledembedded-hal-async
until it is ready for integration inside a module inembedded-hal
. This can be found in the subfolderembedded-hal-async
Roadmap:
348
347
349
344
346
async fn
in traits (expected breaking change insideembedded-hal-async
).async fn
in traits are available in Rust stable (Tracking issue)Asynchronous execution holds great potential for embedded. Please join us!