Button

Downstream Copy!

This sample is a copy from Zephyr with identical name and will be used for further development, improvement and preparation of changes for Zephyr within Bridle. However, the original sample still lives within the Zephyr namespace under the exactly same name: Button.

Overview

A simple button demo showcasing the use of GPIO input using a dedicated polling thread, spawned by an init function. Alternatively, it can be configured to use interrupts instead. In either mode, pressing the button will light up an led.

Requirements

The board hardware must have a push button connected via a GPIO pin. These are called “User buttons” on many of Zephyr’s Supported Boards and Shields and Bridle’s Supported Boards.

The button must be configured using the sw0 devicetree alias, usually in the BOARD.dts file. You will see this error if you try to build this sample for an unsupported board:

Unsupported board: sw0 devicetree alias is not defined

You may see additional build errors if the sw0 alias exists, but is not properly defined.

Additionally, the sample requires the led0 devicetree alias.

The sample supports the following platforms (located in samples/button/sample.yaml):

Hardware platforms

Order number

Board name

Board target

RP2040

The PicoBoy (Color)

  • picoboy/rp2040

  • picoboy_color/rp2040

  • picoboy_color_plus/rp2350a/m33

STM32L496ZG

Nucleo L496ZG

  • nucleo_l496zg

STM32F767ZI

Nucleo F767ZI

  • nucleo_f767zi

STM32F746ZG

Nucleo F746ZG

  • nucleo_f746zg

STM32F413ZH

Nucleo F413ZH

  • nucleo_f413zh

STM32F401RE

Nucleo F401RE

  • nucleo_f401re

STM32F303RE

Nucleo F303RE

  • nucleo_f303re

nRF9160

nRF9160 DK

  • nrf9160dk/nrf9160

nRF52840

nRF52840 DK

  • nrf52840dk/nrf52840

i.MX RT1170 (CM7)

MIMXRT1170-EVK/EVKB

  • mimxrt1170_evk/mimxrt1176/cm7

  • mimxrt1170_evk@B/mimxrt1176/cm7

i.MX RT1170 (CM4)

MIMXRT1170-EVK/EVKB

  • mimxrt1170_evk/mimxrt1176/cm4

  • mimxrt1170_evk@B/mimxrt1176/cm4

i.MX RT1060

MIMXRT1060-EVK

  • mimxrt1060_evk/mimxrt1062/hyperflash

  • mimxrt1060_evk@C/mimxrt1062/qspi

  • mimxrt1060_evk@B/mimxrt1062/qspi

  • mimxrt1060_evk@A/mimxrt1062/qspi

i.MX RT1010

MIMXRT1010-EVK

  • mimxrt1010_evk

RP2040

Cytron Maker RP2040

  • cytron_maker_pi_rp2040

  • cytron_maker_nano_rp2040

Configuration options

The following sample-specific Kconfig options are used in this sample (located in samples/button/Kconfig):

CONFIG_APPLICATION_MODE_POLLING

Poll button state

None

CONFIG_APPLICATION_MODE_INTERRUPT

Use an interrupt and callback

None

CONFIG_SLEEP_TIME_MS

Polling loop sleep time

This defines how long the polling loop waits between subsequent queries of the push button state.

Devicetree details

This section provides more details on devicetree configuration.

Here is a minimal devicetree fragment which supports this sample, containing both an sw0 and an led0 alias:

/ {
    aliases {
        sw0 = &user_button;
        led0 = &user_lamp;
    };

    soc {
        gpio0: gpio@0 {
            status = "okay";
            gpio-controller;
            #gpio-cells = <2>;
            /* ... */
        };
    };

    buttons {
        compatible = "gpio-keys";
        user_button: gpio0_button {
            gpios = <__GPIO_CTRL_NODE__ __PIN__ __FLAGS__>;
            label = "User button";
        };
        /* ... other buttons ... */
    };

    leds {
        compatible = "gpio-leds";
        user_lamp: gpio0_led {
            gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>;
            label = "User LD1";
        };
        /* ... other leds ... */

};

As shown:

The above situation is for the common case where:

  • __GPIO_CTRL_NODE__ should be a reference to a node label of class GPIO controller, e.g. in node user_lamp: gpio0_led {/* … */}; the reference gpios = <&gpio0 /* … */> uses the example node label gpio0: and points to the given GPIO controller

  • __PIN__ should be a pin number, like 8 or 0, see user_lamp: for an example

  • __FLAGS__ should be a logical OR of GPIO configuration flags meant to apply to the button, such as (GPIO_PULL_UP | GPIO_ACTIVE_LOW), see user_lamp: for an example

Required devicetree bindings:

This assumes the common case, where is #gpio-cells = <2> in the gpio0: node, and that the GPIO controller’s devicetree binding declares those two cells pin and flags in gpio-cells like so:

properties:
  "#gpio-cells":
    type: int
    required: true
    const: 2

gpio-cells:
  - pin
  - flags

This sample requires a pin cell in the gpios property. The flags cell is optional, however, and the sample still works if the GPIO cells do not contain flags. This assumes the common case, where the gpios = <&gpio0 /* … */> property in the user_button: and user_lamp: child nodes reflects an GPIO keys and leds devicetree binding similar like so:

child-binding:
  properties:
    gpios:
      type: phandle-array
      required: true

Building and Running

This sample can be built for multiple boards, in this example we will build it for the Nucleo F413ZH board:

  1. polling thread

    west build -b nucleo_f413zh -p -d build/nucleo_f413zh-button-poll bridle/samples/button -- -DCONF_FILE=prj-poll.conf
    west flash -d build/nucleo_f413zh-button-poll
    
  2. interrupt callback

    west build -b nucleo_f413zh -p -d build/nucleo_f413zh-button-event bridle/samples/button -- -DCONF_FILE=prj-event.conf
    west flash -d build/nucleo_f413zh-button-event
    

During startup, an init function look up predefined GPIO devices, and configures their pins in input and output mode, respectively. Depending on the build configuration, an additional init function either spawns a dedicated polling thread which continuously monitors the button state and adjusts the led state to match, or sets up an interrupt that does the same whenever the button is pressed or released.