Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/main/drivers/pwm_mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand All @@ -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);
Comment on lines +293 to 296

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Motor outputs undercounted 🐞 Bug ≡ Correctness

Pass 1 now de-duplicates motor-only counting per physical timer, but it only adds 1 +
pwmClaimTimer(changed), so a timer whose channels are already TIM_USE_MOTOR contributes just 1
regardless of how many motor pads it has. This undercount can make pass 2 promote
TIM_USE_OUTPUT_AUTO pads to motors and claim whole timers as motor-only, silently removing
servo-capable outputs.
Agent Prompt
## Issue description
`pwmEnsureEnoughtMotors()` pass 1 now uses `timerCounted[]` to avoid double-counting a physical timer, but it still relies on `motorOnlyOutputs++` plus `pwmClaimTimer()`'s **changed** count to represent the number of motor outputs on that timer. If all channels on a timer are already motor-only, `pwmClaimTimer()` returns 0, so the timer contributes only 1 to `motorOnlyOutputs` even if it has 2–4 motor pads.

This can leave `motorOnlyOutputs < motorCount` and cause pass 2 to promote `TIM_USE_OUTPUT_AUTO` pads to motors unnecessarily; because promotion calls `pwmClaimTimer()`, it can claim an entire unrelated timer as motor-only and those siblings will not be demoted later (they no longer match the pass-2 `!TIM_IS_MOTOR_ONLY(...)` guard).

## Issue Context
Example target with 4 motor pads on a single timer plus AUTO pads:
- `IFLIGHT_BLITZ_F7_AIO` has 4x `TIM_USE_MOTOR` on `TIM3` and additional `TIM_USE_OUTPUT_AUTO` on `TIM1`/`TIM4`, so after this change pass 1 counts the 4 TIM3 motors as **1**, potentially triggering pass-2 promotion of AUTO outputs.

## Fix Focus Areas
- src/main/drivers/pwm_mapping.c[260-317]
- src/main/target/IFLIGHT_BLITZ_F7_AIO/target.c[32-45]

## Suggested fix approach
When encountering the first motor-only pad for a physical timer (i.e., when `timerCounted[timerId]` is false), compute the number of usable pads for that timer and add that count once, instead of adding `1 + pwmClaimTimer(changed)`.

Concretely:
1. Compute `timerId = timer2id(timHw->tim)` once.
2. If motor-only and not yet counted:
   - Count pads that share `timHw->tim` (optionally excluding conflicts via `checkPwmTimerConflicts()` if the intent is “usable motor outputs”).
   - Add that pad-count to `motorOnlyOutputs`.
   - Call `pwmClaimTimer()` to sync flags, but do **not** use its return value for the motor output count.

This preserves de-duplication while keeping the counter accurate for timers where channels were already motor-only.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

}
Expand Down
Loading