From 024d92e3e73dc7afd0a9733860a1088958e05c4d Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 17 Aug 2026 10:01:49 -0500 Subject: [PATCH 1/2] Fix PWM motor-role double-counting in pwmEnsureEnoughtMotors() Pass 1 counted a shared-timer motor-only group of n outputs as 2n-1 instead of n: pwmClaimTimer() force-syncs every sibling on the same physical timer as soon as the first one is visited, and the loop had no guard against re-counting a sibling that was already promoted by that broadcast when it reached its own turn later in the same pass. The inflated count made pass 2 more conservative than it should be, silently demoting a later AUTO output from motor to servo with no warning. Triggerable both by target.c declaring 2+ TIM_USE_MOTOR channels on one timer (unconditional at boot) and by the ordinary runtime timer_output_mode MOTORS override exposed in Configurator's Mixer tab. Adds a per-physical-timer dedup guard, matching the de-duplication pass 2 already has via its !TIM_IS_MOTOR_ONLY(...) check. --- src/main/drivers/pwm_mapping.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/drivers/pwm_mapping.c b/src/main/drivers/pwm_mapping.c index 2d01127a504..16df84343c2 100644 --- a/src/main/drivers/pwm_mapping.c +++ b/src/main/drivers/pwm_mapping.c @@ -274,6 +274,13 @@ void pwmEnsureEnoughtMotors(uint8_t motorCount) { uint8_t motorOnlyOutputs = 0; + // pwmClaimTimer() syncs every sibling pad sharing a physical timer as soon + // as the first motor-only pad in a group is processed, so later siblings + // already satisfy TIM_IS_MOTOR_ONLY on their own turn below. Without this + // guard each of them would be counted again, inflating motorOnlyOutputs + // for an n-pad shared-timer group to 2n-1 instead of n. + bool timerCounted[HARDWARE_TIMER_DEFINITION_COUNT] = { false }; + for (int idx = 0; idx < timerHardwareCount; idx++) { timerHardware_t *timHw = &timerHardware[idx]; @@ -283,7 +290,8 @@ void pwmEnsureEnoughtMotors(uint8_t motorCount) continue; } - if (TIM_IS_MOTOR_ONLY(timHw->usageFlags)) { + if (TIM_IS_MOTOR_ONLY(timHw->usageFlags) && !timerCounted[timer2id(timHw->tim)]) { + timerCounted[timer2id(timHw->tim)] = true; motorOnlyOutputs++; motorOnlyOutputs += pwmClaimTimer(timHw->tim, timHw->usageFlags); } From e96746c17d8527b1a30e48cd9d140e404d9e8b8d Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 17 Aug 2026 11:16:57 -0500 Subject: [PATCH 2/2] Retrigger CI: transient upload-artifacts infra failure (429/503 downloading actions/download-artifact)