This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

system_off sample, wake from button on port1

Path to sample: v1.6.1\zephyr\samples\boards\nrf\system_off

Board selected: nrf52840dk_nrf52840

-------

I am attempting to modify the sample to use a button connected on P1.06 to wake and reboot from the off state.

I have used an overlay file to make the change:

file: nrf52840dk_nrf52840.overlay

<<<start>>>

&button0 {
    gpios = <&gpio1 6 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
        };
<<<end>>>
This change is correctly reflected in the device tree.
Unfortunately, this doesn't work and the button does not wake the device.
I have identified that the reason is that the port for the pin is not being set in the GPIOTE in these lines from main.c
<<<start>>
nrf_gpio_cfg_input(DT_GPIO_PIN(DT_NODELABEL(button0), gpios), NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(DT_GPIO_PIN(DT_NODELABEL(button0), gpios), NRF_GPIO_PIN_SENSE_LOW);
<<<end>>>
If I hack the pin number to add 32, I can make the code work.
What is the correct method to determine if button0 is on port1 (as set in the device tree) and to apply the required offset?
  • Hi, 

    P1 has 32 pins offset from P0, ex. pin = <42> is   /* P1, Pin10 */ 

    Assigen pin number for the port 1 in the device tree

    -Amanda H.

  • Thanks for the response. I was aware of this. However, I don't feel this is a "correct" solution as the gpios entry in the device tree requires a reference to the port as the first value (&gpio0 or &gpio1).

    gpios = <&gpio1 38 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;

    This works (as a hack), but semantically is incorrect as it is saying pin 38 on port gpio1, which is not correct and may cause issues with other functions.  In the context of the sample code, the port controller specified in the device tree is ignored.

    What is needed is either:

    * a function that generates the correct pin number for the nrf_gpio* functions from the given entries in the device tree; or

    * a GPIOTE library that directly understands the device tree.

    My knowledge of the ecosystem is too limited right now figure out if either of these solutions exist.

  • Sorry to misunderstand the question at first. 

    Try this for the nrf52840dk_nrf52840.overlay

    / {
    	buttons {
    		compatible = "gpio-keys";
    		button0: button_0 {
    			gpios = <&gpio1 6 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    			
    		};	
    	};
    };
    

    -Amanda H.

  • As far as I can see, your suggestion is functionally identical to the overlay file I was originally using.

    In order to make it easier for testing the problem, I have simplified things so that you can use a stock nrf52840dk.

    On the nRF52840 Dev Kit, switching the Trace switch (SW7) to the Alt position moves Button 1 to P1.07.

    Following your suggestion, the overlay file that should allow the system_off sample to work should be:

    / {
    	buttons {
    		compatible = "gpio-keys";
    		button0: button_0 {
    			gpios = <&gpio1 7 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    			
    		};	
    	};
    };
    

    I created a file boards/nrf52840dk_nrf52840.overlay in the system_off project directory with this content, and then loaded the project into SES.

    I confirmed that the overlay was properly processed by looking at the generated zephyr.dts file. The relevant portion is here:

    buttons {
    compatible = "gpio-keys";
    button0: button_0 {
    gpios = < &gpio1 0x7 0x11 >;
    label = "Push button switch 0";
    };
    button1: button_1 {
    gpios = < &gpio0 0xc 0x11 >;
    label = "Push button switch 1";
    };
    button2: button_2 {
    gpios = < &gpio0 0x18 0x11 >;
    label = "Push button switch 2";
    };
    button3: button_3 {
    gpios = < &gpio0 0x19 0x11 >;
    label = "Push button switch 3";
    };
    };
    
    

    This does not make the sample work.

    The problem is that the sample code does not examine the device tree to see which port button0 is connected to, and then add the offset of 32 if it is on gpio1.

    from main.c:

    nrf_gpio_cfg_input(DT_GPIO_PIN(DT_NODELABEL(button0), gpios),
    NRF_GPIO_PIN_PULLUP);
    nrf_gpio_cfg_sense_set(DT_GPIO_PIN(DT_NODELABEL(button0), gpios),
    NRF_GPIO_PIN_SENSE_LOW);

    Presumably, an expression like:
    DT_GPIO_CTLR(DT_NODELABEL(button0), gpios)

    should return the port associated with the button, but this is giving me compile errors and I am unsure what to compare it to.

    What I am expecting is that some logic along these lines is needed.

    int button0_pin = DT_GPIO_PIN(DT_NODELABEL(button0), gpios);
    if( DT_GPIO_CTLR(DT_NODELABEL(button0), gpios) == &gpio1 )
    button0_pin += 32;
    nrf_gpio_cfg_input(button0_pin,
    NRF_GPIO_PIN_PULLUP);
    nrf_gpio_cfg_sense_set(button0_pin
    NRF_GPIO_PIN_SENSE_LOW);

    Better would be a function that converts from the device tree to the nrf pin numbering scheme:

    int button0_pin = GetNrfPinNumberFromDT(button0);

  • Hi, 

    Sorry for the delay. 

    Seems you mixe zephyr gpio-syntax with nrf_gpio.h functions, so those functions don't play well together. You need to use the zephyr gpio API or match the input required by the functions in nrf_gpio.h. Please take a look at this Button sample on how to configure the pin.  

    -Amanda  

Related