blob: 57f6deddfbb98bd1eb5f4a249a296d31543b9da7 [file] [log] [blame]
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "test_gpio.h"
static struct drv_data data;
static int cb_cnt;
static void callback(const struct device *dev,
struct gpio_callback *gpio_cb, uint32_t pins)
{
const struct drv_data *dd = CONTAINER_OF(gpio_cb,
struct drv_data, gpio_cb);
/*= checkpoint: pins should be marked with correct pin number bit =*/
zassert_equal(pins, BIT(PIN_IN),
"unexpected pins %x", pins);
++cb_cnt;
TC_PRINT("callback triggered: %d\n", cb_cnt);
if ((cb_cnt == 1)
&& (dd->mode == GPIO_INT_EDGE_BOTH)) {
gpio_pin_toggle(dev, PIN_OUT);
}
if (cb_cnt >= MAX_INT_CNT) {
gpio_pin_set(dev, PIN_OUT, 0);
gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_DISABLE);
}
}
static int test_callback(int mode)
{
const struct device *dev = device_get_binding(DEV_NAME);
struct drv_data *drv_data = &data;
gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_DISABLE);
gpio_pin_interrupt_configure(dev, PIN_OUT, GPIO_INT_DISABLE);
/* 1. set PIN_OUT to logical initial state inactive */
uint32_t out_flags = GPIO_OUTPUT_LOW;
if ((mode & GPIO_INT_LOW_0) != 0) {
out_flags = GPIO_OUTPUT_HIGH | GPIO_ACTIVE_LOW;
}
int rc = gpio_pin_configure(dev, PIN_OUT, out_flags);
if (rc != 0) {
TC_ERROR("PIN_OUT config fail: %d", rc);
return TC_FAIL;
}
/* 2. configure PIN_IN callback and trigger condition */
rc = gpio_pin_configure(dev, PIN_IN, GPIO_INPUT | GPIO_INT_DEBOUNCE);
if (rc != 0) {
TC_ERROR("config PIN_IN fail: %d\n", rc);
goto err_exit;
}
drv_data->mode = mode;
gpio_init_callback(&drv_data->gpio_cb, callback, BIT(PIN_IN));
rc = gpio_add_callback(dev, &drv_data->gpio_cb);
if (rc == -ENOTSUP) {
TC_PRINT("interrupts not supported\n");
return TC_PASS;
} else if (rc != 0) {
TC_ERROR("set PIN_IN callback fail: %d\n", rc);
return TC_FAIL;
}
/* 3. enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
cb_cnt = 0;
rc = gpio_pin_interrupt_configure(dev, PIN_IN, mode);
if (rc == -ENOTSUP) {
TC_PRINT("Mode %x not supported\n", mode);
goto pass_exit;
} else if (rc != 0) {
TC_ERROR("config PIN_IN interrupt fail: %d\n", rc);
goto err_exit;
}
k_sleep(K_MSEC(100));
gpio_pin_set(dev, PIN_OUT, 1);
k_sleep(K_MSEC(1000));
(void)gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_DISABLE);
/*= checkpoint: check callback is triggered =*/
TC_PRINT("OUT init %x, IN cfg %x, cnt %d\n", out_flags, mode, cb_cnt);
if (mode == GPIO_INT_EDGE_BOTH) {
if (cb_cnt != 2) {
TC_ERROR("double edge not detected\n");
goto err_exit;
}
goto pass_exit;
}
if ((mode & GPIO_INT_EDGE) == GPIO_INT_EDGE) {
if (cb_cnt != 1) {
TC_ERROR("edge not trigger callback correctly\n");
goto err_exit;
}
goto pass_exit;
} else {
if (cb_cnt != MAX_INT_CNT) {
TC_ERROR("level not trigger callback correctly\n");
goto err_exit;
}
}
pass_exit:
gpio_remove_callback(dev, &drv_data->gpio_cb);
return TC_PASS;
err_exit:
gpio_remove_callback(dev, &drv_data->gpio_cb);
return TC_FAIL;
}
/* export test cases */
void test_gpio_callback_variants(void)
{
zassert_equal(test_callback(GPIO_INT_EDGE_FALLING), TC_PASS,
"falling edge failed");
zassert_equal(test_callback(GPIO_INT_EDGE_RISING), TC_PASS,
"rising edge failed");
zassert_equal(test_callback(GPIO_INT_EDGE_TO_ACTIVE), TC_PASS,
"edge active failed");
zassert_equal(test_callback(GPIO_INT_EDGE_TO_INACTIVE), TC_PASS,
"edge inactive failed");
zassert_equal(test_callback(GPIO_INT_LEVEL_HIGH), TC_PASS,
"level high failed");
zassert_equal(test_callback(GPIO_INT_LEVEL_LOW), TC_PASS,
"level low failed");
zassert_equal(test_callback(GPIO_INT_LEVEL_ACTIVE), TC_PASS,
"level active failed");
zassert_equal(test_callback(GPIO_INT_LEVEL_INACTIVE), TC_PASS,
"level inactive failed");
zassert_equal(test_callback(GPIO_INT_EDGE_BOTH), TC_PASS,
"edge both failed");
}