1 /*
2  * Copyright (c) 2019 Piotr Mienkowski
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 
8 #include <limits.h>
9 #include <zephyr/sys/util.h>
10 #include "test_gpio_api.h"
11 
pin_get_raw_and_verify(const struct device * port,unsigned int pin,int val_expected,int idx)12 static void pin_get_raw_and_verify(const struct device *port,
13 				   unsigned int pin,
14 				   int val_expected, int idx)
15 {
16 	int val_actual;
17 
18 	val_actual = gpio_pin_get_raw(port, pin);
19 	zassert_true(val_actual >= 0,
20 		     "Test point %d: failed to get physical pin value", idx);
21 	zassert_equal(val_expected, val_actual,
22 		      "Test point %d: invalid physical pin get value", idx);
23 }
24 
pin_get_and_verify(const struct device * port,unsigned int pin,int val_expected,int idx)25 static void pin_get_and_verify(const struct device *port, unsigned int pin,
26 			       int val_expected, int idx)
27 {
28 	int val_actual;
29 
30 	val_actual = gpio_pin_get(port, pin);
31 	zassert_true(val_actual >= 0,
32 		     "Test point %d: failed to get logical pin value", idx);
33 	zassert_equal(val_expected, val_actual,
34 		      "Test point %d: invalid logical pin get value", idx);
35 }
36 
pin_set_raw_and_verify(const struct device * port,unsigned int pin,int val,int idx)37 static void pin_set_raw_and_verify(const struct device *port,
38 				   unsigned int pin,
39 				   int val, int idx)
40 {
41 	zassert_equal(gpio_pin_set_raw(port, pin, val), 0,
42 		      "Test point %d: failed to set physical pin value", idx);
43 	k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
44 }
45 
pin_set_and_verify(const struct device * port,unsigned int pin,int val,int idx)46 static void pin_set_and_verify(const struct device *port, unsigned int pin,
47 			       int val,
48 			       int idx)
49 {
50 	zassert_equal(gpio_pin_set(port, pin, val), 0,
51 		      "Test point %d: failed to set logical pin value", idx);
52 	k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
53 }
54 
55 /** @brief Verify gpio_pin_toggle function.
56  *
57  * - Verify that gpio_pin_toggle function changes pin state from active to
58  *   inactive and vice versa.
59  */
ZTEST(gpio_api_1pin_pin,test_gpio_pin_toggle)60 ZTEST(gpio_api_1pin_pin, test_gpio_pin_toggle)
61 {
62 	const struct device *port;
63 	int val_expected;
64 	int ret;
65 
66 	port = DEVICE_DT_GET(TEST_NODE);
67 	zassert_true(device_is_ready(port), "GPIO dev is not ready");
68 
69 	TC_PRINT("Running test on port=%s, pin=%d\n", port->name, TEST_PIN);
70 
71 	ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
72 	if (ret == -ENOTSUP) {
73 		TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
74 		ztest_test_skip();
75 		return;
76 	}
77 	zassert_equal(ret, 0, "Failed to configure the pin");
78 
79 	pin_set_raw_and_verify(port, TEST_PIN, 1, 0);
80 
81 	for (int i = 0; i < 5; i++) {
82 		ret = gpio_pin_toggle(port, TEST_PIN);
83 		zassert_equal(ret, 0, "Failed to toggle pin value");
84 		k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
85 
86 		val_expected = i % 2;
87 
88 		pin_get_raw_and_verify(port, TEST_PIN, val_expected, i);
89 	}
90 }
91 
92 /** @brief Verify visually gpio_pin_toggle function.
93  *
94  * This test configures the pin using board DTS flags which should
95  * correctly set pin active state via GPIO_ACTIVE_LOW/_HIGH flags.
96  * It is possible to do a visual check to confirm that "LED ON", "LED OFF"
97  * messages correspond to the LED being turned ON or OFF.
98  *
99  * - Verify visually that gpio_pin_toggle function changes pin state from active
100  *   to inactive and vice versa.
101  */
ZTEST(gpio_api_1pin_pin,test_gpio_pin_toggle_visual)102 ZTEST(gpio_api_1pin_pin, test_gpio_pin_toggle_visual)
103 {
104 	const struct device *port;
105 	int val_expected;
106 	int ret;
107 
108 	port = DEVICE_DT_GET(TEST_NODE);
109 	zassert_true(device_is_ready(port), "GPIO dev is not ready");
110 
111 	TC_PRINT("Running test on port=%s, pin=%d\n", port->name, TEST_PIN);
112 
113 	ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT |
114 				 TEST_PIN_DTS_FLAGS);
115 	zassert_equal(ret, 0, "Failed to configure the pin");
116 
117 	pin_set_and_verify(port, TEST_PIN, 1, 0);
118 	TC_PRINT("LED ON\n");
119 
120 	for (int i = 0; i < 3; i++) {
121 		k_sleep(K_SECONDS(2));
122 
123 		ret = gpio_pin_toggle(port, TEST_PIN);
124 		zassert_equal(ret, 0, "Failed to toggle pin value");
125 		k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
126 
127 		val_expected = i % 2;
128 		TC_PRINT("LED %s\n", val_expected == 1 ? "ON" : "OFF");
129 	}
130 }
131 
132 /** @brief Verify gpio_pin_set_raw, gpio_pin_get_raw functions.
133  *
134  * - Verify that gpio_pin_get_raw reads the same value as set by
135  *   gpio_pin_set_raw function.
136  */
ZTEST(gpio_api_1pin_pin,test_gpio_pin_set_get_raw)137 ZTEST(gpio_api_1pin_pin, test_gpio_pin_set_get_raw)
138 {
139 	const struct device *port;
140 	int val_expected;
141 	int ret;
142 
143 	const int test_vector[] = {
144 		4, 1, 45, 0, 0, -7, 0, 0, 0, INT_MAX, INT_MIN, 0
145 	};
146 
147 	port = DEVICE_DT_GET(TEST_NODE);
148 	zassert_true(device_is_ready(port), "GPIO dev is not ready");
149 
150 	TC_PRINT("Running test on port=%s, pin=%d\n", port->name, TEST_PIN);
151 
152 	ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
153 	if (ret == -ENOTSUP) {
154 		TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
155 		ztest_test_skip();
156 		return;
157 	}
158 	zassert_equal(ret, 0, "Failed to configure the pin");
159 
160 	for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
161 		pin_set_raw_and_verify(port, TEST_PIN, test_vector[i], i);
162 
163 		val_expected = test_vector[i] != 0 ? 1 : 0;
164 
165 		pin_get_raw_and_verify(port, TEST_PIN, val_expected, i);
166 	}
167 }
168 
169 /** @brief Verify gpio_pin_set, gpio_pin_get functions.
170  *
171  * - Verify that gpio_pin_get reads the same value as set by gpio_pin_set
172  *   function.
173  */
ZTEST(gpio_api_1pin_pin,test_gpio_pin_set_get)174 ZTEST(gpio_api_1pin_pin, test_gpio_pin_set_get)
175 {
176 	const struct device *port;
177 	int val_expected;
178 	int ret;
179 
180 	const int test_vector[] = {
181 		1, 2, 3, 0, 4, 0, 0, 0, 17, INT_MAX, INT_MIN, 0
182 	};
183 
184 	port = DEVICE_DT_GET(TEST_NODE);
185 	zassert_true(device_is_ready(port), "GPIO dev is not ready");
186 
187 	TC_PRINT("Running test on port=%s, pin=%d\n", port->name, TEST_PIN);
188 
189 	ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
190 	if (ret == -ENOTSUP) {
191 		TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
192 		ztest_test_skip();
193 		return;
194 	}
195 	zassert_equal(ret, 0, "Failed to configure the pin");
196 
197 	for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
198 		pin_set_and_verify(port, TEST_PIN, test_vector[i], i);
199 
200 		val_expected = test_vector[i] != 0 ? 1 : 0;
201 
202 		pin_get_and_verify(port, TEST_PIN, val_expected, i);
203 	}
204 }
205 
206 /** @brief Verify GPIO_ACTIVE_HIGH flag.
207  *
208  * - Verify that there is no functional difference between gpio_pin_set_raw and
209  *   gpio_pin_set functions if the pin is configured as Active High.
210  * - Verify that there is no functional difference between gpio_pin_get_raw and
211  *   gpio_pin_get functions if the pin is configured as Active High.
212  */
ZTEST(gpio_api_1pin_pin,test_gpio_pin_set_get_active_high)213 ZTEST(gpio_api_1pin_pin, test_gpio_pin_set_get_active_high)
214 {
215 	const struct device *port;
216 	int val_expected;
217 	int ret;
218 
219 	const int test_vector[] = {0, 2, 0, 9, -1, 0, 0, 1, INT_MAX, INT_MIN};
220 
221 	port = DEVICE_DT_GET(TEST_NODE);
222 	zassert_true(device_is_ready(port), "GPIO dev is not ready");
223 
224 	TC_PRINT("Running test on port=%s, pin=%d\n", port->name, TEST_PIN);
225 
226 	ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT |
227 				 GPIO_ACTIVE_HIGH);
228 	if (ret == -ENOTSUP) {
229 		TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
230 		ztest_test_skip();
231 		return;
232 	}
233 	zassert_equal(ret, 0, "Failed to configure the pin");
234 
235 	TC_PRINT("Step 1: Set logical, get logical and physical pin value\n");
236 	for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
237 		pin_set_and_verify(port, TEST_PIN, test_vector[i], i);
238 
239 		val_expected = test_vector[i] != 0 ? 1 : 0;
240 
241 		pin_get_and_verify(port, TEST_PIN, val_expected, i);
242 		pin_get_raw_and_verify(port, TEST_PIN, val_expected, i);
243 	}
244 
245 	TC_PRINT("Step 2: Set physical, get logical and physical pin value\n");
246 	for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
247 		pin_set_raw_and_verify(port, TEST_PIN, test_vector[i], i);
248 
249 		val_expected = test_vector[i] != 0 ? 1 : 0;
250 
251 		pin_get_and_verify(port, TEST_PIN, val_expected, i);
252 		pin_get_raw_and_verify(port, TEST_PIN, val_expected, i);
253 	}
254 }
255 
256 /** @brief Verify GPIO_ACTIVE_LOW flag.
257  *
258  * - Verify that value set by gpio_pin_set function is inverted compared to
259  *   gpio_pin_set_raw if the pin is configured as Active Low.
260  * - Verify that value read by gpio_pin_get function is inverted compared to
261  *   gpio_pin_get_raw if the pin is configured as Active Low.
262  */
ZTEST(gpio_api_1pin_pin,test_gpio_pin_set_get_active_low)263 ZTEST(gpio_api_1pin_pin, test_gpio_pin_set_get_active_low)
264 {
265 	const struct device *port;
266 	int val_expected, val_raw_expected;
267 	int ret;
268 
269 	const int test_vector[] = {0, 4, 0, 0, 1, 8, -3, -12, 0};
270 
271 	port = DEVICE_DT_GET(TEST_NODE);
272 	zassert_true(device_is_ready(port), "GPIO dev is not ready");
273 
274 	TC_PRINT("Running test on port=%s, pin=%d\n", port->name, TEST_PIN);
275 
276 	ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT |
277 				 GPIO_ACTIVE_LOW);
278 	if (ret == -ENOTSUP) {
279 		TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
280 		ztest_test_skip();
281 		return;
282 	}
283 	zassert_equal(ret, 0, "Failed to configure the pin");
284 
285 	TC_PRINT("Step 1: Set logical, get logical and physical pin value\n");
286 	for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
287 		pin_set_and_verify(port, TEST_PIN, test_vector[i], i);
288 
289 		val_expected = (test_vector[i] != 0) ? 1 : 0;
290 		val_raw_expected = (val_expected != 0) ? 0 : 1;
291 
292 		pin_get_and_verify(port, TEST_PIN, val_expected, i);
293 		pin_get_raw_and_verify(port, TEST_PIN, val_raw_expected, i);
294 	}
295 
296 	TC_PRINT("Step 2: Set physical, get logical and physical pin value\n");
297 	for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
298 		pin_set_raw_and_verify(port, TEST_PIN, test_vector[i], i);
299 
300 		val_expected = (test_vector[i] != 0) ? 0 : 1;
301 		val_raw_expected = (val_expected != 0) ? 0 : 1;
302 
303 		pin_get_and_verify(port, TEST_PIN, val_expected, i);
304 		pin_get_raw_and_verify(port, TEST_PIN, val_raw_expected, i);
305 	}
306 }
307 
308 ZTEST_SUITE(gpio_api_1pin_pin, NULL, NULL, NULL, NULL, NULL);
309