-
Notifications
You must be signed in to change notification settings - Fork 201
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
Async #334
Async #334
Conversation
r? @eldruin (rust-highfive has picked a reviewer for you, use r? to override) |
This is excellent. But moving |
Thank you for this proposal and the write-up.
Drawbacks:
I have created an RFC in the WG about taking over |
Git is able to track moved files, I think it should be able to merge across renames? 🤔 If moves are a concern I'd leave the subdir in when merging the crates. It's not useless, it'll avoid more file moves if/when we want to maintain more crates here. (Perhaps embedded-hal-compat? Perhaps stuff for sharing spi/i2c buses?) and re single-purpose: I'd argue async and blocking traits are two sides of the same coin, same purpose :) There are more advantages to have stuff in a single repo:
From my experience in embassy, managing a set of interdependent crates in separate repos gets really annoying really fast. The probe-rs project is also moving to single-repo for the same reasons. I strongly suggest doing single-repo :) |
Another option is leaving |
I would also like to voice my support for a single repo as the start point. CI, release cadence, team structure and perhaps other factors can influence the decision on multiple vs single repositories. However, I’ve also come to learn that starting with a single repository generally works out well. Also, async and non-async embedded development solves the same problem, sometimes together, so it feels right to combine them in this repository. We can avoid promoting a division between async and non-async development. :-) |
If Opinions @rust-embedded/hal? |
|
Co-authored-by: Lachlan Sneff <lachlan.sneff@gmail.com>
so perhaps the sweet spot is to have only No pain of moving files, no pain of multiple repos. The only pain is the "weird" file structure, but that's much less than separate repos IMO, and it's temporary until they get merged. |
Yes, should be the best way. |
That would be an acceptable compromise, thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, thanks for bearing with us!
Self: 'a; | ||
|
||
/// Reads words from the serial interface into the supplied slice. | ||
fn read<'a>(&'a mut self, read: &'a mut [Word]) -> Self::ReadFuture<'a>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't really want to derail this PR further / we can totally discuss elsewhere, but, it seems to me this needs to be able to return a partially filled result.
say you're reading serial payloads of size up to N, to use this trait you're going to need to always poll with &[Word; 1]
to guarantee you'll return, undermining the benefits of buffering / DMA.
i think in this case the trait would be more useful with Result<usize, Self::Error>
that tells you how full the buffer is, then the HAL can choose to return on EOF
/ timeout / buffer full as is relevant for the hardware.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with that is it's not specified when it returns, so different impls will do different things, making it useless for drivers.
In Embassy we specified it like this:
read
returns on buffer full.read_until_idle
returns on buffer full, or when at least 1 byte has been received and then the line goes idle.
read_until_idle
is a separate trait because some chips (nrf) can't do it natively so they need a hardware timer to do it. Forcing everyone to waste a timer when not needed would be rude, so there's a special impl supporting it that you can opt-in to use.
in my experience, read
is still useful if you know your packets have a fixed size, and it maps to a single DMA read operation which is the lowest overhead possible.
(this also applies to the uart blocking traits, IMO we should have a way to do reads without nb
. The current nb
read trait works really badly in the nRF because it can only do DMA reads.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with that is it's not specified when it returns, so different impls will do different things, making it useless for drivers.
i don't think adding this _may_ return a partial buffer on timeout or idle
is useless? this is how reads under linux typically work, it just implies the need for a check and buffering at the driver level if you're not doing byte-wise processing.
... some chips (nrf) can't do it natively so they need a hardware timer to do it
rude of them (nrf) imo
in my experience, read is still useful if you know your packets have a fixed size, and it maps to a single DMA read operation which is the lowest overhead possible.
the problem with this approach appears when you know your packet sizes but you somehow end up out-of-sync or with corrupted data, then you have to have application timeouts to recover anyway.
342: Add embedded-hal-async crate in subdirectory r=ryankurte a=eldruin This is a simpler version of #334 where an empty `embedded-hal-async` crate is added inside a subfolder. I propose merging this and add all the traits and docs piece by piece so that they can be discussed comfortably. The CI adaption went fine except for the changelog check, which cannot check that the changelog in the `embedded-hal-async` subfolder was touched. All credit for this idea goes to `@Dirbaio` ! Co-authored-by: Diego Barrios Romero <eldruin@gmail.com>
Converting to draft, will open PRs for each individual trait, first is #344 . Will close this when they're all opened. |
Depends on #331 #323
Separate crate
Following the discussions on #285, this adds the async traits in a separate crate. TLDR of the reasons:
Once we're confident EHA is "1.0 ready", we can move the traits to the main EH crate. This can be done backwards-compatibly: move the traits, then do one last update to EHA making it just reexport them from EH.
Single repo
This moves
embedded-hal
to a subdir, then adds another forembedded-hal-async
.The advantage of having both crates in this repository is that a single PR can update both the blocking and async traits. Since they are close mirrors of each other, it's very likely a change to one (e.g. docs) will affect the other.
Trait design
The design closely mirrors the blocking traits.
The only differrence is I have removed the
iter
methods such aswrite_iter
because they don't work well with async. Fundamentally operate byte by byte, so the core has to wake up for each one. It can't kick off a single bit DMA transfer and then sleep or do something else.HAL use
GAT-based async traits have been in use for a while at embassy-traits and have worked great. IMO the approach is proven.
Working HAL implementation for nRF chips here embassy-rs/embassy#552. STM32 coming soon.
TODO: