1 /*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7
8 #include "test_gpio.h"
9
10 static struct drv_data cb_data[2];
11 static int cb_cnt[2];
12
callback_1(const struct device * dev,struct gpio_callback * gpio_cb,uint32_t pins)13 static void callback_1(const struct device *dev,
14 struct gpio_callback *gpio_cb, uint32_t pins)
15 {
16 TC_PRINT("%s triggered: %d\n", __func__, ++cb_cnt[0]);
17
18 }
19
callback_2(const struct device * dev,struct gpio_callback * gpio_cb,uint32_t pins)20 static void callback_2(const struct device *dev,
21 struct gpio_callback *gpio_cb, uint32_t pins)
22 {
23 TC_PRINT("%s triggered: %d\n", __func__, ++cb_cnt[1]);
24 }
25
callback_remove_self(const struct device * dev,struct gpio_callback * gpio_cb,uint32_t pins)26 static void callback_remove_self(const struct device *dev,
27 struct gpio_callback *gpio_cb, uint32_t pins)
28 {
29 struct drv_data *dd = CONTAINER_OF(gpio_cb, struct drv_data, gpio_cb);
30
31 TC_PRINT("%s triggered: %d\n", __func__, ++cb_cnt[1]);
32 dd->aux = gpio_remove_callback(dev, gpio_cb);
33 }
34
init_callback(const struct device * dev,gpio_callback_handler_t handler_1,gpio_callback_handler_t handler_2)35 static int init_callback(const struct device *dev,
36 gpio_callback_handler_t handler_1,
37 gpio_callback_handler_t handler_2)
38 {
39 int rc = gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_DISABLE);
40
41 if (rc == 0) {
42 rc = gpio_pin_interrupt_configure(dev, PIN_OUT, GPIO_INT_DISABLE);
43 }
44 if (rc == 0) {
45 /* 1. set PIN_OUT */
46 rc = gpio_pin_configure(dev, PIN_OUT, (GPIO_OUTPUT_LOW | PIN_OUT_FLAGS));
47 }
48
49 if (rc == 0) {
50 /* 2. configure PIN_IN callback, but don't enable */
51 rc = gpio_pin_configure(dev, PIN_IN, (GPIO_INPUT | PIN_IN_FLAGS));
52 }
53
54 if (rc == 0) {
55 gpio_init_callback(&cb_data[0].gpio_cb, handler_1, BIT(PIN_IN));
56 rc = gpio_add_callback(dev, &cb_data[0].gpio_cb);
57 }
58
59 if (rc == 0) {
60 gpio_init_callback(&cb_data[1].gpio_cb, handler_2, BIT(PIN_IN));
61 rc = gpio_add_callback(dev, &cb_data[1].gpio_cb);
62 }
63
64 return rc;
65 }
66
trigger_callback(const struct device * dev,int enable_cb)67 static void trigger_callback(const struct device *dev, int enable_cb)
68 {
69 gpio_pin_set(dev, PIN_OUT, 0);
70 k_sleep(K_MSEC(100));
71
72 cb_cnt[0] = 0;
73 cb_cnt[1] = 0;
74 if (enable_cb == 1) {
75 gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_EDGE_RISING);
76 } else {
77 gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_DISABLE);
78 }
79 k_sleep(K_MSEC(100));
80 gpio_pin_set(dev, PIN_OUT, 1);
81 k_sleep(K_MSEC(1000));
82 }
83
test_callback_add_remove(void)84 static int test_callback_add_remove(void)
85 {
86 const struct device *const dev = DEVICE_DT_GET(DEV);
87
88 /* SetUp: initialize environment */
89 int rc = init_callback(dev, callback_1, callback_2);
90
91 if (rc == -ENOTSUP) {
92 TC_PRINT("%s not supported\n", __func__);
93 return TC_PASS;
94 }
95 zassert_equal(rc, 0,
96 "init_callback failed");
97
98 /* 3. enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
99 trigger_callback(dev, 1);
100 /*= checkpoint: check callback is triggered =*/
101 if (cb_cnt[0] != 1 || cb_cnt[1] != 1) {
102 TC_ERROR("not trigger callback correctly\n");
103 goto err_exit;
104 }
105
106 /* 4. remove callback_1 */
107 gpio_remove_callback(dev, &cb_data[0].gpio_cb);
108 trigger_callback(dev, 1);
109
110 /*= checkpoint: check callback is triggered =*/
111 if (cb_cnt[0] != 0 || cb_cnt[1] != 1) {
112 TC_ERROR("not trigger callback correctly\n");
113 goto err_exit;
114 }
115
116 /* 5. remove callback_2 */
117 gpio_remove_callback(dev, &cb_data[1].gpio_cb);
118 trigger_callback(dev, 1);
119 /*= checkpoint: check callback is triggered =*/
120 if (cb_cnt[0] != 0 || cb_cnt[1] != 0) {
121 TC_ERROR("not trigger callback correctly\n");
122 goto err_exit;
123 }
124 return TC_PASS;
125
126 err_exit:
127 gpio_remove_callback(dev, &cb_data[0].gpio_cb);
128 gpio_remove_callback(dev, &cb_data[1].gpio_cb);
129 return TC_FAIL;
130 }
131
test_callback_self_remove(void)132 static int test_callback_self_remove(void)
133 {
134 int res = TC_FAIL;
135 const struct device *const dev = DEVICE_DT_GET(DEV);
136
137 /* SetUp: initialize environment */
138 int rc = init_callback(dev, callback_1, callback_remove_self);
139
140 if (rc == -ENOTSUP) {
141 TC_PRINT("%s not supported\n", __func__);
142 return TC_PASS;
143 }
144 zassert_equal(rc, 0,
145 "init_callback failed");
146
147 gpio_pin_set(dev, PIN_OUT, 0);
148 k_sleep(K_MSEC(100));
149
150 cb_data[0].aux = INT_MAX;
151 cb_data[1].aux = INT_MAX;
152
153 /* 3. enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
154 trigger_callback(dev, 1);
155
156 /*= checkpoint: check both callbacks are triggered =*/
157 if (cb_cnt[0] != 1 || cb_cnt[1] != 1) {
158 TC_ERROR("not trigger callback correctly\n");
159 goto err_exit;
160 }
161
162 /*= checkpoint: check remove executed is invoked =*/
163 if (cb_data[0].aux != INT_MAX || cb_data[1].aux != 0) {
164 TC_ERROR("not remove callback correctly\n");
165 goto err_exit;
166 }
167
168 /* 4 enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
169 trigger_callback(dev, 1);
170
171 /*= checkpoint: check only remaining callback is triggered =*/
172 if (cb_cnt[0] != 1 || cb_cnt[1] != 0) {
173 TC_ERROR("not trigger remaining callback correctly\n");
174 goto err_exit;
175 }
176
177 res = TC_PASS;
178
179 err_exit:
180 gpio_remove_callback(dev, &cb_data[0].gpio_cb);
181 gpio_remove_callback(dev, &cb_data[1].gpio_cb);
182 return res;
183 }
184
test_callback_enable_disable(void)185 static int test_callback_enable_disable(void)
186 {
187 const struct device *const dev = DEVICE_DT_GET(DEV);
188
189 /* SetUp: initialize environment */
190 int rc = init_callback(dev, callback_1, callback_2);
191
192 if (rc == -ENOTSUP) {
193 TC_PRINT("%s not supported\n", __func__);
194 return TC_PASS;
195 }
196 zassert_equal(rc, 0,
197 "init_callback failed");
198
199 /* 3. enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
200 trigger_callback(dev, 1);
201 /*= checkpoint: check callback is triggered =*/
202 if (cb_cnt[0] != 1 || cb_cnt[1] != 1) {
203 TC_ERROR("not trigger callback correctly\n");
204 goto err_exit;
205 }
206
207 /* 4. disable callback */
208 trigger_callback(dev, 0);
209 /*= checkpoint: check callback is triggered =*/
210 if (cb_cnt[0] != 0 || cb_cnt[1] != 0) {
211 TC_ERROR("not trigger callback correctly\n");
212 goto err_exit;
213 }
214
215 /* 5. enable callback again */
216 trigger_callback(dev, 1);
217 /*= checkpoint: check callback is triggered =*/
218 if (cb_cnt[0] != 1 || cb_cnt[1] != 1) {
219 TC_ERROR("not trigger callback correctly\n");
220 goto err_exit;
221 }
222 gpio_remove_callback(dev, &cb_data[0].gpio_cb);
223 gpio_remove_callback(dev, &cb_data[1].gpio_cb);
224 return TC_PASS;
225
226 err_exit:
227 gpio_remove_callback(dev, &cb_data[0].gpio_cb);
228 gpio_remove_callback(dev, &cb_data[1].gpio_cb);
229 return TC_FAIL;
230 }
231
ZTEST(gpio_port_cb_mgmt,test_gpio_callback_add_remove)232 ZTEST(gpio_port_cb_mgmt, test_gpio_callback_add_remove)
233 {
234 zassert_equal(test_callback_add_remove(), TC_PASS,
235 NULL);
236 }
237
ZTEST(gpio_port_cb_mgmt,test_gpio_callback_self_remove)238 ZTEST(gpio_port_cb_mgmt, test_gpio_callback_self_remove)
239 {
240 zassert_equal(test_callback_self_remove(), TC_PASS,
241 NULL);
242 }
243
ZTEST(gpio_port_cb_mgmt,test_gpio_callback_enable_disable)244 ZTEST(gpio_port_cb_mgmt, test_gpio_callback_enable_disable)
245 {
246 zassert_equal(test_callback_enable_disable(), TC_PASS,
247 NULL);
248 }
249