Skip to content

Commit b7648f8

Browse files
bjarki-andreasennashif
authored andcommitted
drivers: comparator: add shell
Add shell for comparator device drivers. Signed-off-by: Bjarki Arge Andreasen <[email protected]>
1 parent 6ed855a commit b7648f8

File tree

4 files changed

+302
-0
lines changed

4 files changed

+302
-0
lines changed

drivers/comparator/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ zephyr_library_sources_ifdef(CONFIG_USERSPACE comparator_handlers.c)
99
zephyr_library_sources_ifdef(CONFIG_COMPARATOR_MCUX_ACMP comparator_mcux_acmp.c)
1010
zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_COMP comparator_nrf_comp.c)
1111
zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_LPCOMP comparator_nrf_lpcomp.c)
12+
zephyr_library_sources_ifdef(CONFIG_COMPARATOR_SHELL comparator_shell.c)

drivers/comparator/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ config COMPARATOR_INIT_PRIORITY
2121
rsource "Kconfig.mcux_acmp"
2222
rsource "Kconfig.nrf_comp"
2323
rsource "Kconfig.nrf_lpcomp"
24+
rsource "Kconfig.shell"
2425

2526
endif # COMPARATOR

drivers/comparator/Kconfig.shell

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright (c) 2024 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config COMPARATOR_SHELL
5+
bool "Comparator shell"
6+
default y
7+
depends on SHELL
8+
help
9+
Comparator device driver shell.
10+
11+
if COMPARATOR_SHELL
12+
13+
config COMPARATOR_SHELL_AWAIT_TRIGGER_DEFAULT_TIMEOUT
14+
int "Default timeout for await_trigger command in seconds"
15+
default 10
16+
17+
config COMPARATOR_SHELL_AWAIT_TRIGGER_MAX_TIMEOUT
18+
int "Max timeout for await_trigger command in seconds"
19+
default 60
20+
21+
endif # COMPARATOR_SHELL

drivers/comparator/comparator_shell.c

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/drivers/comparator.h>
8+
#include <zephyr/shell/shell.h>
9+
#include <zephyr/kernel.h>
10+
11+
#include <stdlib.h>
12+
13+
#define AWAIT_TRIGGER_DEFAULT_TIMEOUT \
14+
CONFIG_COMPARATOR_SHELL_AWAIT_TRIGGER_DEFAULT_TIMEOUT
15+
16+
#define AWAIT_TRIGGER_MAX_TIMEOUT \
17+
CONFIG_COMPARATOR_SHELL_AWAIT_TRIGGER_MAX_TIMEOUT
18+
19+
/* Mapped 1-1 to enum comparator_trigger */
20+
static const char *const trigger_lookup[] = {
21+
"NONE",
22+
"RISING_EDGE",
23+
"FALLING_EDGE",
24+
"BOTH_EDGES",
25+
};
26+
27+
static K_SEM_DEFINE(triggered_sem, 0, 1);
28+
29+
static int get_device_from_str(const struct shell *sh,
30+
const char *dev_str,
31+
const struct device **dev)
32+
{
33+
*dev = device_get_binding(dev_str);
34+
35+
if (*dev == NULL) {
36+
shell_error(sh, "%s not %s", dev_str, "found");
37+
return -ENODEV;
38+
}
39+
40+
if (!device_is_ready(*dev)) {
41+
shell_error(sh, "%s not %s", dev_str, "ready");
42+
return -ENODEV;
43+
}
44+
45+
return 0;
46+
}
47+
48+
static int cmd_get_output(const struct shell *sh, size_t argc, char **argv)
49+
{
50+
int ret;
51+
const char *dev_str;
52+
const struct device *dev;
53+
54+
ARG_UNUSED(argc);
55+
56+
dev_str = argv[1];
57+
ret = get_device_from_str(sh, dev_str, &dev);
58+
if (ret < 0) {
59+
return ret;
60+
}
61+
62+
ret = comparator_get_output(dev);
63+
if (ret < 0) {
64+
shell_error(sh, "failed to %s %s", "get", "output");
65+
return -EIO;
66+
}
67+
68+
shell_print(sh, "%i", ret);
69+
return 0;
70+
}
71+
72+
static int get_trigger_from_str(const struct shell *sh,
73+
const char *trigger_str,
74+
enum comparator_trigger *trigger)
75+
{
76+
ARRAY_FOR_EACH(trigger_lookup, i) {
77+
if (strcmp(trigger_lookup[i], trigger_str) == 0) {
78+
*trigger = (enum comparator_trigger)i;
79+
return 0;
80+
}
81+
}
82+
83+
shell_error(sh, "%s not %s", trigger_str, "valid");
84+
return -EINVAL;
85+
}
86+
87+
static int cmd_set_trigger(const struct shell *sh, size_t argc, char **argv)
88+
{
89+
const char *dev_str;
90+
const char *trigger_str;
91+
int ret;
92+
const struct device *dev;
93+
enum comparator_trigger trigger;
94+
95+
ARG_UNUSED(argc);
96+
97+
dev_str = argv[1];
98+
ret = get_device_from_str(sh, dev_str, &dev);
99+
if (ret < 0) {
100+
return ret;
101+
}
102+
103+
trigger_str = argv[2];
104+
ret = get_trigger_from_str(sh, trigger_str, &trigger);
105+
if (ret < 0) {
106+
return ret;
107+
}
108+
109+
ret = comparator_set_trigger(dev, trigger);
110+
if (ret < 0) {
111+
shell_error(sh, "failed to %s %s", "set", "trigger");
112+
return -EIO;
113+
}
114+
115+
return 0;
116+
}
117+
118+
static int get_timeout_from_str(const struct shell *sh,
119+
const char *timeout_str,
120+
k_timeout_t *timeout)
121+
{
122+
long seconds;
123+
char *end;
124+
125+
seconds = strtol(timeout_str, &end, 10);
126+
if ((*end != '\0') ||
127+
(seconds < 1) ||
128+
(seconds > AWAIT_TRIGGER_MAX_TIMEOUT)) {
129+
shell_error(sh, "%s not %s", timeout_str, "valid");
130+
return -EINVAL;
131+
}
132+
133+
*timeout = K_SECONDS(seconds);
134+
return 0;
135+
}
136+
137+
static void trigger_cb(const struct device *dev, void *user_data)
138+
{
139+
ARG_UNUSED(dev);
140+
ARG_UNUSED(user_data);
141+
142+
k_sem_give(&triggered_sem);
143+
}
144+
145+
static int cmd_await_trigger(const struct shell *sh, size_t argc, char **argv)
146+
{
147+
const char *dev_str;
148+
const char *timeout_str;
149+
int ret;
150+
const struct device *dev;
151+
k_timeout_t timeout;
152+
153+
dev_str = argv[1];
154+
ret = get_device_from_str(sh, dev_str, &dev);
155+
if (ret < 0) {
156+
return ret;
157+
}
158+
159+
if (argc == 3) {
160+
timeout_str = argv[2];
161+
ret = get_timeout_from_str(sh, timeout_str, &timeout);
162+
if (ret < 0) {
163+
return ret;
164+
}
165+
} else {
166+
timeout = K_SECONDS(AWAIT_TRIGGER_DEFAULT_TIMEOUT);
167+
}
168+
169+
k_sem_reset(&triggered_sem);
170+
171+
ret = comparator_set_trigger_callback(dev, trigger_cb, NULL);
172+
if (ret < 0) {
173+
shell_error(sh, "failed to %s %s", "set", "trigger callback");
174+
return -EIO;
175+
}
176+
177+
ret = k_sem_take(&triggered_sem, timeout);
178+
if (ret == 0) {
179+
shell_print(sh, "triggered");
180+
} else if (ret == -EAGAIN) {
181+
shell_print(sh, "timed out");
182+
} else {
183+
shell_error(sh, "internal error");
184+
}
185+
186+
ret = comparator_set_trigger_callback(dev, NULL, NULL);
187+
if (ret < 0) {
188+
shell_error(sh, "failed to %s %s", "clear", "trigger callback");
189+
return -EIO;
190+
}
191+
192+
return 0;
193+
}
194+
195+
static int cmd_trigger_is_pending(const struct shell *sh, size_t argc, char **argv)
196+
{
197+
int ret;
198+
const char *dev_str;
199+
const struct device *dev;
200+
201+
ARG_UNUSED(argc);
202+
203+
dev_str = argv[1];
204+
ret = get_device_from_str(sh, dev_str, &dev);
205+
if (ret < 0) {
206+
return ret;
207+
}
208+
209+
ret = comparator_trigger_is_pending(dev);
210+
if (ret < 0) {
211+
shell_error(sh, "failed to %s %s", "get", "trigger status");
212+
return -EIO;
213+
}
214+
215+
shell_print(sh, "%i", ret);
216+
return 0;
217+
}
218+
219+
static void dsub_set_trigger_lookup_1(size_t idx, struct shell_static_entry *entry)
220+
{
221+
entry->syntax = (idx < ARRAY_SIZE(trigger_lookup)) ? trigger_lookup[idx] : NULL;
222+
entry->handler = NULL;
223+
entry->help = NULL;
224+
entry->subcmd = NULL;
225+
}
226+
227+
SHELL_DYNAMIC_CMD_CREATE(dsub_set_trigger_1, dsub_set_trigger_lookup_1);
228+
229+
static void dsub_set_trigger_lookup_0(size_t idx, struct shell_static_entry *entry)
230+
{
231+
const struct device *dev = shell_device_lookup(idx, NULL);
232+
233+
entry->syntax = dev != NULL ? dev->name : NULL;
234+
entry->handler = NULL;
235+
entry->help = NULL;
236+
entry->subcmd = &dsub_set_trigger_1;
237+
}
238+
239+
SHELL_DYNAMIC_CMD_CREATE(dsub_set_trigger_0, dsub_set_trigger_lookup_0);
240+
241+
static void dsub_device_lookup_0(size_t idx, struct shell_static_entry *entry)
242+
{
243+
const struct device *dev = shell_device_lookup(idx, NULL);
244+
245+
entry->syntax = (dev != NULL) ? dev->name : NULL;
246+
entry->handler = NULL;
247+
entry->help = NULL;
248+
entry->subcmd = NULL;
249+
}
250+
251+
SHELL_DYNAMIC_CMD_CREATE(dsub_device_0, dsub_device_lookup_0);
252+
253+
#define GET_OUTPUT_HELP \
254+
("comp get_output <device>")
255+
256+
#define SET_TRIGGER_HELP \
257+
("comp set_trigger <device> <NONE | RISING_EDGE | FALLING_EDGE | BOTH_EDGES>")
258+
259+
#define AWAIT_TRIGGER_HELP \
260+
("comp await_trigger <device> [timeout] (default " \
261+
STRINGIFY(AWAIT_TRIGGER_DEFAULT_TIMEOUT) \
262+
"s, max " \
263+
STRINGIFY(AWAIT_TRIGGER_MAX_TIMEOUT) \
264+
"s)")
265+
266+
#define TRIGGER_PENDING_HELP \
267+
("comp trigger_is_pending <device>")
268+
269+
SHELL_STATIC_SUBCMD_SET_CREATE(
270+
sub_comp,
271+
SHELL_CMD_ARG(get_output, &dsub_device_0, GET_OUTPUT_HELP, cmd_get_output, 2, 0),
272+
SHELL_CMD_ARG(set_trigger, &dsub_set_trigger_0, SET_TRIGGER_HELP, cmd_set_trigger, 3, 0),
273+
SHELL_CMD_ARG(await_trigger, &dsub_device_0, AWAIT_TRIGGER_HELP, cmd_await_trigger, 2, 1),
274+
SHELL_CMD_ARG(trigger_is_pending, &dsub_device_0, TRIGGER_PENDING_HELP,
275+
cmd_trigger_is_pending, 2, 1),
276+
SHELL_SUBCMD_SET_END
277+
);
278+
279+
SHELL_CMD_REGISTER(comp, &sub_comp, "Comparator device commands", NULL);

0 commit comments

Comments
 (0)