nRF52820 PWM Device Tree / API

I am new to Zephyr/nRF environemnt and using the nRF52833-DK to emulate nRF52820 which does not have any dedicated PWM hardware

From my understanding I am limited to the software PWM API from nRF Connect SDK (using v2.3.0) - nordic,nrf-sw-pwm
I am trying to work out the preprocessor macro API available to control the 'sw_pwm' node and its channels
So far I am able to build the following:
printf("DTS sw-pwm driver name: %s\n", (DEVICE_DT_GET(DT_NODELABEL(sw_pwm)))->name);

uint64_t cycles;
pwm_get_cycles_per_sec((DEVICE_DT_GET(DT_NODELABEL(sw_pwm))), 0, &cycles);
printf("pwm cycles per sec: %lld\n", cycles);

Giving:
DTS sw-pwm driver name: sw-pwm
pwm cycles per sec: 16000000       // not validated this value but seems consistent & code compiles so...
Does this API set/get duty/freq/period (whatever it uses)?
Is there any documentation or another project I can reference as I can only find code that uses pwm-leds. Ideally I am looking to bypass modules like pwm-leds and control the sw-pwm channels from application code


nrf52820.dtsi
    sw_pwm: sw-pwm {
        compatible = "nordic,nrf-sw-pwm";
        status = "disabled";
        generator = <&timer2>;
        clock-prescaler = <0>;
        #pwm-cells = <3>;
    };

app device tree (.dts)
&sw_pwm {
	status ="okay";
	channel-gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>,
					<&gpio0 16 GPIO_ACTIVE_LOW>;
	clock-prescaler = <0>;
};
.config (\build Kconfig)
CONFIG_PWM=y
CONFIG_DT_HAS_NORDIC_NRF_SW_PWM_ENABLED=y
snippet from devicetree_generated.h (\build device tree source)
Parents
  • Hello,

    I have attached an example project that shows how to use software PWM to blink an LED (directly! not through the LED library). It is set up to be used for an nRF52840-DK because that I don't have a 52833-DK handy but you should be able to just rename the board overlay file that I included.

    I included a comment w/ a link to the nRF5 SW-PWM implementation for more information.

    https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/pwm/pwm_nrf5_sw.c

    led_pwm.zip

    Thanks,

    Helmut Lord

  • Thank you for you help, I have now successfully implemented all 3 pwm channels via the single sw-pwm instance.

    I am experimenting adding more sw-pwm instances (I believe each requires 1 generator and X PPI channels). I am hitting compilation errors. In the code below 'sw-pwm' is defined in #include <nordic/nrf52820_qdaa.dtsi> however I am leaving that 'status=disabled' and creating 2 new nodes: 'sw_pwm0: sw-pwm0' & 'sw_pwm1: sw-pwm1' that are compatible with 'nordic,nrf-sw-pwm'


    /dts-v1/;
    #include <nordic/nrf52820_qdaa.dtsi>
    
    / {
    	sw_pwm1: sw-pwm1 {
    		compatible = "nordic,nrf-sw-pwm";
        	status ="okay";
        	channel-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>,
        					<&gpio0 15 GPIO_ACTIVE_LOW>;
        	clock-prescaler = <0>;
        	generator = <&timer2>;
    		#pwm-cells = <3>;
    	};
    
    	sw_pwm0: sw-pwm0 {
    		compatible = "nordic,nrf-sw-pwm";
        	status ="okay";
        	channel-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
        	clock-prescaler = <0>;
        	generator = <&timer1>;
    		#pwm-cells = <3>;
    	};
    };

    pwm_init()

    	const struct device *driver0;
    	driver0 = DEVICE_DT_GET(DT_NODELABEL(sw_pwm0));
    	pwm_set_cycles(driver0, 0, CONFIG_SYS_CLOCK_TICKS_PER_SEC, CONFIG_SYS_CLOCK_TICKS_PER_SEC / 8, PWM_POLARITY_INVERTED);
    
    	const struct device *driver1;
    	driver1 = DEVICE_DT_GET(DT_NODELABEL(sw_pwm1));
        pwm_set_cycles(driver1, 0, CONFIG_SYS_CLOCK_TICKS_PER_SEC, CONFIG_SYS_CLOCK_TICKS_PER_SEC, PWM_POLARITY_INVERTED);

    compile error:

Reply
  • Thank you for you help, I have now successfully implemented all 3 pwm channels via the single sw-pwm instance.

    I am experimenting adding more sw-pwm instances (I believe each requires 1 generator and X PPI channels). I am hitting compilation errors. In the code below 'sw-pwm' is defined in #include <nordic/nrf52820_qdaa.dtsi> however I am leaving that 'status=disabled' and creating 2 new nodes: 'sw_pwm0: sw-pwm0' & 'sw_pwm1: sw-pwm1' that are compatible with 'nordic,nrf-sw-pwm'


    /dts-v1/;
    #include <nordic/nrf52820_qdaa.dtsi>
    
    / {
    	sw_pwm1: sw-pwm1 {
    		compatible = "nordic,nrf-sw-pwm";
        	status ="okay";
        	channel-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>,
        					<&gpio0 15 GPIO_ACTIVE_LOW>;
        	clock-prescaler = <0>;
        	generator = <&timer2>;
    		#pwm-cells = <3>;
    	};
    
    	sw_pwm0: sw-pwm0 {
    		compatible = "nordic,nrf-sw-pwm";
        	status ="okay";
        	channel-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
        	clock-prescaler = <0>;
        	generator = <&timer1>;
    		#pwm-cells = <3>;
    	};
    };

    pwm_init()

    	const struct device *driver0;
    	driver0 = DEVICE_DT_GET(DT_NODELABEL(sw_pwm0));
    	pwm_set_cycles(driver0, 0, CONFIG_SYS_CLOCK_TICKS_PER_SEC, CONFIG_SYS_CLOCK_TICKS_PER_SEC / 8, PWM_POLARITY_INVERTED);
    
    	const struct device *driver1;
    	driver1 = DEVICE_DT_GET(DT_NODELABEL(sw_pwm1));
        pwm_set_cycles(driver1, 0, CONFIG_SYS_CLOCK_TICKS_PER_SEC, CONFIG_SYS_CLOCK_TICKS_PER_SEC, PWM_POLARITY_INVERTED);

    compile error:

Children
Related