stm32-rs / stm32l4xx-hal

A Hardware abstraction layer for the stm32l432xx series chips written in rust.
156 stars 103 forks source link

Replace extension traits with constructors? #57

Open nickray opened 5 years ago

nickray commented 5 years ago

Somewhat orthogonal to https://github.com/stm32-rs/stm32l4xx-hal/issues/56, there is a fundamental rethink of the HAL API going on in nRF land. Instead of extension traits with associated constrain/split methods, "constructors" (new methods) can be used.

Examples:

This is mostly being driven by @hannobraun. Some obvious advantages:

@MabezDev @mathk @FrozenDroid: Do we want this too? :)

hannobraun commented 5 years ago

I'd like to note that this was only the first step towards a larger refactoring. The end goal is to create a HAL-level Peripherals struct that wraps the PAC-level Peripherals. There are many reasons for this (and a few criticisms :-) ), and I intend to write an article about it that talks about the subject exhaustively.

Since I haven't written that article yet, here's a very short summary of my reasoning:

The criticisms of this approach mainly revolve around two areas:

I'd say all those criticisms are valid, but equally (or more so!) apply to whatever we have today, so my approach doesn't make things worse, at least. I also think some of it can be addressed by thinking hard about the subject for some time, which I've only started to do.

hannobraun commented 5 years ago

But whether you buy into my grand vision or not, I believe that replacing extension traits with plain constructors is worthwhile, for the reasons mentioned.

nickray commented 5 years ago

@hannobraun: Thanks for piping in with background, and looking forward to your article, please do write it! Agree that the interplay between HAL and PAC is not satisfactory yet. Seems hard to get right...

Certainly interesting and worthwhile to think about what can be moved from PAC to HAL level though! I'd really like there to be substantial consistency between HALs for different vendors (instead of, say, STM32 and nRF forking at some point). Like... a better Java haha.

hannobraun commented 5 years ago

@nickray

As an example: This L4 chip series has a lower voltage range mode [...] At least in this case, an "unfreeze" might be able via some tricks to know what is different from reset state, as checking for all assumptions is not a very zero cost approach :)

Wanting to avoid having to check all assumptions is definitely one of the motivations that led me to the Peripherals pattern. In lpc82x-hal, there's the switch matrix, which controls assignment of functions to various pins. Unlike other peripherals, it can't easily (and cheaply) be reset, so preventing the user from messing with the initial state was the only zero-cost way of upholding the static guarantees that I could find.

I hope my approach will hold up in different scenarios, like the one you describe. I think my article (once I get around to writing it) will only be the start of the discussion though.

Another issue [...] is that all these HAL APIs need to be thought out and implemented [...] to avoid most non-trivial use cases from having to do an unsafe direct access to the original PAC anyway.

I think the initial step when starting a new HAL using the Peripherals approach would be to just add the unwrapped PAC-level peripherals to the Peripherals struct, to make them available to the user, then write wrappers over time.

If modifying one peripheral can affect the guarantees of another peripheral's HAL API, add a wrapper that does nothing but provide an unsafe free method that returns the unwrapped peripheral. This gives you a good place to document what could go wrong, and the unsafe will hopefully make the user pause and read the documentation :-)

Depending on how much work is put into the HAL, it might take a long time until non-trivial use cases can be handled without dipping into unwrapped APIs, but I agree with you that it's still better (or at least not worse) than the current situation.

Certainly interesting and worthwhile to think about what can be moved from PAC to HAL level though! I'd really like there to be substantial consistency between HALs for different vendors (instead of, say, STM32 and nRF forking at some point). Like... a better Java haha.

I think consistency has its limits in this space, due to the differences between microcontrollers (at least as long as you want to be zero-cost, or as close as possible). I certainly hope that we can come up with some generally accepted solutions though, that work for a broad range of HALs.

nickray commented 5 years ago

For the record, I will definitely not do this in this HAL, putting all effort in LPC55S6x.