Skip to content

Commit 4a73546

Browse files
nordic-seglnordicjm
authored andcommitted
tests: drivers: gpio: Add loopback test that uses multiple GPIO ports
Check that power moding is aware of GPIO ports/pins in use. Verify that GPIO toggle works after 8 seconds since test starts. Signed-off-by: Sebastian Głąb <[email protected]>
1 parent 2e06803 commit 4a73546

File tree

9 files changed

+266
-0
lines changed

9 files changed

+266
-0
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,7 @@
714714
/tests/bluetooth/tester/ @carlescufi @nrfconnect/ncs-paladin
715715
/tests/crypto/ @stephen-nordic @magnev
716716
/tests/drivers/gpio/egpio_basic_api/ @nrfconnect/ncs-ll-ursus
717+
/tests/drivers/gpio/gpio_more_loops/ @nrfconnect/ncs-low-level-test
717718
/tests/drivers/flash/flash_rpc/ @nrfconnect/ncs-pluto
718719
/tests/drivers/flash_patch/ @nrfconnect/ncs-pluto
719720
/tests/drivers/fprotect/ @nrfconnect/ncs-pluto
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#
2+
# Copyright (c) 2024 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
cmake_minimum_required(VERSION 3.20.0)
8+
9+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
10+
project(gpio_more_loops)
11+
12+
FILE(GLOB app_sources src/main.c)
13+
target_sources(app PRIVATE ${app_sources})
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright (c) 2024 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
3+
4+
config TEST_DURATION
5+
int "Test duration in ms"
6+
default 8000
7+
help
8+
Test will run for (at least) defined time.
9+
This value affects how many times GPIOs will be toggled.
10+
11+
source "Kconfig.zephyr"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CONFIG_NRF_REGTOOL_VERBOSITY=1
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
/ {
8+
/* Test requirements:
9+
* out-gpios[0] wire connected with in-gpios[0],
10+
* out-gpios[1] wire connected with in-gpios[1],
11+
* etc.
12+
* Output-input GPIO pair must have identical active level flag.
13+
*/
14+
test_gpios {
15+
compatible = "gpio-leds";
16+
out_gpios: out_gpios {
17+
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>, <&gpio2 8 GPIO_ACTIVE_HIGH>,
18+
<&gpio1 2 GPIO_ACTIVE_HIGH>, <&gpio7 2 GPIO_ACTIVE_HIGH>,
19+
<&gpio7 6 GPIO_ACTIVE_HIGH>, <&gpio1 5 GPIO_ACTIVE_HIGH>;
20+
};
21+
22+
in_gpios: in_gpios {
23+
gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>, <&gpio2 9 GPIO_ACTIVE_HIGH>,
24+
<&gpio1 3 GPIO_ACTIVE_HIGH>, <&gpio1 0 GPIO_ACTIVE_HIGH>,
25+
<&gpio7 7 GPIO_ACTIVE_HIGH>, <&gpio7 1 GPIO_ACTIVE_HIGH>;
26+
};
27+
};
28+
};
29+
30+
&gpiote130 {
31+
status = "okay";
32+
owned-channels = <7>;
33+
};
34+
35+
&gpio0 {
36+
status = "okay";
37+
};
38+
39+
&gpio1 {
40+
status = "okay";
41+
};
42+
43+
&gpio2 {
44+
status = "okay";
45+
};
46+
47+
&gpio7 {
48+
status = "okay";
49+
};
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
/ {
8+
/* Test requirements:
9+
* out-gpios[0] wire connected with in-gpios[0],
10+
* out-gpios[1] wire connected with in-gpios[1],
11+
* etc.
12+
* Output-input GPIO pair must have identical active level flag.
13+
*/
14+
test_gpios {
15+
compatible = "gpio-leds";
16+
out_gpios: out_gpios {
17+
gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>, <&gpio1 8 GPIO_ACTIVE_HIGH>,
18+
<&gpio1 10 GPIO_ACTIVE_HIGH>, <&gpio1 12 GPIO_ACTIVE_HIGH>,
19+
<&gpio2 10 GPIO_ACTIVE_HIGH>;
20+
};
21+
22+
in_gpios: in_gpios {
23+
gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>, <&gpio1 9 GPIO_ACTIVE_HIGH>,
24+
<&gpio1 11 GPIO_ACTIVE_HIGH>, <&gpio1 13 GPIO_ACTIVE_HIGH>,
25+
<&gpio1 14 GPIO_ACTIVE_HIGH>;
26+
};
27+
};
28+
};
29+
30+
&gpiote20 {
31+
status = "okay";
32+
};
33+
34+
&gpio1 {
35+
status = "okay";
36+
};
37+
38+
&gpio2 {
39+
status = "okay";
40+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CONFIG_GPIO=y
2+
CONFIG_ZTEST=y
3+
CONFIG_LOG=y
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <zephyr/logging/log.h>
8+
LOG_MODULE_REGISTER(gpio_loops, LOG_LEVEL_INF);
9+
10+
#include <zephyr/kernel.h>
11+
#include <zephyr/drivers/gpio.h>
12+
#include <zephyr/ztest.h>
13+
14+
#if !DT_NODE_EXISTS(DT_NODELABEL(out_gpios)) || !DT_NODE_EXISTS(DT_NODELABEL(in_gpios))
15+
#error "Unsupported board: test_gpio node is not defined"
16+
#endif
17+
18+
/* Delay after setting GPIO ouputs. It allows signals to settle. */
19+
#define PROPAGATION_DELAY_MS K_MSEC(1U)
20+
21+
/* Delay between GPIO toggle. */
22+
#define TOGGLE_DELAY_MS 500U
23+
24+
const struct gpio_dt_spec out_pins[] = {
25+
DT_FOREACH_PROP_ELEM_SEP(DT_NODELABEL(out_gpios), gpios, GPIO_DT_SPEC_GET_BY_IDX, (,))
26+
};
27+
const struct gpio_dt_spec in_pins[] = {
28+
DT_FOREACH_PROP_ELEM_SEP(DT_NODELABEL(in_gpios), gpios, GPIO_DT_SPEC_GET_BY_IDX, (,))
29+
};
30+
BUILD_ASSERT(ARRAY_SIZE(in_pins) == ARRAY_SIZE(out_pins), "mismatched in/out pairs");
31+
const uint8_t npairs = ARRAY_SIZE(in_pins);
32+
33+
34+
/* Check that input GPIOs state match with input parameter 'value'. */
35+
static void _check_inputs(uint32_t value)
36+
{
37+
bool current;
38+
bool expected;
39+
40+
LOG_DBG("_check_inputs(%d)", value);
41+
42+
/* Wait a bit to stabilize logic level. */
43+
k_sleep(PROPAGATION_DELAY_MS);
44+
45+
for (uint8_t i = 0; i < npairs; i++) {
46+
current = gpio_pin_get_dt(&in_pins[i]);
47+
expected = value & BIT(i);
48+
LOG_DBG("_check_inputs L[%d]: current: %d, expected: %d", i, current, expected);
49+
zassert_equal(current, expected,
50+
"IN[%d] = %d, while expected %d", i, current, expected);
51+
}
52+
}
53+
54+
/* Set output GPIOs with gpio_pin_set_dt()
55+
* and confirm that input GPIOs have expected state.
56+
*/
57+
static void _gpio_pin_set_dt_and_check(uint32_t value)
58+
{
59+
int out_state;
60+
int rc;
61+
62+
LOG_DBG("_gpio_pin_set_dt_and_check(%d)", value);
63+
64+
for (uint8_t i = 0; i < npairs; i++) {
65+
out_state = (value & BIT(i)) >> i;
66+
rc = gpio_pin_set_dt(&out_pins[i], out_state);
67+
LOG_DBG("_gpio_pin_set_dt_and_check: setting OUT[%d] to %d", i, out_state);
68+
zassert_equal(rc, 0, "gpio_pin_set_dt(OUT[%d], %d) failed", i, out_state);
69+
}
70+
71+
/* Check inputs. */
72+
_check_inputs(value);
73+
}
74+
75+
/**
76+
* @brief Test GPIOs are working for CONFIG_TEST_DURATION ms.
77+
*/
78+
ZTEST(gpio_more_loops, test_gpios_are_working)
79+
{
80+
for (int total_delay = 0; total_delay <= CONFIG_TEST_DURATION;
81+
total_delay += (2 * TOGGLE_DELAY_MS)) {
82+
83+
_gpio_pin_set_dt_and_check(0b01010101010101010101010101010101);
84+
k_msleep(TOGGLE_DELAY_MS);
85+
_gpio_pin_set_dt_and_check(0b10101010101010101010101010101010);
86+
k_msleep(TOGGLE_DELAY_MS);
87+
}
88+
}
89+
90+
static void *suite_setup(void)
91+
{
92+
uint8_t i;
93+
int rc;
94+
95+
TC_PRINT("Test executed on %s\n", CONFIG_BOARD_TARGET);
96+
TC_PRINT("GPIO Loops count: %d\n", npairs);
97+
TC_PRINT("===================================================================\n");
98+
99+
for (i = 0; i < npairs; i++) {
100+
zassert_true(gpio_is_ready_dt(&in_pins[i]), "IN[%d] is not ready", i);
101+
zassert_true(gpio_is_ready_dt(&out_pins[i]), "OUT[%d] is not ready", i);
102+
103+
}
104+
105+
for (i = 0; i < npairs; i++) {
106+
rc = gpio_pin_configure_dt(&in_pins[i], GPIO_INPUT | GPIO_PULL_UP);
107+
zassert_equal(rc, 0, "IN[%d] config failed", i);
108+
}
109+
_check_inputs(0b11111111111111111111111111111111);
110+
TC_PRINT("Input pull up works.\n");
111+
112+
for (i = 0; i < npairs; i++) {
113+
rc = gpio_pin_configure_dt(&in_pins[i], GPIO_INPUT | GPIO_PULL_DOWN);
114+
zassert_equal(rc, 0, "IN[%d] config failed", i);
115+
}
116+
_check_inputs(0b00000000000000000000000000000000);
117+
TC_PRINT("Input pull down works.\n");
118+
119+
for (i = 0; i < npairs; i++) {
120+
rc = gpio_pin_configure_dt(&in_pins[i], GPIO_INPUT);
121+
zassert_equal(rc, 0, "IN[%d] config failed", i);
122+
rc = gpio_pin_configure_dt(&out_pins[i], GPIO_OUTPUT);
123+
zassert_equal(rc, 0, "OUT[%d] config failed", i);
124+
LOG_DBG("IN[%d] - OUT[%d] were configured", i, i);
125+
}
126+
127+
return NULL;
128+
}
129+
130+
ZTEST_SUITE(gpio_more_loops, NULL, suite_setup, NULL, NULL, NULL);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
common:
2+
tags:
3+
- drivers
4+
- gpio
5+
depends_on: gpio
6+
filter: not CONFIG_COVERAGE
7+
harness: ztest
8+
harness_config:
9+
fixture: gpio_loopback
10+
11+
tests:
12+
drivers.gpio.gpio_more_loops:
13+
platform_allow:
14+
- nrf54l15dk/nrf54l15/cpuapp
15+
- nrf54h20dk/nrf54h20/cpuapp
16+
integration_platforms:
17+
- nrf54l15dk/nrf54l15/cpuapp
18+
- nrf54h20dk/nrf54h20/cpuapp

0 commit comments

Comments
 (0)