Now PACs are generated by svd2rust and used both in HALs and in the user code via HAL reexport. Most PAC updates are technically breaking changes that require a PAC version bump, and then a HAL version bump. Given the overall "breaking changes are bad" attitude, it's better to reduce the consequences caused by PAC updates. The proposed solution here is:
- Don't re-export PAC APIs in HAL, use PACs internally instead.
- Separate ownership part of PAC from the register access API part
- Allow both users and HALs use different register access API over the common "ownership" base.
Ownership part, or "common base" will serve a problem of defining peripherals for all the supported microcontrollers and should be stable as stone. It provides:
- Separate peripheral definitions in form of ZST, that can only be constructed unsafely. Each peripheral implements a trait that contains an associated constant -- an address of the peripheral.
- Optional safe abstraction (
Peripherals
structure) for constructing the peripherals once.
Outcomes:
- More freedom in using different peripheral access API layers (svd2rust vs stm32ral vs something new)
- PAC updates no longer require HAL "breaking" version update
Despite great efforts towards svd2rust code optimization, build times for "big" chips are still really slow, especially compared to the stm32ral "baseline".
The proposed solution allows importing peripheral access API only for those peripherals that are actually used in HAL. This, with the corresponding support for partial import from the svd2rust, should improve build times a lot.
At the moment non-trivial drivers like stm32-usbd
require
PAC layer to access the peripherals. Early experience showed that
using peripherals re-exported from HALs is not an option, so such
crates pull their own peripheral access layer, independent of that
provided by HALs.
The proposed solution allows importing arbitrary PAC API instead of vendoring it. This allows updating PAC API in a regular way to get bug fixes and missing field definitions.
Additionally, with the presence of the common base, this solution allows defining a driver trait that will be implemented for all the supported peripherals from different families.