Zephyr PWM Channels on One nrfx Instance: A Second Period Can Fail While the First Output Is Active
Two PWM outputs can work separately yet fail when enabled together because their channel numbers do not identify independent period generators. In Zephyr v4.4.0, the nrfx PWM driver refuses a different period when another channel on the same instance still requires PWM generation.
This is a specific runtime check in the tagged nrfx driver, not a universal Zephyr PWM rule. The example below uses two valid, routed channels in edge-aligned mode, with nonconstant duties and representable cycle counts. It is a source-derived branch analysis; no PWM call or waveform capture was executed.
Resolve both consumers to a controller instance
A pwm_dt_spec contains a device pointer, channel, period and flags. Two consumer nodes can therefore identify different channels of the same device. Separate application objects do not create separate hardware timing resources.
Compare the resolved dev values as well as the channel numbers. For this problem, channels zero and one belong to the same nrfx instance. If they actually belong to different instances, the sibling-mask check described here does not cross that boundary, although each instance still has its own configuration and board constraints.
Also record the units at the call boundary. pwm_set() converts nanoseconds to cycles before dispatching to pwm_set_cycles(). The driver compares cycle values, after its center-aligned adjustment where applicable. Keeping this example edge-aligned avoids attributing an alignment-rounding issue to the sharing check.
Trace the period check before changing the request
pwm_period_check_and_set() first accepts a request whose period matches data->period_cycles. Otherwise it checks whether any channel other than the requested channel appears in data->pwm_needed:
other active generators = pwm_needed & ~BIT(requested_channel)
A different period is refused when that mask is nonzero.
If no sibling needs generation, the helper attempts to select a prescaler and counter limit for the new period. For an ordinary nonconstant output, pwm_nrfx_set_cycles() converts a failed period check into -EINVAL before updating that channel’s sequence value.
Consider channel zero already generating a 4,000-cycle period with a 1,000-cycle pulse. Its generation bit is set. Channel one then requests an 8,000-cycle period and a 2,000-cycle pulse. Both requests describe a 25-percent duty, but the periods differ. The existing channel-zero bit causes the second request to fail at the sibling check.

A channel-one request using the same 4,000-cycle period passes this particular check. Conversely, if channel zero is the only channel needing generation, its own period change is not vetoed by its own bit. The expression deliberately excludes the requested channel. Neither statement promises that every other validation or physical transition succeeds.
Interpret the error with its branch context
-EINVAL alone cannot identify a shared-period conflict. The public wrapper rejects pulse > period. The driver rejects invalid channel numbers, and its period helper can fail because no permitted prescaler represents the request. Log the device, channel, requested period and pulse, plus the other consumers’ accepted states.
A second output that works alone is useful evidence for investigating sharing, but it is not proof of the cause. Confirm the actual branch in the deployed version and configuration. Do not keep changing duty ratios when the conflicting quantity is the shared period.
The driver selects one prescaler and counter limit for the instance. A different application label, pin or sequence entry cannot assign an independent period to a sibling that uses that same timing engine.
Distinguish constant output from continued generation
For zero pulse width, this implementation uses its constant-inactive path and clears the channel’s pwm_needed bit. Logical inactive level still depends on polarity and the board’s downstream circuit. It is not a universal statement that the pin is low or that stopping a connected load is harmless.
Full duty needs a more careful reading. The driver can keep hardware generation required when both NRF_PWM_HAS_IDLEOUT and CONFIG_PWM_NRFX_NO_GLITCH_DUTY_100 are enabled. Do not assume every 100-percent request releases that channel’s claim on the running peripheral.
When no channel needs generation, the driver requests a stop. A later playback waits for that stop to finish. These operations are separate from accepting a shared period; clearing a bookkeeping bit does not establish an instantaneous, edge-perfect transition at the output.
Choose a feasible period plan before coordinating updates
If both consumers can meet their requirements at a common period, express that common choice explicitly. If they require genuinely different periods, investigate separately routed controller instances supported by the board. A coordinated retiming policy is appropriate only if the application permits all affected outputs to pass through its qualified intermediate states.
Sequential calls are not an atomic multichannel update, and the API warns that glitch-free updates depend on hardware. A later isolated logic-level fixture should inspect both outputs and every return value for matching periods, conflicting periods, a released sibling and invalid-input controls. The immediate result is a precise diagnosis: an active sibling can veto an otherwise legal period request before the new waveform is generated.