PWM peripheral defaults pins to 0 when I want them to invert and default to 1

Hello,

I am using the nrf5340 on some custom hardware, and I am using 3 LEDʻs and running them with the PWM0 peripheral to fade and blink and indicate states for the firmware. The LEDʻs are driven as active-low, and I am using the PWM flag PWM_POLARITY_INVERTED in the device tree to make sure this works.

After initialization, the PWM peripheral works very well, and using the zephyr driver is very easy to use. However, I am finding that before initialization, there is a function called in the pwm_nrfx.c that will reset the LEDʻs pin states to 0. This, of course, turns the LEDʻs on, and I have to set the PWM peripheral to 0% duty cycle when I initialize in my own code in order to make sure they start in the OFF state.

This results in a brief flash of white at the start of the firmware, of which I found no way to control. I am trying to debug and step through to figure out why this is not working but what I am arriving at is the PWM_POLARITY_INVERTED is not actually taken into account when the pins get initialized. Is this correct? Is there a way I can configure this and make sure the pins initialize to digital 1 because they should be ACTIVE_LOW?

Here is my device tree file configuring PWM0:

/ {
    pwmleds {
        compatible = "pwm-leds";
        pwm_led0: pwm_led_0 {
            pwms = <&pwm0 0 PWM_MSEC(10) PWM_POLARITY_INVERTED>;
        };
        pwm_led1: pwm_led_1 {
			pwms = <&pwm0 1 PWM_MSEC(10) PWM_POLARITY_INVERTED>;
		};
        pwm_led2: pwm_led_2 {
			pwms = <&pwm0 2 PWM_MSEC(10) PWM_POLARITY_INVERTED>;
		};
	};
};

&pwm0 {
	status = "okay";
	pinctrl-0 = <&pwm0_default>;
	pinctrl-1 = <&pwm0_sleep>;
	pinctrl-names = "default", "sleep";
};

pwm0_default: pwm0_default {
	group1 {
		psels = <NRF_PSEL(PWM_OUT0, 0, 28)>,
		        <NRF_PSEL(PWM_OUT1, 0, 29)>,
		        <NRF_PSEL(PWM_OUT2, 0, 30)>;
        };
};

Here is my code that initializes the PWM LEDs:

static const struct pwm_dt_spec _ledr       = PWM_DT_SPEC_GET(DT_ALIAS(pwm_ledr));
static const struct pwm_dt_spec _ledg       = PWM_DT_SPEC_GET(DT_ALIAS(pwm_ledg));
static const struct pwm_dt_spec _ledb       = PWM_DT_SPEC_GET(DT_ALIAS(pwm_ledb));

// These identifiers match up to the DT node identifiers
static const struct pwm_dt_spec *_leds[3] = {
    &_ledr,
    &_ledg,
    &_ledb,
};

if (!device_is_ready(_ledr.dev)) {
	LOG_ERR("Error: PWM device %s is not ready", _ledr.dev->name);
	return -ENODEV;
} else if (!device_is_ready(_ledg.dev)) {
	LOG_ERR("Error: PWM device %s is not ready", _ledg.dev->name);
	return -ENODEV;
} else if (!device_is_ready(_ledb.dev)) {
	LOG_ERR("Error: PWM device %s is not ready", _ledb.dev->name);
	return -ENODEV;
}

int err = pwm_leds_off(LED_ALL);
LOG_ERR_AND_RETURN(err, "pwm_leds_off");

and here is the line of code (line 239 in pwm_nrfx.c) that I am referring to that results in all LEDʻs (despite the PWM_POLARITY_INVERTED)  setting to 0 and therefore turning on:

int ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);

Related