Skip to content

Commit a072236

Browse files
asemjonovscarlescufi
authored andcommitted
gpio: Add tests for software based GPIO debounce driver
Add tests to validate software based GPIO debounce driver. Signed-off-by: Al Semjonovs <[email protected]>
1 parent 211e4d2 commit a072236

File tree

2 files changed

+148
-1
lines changed

2 files changed

+148
-1
lines changed

tests/drivers/gpio/gpio_api_1pin/boards/native_posix.overlay

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,31 @@
55
*/
66

77
&gpio0 {
8-
ngpios = <2>;
8+
ngpios = <3>;
9+
};
10+
11+
/ {
12+
gpio-keys0 {
13+
compatible = "zephyr,gpio-keys";
14+
debounce-interval-ms = <30>;
15+
16+
voldown_button: button_0 {
17+
gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
18+
zephyr,code = <10>;
19+
};
20+
volup_button: button_1 {
21+
gpios = <&gpio0 1 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
22+
zephyr,code = <11>;
23+
};
24+
};
25+
26+
gpio-keys1 {
27+
compatible = "zephyr,gpio-keys";
28+
debounce-interval-ms = <100>;
29+
30+
power_button: button_2 {
31+
gpios = <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
32+
zephyr,code = <20>;
33+
};
34+
};
935
};
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright (c) 2022 Google LLC
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "zephyr/sys/util.h"
8+
#include <zephyr/device.h>
9+
#include <zephyr/drivers/gpio/gpio_emul.h>
10+
#include <zephyr/kernel.h>
11+
#include <zephyr/logging/log.h>
12+
#include <zephyr/ztest.h>
13+
14+
#include <zephyr/drivers/gpio_keys.h>
15+
16+
LOG_MODULE_REGISTER(gpio_keys_test, LOG_LEVEL_DBG);
17+
18+
#if DT_NODE_EXISTS(DT_NODELABEL(voldown_button))
19+
20+
const struct device *test_gpio_keys_dev = DEVICE_DT_GET(DT_PARENT(DT_NODELABEL(voldown_button)));
21+
#define BUTTON_0_IDX DT_NODE_CHILD_IDX(DT_NODELABEL(voldown_button))
22+
#define BUTTON_1_IDX DT_NODE_CHILD_IDX(DT_NODELABEL(volup_button))
23+
24+
struct gpio_keys_pin_config {
25+
/** GPIO specification from devicetree */
26+
struct gpio_dt_spec spec;
27+
/** Zephyr code from devicetree */
28+
uint32_t zephyr_code;
29+
};
30+
struct gpio_keys_config {
31+
/** Debounce interval in milliseconds from devicetree */
32+
uint32_t debounce_interval_ms;
33+
const int num_keys;
34+
const struct gpio_keys_pin_config *pin_cfg;
35+
};
36+
37+
/**
38+
* @brief Test Suite: Verifies gpio_keys_config functionality.
39+
*/
40+
ZTEST_SUITE(gpio_keys, NULL, NULL, NULL, NULL, NULL);
41+
42+
/**
43+
* @brief TestPurpose: Verify gpio_keys_config pressed raw.
44+
*
45+
*/
46+
ZTEST(gpio_keys, test_gpio_keys_pressed)
47+
{
48+
const struct gpio_keys_config *config = test_gpio_keys_dev->config;
49+
const struct gpio_keys_pin_config *pin_cfg = &config->pin_cfg[BUTTON_0_IDX];
50+
const struct gpio_dt_spec *spec = &pin_cfg->spec;
51+
52+
zassert_ok(gpio_pin_configure(spec->port, spec->pin, GPIO_INPUT));
53+
54+
zassert_ok(gpio_emul_input_set(spec->port, spec->pin, 1));
55+
zassert_equal(1, gpio_keys_get_pin(test_gpio_keys_dev, BUTTON_0_IDX));
56+
57+
zassert_ok(gpio_emul_input_set(spec->port, spec->pin, 0));
58+
zassert_equal(0, gpio_keys_get_pin(test_gpio_keys_dev, BUTTON_0_IDX));
59+
}
60+
61+
/**
62+
* @brief TestPurpose: Verify button interrupt.
63+
*
64+
*/
65+
uint32_t gpio_keys_interrupt_called;
66+
void test_gpio_keys_cb_handler(const struct device *dev, struct gpio_keys_callback *cbdata,
67+
uint32_t pins)
68+
{
69+
LOG_DBG("GPIO_KEY %s pressed, pins=%d, zephyr_code=%u, pin_state=%d", dev->name, pins,
70+
cbdata->zephyr_code, cbdata->pin_state);
71+
gpio_keys_interrupt_called = cbdata->zephyr_code;
72+
}
73+
74+
ZTEST(gpio_keys, test_gpio_keys_interrupt)
75+
{
76+
int button_idx[] = {BUTTON_0_IDX, BUTTON_1_IDX};
77+
int num_gpio_keys = ARRAY_SIZE(button_idx);
78+
const struct gpio_keys_config *config = test_gpio_keys_dev->config;
79+
const struct gpio_keys_pin_config *pin_cfg;
80+
const struct gpio_dt_spec *spec;
81+
82+
for (int i = 0; i < num_gpio_keys; i++) {
83+
pin_cfg = &config->pin_cfg[button_idx[i]];
84+
spec = &pin_cfg->spec;
85+
86+
LOG_DBG("GPIO_KEY config=[0x%p, %d]", config->debounce_interval_ms,
87+
pin_cfg->zephyr_code);
88+
LOG_DBG("GPIO_KEY spec=[0x%p, %d]", spec->port, spec->pin);
89+
90+
zassert_ok(gpio_pin_configure(spec->port, spec->pin, GPIO_INPUT));
91+
zassert_ok(gpio_keys_disable_interrupt(test_gpio_keys_dev), NULL);
92+
k_sleep(K_MSEC(500));
93+
94+
/* Check interrupts are disabled */
95+
gpio_keys_interrupt_called = 0;
96+
zassert_ok(gpio_emul_input_set(spec->port, spec->pin, 0));
97+
k_sleep(K_MSEC(1000));
98+
zassert_ok(gpio_emul_input_set(spec->port, spec->pin, 1));
99+
k_sleep(K_MSEC(1000));
100+
zassert_equal(gpio_keys_interrupt_called, 0);
101+
102+
zassert_ok(
103+
gpio_keys_enable_interrupt(test_gpio_keys_dev, test_gpio_keys_cb_handler),
104+
NULL);
105+
zassert_ok(gpio_emul_input_set(spec->port, spec->pin, 0));
106+
k_sleep(K_MSEC(1000));
107+
108+
gpio_keys_interrupt_called = 0;
109+
zassert_ok(gpio_emul_input_set(spec->port, spec->pin, 1));
110+
111+
/* Check interrupt doesn't prematurely fires */
112+
k_sleep(K_MSEC(config->debounce_interval_ms / 2));
113+
zassert_equal(gpio_keys_interrupt_called, 0);
114+
115+
/* Check interrupt fires after debounce interval */
116+
k_sleep(K_MSEC(config->debounce_interval_ms));
117+
zassert_equal(gpio_keys_interrupt_called, pin_cfg->zephyr_code);
118+
}
119+
}
120+
121+
#endif /* DT_NODE_EXISTS(DT_NODELABEL(voldown_button)) */

0 commit comments

Comments
 (0)