You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
676 lines
17 KiB
676 lines
17 KiB
/* |
|
* Copyright (c) 2018 Intel Corporation |
|
* Copyright (c) 2021 Dennis Ruffer <daruffer@gmail.com> |
|
* Copyright (c) 2023 Nick Ward <nix.ward@gmail.com> |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#include <zephyr/drivers/gpio.h> |
|
#include <zephyr/shell/shell.h> |
|
|
|
#include <stdio.h> |
|
|
|
#define ARGV_DEV 1 |
|
#define ARGV_PIN 2 |
|
#define ARGV_CONF 3 |
|
#define ARGV_VALUE 3 |
|
#define ARGV_VENDOR_SPECIFIC 4 |
|
|
|
#define NGPIOS_UNKNOWN -1 |
|
#define PIN_NOT_FOUND UINT8_MAX |
|
|
|
/* Pin syntax maximum length */ |
|
#define PIN_SYNTAX_MAX 32 |
|
#define PIN_NUM_MAX 4 |
|
|
|
struct gpio_ctrl { |
|
const struct device *dev; |
|
int8_t ngpios; |
|
gpio_port_pins_t reserved_mask; |
|
const char **line_names; |
|
uint8_t line_names_len; |
|
const union shell_cmd_entry *subcmd; |
|
}; |
|
|
|
struct sh_gpio { |
|
const struct device *dev; |
|
gpio_pin_t pin; |
|
}; |
|
/* |
|
* Find idx-th pin reference from the set of non reserved |
|
* pin numbers and provided line names. |
|
*/ |
|
static void port_pin_get(gpio_port_pins_t reserved_mask, const char **line_names, |
|
uint8_t line_names_len, size_t idx, struct shell_static_entry *entry) |
|
{ |
|
static char pin_syntax[PIN_SYNTAX_MAX]; |
|
static char pin_num[PIN_NUM_MAX]; |
|
const char *name; |
|
gpio_pin_t pin; |
|
bool reserved; |
|
|
|
entry->handler = NULL; |
|
|
|
/* Find allowed numeric pin reference */ |
|
for (pin = 0; pin < GPIO_MAX_PINS_PER_PORT; pin++) { |
|
reserved = ((BIT64(pin) & reserved_mask) != 0); |
|
if (!reserved) { |
|
if (idx == 0) { |
|
break; |
|
} |
|
idx--; |
|
} |
|
} |
|
|
|
if (pin < GPIO_MAX_PINS_PER_PORT) { |
|
sprintf(pin_num, "%u", pin); |
|
if ((pin < line_names_len) && (strlen(line_names[pin]) > 0)) { |
|
/* pin can be specified by line name */ |
|
name = line_names[pin]; |
|
for (int i = 0; i < (sizeof(pin_syntax) - 1); i++) { |
|
/* |
|
* For line-name tab completion to work replace any |
|
* space characters with '_'. |
|
*/ |
|
pin_syntax[i] = (name[i] != ' ') ? name[i] : '_'; |
|
if (name[i] == '\0') { |
|
break; |
|
} |
|
} |
|
pin_syntax[sizeof(pin_syntax) - 1] = '\0'; |
|
entry->syntax = pin_syntax; |
|
entry->help = pin_num; |
|
} else { |
|
/* fallback to pin specified by pin number */ |
|
entry->syntax = pin_num; |
|
entry->help = NULL; |
|
} |
|
} else { |
|
/* No more pins */ |
|
entry->syntax = NULL; |
|
entry->help = NULL; |
|
} |
|
} |
|
|
|
#define GPIO_DT_RESERVED_RANGES_NGPIOS_SHELL(node_id) \ |
|
COND_CODE_1(DT_NODE_HAS_PROP(node_id, ngpios), \ |
|
(GPIO_DT_RESERVED_RANGES_NGPIOS(node_id, DT_PROP(node_id, ngpios))), \ |
|
(GPIO_MAX_PINS_PER_PORT)) |
|
|
|
#define GPIO_CTRL_PIN_GET_FN(node_id) \ |
|
static const char *node_id##line_names[] = DT_PROP_OR(node_id, gpio_line_names, {NULL}); \ |
|
\ |
|
static void node_id##cmd_gpio_pin_get(size_t idx, struct shell_static_entry *entry) \ |
|
{ \ |
|
gpio_port_pins_t reserved_mask = GPIO_DT_RESERVED_RANGES_NGPIOS_SHELL(node_id); \ |
|
uint8_t line_names_len = DT_PROP_LEN_OR(node_id, gpio_line_names, 0); \ |
|
\ |
|
port_pin_get(reserved_mask, node_id##line_names, line_names_len, idx, entry); \ |
|
entry->subcmd = NULL; \ |
|
} \ |
|
\ |
|
SHELL_DYNAMIC_CMD_CREATE(node_id##sub_gpio_pin, node_id##cmd_gpio_pin_get); |
|
|
|
#define IS_GPIO_CTRL_PIN_GET(node_id) \ |
|
COND_CODE_1(DT_PROP(node_id, gpio_controller), (GPIO_CTRL_PIN_GET_FN(node_id)), ()) |
|
|
|
DT_FOREACH_STATUS_OKAY_NODE(IS_GPIO_CTRL_PIN_GET) |
|
|
|
#define GPIO_CTRL_LIST_ENTRY(node_id) \ |
|
{ \ |
|
.dev = DEVICE_DT_GET(node_id), \ |
|
.ngpios = DT_PROP_OR(node_id, ngpios, NGPIOS_UNKNOWN), \ |
|
.reserved_mask = GPIO_DT_RESERVED_RANGES_NGPIOS_SHELL(node_id), \ |
|
.line_names = node_id##line_names, \ |
|
.line_names_len = DT_PROP_LEN_OR(node_id, gpio_line_names, 0), \ |
|
.subcmd = &node_id##sub_gpio_pin, \ |
|
}, |
|
|
|
#define IS_GPIO_CTRL_LIST(node_id) \ |
|
COND_CODE_1(DT_PROP(node_id, gpio_controller), (GPIO_CTRL_LIST_ENTRY(node_id)), ()) |
|
|
|
static const struct gpio_ctrl gpio_list[] = {DT_FOREACH_STATUS_OKAY_NODE(IS_GPIO_CTRL_LIST)}; |
|
|
|
static const struct gpio_ctrl *get_gpio_ctrl(const char *name) |
|
{ |
|
size_t i; |
|
const struct device *dev = shell_device_get_binding(name); |
|
|
|
if (dev == NULL) { |
|
return NULL; |
|
} |
|
|
|
for (i = 0; i < ARRAY_SIZE(gpio_list); i++) { |
|
if (gpio_list[i].dev == dev) { |
|
return &gpio_list[i]; |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
static int line_cmp(const char *input, const char *line_name) |
|
{ |
|
int i = 0; |
|
|
|
while (true) { |
|
if ((input[i] == '_') && (line_name[i] == ' ')) { |
|
/* Allow input underscore to match line_name space */ |
|
} else if (input[i] != line_name[i]) { |
|
return (input[i] > line_name[i]) ? 1 : -1; |
|
} else if (line_name[i] == '\0') { |
|
return 0; |
|
} |
|
i++; |
|
} |
|
} |
|
|
|
static int get_gpio_pin(const struct shell *sh, const struct gpio_ctrl *ctrl, char *line_name) |
|
{ |
|
gpio_pin_t pin = PIN_NOT_FOUND; |
|
gpio_pin_t i; |
|
int result; |
|
|
|
for (i = 0; i < ctrl->ngpios && i < ctrl->line_names_len; i++) { |
|
result = line_cmp(line_name, ctrl->line_names[i]); |
|
if (result == 0) { |
|
if ((BIT64(i) & ctrl->reserved_mask) != 0) { |
|
shell_error(sh, "Reserved pin"); |
|
return -EACCES; |
|
} else if (pin == PIN_NOT_FOUND) { |
|
pin = i; |
|
} else { |
|
shell_error(sh, "Line name ambiguous"); |
|
return -EFAULT; |
|
} |
|
} |
|
} |
|
|
|
if (pin == PIN_NOT_FOUND) { |
|
shell_error(sh, "Line name not found: '%s'", line_name); |
|
return -ENOENT; |
|
} |
|
|
|
return pin; |
|
} |
|
|
|
static int get_sh_gpio(const struct shell *sh, char **argv, struct sh_gpio *gpio) |
|
{ |
|
const struct gpio_ctrl *ctrl; |
|
int ret = 0; |
|
int pin; |
|
|
|
ctrl = get_gpio_ctrl(argv[ARGV_DEV]); |
|
if (ctrl == NULL) { |
|
shell_error(sh, "unknown gpio controller: %s", argv[ARGV_DEV]); |
|
return -EINVAL; |
|
} |
|
gpio->dev = ctrl->dev; |
|
pin = shell_strtoul(argv[ARGV_PIN], 0, &ret); |
|
if (ret != 0) { |
|
pin = get_gpio_pin(sh, ctrl, argv[ARGV_PIN]); |
|
if (pin < 0) { |
|
return pin; |
|
} |
|
} else if ((BIT64(pin) & ctrl->reserved_mask) != 0) { |
|
shell_error(sh, "Reserved pin"); |
|
return -EACCES; |
|
} |
|
gpio->pin = pin; |
|
|
|
return 0; |
|
} |
|
|
|
static int cmd_gpio_conf(const struct shell *sh, size_t argc, char **argv) |
|
{ |
|
gpio_flags_t flags = 0; |
|
gpio_flags_t vendor_specific; |
|
struct sh_gpio gpio; |
|
int ret; |
|
size_t len; |
|
|
|
ret = get_sh_gpio(sh, argv, &gpio); |
|
if (ret != 0) { |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
|
|
len = strlen(argv[ARGV_CONF]); |
|
for (int i = 0; i < len; i++) { |
|
switch (argv[ARGV_CONF][i]) { |
|
case 'i': |
|
flags |= GPIO_INPUT; |
|
break; |
|
case 'o': |
|
flags |= GPIO_OUTPUT; |
|
break; |
|
case 'u': |
|
flags |= GPIO_PULL_UP; |
|
break; |
|
case 'd': |
|
flags |= GPIO_PULL_DOWN; |
|
break; |
|
case 'h': |
|
flags |= GPIO_ACTIVE_HIGH; |
|
break; |
|
case 'l': |
|
flags |= GPIO_ACTIVE_LOW; |
|
break; |
|
case '0': |
|
flags |= GPIO_OUTPUT_INIT_LOGICAL | GPIO_OUTPUT_INIT_LOW; |
|
break; |
|
case '1': |
|
flags |= GPIO_OUTPUT_INIT_LOGICAL | GPIO_OUTPUT_INIT_HIGH; |
|
break; |
|
default: |
|
shell_error(sh, "Unknown: '%c'", argv[ARGV_CONF][i]); |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
} |
|
|
|
if (((flags & GPIO_INPUT) != 0) == ((flags & GPIO_OUTPUT) != 0)) { |
|
shell_error(sh, "must be either input or output"); |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
|
|
if (((flags & GPIO_PULL_UP) != 0) && ((flags & GPIO_PULL_DOWN) != 0)) { |
|
shell_error(sh, "cannot be pull up and pull down"); |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
|
|
if (((flags & GPIO_ACTIVE_LOW) != 0) && ((flags & GPIO_ACTIVE_HIGH) != 0)) { |
|
shell_error(sh, "cannot be active low and active high"); |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
|
|
if ((flags & GPIO_OUTPUT) != 0) { |
|
/* Default to active high if not specified */ |
|
if ((flags & (GPIO_ACTIVE_LOW | GPIO_ACTIVE_HIGH)) == 0) { |
|
flags |= GPIO_ACTIVE_HIGH; |
|
} |
|
/* Default to initialisation to logic 0 if not specified */ |
|
if ((flags & GPIO_OUTPUT_INIT_LOGICAL) == 0) { |
|
flags |= GPIO_OUTPUT_INIT_LOGICAL | GPIO_OUTPUT_INIT_LOW; |
|
} |
|
} |
|
|
|
if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT_INIT_LOGICAL) != 0)) { |
|
shell_error(sh, "an input cannot be initialised to a logic level"); |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
|
|
if (((flags & GPIO_OUTPUT_INIT_LOW) != 0) && ((flags & GPIO_OUTPUT_INIT_HIGH) != 0)) { |
|
shell_error(sh, "cannot initialise to logic 0 and logic 1"); |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
|
|
if (argc == 5) { |
|
vendor_specific = shell_strtoul(argv[ARGV_VENDOR_SPECIFIC], 0, &ret); |
|
if ((ret == 0) && ((vendor_specific & ~(0xFF00U)) == 0)) { |
|
flags |= vendor_specific; |
|
} else { |
|
/* |
|
* See include/zephyr/dt-bindings/gpio/ for the |
|
* available flags for your vendor. |
|
*/ |
|
shell_error(sh, "vendor specific flags must be within " |
|
"the mask 0xFF00"); |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
} |
|
|
|
ret = gpio_pin_configure(gpio.dev, gpio.pin, flags); |
|
if (ret != 0) { |
|
shell_error(sh, "error: %d", ret); |
|
return ret; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static int cmd_gpio_get(const struct shell *sh, size_t argc, char **argv) |
|
{ |
|
struct sh_gpio gpio; |
|
int value; |
|
int ret; |
|
|
|
ret = get_sh_gpio(sh, argv, &gpio); |
|
if (ret != 0) { |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
|
|
value = gpio_pin_get(gpio.dev, gpio.pin); |
|
if (value >= 0) { |
|
shell_print(sh, "%u", value); |
|
} else { |
|
shell_error(sh, "error: %d", value); |
|
return value; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static int cmd_gpio_set(const struct shell *sh, size_t argc, char **argv) |
|
{ |
|
struct sh_gpio gpio; |
|
unsigned long value; |
|
int ret; |
|
|
|
ret = get_sh_gpio(sh, argv, &gpio); |
|
if (ret != 0) { |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
|
|
value = shell_strtoul(argv[ARGV_VALUE], 0, &ret); |
|
if (ret != 0) { |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
|
|
ret = gpio_pin_set(gpio.dev, gpio.pin, value != 0); |
|
if (ret != 0) { |
|
shell_error(sh, "error: %d", ret); |
|
return ret; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static int cmd_gpio_toggle(const struct shell *sh, size_t argc, char **argv) |
|
{ |
|
struct sh_gpio gpio; |
|
int ret; |
|
|
|
ret = get_sh_gpio(sh, argv, &gpio); |
|
if (ret != 0) { |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
|
|
ret = gpio_pin_toggle(gpio.dev, gpio.pin); |
|
if (ret != 0) { |
|
shell_error(sh, "error: %d", ret); |
|
return ret; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static int cmd_gpio_devices(const struct shell *sh, size_t argc, char **argv) |
|
{ |
|
size_t i; |
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "%-16s Other names\n", "Device"); |
|
|
|
for (i = 0; i < ARRAY_SIZE(gpio_list); i++) { |
|
const struct device *dev = gpio_list[i].dev; |
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "%-16s", dev->name); |
|
|
|
#ifdef CONFIG_DEVICE_DT_METADATA |
|
const struct device_dt_nodelabels *nl = device_get_dt_nodelabels(dev); |
|
|
|
if (nl != NULL && nl->num_nodelabels > 0) { |
|
for (size_t j = 0; j < nl->num_nodelabels; j++) { |
|
const char *nodelabel = nl->nodelabels[j]; |
|
|
|
shell_fprintf(sh, SHELL_NORMAL, " %s", nodelabel); |
|
} |
|
} |
|
#endif |
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "\n"); |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
/* 500 msec = 1/2 sec */ |
|
#define SLEEP_TIME_MS 500 |
|
|
|
static int cmd_gpio_blink(const struct shell *sh, size_t argc, char **argv) |
|
{ |
|
bool msg_one_shot = true; |
|
struct sh_gpio gpio; |
|
size_t count; |
|
char data; |
|
int ret; |
|
|
|
ret = get_sh_gpio(sh, argv, &gpio); |
|
if (ret != 0) { |
|
shell_help(sh); |
|
return SHELL_CMD_HELP_PRINTED; |
|
} |
|
|
|
/* dummy read to clear any pending input */ |
|
(void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count); |
|
|
|
while (true) { |
|
(void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count); |
|
if (count != 0) { |
|
break; |
|
} |
|
ret = gpio_pin_toggle(gpio.dev, gpio.pin); |
|
if (ret != 0) { |
|
shell_error(sh, "%d", ret); |
|
break; |
|
} else if (msg_one_shot) { |
|
msg_one_shot = false; |
|
shell_print(sh, "Hit any key to exit"); |
|
} |
|
k_msleep(SLEEP_TIME_MS); |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static const char *gpio_device_name(const struct device *dev) |
|
{ |
|
#ifdef CONFIG_DEVICE_DT_METADATA |
|
const struct device_dt_nodelabels *nl = device_get_dt_nodelabels(dev); |
|
|
|
if (nl != NULL && nl->num_nodelabels > 0) { |
|
return nl->nodelabels[0]; |
|
} |
|
#endif |
|
return dev->name; |
|
} |
|
|
|
static void device_name_get(size_t idx, struct shell_static_entry *entry) |
|
{ |
|
const struct device *dev = gpio_list[idx].dev; |
|
|
|
if (idx >= ARRAY_SIZE(gpio_list)) { |
|
entry->syntax = NULL; |
|
return; |
|
} |
|
|
|
entry->syntax = gpio_device_name(dev); |
|
entry->handler = NULL; |
|
entry->help = "Device"; |
|
entry->subcmd = gpio_list[idx].subcmd; |
|
} |
|
|
|
SHELL_DYNAMIC_CMD_CREATE(sub_gpio_dev, device_name_get); |
|
|
|
struct pin_info { |
|
const struct device *dev; |
|
bool reserved; |
|
gpio_pin_t pin; |
|
const char *line_name; |
|
}; |
|
|
|
struct pin_order_user_data { |
|
const struct shell *sh; |
|
struct pin_info prev; |
|
struct pin_info next; |
|
}; |
|
|
|
typedef void (*pin_foreach_func_t)(const struct pin_info *info, void *user_data); |
|
|
|
static void print_gpio_ctrl_info(const struct shell *sh, const struct gpio_ctrl *ctrl) |
|
{ |
|
gpio_pin_t pin; |
|
bool reserved; |
|
const char *line_name; |
|
|
|
shell_print(sh, " ngpios: %u", ctrl->ngpios); |
|
shell_print(sh, " Reserved pin mask: 0x%08X\n", ctrl->reserved_mask); |
|
|
|
shell_print(sh, " Reserved Pin Line Name"); |
|
for (pin = 0; pin < ctrl->ngpios; pin++) { |
|
reserved = (BIT64(pin) & ctrl->reserved_mask) != 0; |
|
if (pin < ctrl->line_names_len) { |
|
line_name = ctrl->line_names[pin]; |
|
} else { |
|
line_name = ""; |
|
} |
|
shell_print(sh, " %c %2u %s", reserved ? '*' : ' ', pin, line_name); |
|
} |
|
} |
|
|
|
static void foreach_pin(pin_foreach_func_t func, void *user_data) |
|
{ |
|
gpio_port_pins_t reserved_mask; |
|
struct pin_info info; |
|
gpio_pin_t pin; |
|
size_t i; |
|
|
|
for (i = 0; i < ARRAY_SIZE(gpio_list); i++) { |
|
for (pin = 0; pin < gpio_list[i].ngpios; pin++) { |
|
info.dev = gpio_list[i].dev; |
|
reserved_mask = gpio_list[i].reserved_mask; |
|
info.reserved = (BIT64(pin) & reserved_mask) != 0; |
|
info.pin = pin; |
|
if (pin < gpio_list[i].line_names_len) { |
|
info.line_name = gpio_list[i].line_names[pin]; |
|
} else { |
|
info.line_name = ""; |
|
} |
|
func(&info, user_data); |
|
} |
|
} |
|
} |
|
|
|
static int pin_cmp(const struct pin_info *a, const struct pin_info *b) |
|
{ |
|
int result = strcmp(a->line_name, b->line_name); |
|
|
|
if (result != 0) { |
|
return result; |
|
} |
|
result = strcmp(a->dev->name, b->dev->name); |
|
if (result != 0) { |
|
return result; |
|
} |
|
result = (int)a->pin - (int)b->pin; |
|
|
|
return result; |
|
} |
|
|
|
static void pin_get_next(const struct pin_info *info, void *user_data) |
|
{ |
|
struct pin_order_user_data *data = user_data; |
|
int result; |
|
|
|
if (data->prev.line_name != NULL) { |
|
result = pin_cmp(info, &data->prev); |
|
} else { |
|
result = 1; |
|
} |
|
if (result > 0) { |
|
if (data->next.line_name == NULL) { |
|
data->next = *info; |
|
return; |
|
} |
|
result = pin_cmp(info, &data->next); |
|
if (result < 0) { |
|
data->next = *info; |
|
} |
|
} |
|
} |
|
|
|
static void pin_ordered(const struct pin_info *info, void *user_data) |
|
{ |
|
struct pin_order_user_data *data = user_data; |
|
|
|
ARG_UNUSED(info); |
|
|
|
foreach_pin(pin_get_next, data); |
|
|
|
shell_print(data->sh, " %-12s %-8c %-16s %2u", |
|
data->next.line_name, |
|
data->next.reserved ? '*' : ' ', |
|
gpio_device_name(data->next.dev), |
|
data->next.pin); |
|
|
|
data->prev = data->next; |
|
data->next.line_name = NULL; |
|
} |
|
|
|
static void print_ordered_info(const struct shell *sh) |
|
{ |
|
struct pin_order_user_data data = {0}; |
|
|
|
data.sh = sh; |
|
|
|
shell_print(sh, " %-12s %-8s %-16s %-3s", |
|
"Line", "Reserved", "Device", "Pin"); |
|
|
|
foreach_pin(pin_ordered, &data); |
|
} |
|
|
|
static int cmd_gpio_info(const struct shell *sh, size_t argc, char **argv) |
|
{ |
|
const struct gpio_ctrl *ctrl = get_gpio_ctrl(argv[ARGV_DEV]); |
|
|
|
if (ctrl == NULL) { |
|
/* No device specified */ |
|
print_ordered_info(sh); |
|
return 0; |
|
} |
|
|
|
print_gpio_ctrl_info(sh, ctrl); |
|
|
|
return 0; |
|
} |
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE( |
|
sub_gpio, |
|
SHELL_CMD_ARG( |
|
conf, &sub_gpio_dev, |
|
SHELL_HELP("Configure GPIO pin", |
|
"<device> <pin> <configuration <i|o>[u|d][h|l][0|1]> [vendor specific]\n" |
|
"<i|o> - input|output\n" |
|
"[u|d] - pull up|pull down, otherwise open\n" |
|
"[h|l] - active high|active low, otherwise defaults to active high\n" |
|
"[0|1] - initialise to logic 0|logic 1, otherwise defaults to logic 0\n" |
|
"[vendor specific] - configuration flags within the mask 0xFF00\n" |
|
" see include/zephyr/dt-bindings/gpio/"), |
|
cmd_gpio_conf, 4, 1), |
|
SHELL_CMD_ARG(get, &sub_gpio_dev, SHELL_HELP("Get GPIO pin value", "<device> <pin>"), |
|
cmd_gpio_get, 3, 0), |
|
SHELL_CMD_ARG(set, &sub_gpio_dev, |
|
SHELL_HELP("Set GPIO pin value", "<device> <pin> <level 0|1>"), cmd_gpio_set, |
|
4, 0), |
|
SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_TOGGLE_CMD, toggle, &sub_gpio_dev, |
|
SHELL_HELP("Toggle GPIO pin", "<device> <pin>"), cmd_gpio_toggle, 3, 0), |
|
SHELL_CMD(devices, NULL, SHELL_HELP("List all GPIO devices", ""), cmd_gpio_devices), |
|
SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_BLINK_CMD, blink, &sub_gpio_dev, |
|
SHELL_HELP("Blink GPIO pin", "<device> <pin>"), cmd_gpio_blink, 3, 0), |
|
SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_INFO_CMD, info, &sub_gpio_dev, |
|
SHELL_HELP("GPIO Information", "[device]"), cmd_gpio_info, 1, 1), |
|
SHELL_SUBCMD_SET_END /* Array terminated. */ |
|
); |
|
|
|
SHELL_CMD_REGISTER(gpio, &sub_gpio, "GPIO commands", NULL);
|
|
|