-
Notifications
You must be signed in to change notification settings - Fork 269
Created a first draft of the I3C trait. #724
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
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
|
|
||
| [package] | ||
| authors = [ | ||
| "The Embedded HAL Team and Contributors <embedded-hal@teams.rust-embedded.org>", | ||
| ] | ||
| categories = ["embedded", "hardware-support", "no-std"] | ||
| description = "Traits for abstracting I3C Databusses" | ||
| documentation = "https://docs.rs/embedded-hal-i3c" | ||
| edition = "2021" | ||
| rust-version = "1.81" | ||
| keywords = ["hal", "IO"] | ||
| license = "MIT OR Apache-2.0" | ||
| name = "embedded-hal-i3c" | ||
| readme = "README.md" | ||
| repository = "https://github.com/rust-embedded/embedded-hal" | ||
| version = "0.1.0" | ||
|
|
||
| [features] | ||
| async = ["dep:embedded-hal-async"] | ||
| # Derive `defmt::Format` from `defmt` 0.3 for enums and structs. See https://github.com/knurling-rs/defmt for more info | ||
| defmt-03 = ["dep:defmt-03", "embedded-hal/defmt-03", "embedded-hal-async?/defmt-03"] | ||
|
|
||
| [dependencies] | ||
| embedded-hal = { version = "1.0.0", path = "../embedded-hal" } | ||
| embedded-hal-async = { version = "1.0.0", path = "../embedded-hal-async", optional = true } | ||
| defmt-03 = { package = "defmt", version = "0.3", optional = true } | ||
|
|
||
| [package.metadata.docs.rs] | ||
| features = ["async"] | ||
| rustdoc-args = ["--cfg", "docsrs"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| pub use embedded_hal::i2c::Operation; | ||
|
|
||
| /// I3C error. | ||
| pub trait Error: core::fmt::Debug { | ||
| /// Convert error to a generic I3C error kind. | ||
| /// | ||
| /// By using this method, I3C errors freely defined by HAL implementations | ||
| /// can be converted to a set of generic I3C errors upon which generic | ||
| /// code can act. | ||
| fn kind(&self) -> ErrorKind; | ||
| } | ||
|
|
||
| impl Error for core::convert::Infallible { | ||
| #[inline] | ||
| fn kind(&self) -> ErrorKind { | ||
| match *self {} | ||
| } | ||
| } | ||
|
|
||
| #[non_exhaustive] | ||
| pub enum ErrorKind { | ||
| Bus, | ||
| ArbitrationLoss, | ||
| Ovverun, | ||
| Other, | ||
| } | ||
|
|
||
| /// I3C error type trait. | ||
| /// | ||
| /// This just defines the error type, to be used by the other traits. | ||
| pub trait ErrorType { | ||
| type Error: Error; | ||
| } | ||
|
|
||
| impl<T: ErrorType + ?Sized> ErrorType for &mut T { | ||
| type Error = T::Error; | ||
| } | ||
|
|
||
| pub trait I3c<S: SpeedMode = Sdr>: ErrorType { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure I agree with the Speed mode typestate here. We can switch between DDR and SDR in runtime, right? Will you require folks to consume and recreate the I3C (presumably with helpers
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought about the controller implementing all supported speeds for the same object. The client can then use the different supported speeds depending on which trait is used to call transaction. In this design the whole transaction has the same speed. The switch from i2c to i3c would happen after the first address byte has been sent and arbitration is over.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apparently my idea on how I would implement this didn't work out or I'm missing on how to constrain the types properly. As can be seen in the test. Ideas on another Idea. Different traits for the different speeds could work, but they'd be unwieldy. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it'll be hard to come up with something sensible. But I think a single trait that lets you do a
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My idea behin the typestates was to ensure that a user is never able to combine a slave and controller, where the speed is not suported by both. |
||
| // Here we also add read, write read_write like I2C removed for brevity | ||
|
|
||
| /// Execute the provided operations on the I3C bus. | ||
| /// | ||
| /// Transaction contract: | ||
| /// - Before executing the first operation an ST is sent automatically. This is followed by SAD+R/W as appropriate. | ||
| /// - After the first time the address is send the bus switches to the specified speed | ||
| /// - Data from adjacent operations of the same type are sent after each other without an SP or SR. | ||
| /// - Between adjacent operations of a different type an SR and SAD+R/W is sent. | ||
| /// - After executing the last operation an SP is sent automatically. | ||
| /// - If the last operation is a `Read` the master does not send an acknowledge for the last byte. | ||
| /// | ||
| /// - `ST` = start condition | ||
| /// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing | ||
| /// - `SR` = repeated start condition | ||
| /// - `SP` = stop condition | ||
| fn transaction( | ||
| &mut self, | ||
| address: u8, | ||
| operations: &mut [Operation<'_>], | ||
| ) -> Result<(), Self::Error>; | ||
| } | ||
|
|
||
| trait Sealed {} | ||
|
|
||
| #[allow(private_bounds)] | ||
| pub trait SpeedMode: Sealed + 'static {} | ||
|
|
||
| /// Single data rate | ||
| pub struct Sdr {} | ||
|
|
||
| impl Sealed for Sdr {} | ||
|
|
||
| impl SpeedMode for Sdr {} | ||
|
|
||
| /// Double data rate | ||
| pub struct Ddr {} | ||
|
|
||
| impl Sealed for Ddr {} | ||
|
|
||
| impl SpeedMode for Ddr {} | ||
Uh oh!
There was an error while loading. Please reload this page.