-
- Downloads
Auto merge of #69 - japaric:revise-api, r=japaric
revise peripheral API This PR changes the signature of many of the high level methods available on peripherals like `NVIC::get_priority`. Additionally some instance methods have been turned into static methods. The following guidelines have been used to apply the changes: - If the method body contains a single, atomic read operation with *no* side effects (e.g. the read operation clears one of the bits of the register): the signature changed to make the method static, i.e. `&self` was removed from the signature. - If the method involves writing to or a RMW operation on a register: the signature changed to take the singleton by `&mut self` reference. - If the method involves only read operations where at least one of them modifies the value of a register: the signature changed to take the singleton by `&mut self` reference. The rationale for this last guideline is that using `&self`, instead of `&mut self`, lets the user (unintentionally) break abstractions in the presence of generators. Example below: ``` rust let peripherals = Peripherals::take().unwrap(); let syst = &peripherals.SYST; // tasks let mut a = || { loop { // yielding "busy wait" while !a.has_wrapped() { yield; } // do stuff } }; let mut b = || { // .. // *NOTE* the problem is in the line below: this `is_counter_enabled` method reads the CSR // register and that read operation clears the COUNTFLAG bit of the register (if set), which is // the bit the `has_wrapped` method checks for. if syst.is_counter_enabled() { // .. } // .. }; ``` One more guideline was considered but the required conditions didn't apply to any of the existing methods: - If the method involves only non side effectful, non necessarily atomic read operations: the signature of the method should remain as `&self`. The rationale for this guideline is that a static method (no `self` argument) wouldn't be appropriate because that can result in a torn read if the read operation can be preempted by some context that modifies the register. In any case, this last guideline doesn't seem to apply well to the peripherals structs exposed by this crate because they *deref* to a `RegisterBlock` that allows mutation through a `&self` reference. When these two properties (the guideline and `Deref<Target=RegisterBlock>`) are mixed the user can potentially break abstractions using generators (as shown in the `syst` example). cc @hannobraun closes #67
No related branches found
No related tags found
Showing
- src/exception.rs 1 addition, 2 deletionssrc/exception.rs
- src/peripheral/cbp.rs 13 additions, 11 deletionssrc/peripheral/cbp.rs
- src/peripheral/cpuid.rs 6 additions, 3 deletionssrc/peripheral/cpuid.rs
- src/peripheral/dwt.rs 15 additions, 7 deletionssrc/peripheral/dwt.rs
- src/peripheral/mod.rs 68 additions, 1 deletionsrc/peripheral/mod.rs
- src/peripheral/nvic.rs 38 additions, 29 deletionssrc/peripheral/nvic.rs
- src/peripheral/scb.rs 62 additions, 54 deletionssrc/peripheral/scb.rs
- src/peripheral/syst.rs 79 additions, 56 deletionssrc/peripheral/syst.rs
- src/peripheral/test.rs 0 additions, 2 deletionssrc/peripheral/test.rs
Loading
Please register or sign in to comment