diff options
| author | xoviat <[email protected]> | 2023-07-02 09:17:12 -0500 |
|---|---|---|
| committer | xoviat <[email protected]> | 2023-07-02 09:17:12 -0500 |
| commit | 2e6b813225450828ebeb9908048675db0e843330 (patch) | |
| tree | 81e2b94bb1b3a52881cfe94dbaf3d9053e1342f9 | |
| parent | aceba1c03fc45179d4e910fad254a31191cf0c44 (diff) | |
hrtim: add guardrails on bridge sec. duty
| -rw-r--r-- | embassy-stm32/src/pwm/advanced_pwm.rs | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/embassy-stm32/src/pwm/advanced_pwm.rs b/embassy-stm32/src/pwm/advanced_pwm.rs index fa34b2e18..07d8708dc 100644 --- a/embassy-stm32/src/pwm/advanced_pwm.rs +++ b/embassy-stm32/src/pwm/advanced_pwm.rs | |||
| @@ -177,7 +177,7 @@ impl<T: HighResolutionCaptureCompare16bitInstance> BurstController<T> { | |||
| 177 | 177 | ||
| 178 | /// Represents a fixed-frequency bridge converter | 178 | /// Represents a fixed-frequency bridge converter |
| 179 | /// | 179 | /// |
| 180 | /// Our implementation of the bridge converter uses a single channel and two compare registers, | 180 | /// Our implementation of the bridge converter uses a single channel and three compare registers, |
| 181 | /// allowing implementation of a synchronous buck or boost converter in continuous or discontinuous | 181 | /// allowing implementation of a synchronous buck or boost converter in continuous or discontinuous |
| 182 | /// conduction mode. | 182 | /// conduction mode. |
| 183 | /// | 183 | /// |
| @@ -189,6 +189,8 @@ pub struct BridgeConverter<T: HighResolutionCaptureCompare16bitInstance, C: Adva | |||
| 189 | channel: PhantomData<C>, | 189 | channel: PhantomData<C>, |
| 190 | dead_time: u16, | 190 | dead_time: u16, |
| 191 | primary_duty: u16, | 191 | primary_duty: u16, |
| 192 | min_secondary_duty: u16, | ||
| 193 | max_secondary_duty: u16, | ||
| 192 | } | 194 | } |
| 193 | 195 | ||
| 194 | impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> BridgeConverter<T, C> { | 196 | impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> BridgeConverter<T, C> { |
| @@ -244,6 +246,8 @@ impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> Bridge | |||
| 244 | channel: PhantomData, | 246 | channel: PhantomData, |
| 245 | dead_time: 0, | 247 | dead_time: 0, |
| 246 | primary_duty: 0, | 248 | primary_duty: 0, |
| 249 | min_secondary_duty: 0, | ||
| 250 | max_secondary_duty: 0, | ||
| 247 | } | 251 | } |
| 248 | } | 252 | } |
| 249 | 253 | ||
| @@ -280,16 +284,19 @@ impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> Bridge | |||
| 280 | } | 284 | } |
| 281 | 285 | ||
| 282 | fn update_primary_duty_or_dead_time(&mut self) { | 286 | fn update_primary_duty_or_dead_time(&mut self) { |
| 287 | self.min_secondary_duty = self.primary_duty + self.dead_time; | ||
| 288 | |||
| 283 | T::regs().tim(C::raw()).cmp(0).modify(|w| w.set_cmp(self.primary_duty)); | 289 | T::regs().tim(C::raw()).cmp(0).modify(|w| w.set_cmp(self.primary_duty)); |
| 284 | T::regs() | 290 | T::regs() |
| 285 | .tim(C::raw()) | 291 | .tim(C::raw()) |
| 286 | .cmp(1) | 292 | .cmp(1) |
| 287 | .modify(|w| w.set_cmp(self.primary_duty + self.dead_time)); | 293 | .modify(|w| w.set_cmp(self.min_secondary_duty)); |
| 288 | } | 294 | } |
| 289 | 295 | ||
| 290 | /// Set the dead time as a proportion of the maximum compare value | 296 | /// Set the dead time as a proportion of the maximum compare value |
| 291 | pub fn set_dead_time(&mut self, dead_time: u16) { | 297 | pub fn set_dead_time(&mut self, dead_time: u16) { |
| 292 | self.dead_time = dead_time; | 298 | self.dead_time = dead_time; |
| 299 | self.max_secondary_duty = self.get_max_compare_value() - dead_time; | ||
| 293 | self.update_primary_duty_or_dead_time(); | 300 | self.update_primary_duty_or_dead_time(); |
| 294 | } | 301 | } |
| 295 | 302 | ||
| @@ -309,9 +316,17 @@ impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> Bridge | |||
| 309 | 316 | ||
| 310 | /// The secondary duty is the period in any switch is active | 317 | /// The secondary duty is the period in any switch is active |
| 311 | /// | 318 | /// |
| 312 | /// If less than or equal to the primary duty, the secondary switch will never be active | 319 | /// If less than or equal to the primary duty, the secondary switch will be active for one tick |
| 313 | /// If a fully complementary output is desired, the secondary duty can be set to the max compare | 320 | /// If a fully complementary output is desired, the secondary duty can be set to the max compare |
| 314 | pub fn set_secondary_duty(&mut self, secondary_duty: u16) { | 321 | pub fn set_secondary_duty(&mut self, secondary_duty: u16) { |
| 322 | let secondary_duty = if secondary_duty > self.max_secondary_duty { | ||
| 323 | self.max_secondary_duty | ||
| 324 | } else if secondary_duty <= self.min_secondary_duty { | ||
| 325 | self.min_secondary_duty + 1 | ||
| 326 | } else { | ||
| 327 | secondary_duty | ||
| 328 | }; | ||
| 329 | |||
| 315 | T::regs().tim(C::raw()).cmp(2).modify(|w| w.set_cmp(secondary_duty)); | 330 | T::regs().tim(C::raw()).cmp(2).modify(|w| w.set_cmp(secondary_duty)); |
| 316 | } | 331 | } |
| 317 | } | 332 | } |
