Skip to content

transfer all current feature gating to device specific features #266

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

Merged

Conversation

Crzyrndm
Copy link
Contributor

@Crzyrndm Crzyrndm commented Oct 30, 2021

MCU with missing PAC support is marked like
// feature = "stm32l471", // missing PAC support
when PAC support is resolved, feature gate can just be uncommented

This is pretty much the exact opposite style to #261 with no derived / internal features at all. There's enough inconsistencies that I can see this being beneficial, although some of the longer conditions are quite knarly

Missing PAC support is notably problematic, particularly for L451/L471, but several other locations as well. I've tried to leave these in place but commented where I find them

@Crzyrndm Crzyrndm mentioned this pull request Oct 30, 2021
@korken89
Copy link
Collaborator

Hmm, I'm still at a loss on how to handle all these features...
I'm not sure what's a sensible approach to actually use. It does however seem like something per MCU is needed.

@Crzyrndm
Copy link
Contributor Author

Crzyrndm commented Nov 11, 2021

Hmm, I'm still at a loss on how to handle all these features... I'm not sure what's a sensible approach to actually use. It does however seem like something per MCU is needed.

I can't see a way to avoid per-MCU features. There's just too many "on this device / group of devices, needs to be done this way".

  • Note that that most likely goes for the PAC too, there's already a few examples here where the PAC is missing definitions for devices in this PR. L471 was hit quite frequently by this (nevermind L4P/Q/R/S)

A quick skim of the other stm32 hal crates

As a side note, the F3 use of the build script made me a bit curious. The build script can be used to enable crate local features, but no dependencies (since dependencies are built prior to the build script running, this does make a lot of sense...). Pretty sure this is not a good idea as it's just a bit outside the box

println!("cargo:rustc-cfg=feature=\"{}\"", name);

@Crzyrndm
Copy link
Contributor Author

Crzyrndm commented Nov 12, 2021

I do have a slightly different idea that, while it may not necessarily reduce the total complexity involved here, could help localise it (+ side benefits). Multiple crates

Each module has a relatively limited number of points where differences are encountered (and therefore features required if it was a crate). This crate acting as the umbrella connecting them all together needs only the device features (which then enable the relevant features in the sub-crates) and it would be quite easy to make the API of this crate look unchanged (i.e. modules or crates doesn't matter to a consumer). The number of features at a single crate is reduced to a manageable level (no combinatorial explosion -> testable).

Cargo workspaces work extremely well (including being able to use paths for development and versions for published releases so it can all be developed in a single repo without issue) so the downsides that I can see are mostly to do with publishing multiple crates rather than just a single crate and I have not a clue what is involved there.

The side benefit I mentioned would be that fracturing the crate will most likely generate some pretty good compile time improvements. For the project I have been working on (a moderate sized firmware), it takes about 100 seconds to build (minimal effort to optimise that). 40 of those seconds are spent waiting for the PAC and HAL crates to chug through as the last two crates, completely single threaded (note that this is just as pronounced when making changes to the HAL. One small change == 20 seconds compiling, and it hampers IDE responsiveness too)

Note: I refer to the module as being the crate boundaries here mostly because that's the smallest that could be sensible. groupings of several modules that reuse a common set of features would work as well
Note2: This split could be done progressively. Doesn't need to happen in a single PR. Would need to start with the core bits that are dependencies of the peripheral modules though (rcc, gpio, etc.)

@DrTobe
Copy link
Contributor

DrTobe commented Nov 18, 2021

I like this approach here more than the one shown in #261 because it leaves us with a cleaner Cargo.toml and that is where users will most probably have a look first. So I guess this approach here is less overwhelming from a user's perspective. I agree that "some of the longer conditions are quite knarly" as you have already noted but I would just live with that in those places where specific peripherals are enabled/disabled as a whole, e.g. enabling I2C4 or UART4.

And I would also like to remind that feature-gating devices also requires setting up alternate function pin mappings. I still think that the approach I have sketched in #253 could be a viable option there because it lists out the mappings per-device instead of per-peripheral. Currently, this is done in the peripheral implementations itself but I already find those hard to read, i.e. hard to verify.

@DrTobe DrTobe mentioned this pull request Nov 18, 2021
@Crzyrndm
Copy link
Contributor Author

Crzyrndm commented Nov 18, 2021

I would agree that doing GPIO / AFx probably needs to be rethought and probably in a single location. The approach in gpio.rs does not make it easy to identify which device has which pins quickly. Second stage / #253 / changes here?

I would agree that this is the better starting point for per device features. It is more flexible inside the code (at the cost of verbosity) and can easily be extended later if reduced verbosity is required. #261 has probably served its purpose so I will close it

As far as overwhelming feature sets goes, Documenting it well in the readme, compile error message, and a large comment block / clear naming and separation in the cargo.toml (i.e. device features first, big comment block before internal features, internal features with clear naming convention e.g. prv_GPIOE, prv_GPIOF). Something like https://github.com/rust-lang/rfcs/blob/master/text/1977-public-private-dependencies.md would be really handy for this stuff

MCU with missing PAC support is marked like
`// feature = "stm32l471",  // missing PAC support`
@Crzyrndm Crzyrndm force-pushed the #29-device-feature-gates-no-derive branch from e9e1caf to 2886de1 Compare December 3, 2021 22:25
@Crzyrndm
Copy link
Contributor Author

Crzyrndm commented Dec 3, 2021

@korken89 rebased on master. What needs to happen to close this?

  • Not sure if should add the full set of devices to CI
  • A number of things that should be possible are blocked on PAC support (e.g. TIM3/UART4 for L45/L46)
  • ??

@korken89
Copy link
Collaborator

korken89 commented Dec 5, 2021

Overall LGTM. Lets add all feature gates to the CI though, so we at least test that them all can build the HAL.

After that I'll merge this!

@Crzyrndm Crzyrndm force-pushed the #29-device-feature-gates-no-derive branch from d5538cf to 085f69b Compare December 7, 2021 07:09
@Crzyrndm
Copy link
Contributor Author

Crzyrndm commented Dec 7, 2021

All of the standard L4 parts added. L4R/S (L4+) are not because support is pretty light and it makes examples quite difficult
Also added a group of comments in lib.rs with the major feature groups (L4x1, L4x2, ... / L41_L42, L43_L44, ...). Makes things a bit easier

@korken89 korken89 merged commit 9a2d2bd into stm32-rs:master Dec 7, 2021
@Crzyrndm Crzyrndm deleted the #29-device-feature-gates-no-derive branch December 7, 2021 18:14
@Crzyrndm Crzyrndm mentioned this pull request Dec 11, 2021
16 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants