Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add async API for CAN#585

Open
liamkinne wants to merge 8 commits into
rust-embedded:master from
umi-eng:feature/embedded-can-async
Open

Add async API for CAN #585
liamkinne wants to merge 8 commits into
rust-embedded:master from
umi-eng:feature/embedded-can-async

Conversation

@liamkinne

@liamkinne liamkinne commented Apr 2, 2024

Copy link
Copy Markdown
Contributor

Adds a new CAN trait with both async and fallback non-blocking methods.

Module is named asynch to avoid a collision with the async keyword. Alternatively a separate crate embedded-can-async could be published.

@liamkinne liamkinne requested a review from a team as a code owner April 2, 2024 13:53
Comment thread embedded-can/src/asynch.rs Outdated

/// Tries to put a frame in the transmit buffer.
/// If no space is available in the transmit buffer `None` is returned.
fn try_transmit(&mut self, frame: &Self::Frame) -> Option<Result<(), Self::Error>>;

@burrbull burrbull Apr 2, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange signature.

@liamkinne liamkinne Apr 2, 2024

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inspired by a pattern I've seen around like here: https://docs.rs/rtic-sync/latest/rtic_sync/arbiter/struct.Arbiter.html

Can just get rid of it, but I think it's useful.

Copy link
Copy Markdown
Member

Thanks for the PR! We had a brief discussion about it in the weekly meeting today. Having the trait in the asynch module is fine. I think the only remaining question is whether to keep the try_x() methods, move to to another trait, or delete them entirely.

It looks like either the crate's MSRV (and related CI tests) will need updating, or the trait needs to be gated, to get CI passing, too.

Copy link
Copy Markdown
Contributor Author

@adamgreig thanks for the update.

I'm still strongly for keeping the try methods. The use case is that when libraries (bxcan, fdcan, etc) implement these traits they can only implement one trait at a time so they will have a blocking client and an async client. If you're using the async client but need to do something in a non-async context (think RTIC hardware task) you need something to fallback to that doesn't require .await.

It is very similar to the ideas around nb but more like "hey this method will work first time most of the time, unless your buffer is full which you can chose how to handle".

edisno reacted with thumbs up emoji

Copy link
Copy Markdown
Contributor Author

@adamgreig in the interest of getting this through so it can start being used downstream, I've removed the try methods.

Copy link
Copy Markdown
Member

Thanks for the prompt and the update. I'll add this to the agenda for discussion in the weekly meeting this Tues.

liamkinne reacted with thumbs up emoji

Comment thread embedded-can/src/lib.rs Outdated
// We don't immediately remove them to not immediately break older nightlies.
// When all features are stable, we'll remove them.
#![cfg_attr(nightly, allow(stable_features, unknown_lints))]
#![cfg_attr(nightly, feature(async_fn_in_trait, impl_trait_projections))]

@Dirbaio Dirbaio Jul 2, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these cfg_attrs do nothing without this in build.rs.

These were for compat with older nightlies before AFIT was stable. Now that AFIT has been stable for a few rust versions since 1.75, i'd just not put them, and support stable 1.75+ only.

@liamkinne liamkinne force-pushed the feature/embedded-can-async branch from b8f8ec1 to 37f4be6 Compare July 4, 2024 10:54

elpiel commented Dec 6, 2024

Copy link
Copy Markdown

Are there any blockers for this PR?

Thom-de-Jong, mbrieske, and 02alexander reacted with eyes emoji

MabezDev
MabezDev previously approved these changes Feb 7, 2025

@MabezDev MabezDev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on https://github.com/rust-embedded/embedded-hal/blob/master/docs/how-to-add-a-new-trait.md we should encourage some experimentation here.

IMO with CI fixed, we should merge this it looks like a good first run to me and time will tell if it's suitable in the long term.

liamkinne reacted with thumbs up emoji
@MabezDev MabezDev requested a review from a team February 7, 2025 12:20
Comment thread embedded-can/src/asynch.rs Outdated

/// Puts a frame in the transmit buffer.
/// Awaits until space is available in the transmit buffer.
async fn transmit(&mut self, frame: &Self::Frame) -> Result<(), Self::Error>;

@ryankurte ryankurte Feb 10, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think these should be in the form

fn transmit(&mut self, frame: &Self::Frame) -> Future<Output=Result<(), Self::Error>>;

to avoid needing #![allow(async_fn_in_trait)] (which iirc will be deprecated in the future). you can still implement using async fn in either case.

robamu commented Apr 9, 2025
edited
Loading

Copy link
Copy Markdown
Contributor

What is the state of this PR? async fn in traits should now work without any additional attributes, right?

Thom-de-Jong reacted with eyes emoji

Comment thread embedded-can/src/lib.rs Outdated

#![warn(missing_docs)]
#![no_std]
#![allow(async_fn_in_trait)]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this still required on stable Rust?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not, however, an appropriate MSRV should be used in Cargo.toml for this.

@liamkinne liamkinne Aug 8, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is required for the MSRV listed in the Cargo.toml (1.81). Do you want me to keep it or bump the MSRV?

Copy link
Copy Markdown
Contributor Author

Before I go any further on this, do we want a single trait to encapsulate transmit and receive or would it be better split into a Tx and Rx trait?

Copy link
Copy Markdown

I would like to chime in as I have been using this branch for a project for some time now, I actually did implement the split method in my fork because I needed exactly that: https://github.com/swobbee-dev/embedded-hal/tree/feature/embedded-can-async

Therefore I would be greatly in favour of splitting 👍

liamkinne, Quettle, mbrieske, theo-proception, and ryankurte reacted with thumbs up emoji

@liamkinne liamkinne force-pushed the feature/embedded-can-async branch from 5d35622 to 68d91c8 Compare January 24, 2026 10:20

Copy link
Copy Markdown
Contributor Author

@adamgreig I've rebased this so it is ready for review again. Notable changes since last time is the trait is now split into tx and rx.

@eldruin eldruin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this!
Would it be possible to remove the async_fn_in_trait feature if rewriting the signatures like this like stated above?

fn transmit(&mut self, frame: &Self::Frame) -> Future<Output=Result<(), Self::Error>>;

Then we do not need to touch the MSRV. What version would not need it?

Copy link
Copy Markdown
Contributor Author

@eldruin no worries. Have updated the function signatures and left the MSRV as is.

@eldruin eldruin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me, thank you!
Do you have any implementations of the trait somewhere?

Copy link
Copy Markdown

Do you have any implementations of the trait somewhere?

I am currently waiting for this PR before using it here:
ch32-rs/ch32-hal#146

liamkinne and 02alexander reacted with thumbs up emoji

Copy link
Copy Markdown
Contributor Author

Looking at the embassy fdcan implementation, I realised there's something missing from the transmit signature. It needs to return Ok(Option<Frame>) in the case that the transmit mailboxes are full. This is the existing API with the non-blocking traits.

mickeprag reacted with thumbs up emoji

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@eldruin eldruin eldruin left review comments

@ryankurte ryankurte ryankurte left review comments

@Dirbaio Dirbaio Dirbaio left review comments

@MabezDev MabezDev MabezDev left review comments

+3 more reviewers

@burrbull burrbull burrbull left review comments

@elpiel elpiel elpiel left review comments

@robamu robamu robamu left review comments

Reviewers whose approvals may not affect merge requirements

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

AltStyle によって変換されたページ (->オリジナル) /