-
Notifications
You must be signed in to change notification settings - Fork 150
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
return raw value from write/modify #873
base: master
Are you sure you want to change the base?
Conversation
This is certainly similar to my idea but not quite the same. This does not permit arbitrary return types. I have been using the ability to return arbitrary return types to enforce type-state validity for HALs like so: let state = reg.modify(|_, w| {
State::set(w.some_field())
}); |
Ok. After you've wrote I understand even less. I cannot to chain field more? |
Yes, a type-state corresponds to the value of a bitfield.
Imagine a hypothetical peripheral which can only be enabled or disabled: struct ImaginaryPeripheral<State: PowerState> {
rb: IMGPERIPH,
state: State,
} If I wanted a So I could write a function for conversion: impl<State: PowerState> ImaginaryPeripheral<State> {
fn freeze<NewState: PowerState>(self) -> ImaginaryPeripheral<NewState> {
let new_state = self.rb.reg().modify(|_, w| { // peripheral has a single register called "reg"
NewState::set(w.power()) // power type-state only needs the power bitfield of this register
});
ImaginaryPeripheral {
rb: self.rb,
state: new_state,
}
}
} The peripheral type holds instances of type-states to prove that the type-state was in fact The definition of All of this is just an example of my reason for wanting to return arbitrary values from the register write/modify closure. It is conceivable other use-cases exist, but this is mine. |
Looking at your example, I think I see what you're going for, and that's definitely a different problem than the one I am trying to solve. |
Traditional solution for your example. Stable Rust: struct ImaginaryPeripheral<State: PowerState> {
rb: IMGPERIPH,
state: State, // or even PhantomData<State>
}
trait PowerState {
const STATE: StateEnum; // generated by svd2rust
}
struct Enabled;
impl PowerState for Enabled {
const STATE: StateEnum = StateEnum::Enabled;
}
self.rb.reg().modify(|_, w| w.power().variant(NewState::STATE));
ImaginaryPeripheral {
rb: self.rb,
state: NewState,
} Nightly Rust: #![feature(adt_const_params)]
struct ImaginaryPeripheral<const State: StateEnum> {
rb: IMGPERIPH,
}
self.rb.reg().modify(|_, w| w.power().variant(State));
ImaginaryPeripheral::<NewState> {
rb: self.rb,
} |
Anyway I suggest you to discuss this in Tuesday meeting. |
Yeah that is how HALs primarily look right now, and in fact the version of the example I linked earlier that made it into stm32g4xx-hal looks like this. The problem I have with it is that the line: self.rb.reg().modify(|_, w| w.power().variant(NewState::STATE)); could be commented out and the program would still compile no problem. More complex peripherals have unintuitive type-state relations where errors can slip through easily. I'm trying to eliminate these kinds of errors. I like knowing that any and all undesired behavior is limited to |
Ok I still don't know what the procedure is for this but I will try. Thanks! |
Ok. It's clearer now. |
The idea from @AdinAck . See #859
This looks not so beautiful like #738, but almost not breaking and allows to transfer data between writes with unsafe.