Zephyr PWM: pwm_nrfx err -> Invalid channel

Hoping to get pointed in the right direction to resolve an error using Zephyr and PWM on an nRF52833DK (SDK 2.2).

The error is: <err> pwm_nrfx: Invalid channel: #.

The specific pins I'm using are P0.28 and P0.29, but this seems to be pin agnostic outside of the pre-defined LED pins on the DK.

My prj.conf file contains:

CONFIG_PWM=y

CONFIG_PINCTRL=y

Devicetree Overlay (relevant sections):

/ {

    pwm_mtr {
		compatible = "pwm-leds";
		in1: in_1 {
			pwms = < &pwm0 28 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
			label = "MTR IN 1";
		};

		in2: in_2 {
			pwms = < &pwm0 29 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
			label = "MTR IN 2";
		};
    };
};

&pinctrl {
    pwm0_default: pwm0_default {
            group1 {
                    psels = <NRF_PSEL(PWM_OUT0, 0, 28)>,
                            <NRF_PSEL(PWM_OUT0, 0, 29)>;
                    nordic,invert;
            };

    };

    pwm0_sleep: pwm0_sleep {
            group1 {
                    psels = <NRF_PSEL(PWM_OUT0, 0, 28)>,
                            <NRF_PSEL(PWM_OUT0, 0, 29)>;
                    low-power-enable;
            };

    };
};
&pwm0 {
    compatible = "nordic,nrf-pwm";
    reg = <0x4001c000 0x1000>;
    interrupts = <28 NRF_DEFAULT_IRQ_PRIORITY>;
    status = "okay";
    #pwm-cells = <3>;
    pinctrl-0 = <&pwm0_default>;
	pinctrl-1 = <&pwm0_sleep>;
	pinctrl-names = "default", "sleep";
};

Relevant parts of main.c:

static const struct pwm_dt_spec mtr_drv1 = PWM_DT_SPEC_GET(DT_ALIAS(mtrdrv1));

...
[within main()]
if (!device_is_ready(mtr_drv1.dev) {
    LOG_ERR("PWM device is not ready.");
    return -1;
}

pwm_set_pulse_dt(in2, in2->period/period_div);


Are there any other things that need to be done to activate GPIO pins to be used for PWM? I don't have the equivalent of a gpio_configure_pin_dt() call.

Are there some GPIO pins that cannot be used for PWM?

Any guidance would be appreciated!

Parents
  • Hi mlp6,

    The usage of Zephyr's PWM driver is demonstrated in the PWM Blinky sample. The documentation for that is here: PWM Blinky — Zephyr Project Documentation (nordicsemi.com).

    Could you please take a look at that and see if it helps?

    Hieu

  • I have looked at that example, but that doesn't yield much help as I feel that I've already implement things--as detailed above--in a similar manner to the example, but using GPIO pins that are not "live" by default.

  • I was able to modify the PWM Blinky sample to work with two LEDs. The application code is nothing special, just getting the newly defined pwm_led1. Most of the work is in the DTS.

    Below is my overlay code, where I added some comments to highlight the parts which seem wrong in your DTS.

    Perhaps this would help you? 

    / {
        // This overlay setup pwm_led0 on pin 13, and pwm_led1 on pin 15
        aliases {
                pwm-led0 = &pwm_led0;
                pwm-led1 = &pwm_led1;
        };
    
        pwmleds {
            compatible = "pwm-leds";
            pwm_led0: pwm_led_0 {
                    //            |- This is PWM channel, not pin
                    //            v
                    pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
            };
            pwm_led1: pwm_led_1 {
                    //            |- This is PWM channel, not pin
                    //            v
                    pwms = <&pwm0 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
            };
    
        };
    
        pinctrl: pin-controller {
            compatible = "nordic,nrf-pinctrl";
            
    
            pwm0_default: pwm0_default {
                    group1 {
                            psels = <NRF_PSEL(PWM_OUT0, 0, 13)>,
                                    //            |- The second pin should be selected for output 1, not 0
                                    //        vvvvvvvv
                                    <NRF_PSEL(PWM_OUT1, 0, 15)>;
                            nordic,invert;
                    };
    
            };
    
            pwm0_sleep: pwm0_sleep {
                    group1 {
                            psels = <NRF_PSEL(PWM_OUT0, 0, 13)>,
                                    //            |- The second pin should be selected for output 1, not 0
                                    //        vvvvvvvv
                                    <NRF_PSEL(PWM_OUT1, 0, 15)>;
                            low-power-enable;
                    };
    
            };
    
        };
    
    };

Reply
  • I was able to modify the PWM Blinky sample to work with two LEDs. The application code is nothing special, just getting the newly defined pwm_led1. Most of the work is in the DTS.

    Below is my overlay code, where I added some comments to highlight the parts which seem wrong in your DTS.

    Perhaps this would help you? 

    / {
        // This overlay setup pwm_led0 on pin 13, and pwm_led1 on pin 15
        aliases {
                pwm-led0 = &pwm_led0;
                pwm-led1 = &pwm_led1;
        };
    
        pwmleds {
            compatible = "pwm-leds";
            pwm_led0: pwm_led_0 {
                    //            |- This is PWM channel, not pin
                    //            v
                    pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
            };
            pwm_led1: pwm_led_1 {
                    //            |- This is PWM channel, not pin
                    //            v
                    pwms = <&pwm0 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
            };
    
        };
    
        pinctrl: pin-controller {
            compatible = "nordic,nrf-pinctrl";
            
    
            pwm0_default: pwm0_default {
                    group1 {
                            psels = <NRF_PSEL(PWM_OUT0, 0, 13)>,
                                    //            |- The second pin should be selected for output 1, not 0
                                    //        vvvvvvvv
                                    <NRF_PSEL(PWM_OUT1, 0, 15)>;
                            nordic,invert;
                    };
    
            };
    
            pwm0_sleep: pwm0_sleep {
                    group1 {
                            psels = <NRF_PSEL(PWM_OUT0, 0, 13)>,
                                    //            |- The second pin should be selected for output 1, not 0
                                    //        vvvvvvvv
                                    <NRF_PSEL(PWM_OUT1, 0, 15)>;
                            low-power-enable;
                    };
    
            };
    
        };
    
    };

Children
Related