-
Notifications
You must be signed in to change notification settings - Fork 33
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
Cleanup IOMUXC feature #75
Conversation
Reference documentation in sub-modules.
The empty enum cannot be made into an instance. This should indicate that, even though they're public, they're only type-level identifiers.
- remove ConfigBuilder; just use Config - add a mask that specifies which fields were changing - add documentation and examples - add a few unit tests
These tests are visually larger. I moved them into their own files so they're easier to study. This also gives us the opportunity to do some more advanced failure analysis, like a formal diff between the two files (today's error messages are hard to parse...).
Generate a top-level erase() method to perform cascading pad type erasure.
Rather than having a separate crate per chip implementation, I'm proposing that we have a single, imxrt-iomuxc crate. We expose chip-specific pads behind feature flags. I know this is the opposite of what I originally proposed, but hear me out. We won't require a feature flag, but a feature flags will be needed to access processor-specific pads. The interfaces are the only thing that we expose if we don't use a feature flag, so that's the same as using the imxrt-iomuxc crate by itself. Adding more and more feature flags is the same as depending on more and more crates. If we expand that through a user's dependency graph, it ends up being equivalent. But, managing a single crate with multiple feature flags is easier than managing multiple crates that effectively represent features. We will still compile all of the tests without feature flags. And, we can document everything by specifying '--all-features'. Finally, we can expose a simpler interface without the "if it's not documented, it's not public" clauses.
Check the imxrt-iomuxc crate separately from the HAL
In #72, we proposed that we should have an interface crate, This PR includes the refactor and IOMUXC consolidation. |
Remove documentation notes about "crate family" or implementation crates. Fix some 'public but internal' visibility, and justify other #[doc(hidden)] attributes.
The `imxrt-iomuxc` crate family does not require any feature flags, and it will build for your host. Consider using `--package` flags to build and test the crate family in one command: | ||
|
||
``` | ||
cargo build --package=imxrt-iomuxc --package=imxrt106x-iomuxc --package=imxrt-iomuxc-build |
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.
Is this right now, since you've removed the imxrt106x-iomuxc crate?
|
||
```rust | ||
let mut uart = uarts.uart2.init( | ||
peripherals.iomuxc.ad_b1.p02, |
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.
This is a really nice API now, I really like the way this call looks with the changes made here
should change to | ||
|
||
```rust | ||
type HardwareFlag = hal::gpio::GPIO<hal::iomuxc::ad_b1::AD_B1_10, hal::gpio::Output>; |
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.
And again here, the resulting type and API is much nicer now
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.
Not sure what I was thinking when putting together the previous GPIO types 😛they were gnarly! There's still more gnarly HAL code I need to rethink...
type HardwareFlag = hal::gpio::GPIO<hal::iomuxc::ad_b1::AD_B1_10, hal::gpio::Output>; | ||
``` | ||
|
||
The new GPIO types expose a no-return `toggle()` method, which shadows an embedded_hal |
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 suppose there's a reason we don't need to return here, its because its effectively infallible correct? Very nice if so
|
||
```toml | ||
[dependencies] | ||
imxrt106x-iomuxc = { version = "0.1", features = ["imxrt102x", "imxrt106x"] } |
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 believe this is now imxrt-ioxmuc correct?
|
||
```toml | ||
[dependencies] | ||
imxrt106x-iomuxc = { version = "0.1", features = ["imxrt106x"] } |
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 believe this should be imxrt-iomuxc
|
||
/// Tag that indicates the SCL signal | ||
pub struct SCL; | ||
pub enum SCL {} |
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.
why the type change here?
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.
It's one of a few ways to express a zero-sized type. But, this ZST can never (accidentally) be an object, unlike the current approach.
pub struct SCL; // 1
could be instantiated by crate users. Not a big deal, but it's not something they should do.
pub struct SCL(()); // 2
cannot be instantiated by crate users, since they can't see the inner unit. But, us imxrt-iomuxc
maintainers can still create an instance of it inside our crate, then pass an instance of it through our API. Again, not something we should do, but we're not preventing it.
pub enum SCL {} // 3
cannot be instantiated outside our crate, or inside our crate, since there's no variants. It's the strongest signal of "don't make an instance," since it's intended be a type-level tag.
The only difference I can note is how rustdoc documents these type-level tags. They're either grouped as enums or structs. I've no preference here. If we prefer organizing type tags as structs
, I'll recommend that we go to option // 2
to prevent users from creating needless SCL
objects.
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.
This makes sense to me, thanks for explaining. Enums seem fine to me
#[repr(u32)] | ||
pub enum Hysteresis { | ||
Enabled = 1 << 16, | ||
Disabled = 0 << 16, | ||
Enabled = 1 << HYSTERESIS_SHIFT, |
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.
Thank you for defining these consts, makes it easier to read
The PR addresses the TODOs described in #73, updates documentation, adds tests, and describes how users should migrate their code.
The only new feature is that there's a convenience function for erasing all pad types. It turns the struct of strongly-typed pads into arrays of type-erased pads, with arrays named by their grouping (like
ad_b0
). Here's a comparison of how one access the same physical pad using the strongly-typed interface, and the type-erased interface:Closes #26.