From 2e6b813225450828ebeb9908048675db0e843330 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 2 Jul 2023 09:17:12 -0500 Subject: [PATCH] hrtim: add guardrails on bridge sec. duty --- embassy-stm32/src/pwm/advanced_pwm.rs | 21 ++++++++++++++++++--- 1 file 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 BurstController { /// Represents a fixed-frequency bridge converter /// -/// Our implementation of the bridge converter uses a single channel and two compare registers, +/// Our implementation of the bridge converter uses a single channel and three compare registers, /// allowing implementation of a synchronous buck or boost converter in continuous or discontinuous /// conduction mode. /// @@ -189,6 +189,8 @@ pub struct BridgeConverter, dead_time: u16, primary_duty: u16, + min_secondary_duty: u16, + max_secondary_duty: u16, } impl> BridgeConverter { @@ -244,6 +246,8 @@ impl> Bridge channel: PhantomData, dead_time: 0, primary_duty: 0, + min_secondary_duty: 0, + max_secondary_duty: 0, } } @@ -280,16 +284,19 @@ impl> Bridge } fn update_primary_duty_or_dead_time(&mut self) { + self.min_secondary_duty = self.primary_duty + self.dead_time; + T::regs().tim(C::raw()).cmp(0).modify(|w| w.set_cmp(self.primary_duty)); T::regs() .tim(C::raw()) .cmp(1) - .modify(|w| w.set_cmp(self.primary_duty + self.dead_time)); + .modify(|w| w.set_cmp(self.min_secondary_duty)); } /// Set the dead time as a proportion of the maximum compare value pub fn set_dead_time(&mut self, dead_time: u16) { self.dead_time = dead_time; + self.max_secondary_duty = self.get_max_compare_value() - dead_time; self.update_primary_duty_or_dead_time(); } @@ -309,9 +316,17 @@ impl> Bridge /// The secondary duty is the period in any switch is active /// - /// If less than or equal to the primary duty, the secondary switch will never be active + /// If less than or equal to the primary duty, the secondary switch will be active for one tick /// If a fully complementary output is desired, the secondary duty can be set to the max compare pub fn set_secondary_duty(&mut self, secondary_duty: u16) { + let secondary_duty = if secondary_duty > self.max_secondary_duty { + self.max_secondary_duty + } else if secondary_duty <= self.min_secondary_duty { + self.min_secondary_duty + 1 + } else { + secondary_duty + }; + T::regs().tim(C::raw()).cmp(2).modify(|w| w.set_cmp(secondary_duty)); } }