Zephyr PWM: pwm_nrfx.c - Limitation with NCS driver? "Incompatible period."

I am working with the nRF54L15 to create a driver for a peripheral which is controlled by two PWM signals.

My driver relies on the Zephyr PWM driver which goes back to your implementation of it in pwm_nrfx.c. Everything works fine except one case, and I don't understand this limitation.

If I command one of the signals to pulse at 100% duty cycle and I leave the other one off, if I then try to set the off PWM signal to a non-static setting (1-99% duty cycle) then it results in the "Incompatible period." error.  [SDK\zephyr\drivers\pwm\pwm_nrfx.c, function  pwm_period_check_and_set()]

Both of my PWM channels are set to the same frequency (PWM_USEC(100)) so I don't understand what the problem is here.  Is the driver optimizing the PWM period to something other than my setting when I command the one signal to 100% duty cycle? And so when I set the other signal, the PWM driver is actually running a different period than my setting? I could understand this for power savings, but I need to somehow deal with this limitation.

Relevant code:

struct tps923653_config
{
    const struct pwm_dt_spec en_pwm;  // EN/PWM pin  (High=Always On, Low=Device Disabled, PWM=PWM Dimming)
    const struct pwm_dt_spec adim_hd; // ADIM/HD pin (High=PWM Dimming, Low=Hybrid Dimming, PWM=Analog Dimming)
};

/* Startup state: */
(void)pwm_set_pulse_dt(&config->en_pwm, 0); // Set low
(void)pwm_set_pulse_dt(&config->adim_hd, config->adim_hd.period); // Set high (100% duty cycle)

/* Produces the error: */
err = pwm_set_pulse_dt(&config->en_pwm, config->en_pwm.period/2);
if (err)
{
    LOG_ERR("Failed to set EN/PWM: %d", err);
    return err;
}

Relevant devicetree overlay:

&pinctrl {
	pwm21_default: pwm21_default {
		group1 {
			psels = <NRF_PSEL(PWM_OUT0, 1, 11)>,
			        <NRF_PSEL(PWM_OUT1, 1, 12)>;
		};
	};
};

&pwm21 {
	status = "okay";
	pinctrl-0 = <&pwm21_default>; /* Only default, no low power config */
	pinctrl-names = "default";
};

/ {
	ir_driver: tps923653 {
		compatible = "indesign,tps923653";
		status = "okay";
		
		/* EN/PWM and ADIM/HD pwm configuration */
		pwms = <&pwm21 0 PWM_USEC(100) PWM_POLARITY_NORMAL>,
			   <&pwm21 1 PWM_USEC(100) PWM_POLARITY_NORMAL>;
		// pwm-names = "en-pwm", "adim-hd";
	};
};

Let me know if I am just outside of the scope of expected use of the pwm_nrfx.c driver and need to make something custom for my application, but I feel like this is may be a bug.

  • For those who are still waiting on some movement from Nordic on this thread, one way to work around this is to just put your PWM signals on separate PWM peripherals.

    I thankfully have a spare PWM peripheral to be able to do this, but it is obviously very wasteful.

       Is there any movement within Nordic on improving the PWM driver to better support multiple PWM signals with the same period (prescaler and countertop)?

Related