tests/periph_gpio: add automatic GPIO test cmd
This adds the `auto_test <port> <pin> <port> <pin>` command. Specify two GPIOs that are electrically connected e.g. via jumper or wire. The command will automatically conduct several tests to ensure that the GPIO implemenation behaves according to the specification.
This commit is contained in:
parent
2509c206ee
commit
53e292569d
@ -27,6 +27,7 @@
|
||||
#include "periph/gpio.h"
|
||||
|
||||
#define BENCH_RUNS_DEFAULT (1000UL * 100)
|
||||
#define IRQ_TIMEOUT_US (1000UL)
|
||||
|
||||
#ifdef MODULE_PERIPH_GPIO_IRQ
|
||||
static void cb(void *arg)
|
||||
@ -246,6 +247,135 @@ static int cmd_toggle(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MODULE_PERIPH_GPIO_IRQ
|
||||
static void _test_cb(void *ctx)
|
||||
{
|
||||
mutex_unlock(ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int cmd_auto_test(int argc, char **argv)
|
||||
{
|
||||
if (argc < 5) {
|
||||
printf("usage: %s <port> <pin> <port> <pin>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
gpio_t pin_in = GPIO_PIN(atoi(argv[1]), atoi(argv[2]));
|
||||
gpio_t pin_out = GPIO_PIN(atoi(argv[3]), atoi(argv[4]));
|
||||
|
||||
puts("[START]");
|
||||
|
||||
if (gpio_init(pin_in, GPIO_IN)) {
|
||||
printf("Error to initialize GPIO_PIN(%s, %s)\n", argv[1], argv[2]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gpio_init(pin_out, GPIO_OUT)) {
|
||||
printf("Error to initialize GPIO_PIN(%s, %s)\n", argv[3], argv[4]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* test set HIGH */
|
||||
gpio_set(pin_out);
|
||||
|
||||
if (gpio_read(pin_in) == 0) {
|
||||
puts("gpio_set() or gpio_read() or failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* test set LOW */
|
||||
gpio_clear(pin_out);
|
||||
|
||||
if (gpio_read(pin_in) != 0) {
|
||||
puts("gpio_clear() or gpio_read() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef MODULE_PERIPH_GPIO_IRQ
|
||||
mutex_t lock = MUTEX_INIT_LOCKED;
|
||||
|
||||
/* test rising interrupt */
|
||||
if (gpio_init_int(pin_in, GPIO_IN, GPIO_RISING, _test_cb, &lock)) {
|
||||
puts("setting rising interrupt failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpio_set(pin_out);
|
||||
if (xtimer_mutex_lock_timeout(&lock, IRQ_TIMEOUT_US)) {
|
||||
puts("rising interrupt timeout");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpio_clear(pin_out);
|
||||
if (xtimer_mutex_lock_timeout(&lock, IRQ_TIMEOUT_US) == 0) {
|
||||
puts("interrupt falsely generated on falling edge");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* test falling interrupt */
|
||||
if (gpio_init_int(pin_in, GPIO_IN, GPIO_FALLING, _test_cb, &lock)) {
|
||||
puts("setting falling interrupt failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpio_set(pin_out);
|
||||
if (xtimer_mutex_lock_timeout(&lock, IRQ_TIMEOUT_US) == 0) {
|
||||
puts("interrupt falsely generated on rising edge");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpio_clear(pin_out);
|
||||
if (xtimer_mutex_lock_timeout(&lock, IRQ_TIMEOUT_US)) {
|
||||
puts("rising interrupt timeout");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* test IRQ disable */
|
||||
gpio_irq_disable(pin_in);
|
||||
|
||||
gpio_set(pin_out);
|
||||
if (xtimer_mutex_lock_timeout(&lock, IRQ_TIMEOUT_US) == 0) {
|
||||
puts("interrupt falsely generated on rising edge while disabled");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpio_clear(pin_out);
|
||||
if (xtimer_mutex_lock_timeout(&lock, IRQ_TIMEOUT_US) == 0) {
|
||||
puts("interrupt falsely generated while disabled");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* test IRQ enable */
|
||||
|
||||
gpio_irq_enable(pin_in);
|
||||
if (xtimer_mutex_lock_timeout(&lock, IRQ_TIMEOUT_US) == 0) {
|
||||
puts("interrupt falsely generated after being re-enabled");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpio_set(pin_out);
|
||||
if (xtimer_mutex_lock_timeout(&lock, IRQ_TIMEOUT_US) == 0) {
|
||||
puts("interrupt falsely generated on rising edge after re-enabled");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpio_clear(pin_out);
|
||||
if (xtimer_mutex_lock_timeout(&lock, IRQ_TIMEOUT_US)) {
|
||||
puts("interrupt not re-enabled");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* disable IRQ to avoid further interrupts */
|
||||
gpio_irq_disable(pin_in);
|
||||
|
||||
#endif
|
||||
|
||||
puts("[SUCCESS]");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bench(int argc, char **argv)
|
||||
{
|
||||
if (argc < 3) {
|
||||
@ -285,6 +415,7 @@ static const shell_command_t shell_commands[] = {
|
||||
{ "set", "set pin to HIGH", cmd_set },
|
||||
{ "clear", "set pin to LOW", cmd_clear },
|
||||
{ "toggle", "toggle pin", cmd_toggle },
|
||||
{ "auto_test", "Run a series of automatic tests on two connected GPIOs", cmd_auto_test },
|
||||
{ "bench", "run a set of predefined benchmarks", bench },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user