I've got to admit, as a maintainer of the crate I'm not even 100% sure. I would say in general, that constrain
takes a set of registers, and wraps them behind some abstraction to make them safe.
split
takes a chunk of registers and divides them into smaller parts. The prime example is the gpio
split function which takes gpiox
and splits it into structs representing each individual pin.
As far as I know, take
is only present on the pac
and gives a unique owned object containing all the registers. If take
is called multiple times, an error is thrown, since the whole abstraction relies on there only being one copy of each register around.
Yes, the docs are pretty lacking in a lot of places. I'm aware of some, and not others. I would really apreciate a heads up whenever the docs are lacking. For example, in this issue: Doc improvements · Issue #158 · stm32-rs/stm32f1xx-hal · GitHub (which I just realised has 0 out of 10 items completed
)
When I search rcc
in the docs I get this . Based on the blog post, I think I understand that there would be two layers here one to represent the svd2rust
generated stuff, and another to represent the higher level embedded-hal
stuff. However, I see at least four stm32f1xx::rcc
, ::device::rcc
, ::pack::rcc
, ::stm32::rcc
. How do I know which is which and when and how to use each? The docs seem almost identical for each one.
Oh yea, that's annoying. Ideally, the stm32f1xx_hal::rcc::RCC
is the one that should be shown. The 4 others are from various names of the pac
crate. These are caused by this issue Exporting the sdv2rust crate as device · Issue #16 · stm32-rs/stm32f1xx-hal · GitHub in which we decided that rather than deciding on one of pac
stm32
and device
, we'd export it as all three. I can see this causing confusion and I think we should deprecate stm32
and device
.
However, I can also think back to several instances I have certainly required more flexibility than just a straight forward static initialization at startup. For instance, having different peripherals connected to the same pins, or changing pin modes at different points in the application's life cycle or disabling peripherals for reduced current consumption, or putting out the system clock through the hardware support for this in RCC
.
This is indeed a limitation. I guess we have to sacrifice some generality to get the safety that rust achieves, but rust can also be pretty good at giving you both safety and other things. Turning peripherals off can certainly be achieved, the ADC for example has a power_down
function (or at least I thought it did, maybe that was in my fork and has never been upstreamed).
As for GPIO, it's a known issue see for example the most angry issue I've ever received. A partial solution is in the works [WIP/RFC] Improve GPIO API by TheZoq2 · Pull Request #211 · stm32-rs/stm32f1xx-hal · GitHub
I agree, there is probably a way to write a function in the hal to modify MCO
without breaking the frozen clock contract, which would expose the MCO
hardware functionality in a safe way while still allowing the clocks to be locked. It's not that I'm not willing to do that, but I'm pretty sure I'm not the right one to do it just yet... Maybe in a few months I'll be able to put a PR together for something like that
.
I don't recall what the MCO
hardware does, but the guarantee given by freeze
is just that the clocks won't change. I assume mco
does not assume that, so it should probably be exposed. If you would like to implement that, I'll gladly give you some pointers for where to start 
Hope that lengthy message answers some of your questions 