aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-07-02 09:17:12 -0500
committerxoviat <[email protected]>2023-07-02 09:17:12 -0500
commit2e6b813225450828ebeb9908048675db0e843330 (patch)
tree81e2b94bb1b3a52881cfe94dbaf3d9053e1342f9
parentaceba1c03fc45179d4e910fad254a31191cf0c44 (diff)
hrtim: add guardrails on bridge sec. duty
-rw-r--r--embassy-stm32/src/pwm/advanced_pwm.rs21
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
194impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> BridgeConverter<T, C> { 196impl<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}