Using a pin both as a GPIO and as a PWM pin. The device tree and the overlay hell.

Hi, we started using nRFConnect SDK a few month ago and we are still having tough time every time we need to implement some configuration not directly available inside some example.

We believe it is mostly our fault because lack of knowledge, anyway I have to say that the learning curve of the Zephyr driver abstraction is quite steep.

Let's start with your example "blinky_pwm" built to run ona nRF52840DK.

It works out of the box but:

Let's say one want to control all the four leds using the same PWM0 peripheral while driving each led with a different PWM comparator (COMP0..COMP3) to achieve different dimming levels for each led.

We tried copy and pasting portions of the .dts file into the overlay one, we tried something like:

&sw_pwm {
	status = "okay";
	channel-gpios = <&gpio0 13 PWM_POLARITY_INVERTED>,<&gpio0 14 PWM_POLARITY_INVERTED>,<&gpio0 15 PWM_POLARITY_INVERTED>,<&gpio0 16 PWM_POLARITY_INVERTED>;
};

&pwm_led0 {
	compatible = "pwm-leds";
	pwms = <&sw_pwm 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
};

&pwm_led1 {
	compatible = "pwm-leds";
	pwms = <&sw_pwm 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
};
&pwm_led2 {
	compatible = "pwm-leds";
	pwms = <&sw_pwm 2 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
};
&pwm_led3 {
	compatible = "pwm-leds";
	pwms = <&sw_pwm 3 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
};

..but it fails miserably.

Can you help us to achieve using the full 4 PWM channels ?

Moreover what is the correct approach to drive a LED both as GPIO and as PWM (of course not at the same time, but during different application phases)?

Let's say we need to drive the LEDs by means of simple GPIO ON or OFF using the gpio driver during initialization and for some time after reset, then after a specific event we need to switch to PWM driving. Eventually after some other event, we will need to go back to GPIO drive ON/OFF only fashion.

Can you kindly advise on the "correct nRFConnect" approach to follow?

Many thanks in advance and best regards

 Davide

  • I am adding a few lines here to avoid receiving an miscentered or off topic answer.

    Of course one can "emulate" a GPIO ON state with a PWM 100% setting and OFF with 0%: but the point is not this one.

    May be I should have asked to use the same pin with both PWM (out) functionality and as a GPIO input (not at the same time obviously)

    So what would be a very valuable hint is: an example of the correct board overly to achieve this, along with a sample code snippet to programmatically switch among PWM and GPIO pin function.

    Looking forward and best regards

    DDN

  • Hello DDN,

    Sorry for the late reply. 

    While it is a bit tedious to use one GPIO for two different peripherals in NCS, it should be possible to use it for a peripheral and as a normal GPIO, just by disabling the peripheral. 

    A colleague of mine just did something similar (except for with UART and GPIO output). Please have a look, and see if this is something you can use. Let me know if you have difficulties translating this to PWM. 

    If you short the P0.06 with P0.13, you should see that you are able to see the UART output (using P0.06 for UART TX), and then the LED will toggle (because P0.06 is shorted to P0.13, which is the LED1 pin).

    hello_world_toggle_uart_onoff.zip

    Best regards,

    Edvin

  • Thank you for the example, but this is not helping me regarding the configuration.


    Do you have any hint on how to define all the required device trees and overlay files?
    We have no idea on how to define that we wish to control 4 leds using the four channels inside PWM0 peripheral.

    br

     Davide

  • Maybe this answer will help you? They have 3 PWM channels set up successfully, it seems: devzone.nordicsemi.com/.../adding-pwm-channels-in-zephyr

    Regards,

    Knut

  • Hello,

    So I took the time to implement something like you suggest. Please have a look at the attached application (tested in ncs v2.5.1):

    hello_world_pwm_gpio_input.zip

    To test on an nRF52840dk, please short P0.11 (button1) and P0.13 (LED1). The way it works is that it starts with 1 second of toggling the LED as a PWM signal. Then it switches over to gpio input on the LED pin. I set up a new button (or switch, really) in nrf52840dk_nrf52840.overlay on P0.13. You can ground the P0.13 directly, but it is easier to test if you short it to button 1 and press the button. The log should let you know when the button is pressed (when the GPIO is in interrupt mode). 

    Best regards,

    Edvin

Related