Skip to content

Commit 10a3384

Browse files
maciejbaczmanskirlubos
authored andcommitted
[nrf fromtree] net: openthread: add gpio diag command implementation
implemented ot diag gpio get, set and mode commands Signed-off-by: Maciej Baczmanski <[email protected]> (cherry picked from commit bf10d0d)
1 parent 45717cd commit 10a3384

File tree

2 files changed

+180
-0
lines changed

2 files changed

+180
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright (c) 2023 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: |
5+
OpenThread configuration node.
6+
7+
Example usage:
8+
options {
9+
openthread {
10+
compatible = "openthread,config";
11+
diag-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>,
12+
<&gpio1 0 GPIO_ACTIVE_LOW>;
13+
};
14+
};
15+
16+
compatible: "openthread,config"
17+
18+
properties:
19+
diag-gpios:
20+
type: phandle-array
21+
description: |
22+
This enables access to diagnostic GPIO pins. Each field consists of
23+
GPIO pin's configuration: controller's phandle, pin number and configuration flags.

modules/openthread/platform/diag.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
*/
66

77
#include <zephyr/kernel.h>
8+
#include <zephyr/drivers/gpio.h>
9+
810
#include <openthread/platform/diag.h>
911

1012
#include "platform-zephyr.h"
13+
#include "utils/code_utils.h"
1114

1215
/**
1316
* Diagnostics mode variables.
@@ -68,3 +71,157 @@ void otPlatDiagAlarmCallback(otInstance *aInstance)
6871
{
6972
ARG_UNUSED(aInstance);
7073
}
74+
75+
/*
76+
* To enable gpio diag commands, in Devicetree create `openthread` node in `/options/` path
77+
* with `compatible = "openthread,config"` property and `diag-gpios` property,
78+
* which should contain array of GPIO pin's configuration properties containing controller phandles,
79+
* pin numbers and pin flags. e.g:
80+
*
81+
* options {
82+
* openthread {
83+
* compatible = "openthread,config";
84+
* diag-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>,
85+
* <&gpio1 0 GPIO_ACTIVE_LOW>;
86+
* };
87+
* };
88+
*
89+
* To enable reading current gpio pin mode, define
90+
* `CONFIG_GPIO_GET_DIRECTION` in prj.conf.
91+
*
92+
* Note: `<gpio>` in `diag gpio` commands is an index of diag-gpios array. For example shown above,
93+
* `ot diag gpio mode 0` will return current mode of pin nmb 0 controlled by `gpio0` controller.
94+
*/
95+
#if DT_HAS_COMPAT_STATUS_OKAY(openthread_config) && \
96+
DT_NODE_HAS_PROP(DT_COMPAT_GET_ANY_STATUS_OKAY(openthread_config), diag_gpios)
97+
98+
static const struct gpio_dt_spec gpio_spec[] = {
99+
DT_FOREACH_PROP_ELEM_SEP(DT_COMPAT_GET_ANY_STATUS_OKAY(openthread_config),
100+
diag_gpios, GPIO_DT_SPEC_GET_BY_IDX, (,))};
101+
102+
static otError gpio_get_spec(uint32_t gpio_idx, const struct gpio_dt_spec **spec)
103+
{
104+
otError error = OT_ERROR_NONE;
105+
106+
otEXPECT_ACTION(gpio_idx < otARRAY_LENGTH(gpio_spec), error = OT_ERROR_INVALID_ARGS);
107+
108+
*spec = &gpio_spec[gpio_idx];
109+
110+
otEXPECT_ACTION(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
111+
otEXPECT_ACTION(gpio_is_ready_dt(*spec), error = OT_ERROR_INVALID_ARGS);
112+
113+
const struct gpio_driver_config *const cfg =
114+
(const struct gpio_driver_config *)((*spec)->port->config);
115+
116+
otEXPECT_ACTION((cfg->port_pin_mask & (gpio_port_pins_t)BIT((*spec)->pin)) != 0U,
117+
error = OT_ERROR_INVALID_ARGS);
118+
119+
exit:
120+
return error;
121+
}
122+
123+
otError otPlatDiagGpioSet(uint32_t aGpio, bool aValue)
124+
{
125+
const struct gpio_dt_spec *spec;
126+
otError error;
127+
int rv;
128+
129+
error = gpio_get_spec(aGpio, &spec);
130+
131+
otEXPECT(error == OT_ERROR_NONE);
132+
133+
#if defined(CONFIG_GPIO_GET_DIRECTION)
134+
rv = gpio_pin_is_output_dt(spec);
135+
otEXPECT_ACTION(rv == 1, error = OT_ERROR_INVALID_STATE);
136+
#endif
137+
138+
rv = gpio_pin_set_dt(spec, (int)aValue);
139+
otEXPECT_ACTION(rv == 0, error = OT_ERROR_FAILED);
140+
141+
exit:
142+
return error;
143+
}
144+
145+
otError otPlatDiagGpioGet(uint32_t aGpio, bool *aValue)
146+
{
147+
const struct gpio_dt_spec *spec;
148+
otError error;
149+
int rv;
150+
151+
error = gpio_get_spec(aGpio, &spec);
152+
153+
otEXPECT(error == OT_ERROR_NONE);
154+
otEXPECT_ACTION(aValue != NULL, error = OT_ERROR_INVALID_ARGS);
155+
156+
#if defined(CONFIG_GPIO_GET_DIRECTION)
157+
rv = gpio_pin_is_input_dt(spec);
158+
otEXPECT_ACTION(rv == 1, error = OT_ERROR_INVALID_STATE);
159+
#endif
160+
161+
rv = gpio_pin_get_dt(spec);
162+
otEXPECT_ACTION(rv >= 0, error = OT_ERROR_FAILED);
163+
*aValue = (bool)rv;
164+
165+
exit:
166+
return error;
167+
}
168+
169+
otError otPlatDiagGpioSetMode(uint32_t aGpio, otGpioMode aMode)
170+
{
171+
const struct gpio_dt_spec *spec;
172+
otError error;
173+
int rv = 0;
174+
175+
error = gpio_get_spec(aGpio, &spec);
176+
177+
otEXPECT(error == OT_ERROR_NONE);
178+
179+
switch (aMode) {
180+
case OT_GPIO_MODE_INPUT:
181+
rv = gpio_pin_configure_dt(spec, GPIO_INPUT);
182+
break;
183+
184+
case OT_GPIO_MODE_OUTPUT:
185+
rv = gpio_pin_configure_dt(spec, GPIO_OUTPUT);
186+
break;
187+
188+
default:
189+
error = OT_ERROR_INVALID_ARGS;
190+
}
191+
192+
otEXPECT_ACTION(rv == 0, error = OT_ERROR_FAILED);
193+
194+
exit:
195+
return error;
196+
}
197+
198+
#if defined(CONFIG_GPIO_GET_DIRECTION)
199+
otError otPlatDiagGpioGetMode(uint32_t aGpio, otGpioMode *aMode)
200+
{
201+
const struct gpio_dt_spec *spec;
202+
otError error;
203+
gpio_port_pins_t pins_in, pins_out;
204+
int rv;
205+
206+
error = gpio_get_spec(aGpio, &spec);
207+
208+
otEXPECT(error == OT_ERROR_NONE);
209+
otEXPECT_ACTION(aMode != NULL, error = OT_ERROR_INVALID_ARGS);
210+
211+
rv = gpio_port_get_direction(spec->port, BIT(spec->pin), &pins_in, &pins_out);
212+
otEXPECT_ACTION(rv >= 0, error = OT_ERROR_FAILED);
213+
214+
if (((gpio_port_pins_t)BIT(spec->pin) & pins_in) != 0U) {
215+
*aMode = OT_GPIO_MODE_INPUT;
216+
} else if (((gpio_port_pins_t)BIT(spec->pin) & pins_out) != 0U) {
217+
*aMode = OT_GPIO_MODE_OUTPUT;
218+
} else {
219+
error = OT_ERROR_FAILED;
220+
}
221+
exit:
222+
return error;
223+
}
224+
#endif /* CONFIG_GPIO_GET_DIRECTION */
225+
#endif /* DT_HAS_COMPAT_STATUS_OKAY(openthread_config) && \
226+
* DT_NODE_HAS_PROP(DT_COMPAT_GET_ANY_STATUS_OKAY(openthread_config), diag_gpios)
227+
*/

0 commit comments

Comments
 (0)