Skip to content

Conversation

@functionpointer
Copy link
Contributor

@functionpointer functionpointer commented Nov 23, 2025

User description

Activate USE_DSHOT_DMAR for target NEXUSX.

Also move pins labelled "RPM" and "TLM" (PA2 and PA3) to timer2 instead of timer5.
This lifts the previous limitation of 7 motor outputs. Apparently, DSHOT_DMAR can only handle 4 timers for motors.

The move causes the pin labelled "TAIL" to be on the same timer as "RPM" and "TLM", removing a small amount of flexibility.
However, it is still possible to have 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9 motors without wasting a pin to timer limitations if the user selects clever timer assignments in the mixer tab.

Furthermore, this PR sets TIM1 as MOTOR by default, which is mapped to the "ESC" pin.
This creates sane defaults for platforms with 1 and 4 motors without user intervention.

This PR is the result of investigation of changes proposed in #11120

I have tested:

  • MULTISHOT with 7, 8 and 9 motor outputs using oscilloscope
  • DSHOT600 with 7, 8 and 9 motor outputs using oscilloscope
  • Servo outputs on remaining pins
  • Default mixer assignments for quadcopter and plane with tail

PR Type

Enhancement


Description

  • Enable DSHOT_DMAR support for NEXUSX target

  • Reassign RPM and TLM pins from TIM5 to TIM2

  • Increases motor output limit from 7 to 9

  • Set TIM1 as default motor output for sane defaults


Diagram Walkthrough

flowchart LR
  A["DSHOT_DMAR enabled"] --> B["Max 4 timers supported"]
  B --> C["Reassign TIM5 to TIM2"]
  C --> D["Motor limit: 7 → 9"]
  E["TIM1 default motor"] --> F["Sane defaults for 1/4 motors"]
Loading

File Walkthrough

Relevant files
Enhancement
target.h
Enable DSHOT_DMAR feature flag                                                     

src/main/target/NEXUSX/target.h

  • Added USE_DSHOT_DMAR define to enable DSHOT DMA support
  • Activates hardware DMA capability for improved DSHOT performance
+2/-0     
Configuration changes
target.c
Reassign RPM and TLM pins to TIM2                                               

src/main/target/NEXUSX/target.c

  • Migrated RPM pin (PA2) from TIM5 CH3 to TIM2 CH3
  • Migrated TLM pin (PA3) from TIM5 CH4 to TIM2 CH4
  • Consolidates timer usage to support DSHOT_DMAR limitation of 4 timers
    max
+2/-2     
config.c
Configure TIM1 as default motor output                                     

src/main/target/NEXUSX/config.c

  • Set TIM1 (ESC pin) as default motor output mode
  • Provides sensible defaults for single and quadcopter configurations
  • Eliminates need for manual timer assignment in common use cases
+3/-0     

Apparently DSHOT_DMAR can only work with max 4 timers.
With the previous timer setup this caused a limit of 7 motors.
The new setup increases it 9.

However, it costs some flexibility.
The new default config sets up TIM1 as MOTOR by default,
creating sane defaults for platforms with 1 or 4 motors.
@qodo-merge-pro
Copy link
Contributor

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
No auditing: The new configuration that sets a default motor output adds no logging or audit trail for
this critical configuration change, but target config files may not handle runtime
auditing.

Referred Code
  // default "ESC" pin to be a motor
  timerOverridesMutable(timer2id(TIM1))->outputMode = OUTPUT_MODE_MOTORS;
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
No null checks: Calls to configuration mutators (e.g., timerOverridesMutable(timer2id(TIM1))) add no error
handling or validation, but these APIs may be guaranteed non-null in this environment.

Referred Code
  timerOverridesMutable(timer2id(TIM1))->outputMode = OUTPUT_MODE_MOTORS;
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Hardware conflicts: New timer assignments (TIM2 CH3/CH4 on PA2/PA3) note UART2 conflicts without validating or
enforcing safe configuration at runtime.

Referred Code
DEF_TIM(TIM2, CH3, PA2,   TIM_USE_OUTPUT_AUTO, 0, 0),   // labelled "RPM", clashes with UART2 TX
DEF_TIM(TIM2, CH4, PA3,   TIM_USE_OUTPUT_AUTO, 0, 0),   // labelled "TLM", clashes with UART2 RX

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-merge-pro
Copy link
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix timer resource conflict

Move the RPM and TLM pin definitions from TIM2 to TIM1 to resolve a timer
resource conflict, as a single timer cannot be used for both motor output and
sensor input simultaneously.

src/main/target/NEXUSX/target.c [32-37]

 DEF_TIM(TIM2, CH1, PA15,  TIM_USE_OUTPUT_AUTO, 0, 0),   // labelled "TAIL"
 
 DEF_TIM(TIM1, CH2, PA9,   TIM_USE_OUTPUT_AUTO, 0, 0),   // labelled "ESC"
+DEF_TIM(TIM1, CH3, PA2,   TIM_USE_OUTPUT_AUTO, 0, 0),   // labelled "RPM", clashes with UART2 TX
+DEF_TIM(TIM1, CH4, PA3,   TIM_USE_OUTPUT_AUTO, 0, 0),   // labelled "TLM", clashes with UART2 RX
 
-DEF_TIM(TIM2, CH3, PA2,   TIM_USE_OUTPUT_AUTO, 0, 0),   // labelled "RPM", clashes with UART2 TX
-DEF_TIM(TIM2, CH4, PA3,   TIM_USE_OUTPUT_AUTO, 0, 0),   // labelled "TLM", clashes with UART2 RX
-

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical hardware resource conflict where TIM2 is used for both motor output and timer inputs, which would cause either motors or sensors to fail.

High
Learned
best practice
Validate timer override existence

Check that the timer override entry exists before writing to it to avoid null or
invalid access when TIM1 isn't mapped.

src/main/target/NEXUSX/config.c [40-41]

 // default "ESC" pin to be a motor
-timerOverridesMutable(timer2id(TIM1))->outputMode = OUTPUT_MODE_MOTORS;
+timerOverride_t *ovr = timerOverridesMutable(timer2id(TIM1));
+if (ovr) {
+    ovr->outputMode = OUTPUT_MODE_MOTORS;
+}
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why:
Relevant best practice - Guard against invalid states by validating timer availability before overriding configuration.

Low
  • More

@sensei-hacker
Copy link
Member

Before I merge this, can you please comment just very briefly on whether you think the suggestions from the bot are useful?
The bot is very often wrong, but sometimes it has good suggestions.

@functionpointer
Copy link
Contributor Author

Suggestion 1 is physically impossible, TIM1 cannot be used on the RPM and TLM pins. See the second table in the readme https://github.com/iNavFlight/inav/blob/master/src/main/target/NEXUSX/README.md

Suggestion 2 makes no sense as TIM1 will always be mapped. It is defined that way in target.c. Furthermore, this exact way of predefined timer assignments is used by plenty of other targets already.

@sensei-hacker
Copy link
Member

Suggestion 1 is physically impossible

Sometimes the bot reminds me of my boss. 😁

@sensei-hacker sensei-hacker merged commit 579daf1 into iNavFlight:master Nov 25, 2025
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants