tests: add gpio_api_1pin testcase

gpio_api_1pin testcase verifies following new GPIO API functionality:
- pin active level flags
- input/output configuration flags
- pin drive flags
- gpio_port_*, gpio_pin_* functions
- pin interrupts

The test is using only 1 GPIO pin (defined in DTS as LED0) and relies on
the ability of the driver to configure pin simultanously as in/out.
Drivers that do not allow to configure pins in in/out mode should still
pass the test, however, most of the testcases will be skipped.

The test does not require any modifications to board hardware.

Signed-off-by: Piotr Mienkowski <piotr.mienkowski@gmail.com>
This commit is contained in:
Piotr Mienkowski 2019-09-03 10:07:49 +02:00 committed by Carles Cufí
commit 7f57737319
9 changed files with 1547 additions and 0 deletions

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.13.1)
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(gpio_basic_api)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})

View file

@ -0,0 +1,2 @@
CONFIG_ZTEST=y
CONFIG_GPIO=y

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2019 Piotr Mienkowski
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "test_gpio_api.h"
void test_main(void)
{
ztest_test_suite(gpio_api_1pin_test,
ztest_unit_test(test_gpio_pin_configure_push_pull),
ztest_unit_test(test_gpio_pin_configure_single_ended),
ztest_unit_test(test_gpio_pin_set_get_raw),
ztest_unit_test(test_gpio_pin_set_get),
ztest_unit_test(test_gpio_pin_set_get_active_high),
ztest_unit_test(test_gpio_pin_set_get_active_low),
ztest_unit_test(test_gpio_pin_toggle),
ztest_unit_test(test_gpio_port_set_masked_get_raw),
ztest_unit_test(test_gpio_port_set_masked_get),
ztest_unit_test(test_gpio_port_set_masked_get_active_high),
ztest_unit_test(test_gpio_port_set_masked_get_active_low),
ztest_unit_test(test_gpio_port_set_bits_clear_bits_raw),
ztest_unit_test(test_gpio_port_set_bits_clear_bits),
ztest_unit_test(test_gpio_port_set_clr_bits_raw),
ztest_unit_test(test_gpio_port_set_clr_bits),
ztest_unit_test(test_gpio_port_toggle),
ztest_unit_test(test_gpio_int_edge_rising),
ztest_unit_test(test_gpio_int_edge_falling),
ztest_unit_test(test_gpio_int_edge_both),
ztest_unit_test(test_gpio_int_edge_to_active),
ztest_unit_test(test_gpio_int_edge_to_inactive),
ztest_unit_test(test_gpio_int_level_high),
ztest_unit_test(test_gpio_int_level_low),
ztest_unit_test(test_gpio_int_level_active),
ztest_unit_test(test_gpio_int_level_inactive),
ztest_unit_test(test_gpio_pin_toggle_visual));
ztest_run_test_suite(gpio_api_1pin_test);
}

View file

@ -0,0 +1,310 @@
/*
* Copyright (c) 2019 Piotr Mienkowski
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @addtogroup t_gpio_api
* @{
* @defgroup t_gpio_api_config test_gpio_api_config
* @brief TestPurpose: verify the gpio config functions using single pin
* configured as input/output.
* @}
*/
#include <limits.h>
#include <sys/util.h>
#include "test_gpio_api.h"
#define TEST_GPIO_MAX_SINGLE_ENDED_RISE_FALL_TIME_MS 100
#define TEST_POINT(n) (n)
static void pin_get_raw_and_verify(struct device *port, unsigned int pin,
int val_expected, int idx)
{
int val_actual;
val_actual = gpio_pin_get_raw(port, pin);
zassert_true(val_actual >= 0,
"Test point %d: failed to get pin value", idx);
zassert_equal(val_expected, val_actual,
"Test point %d: invalid pin get value", idx);
}
static void pin_set_raw_and_verify(struct device *port, unsigned int pin,
int val, int idx)
{
zassert_equal(gpio_pin_set_raw(port, pin, val), 0,
"Test point %d: failed to set pin value", idx);
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}
/** @brief Verify gpio_pin_configure function in push pull mode.
*
* - Configure pin in in/out mode, verify that gpio_pin_set_raw /
* gpio_pin_get_raw operations change pin state.
* - Verify that GPIO_OUTPUT_HIGH flag is initializing the pin to high.
* - Verify that GPIO_OUTPUT_LOW flag is initializing the pin to low.
* - Verify that configuring the pin as an output without initializing it
* to high or low does not change pin state.
* - Verify that it is not possible to change value of a pin via
* gpio_pin_set_raw function if pin is configured as an input.
*/
void test_gpio_pin_configure_push_pull(void)
{
struct device *port;
int ret;
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT);
zassert_equal(ret, 0, "Failed to configure the pin as an output");
pin_set_raw_and_verify(port, TEST_PIN, 1, TEST_POINT(1));
pin_set_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(1));
/* Configure pin in in/out mode, verify that gpio_pin_set_raw /
* gpio_pin_get_raw operations change pin state.
*/
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin in in/out mode");
pin_set_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(2));
pin_get_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(2));
pin_set_raw_and_verify(port, TEST_PIN, 1, TEST_POINT(3));
pin_get_raw_and_verify(port, TEST_PIN, 1, TEST_POINT(3));
pin_set_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(4));
pin_get_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(4));
/* Verify that GPIO_OUTPUT_HIGH flag is initializing the pin to high. */
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT_HIGH | GPIO_INPUT);
zassert_equal(ret, 0,
"Failed to configure the pin in in/out mode and "
"initialize it to high");
pin_get_raw_and_verify(port, TEST_PIN, 1, TEST_POINT(5));
/* Verify that configuring the pin as an output without initializing it
* to high or low does not change pin state.
*/
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
zassert_equal(ret, 0, "Failed to configure the pin in in/out mode");
pin_get_raw_and_verify(port, TEST_PIN, 1, TEST_POINT(6));
/* Verify that GPIO_OUTPUT_LOW flag is initializing the pin to low. */
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT_LOW | GPIO_INPUT);
zassert_equal(ret, 0,
"Failed to configure the pin in in/out mode and "
"initialize it to low");
pin_get_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(7));
/* Verify that configuring the pin as an output without initializing it
* to high or low does not change pin state.
*/
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
zassert_equal(ret, 0, "Failed to configure the pin in in/out mode");
pin_get_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(8));
/* Verify that it is not possible to change value of a pin via
* gpio_pin_set_raw function if pin is configured as an input.
*/
ret = gpio_pin_configure(port, TEST_PIN, GPIO_INPUT);
zassert_equal(ret, 0, "Failed to configure the pin as an input");
int pin_in_val;
pin_in_val = gpio_pin_get_raw(port, TEST_PIN);
zassert_true(pin_in_val >= 0,
"Test point %d: failed to get pin value", TEST_POINT(9));
pin_set_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(10));
pin_get_raw_and_verify(port, TEST_PIN, pin_in_val, TEST_POINT(10));
pin_set_raw_and_verify(port, TEST_PIN, 1, TEST_POINT(11));
pin_get_raw_and_verify(port, TEST_PIN, pin_in_val, TEST_POINT(11));
}
/** @brief Verify gpio_pin_configure function in single ended mode.
*
* @note This test verifies single ended mode only partially. It should not be
* used as a sign off test.
*
* - Verify that pin configured in Open Drain mode and initialized
* to high results in pin high value if the same pin configured
* as input is high. Drivers that do not support Open Drain flag
* return ENOTSUP.
* - Setting pin configured in Open Drain mode to low results in
* pin low value if the same pin configured as input is high.
* - Verify that pin configured in Open Source mode and
* initialized to low results in pin high value if the same pin
* configured as input is high. Drivers that do not support Open
* Source flag return ENOTSUP.
* - Verify that pin configured in Open Source mode and
* initialized to low results in pin low value if the same pin
* configured as input is low. Drivers that do not support Open
* Source flag return ENOTSUP.
* - Setting pin configured in Open Source mode to high results in
* pin high value if the same pin configured as input is low.
* - Verify that pin configured in Open Drain mode and
* initialized to high results in pin low value if the same pin
* configured as input is low. Drivers that do not support Open
* Drain flag return ENOTSUP.
*/
void test_gpio_pin_configure_single_ended(void)
{
struct device *port;
int pin_in_val;
int pin_val;
unsigned int cfg_flag;
int ret;
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
/* If the LED is connected directly between the MCU pin and power or
* ground we can test only one of the Open Drain / Open Source modes.
* Guess pin level when the LED is off. If the pin is not connected
* directly to LED but instead the signal is routed to an input of
* another chip we could test both modes. However, there is no way to
* find it out so only one mode is tested.
*/
if ((TEST_PIN_DTS_FLAGS & GPIO_ACTIVE_LOW) != 0) {
cfg_flag = GPIO_PULL_UP;
pin_val = 1;
} else {
cfg_flag = GPIO_PULL_DOWN;
pin_val = 0;
}
/* Configure pin as an input with pull up/down and check input level. */
ret = gpio_pin_configure(port, TEST_PIN, GPIO_INPUT | cfg_flag);
if (ret == -ENOTSUP) {
TC_PRINT("Pull Up / Pull Down pin bias is not supported\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure pin as an input");
k_sleep(K_MSEC(TEST_GPIO_MAX_SINGLE_ENDED_RISE_FALL_TIME_MS));
pin_in_val = gpio_pin_get_raw(port, TEST_PIN);
zassert_true(pin_in_val >= 0, "Failed to get pin value");
if (pin_val != pin_in_val) {
TC_PRINT("Board configuration does not allow to run the test\n");
ztest_test_skip();
return;
}
if (pin_val == 1) {
TC_PRINT("When configured as input test pin value is high\n");
/* Verify that pin configured in Open Drain mode and initialized
* to high results in pin high value if the same pin configured
* as input is high. Drivers that do not support Open Drain flag
* return -ENOTSUP.
*/
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT_HIGH |
GPIO_OPEN_DRAIN | GPIO_INPUT | GPIO_PULL_UP);
if (ret == -ENOTSUP) {
TC_PRINT("Open Drain configuration or Pull Up pin "
"bias is not supported\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0,
"Failed to configure the pin in Open Drain mode");
pin_get_raw_and_verify(port, TEST_PIN, 1, TEST_POINT(1));
/* Setting pin configured in Open Drain mode to low results in
* pin low value if the same pin configured as input is high.
*/
pin_set_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(2));
pin_get_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(2));
/* Verify that pin configured in Open Source mode and
* initialized to low results in pin high value if the same pin
* configured as input is high. Drivers that do not support Open
* Source flag return -ENOTSUP.
*/
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT_LOW |
GPIO_OPEN_SOURCE | GPIO_INPUT | GPIO_PULL_UP);
if (ret == -ENOTSUP) {
TC_PRINT("Open Source configuration or Pull Up pin "
"bias is not supported\n");
return;
}
zassert_equal(ret, 0,
"Failed to configure the pin in Open Source mode");
k_sleep(K_MSEC(TEST_GPIO_MAX_SINGLE_ENDED_RISE_FALL_TIME_MS));
pin_get_raw_and_verify(port, TEST_PIN, 1, TEST_POINT(3));
pin_set_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(4));
pin_get_raw_and_verify(port, TEST_PIN, 1, TEST_POINT(4));
} else {
TC_PRINT("When configured as input test pin value is low\n");
/* Verify that pin configured in Open Source mode and
* initialized to low results in pin low value if the same pin
* configured as input is low. Drivers that do not support Open
* Source flag return -ENOTSUP.
*/
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT_LOW |
GPIO_OPEN_SOURCE | GPIO_INPUT | GPIO_PULL_DOWN);
if (ret == -ENOTSUP) {
TC_PRINT("Open Source configuration or Pull Down pin "
"bias is not supported\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0,
"Failed to configure the pin in Open Source mode");
pin_get_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(5));
/* Setting pin configured in Open Source mode to high results in
* pin high value if the same pin configured as input is low.
*/
pin_set_raw_and_verify(port, TEST_PIN, 1, TEST_POINT(6));
pin_get_raw_and_verify(port, TEST_PIN, 1, TEST_POINT(6));
/* Verify that pin configured in Open Drain mode and
* initialized to high results in pin low value if the same pin
* configured as input is low. Drivers that do not support Open
* Drain flag return -ENOTSUP.
*/
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT_HIGH |
GPIO_OPEN_DRAIN | GPIO_INPUT | GPIO_PULL_DOWN);
if (ret == -ENOTSUP) {
TC_PRINT("Open Drain configuration or Pull Down pin "
"bias is not supported\n");
return;
}
zassert_equal(ret, 0,
"Failed to configure the pin in Open Drain mode");
k_sleep(K_MSEC(TEST_GPIO_MAX_SINGLE_ENDED_RISE_FALL_TIME_MS));
pin_get_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(7));
pin_set_raw_and_verify(port, TEST_PIN, 1, TEST_POINT(8));
pin_get_raw_and_verify(port, TEST_PIN, 0, TEST_POINT(8));
}
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 Piotr Mienkowski
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef TEST_GPIO_API_H_
#define TEST_GPIO_API_H_
#include <zephyr.h>
#include <drivers/gpio.h>
#include <ztest.h>
#if defined(DT_ALIAS_LED0_GPIOS_CONTROLLER)
#define TEST_DEV DT_ALIAS_LED0_GPIOS_CONTROLLER
#define TEST_PIN DT_ALIAS_LED0_GPIOS_PIN
#ifdef DT_ALIAS_LED0_GPIOS_FLAGS
#define TEST_PIN_DTS_FLAGS DT_ALIAS_LED0_GPIOS_FLAGS
#else
#define TEST_PIN_DTS_FLAGS 0
#endif
#else
#error Unsupported board
#endif
#define TEST_GPIO_MAX_RISE_FALL_TIME_US 200
void test_gpio_pin_configure_push_pull(void);
void test_gpio_pin_configure_single_ended(void);
void test_gpio_pin_set_get_raw(void);
void test_gpio_pin_set_get(void);
void test_gpio_pin_set_get_active_high(void);
void test_gpio_pin_set_get_active_low(void);
void test_gpio_pin_toggle(void);
void test_gpio_pin_toggle_visual(void);
void test_gpio_port_set_masked_get_raw(void);
void test_gpio_port_set_masked_get(void);
void test_gpio_port_set_masked_get_active_high(void);
void test_gpio_port_set_masked_get_active_low(void);
void test_gpio_port_set_bits_clear_bits_raw(void);
void test_gpio_port_set_bits_clear_bits(void);
void test_gpio_port_set_clr_bits_raw(void);
void test_gpio_port_set_clr_bits(void);
void test_gpio_port_toggle(void);
void test_gpio_int_edge_rising(void);
void test_gpio_int_edge_falling(void);
void test_gpio_int_edge_both(void);
void test_gpio_int_edge_to_active(void);
void test_gpio_int_edge_to_inactive(void);
void test_gpio_int_level_high(void);
void test_gpio_int_level_low(void);
void test_gpio_int_level_active(void);
void test_gpio_int_level_inactive(void);
#endif /* TEST_GPIO_API_H_ */

View file

@ -0,0 +1,311 @@
/*
* Copyright (c) 2019 Piotr Mienkowski
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @addtogroup t_gpio_api
* @{
* @defgroup t_gpio_api_pin test_gpio_api_pin
* @brief TestPurpose: verify all gpio pin functions using single pin configured
* as input/output.
* @}
*/
#include <limits.h>
#include <sys/util.h>
#include "test_gpio_api.h"
static void pin_get_raw_and_verify(struct device *port, unsigned int pin,
int val_expected, int idx)
{
int val_actual;
val_actual = gpio_pin_get_raw(port, pin);
zassert_true(val_actual >= 0,
"Test point %d: failed to get physical pin value", idx);
zassert_equal(val_expected, val_actual,
"Test point %d: invalid physical pin get value", idx);
}
static void pin_get_and_verify(struct device *port, unsigned int pin,
int val_expected, int idx)
{
int val_actual;
val_actual = gpio_pin_get(port, pin);
zassert_true(val_actual >= 0,
"Test point %d: failed to get logical pin value", idx);
zassert_equal(val_expected, val_actual,
"Test point %d: invalid logical pin get value", idx);
}
static void pin_set_raw_and_verify(struct device *port, unsigned int pin,
int val, int idx)
{
zassert_equal(gpio_pin_set_raw(port, pin, val), 0,
"Test point %d: failed to set physical pin value", idx);
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}
static void pin_set_and_verify(struct device *port, unsigned int pin, int val,
int idx)
{
zassert_equal(gpio_pin_set(port, pin, val), 0,
"Test point %d: failed to set logical pin value", idx);
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}
/** @brief Verify gpio_pin_toggle function.
*
* - Verify that gpio_pin_toggle function changes pin state from active to
* inactive and vice versa.
*/
void test_gpio_pin_toggle(void)
{
struct device *port;
int val_expected;
int ret;
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
pin_set_raw_and_verify(port, TEST_PIN, 1, 0);
for (int i = 0; i < 5; i++) {
ret = gpio_pin_toggle(port, TEST_PIN);
zassert_equal(ret, 0, "Failed to toggle pin value");
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
val_expected = i % 2;
pin_get_raw_and_verify(port, TEST_PIN, val_expected, i);
}
}
/** @brief Verify visually gpio_pin_toggle function.
*
* This test configures the pin using board DTS flags which should
* correctly set pin active state via GPIO_ACTIVE_LOW/_HIGH flags.
* It is possible to do a visual check to confirm that "LED ON", "LED OFF"
* messages correspond to the LED being turned ON or OFF.
*
* - Verify visually that gpio_pin_toggle function changes pin state from active
* to inactive and vice versa.
*/
void test_gpio_pin_toggle_visual(void)
{
struct device *port;
int val_expected;
int ret;
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT |
TEST_PIN_DTS_FLAGS);
zassert_equal(ret, 0, "Failed to configure the pin");
pin_set_and_verify(port, TEST_PIN, 1, 0);
TC_PRINT("LED ON\n");
for (int i = 0; i < 3; i++) {
k_sleep(K_SECONDS(2));
ret = gpio_pin_toggle(port, TEST_PIN);
zassert_equal(ret, 0, "Failed to toggle pin value");
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
val_expected = i % 2;
TC_PRINT("LED %s\n", val_expected == 1 ? "ON" : "OFF");
}
}
/** @brief Verify gpio_pin_set_raw, gpio_pin_get_raw functions.
*
* - Verify that gpio_pin_get_raw reads the same value as set by
* gpio_pin_set_raw function.
*/
void test_gpio_pin_set_get_raw(void)
{
struct device *port;
int val_expected;
int ret;
const int test_vector[] = {
4, 1, 45, 0, 0, -7, 0, 0, 0, INT_MAX, INT_MIN, 0
};
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
pin_set_raw_and_verify(port, TEST_PIN, test_vector[i], i);
val_expected = test_vector[i] != 0 ? 1 : 0;
pin_get_raw_and_verify(port, TEST_PIN, val_expected, i);
}
}
/** @brief Verify gpio_pin_set, gpio_pin_get functions.
*
* - Verify that gpio_pin_get reads the same value as set by gpio_pin_set
* function.
*/
void test_gpio_pin_set_get(void)
{
struct device *port;
int val_expected;
int ret;
const int test_vector[] = {
1, 2, 3, 0, 4, 0, 0, 0, 17, INT_MAX, INT_MIN, 0
};
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
pin_set_and_verify(port, TEST_PIN, test_vector[i], i);
val_expected = test_vector[i] != 0 ? 1 : 0;
pin_get_and_verify(port, TEST_PIN, val_expected, i);
}
}
/** @brief Verify GPIO_ACTIVE_HIGH flag.
*
* - Verify that there is no functional difference between gpio_pin_set_raw and
* gpio_pin_set functions if the pin is configured as Active High.
* - Verify that there is no functional difference between gpio_pin_get_raw and
* gpio_pin_get functions if the pin is configured as Active High.
*/
void test_gpio_pin_set_get_active_high(void)
{
struct device *port;
int val_expected;
int ret;
const int test_vector[] = {0, 2, 0, 9, -1, 0, 0, 1, INT_MAX, INT_MIN};
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT |
GPIO_ACTIVE_HIGH);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
TC_PRINT("Step 1: Set logical, get logical and physical pin value\n");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
pin_set_and_verify(port, TEST_PIN, test_vector[i], i);
val_expected = test_vector[i] != 0 ? 1 : 0;
pin_get_and_verify(port, TEST_PIN, val_expected, i);
pin_get_raw_and_verify(port, TEST_PIN, val_expected, i);
}
TC_PRINT("Step 2: Set physical, get logical and physical pin value\n");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
pin_set_raw_and_verify(port, TEST_PIN, test_vector[i], i);
val_expected = test_vector[i] != 0 ? 1 : 0;
pin_get_and_verify(port, TEST_PIN, val_expected, i);
pin_get_raw_and_verify(port, TEST_PIN, val_expected, i);
}
}
/** @brief Verify GPIO_ACTIVE_LOW flag.
*
* - Verify that value set by gpio_pin_set function is inverted compared to
* gpio_pin_set_raw if the pin is configured as Active Low.
* - Verify that value read by gpio_pin_get function is inverted compared to
* gpio_pin_get_raw if the pin is configured as Active Low.
*/
void test_gpio_pin_set_get_active_low(void)
{
struct device *port;
int val_expected, val_raw_expected;
int ret;
const int test_vector[] = {0, 4, 0, 0, 1, 8, -3, -12, 0};
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT |
GPIO_ACTIVE_LOW);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
TC_PRINT("Step 1: Set logical, get logical and physical pin value\n");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
pin_set_and_verify(port, TEST_PIN, test_vector[i], i);
val_expected = (test_vector[i] != 0) ? 1 : 0;
val_raw_expected = (val_expected != 0) ? 0 : 1;
pin_get_and_verify(port, TEST_PIN, val_expected, i);
pin_get_raw_and_verify(port, TEST_PIN, val_raw_expected, i);
}
TC_PRINT("Step 2: Set physical, get logical and physical pin value\n");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
pin_set_raw_and_verify(port, TEST_PIN, test_vector[i], i);
val_expected = (test_vector[i] != 0) ? 0 : 1;
val_raw_expected = (val_expected != 0) ? 0 : 1;
pin_get_and_verify(port, TEST_PIN, val_expected, i);
pin_get_raw_and_verify(port, TEST_PIN, val_raw_expected, i);
}
}

View file

@ -0,0 +1,275 @@
/*
* Copyright (c) 2019 Piotr Mienkowski
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @addtogroup t_gpio_api
* @{
* @defgroup t_gpio_api_pin_interrupt test_gpio_api_pin_interrupt
* @brief TestPurpose: verify gpio_pin_interrupt_configure function using single
* pin configured as input/output.
* @}
*/
#include <limits.h>
#include <sys/util.h>
#include "test_gpio_api.h"
struct gpio_callback gpio_cb;
static int cb_count;
static void callback_edge(struct device *port, struct gpio_callback *cb,
u32_t pins)
{
zassert_equal(pins, 1 << TEST_PIN,
"Detected interrupt on an invalid pin");
cb_count++;
}
static void callback_level(struct device *port, struct gpio_callback *cb,
u32_t pins)
{
int ret;
zassert_equal(pins, 1 << TEST_PIN,
"Detected interrupt on an invalid pin");
ret = gpio_pin_interrupt_configure(port, TEST_PIN, GPIO_INT_DISABLE);
zassert_equal(ret, 0,
"Failed to disable pin interrupt in the callback");
cb_count++;
}
static void pin_set_and_verify(struct device *port, unsigned int pin, int val,
int idx)
{
zassert_equal(gpio_pin_set(port, pin, val), 0,
"Test point %d: failed to set logical pin value", idx);
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}
void test_gpio_pin_interrupt_edge(unsigned int cfg_flags,
unsigned int int_flags)
{
struct device *port;
int cb_count_expected;
unsigned int cfg_out_flag;
int ret;
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_INPUT | GPIO_OUTPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
if ((cfg_flags & GPIO_ACTIVE_LOW) != 0) {
cfg_out_flag = GPIO_OUTPUT_HIGH;
} else {
cfg_out_flag = GPIO_OUTPUT_LOW;
}
ret = gpio_pin_configure(port, TEST_PIN, GPIO_INPUT | cfg_out_flag |
cfg_flags);
zassert_equal(ret, 0, "Failed to configure the pin");
cb_count = 0;
cb_count_expected = 0;
gpio_init_callback(&gpio_cb, callback_edge, BIT(TEST_PIN));
ret = gpio_add_callback(port, &gpio_cb);
ret = gpio_pin_interrupt_configure(port, TEST_PIN, int_flags);
if (ret == -ENOTSUP) {
TC_PRINT("Pin interrupt is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure pin interrupt");
for (int i = 0; i < 6; i++) {
pin_set_and_verify(port, TEST_PIN, 1, i);
if (int_flags & GPIO_INT_HIGH_1) {
cb_count_expected++;
}
zassert_equal(cb_count, cb_count_expected,
"Test point %d: Pin interrupt triggered invalid "
"number of times on rising/to active edge", i);
pin_set_and_verify(port, TEST_PIN, 0, i);
if (int_flags & GPIO_INT_LOW_0) {
cb_count_expected++;
}
zassert_equal(cb_count, cb_count_expected,
"Test point %d: Pin interrupt triggered invalid "
"number of times on falling/to inactive edge", i);
}
ret = gpio_pin_interrupt_configure(port, TEST_PIN, GPIO_INT_DISABLE);
zassert_equal(ret, 0, "Failed to disable pin interrupt");
for (int i = 0; i < 6; i++) {
pin_set_and_verify(port, TEST_PIN, 1, i);
pin_set_and_verify(port, TEST_PIN, 0, i);
zassert_equal(cb_count, cb_count_expected,
"Pin interrupt triggered when disabled");
}
}
void test_gpio_pin_interrupt_level(unsigned int cfg_flags,
unsigned int int_flags)
{
struct device *port;
int cb_count_expected;
unsigned int cfg_out_flag;
int pin_out_val;
int ret;
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_INPUT | GPIO_OUTPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
pin_out_val = ((int_flags & GPIO_INT_HIGH_1) != 0) ? 0 : 1;
if ((cfg_flags & GPIO_ACTIVE_LOW) != 0) {
cfg_out_flag = (pin_out_val != 0) ? GPIO_OUTPUT_LOW :
GPIO_OUTPUT_HIGH;
} else {
cfg_out_flag = (pin_out_val != 0) ? GPIO_OUTPUT_HIGH :
GPIO_OUTPUT_LOW;
}
ret = gpio_pin_configure(port, TEST_PIN, GPIO_INPUT | cfg_out_flag |
cfg_flags);
zassert_equal(ret, 0, "Failed to configure the pin");
cb_count = 0;
cb_count_expected = 0;
gpio_init_callback(&gpio_cb, callback_level, BIT(TEST_PIN));
ret = gpio_add_callback(port, &gpio_cb);
ret = gpio_pin_interrupt_configure(port, TEST_PIN, int_flags);
if (ret == -ENOTSUP) {
TC_PRINT("Pin interrupt is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure pin interrupt");
zassert_equal(cb_count, cb_count_expected,
"Pin interrupt triggered on level %d", pin_out_val);
for (int i = 0; i < 6; i++) {
pin_out_val = (pin_out_val != 0) ? 0 : 1;
pin_set_and_verify(port, TEST_PIN, pin_out_val, i);
cb_count_expected++;
zassert_equal(cb_count, cb_count_expected,
"Test point %d: Pin interrupt triggered invalid "
"number of times on level %d", i, pin_out_val);
pin_out_val = (pin_out_val != 0) ? 0 : 1;
pin_set_and_verify(port, TEST_PIN, pin_out_val, i);
zassert_equal(cb_count, cb_count_expected,
"Test point %d: Pin interrupt triggered invalid "
"number of times on level %d", i, pin_out_val);
/* Re-enable pin level interrupt */
ret = gpio_pin_interrupt_configure(port, TEST_PIN, int_flags);
zassert_equal(ret, 0,
"Failed to re-enable pin level interrupt");
}
ret = gpio_pin_interrupt_configure(port, TEST_PIN, GPIO_INT_DISABLE);
zassert_equal(ret, 0, "Failed to disable pin interrupt");
for (int i = 0; i < 6; i++) {
pin_set_and_verify(port, TEST_PIN, 1, i);
pin_set_and_verify(port, TEST_PIN, 0, i);
zassert_equal(cb_count, cb_count_expected,
"Pin interrupt triggered when disabled");
}
}
/** @brief Verify GPIO_INT_EDGE_RISING flag. */
void test_gpio_int_edge_rising(void)
{
test_gpio_pin_interrupt_edge(0, GPIO_INT_EDGE_RISING);
}
/** @brief Verify GPIO_INT_EDGE_FALLING flag. */
void test_gpio_int_edge_falling(void)
{
test_gpio_pin_interrupt_edge(0, GPIO_INT_EDGE_FALLING);
}
/** @brief Verify GPIO_INT_EDGE_BOTH flag. */
void test_gpio_int_edge_both(void)
{
test_gpio_pin_interrupt_edge(0, GPIO_INT_EDGE_BOTH);
}
/** @brief Verify GPIO_INT_EDGE_TO_ACTIVE flag. */
void test_gpio_int_edge_to_active(void)
{
TC_PRINT("Step 1: Configure pin as active high\n");
test_gpio_pin_interrupt_edge(GPIO_ACTIVE_HIGH, GPIO_INT_EDGE_TO_ACTIVE);
TC_PRINT("Step 2: Configure pin as active low\n");
test_gpio_pin_interrupt_edge(GPIO_ACTIVE_LOW, GPIO_INT_EDGE_TO_ACTIVE);
}
/** @brief Verify GPIO_INT_EDGE_TO_INACTIVE flag. */
void test_gpio_int_edge_to_inactive(void)
{
TC_PRINT("Step 1: Configure pin as active high\n");
test_gpio_pin_interrupt_edge(GPIO_ACTIVE_HIGH, GPIO_INT_EDGE_TO_INACTIVE);
TC_PRINT("Step 2: Configure pin as active low\n");
test_gpio_pin_interrupt_edge(GPIO_ACTIVE_LOW, GPIO_INT_EDGE_TO_INACTIVE);
}
/** @brief Verify GPIO_INT_LEVEL_HIGH flag. */
void test_gpio_int_level_high(void)
{
test_gpio_pin_interrupt_level(0, GPIO_INT_LEVEL_HIGH);
}
/** @brief Verify GPIO_INT_LEVEL_LOW flag. */
void test_gpio_int_level_low(void)
{
test_gpio_pin_interrupt_level(0, GPIO_INT_LEVEL_LOW);
}
/** @brief Verify GPIO_INT_LEVEL_ACTIVE flag. */
void test_gpio_int_level_active(void)
{
TC_PRINT("Step 1: Configure pin as active high\n");
test_gpio_pin_interrupt_level(GPIO_ACTIVE_HIGH, GPIO_INT_LEVEL_ACTIVE);
TC_PRINT("Step 2: Configure pin as active low\n");
test_gpio_pin_interrupt_level(GPIO_ACTIVE_LOW, GPIO_INT_LEVEL_ACTIVE);
}
/** @brief Verify GPIO_INT_LEVEL_INACTIVE flag. */
void test_gpio_int_level_inactive(void)
{
TC_PRINT("Step 1: Configure pin as active high\n");
test_gpio_pin_interrupt_level(GPIO_ACTIVE_HIGH, GPIO_INT_LEVEL_INACTIVE);
TC_PRINT("Step 2: Configure pin as active low\n");
test_gpio_pin_interrupt_level(GPIO_ACTIVE_LOW, GPIO_INT_LEVEL_INACTIVE);
}

View file

@ -0,0 +1,538 @@
/*
* Copyright (c) 2019 Piotr Mienkowski
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @addtogroup t_gpio_api
* @{
* @defgroup t_gpio_api_port test_gpio_api_port
* @brief TestPurpose: verify all gpio port functions using single pin
* configured as input/output.
* @}
*/
#include <limits.h>
#include <sys/util.h>
#include "test_gpio_api.h"
#define TEST_GPIO_PORT_VALUE_MAX ((1LLU << GPIO_MAX_PINS_PER_PORT) - 1)
static void port_get_raw_and_verify(struct device *port,
gpio_port_value_t val_expected, int idx)
{
gpio_port_value_t val_actual;
zassert_equal(gpio_port_get_raw(port, &val_actual), 0,
"Test point %d: failed to get physical port value", idx);
zassert_equal(val_expected, val_actual,
"Test point %d: invalid physical port get value", idx);
}
static void port_get_and_verify(struct device *port,
gpio_port_value_t val_expected, int idx)
{
gpio_port_value_t val_actual;
zassert_equal(gpio_port_get(port, &val_actual), 0,
"Test point %d: failed to get logical port value", idx);
zassert_equal(val_expected, val_actual,
"Test point %d: invalid logical port get value", idx);
}
static void port_set_masked_raw_and_verify(struct device *port,
gpio_port_pins_t mask, gpio_port_value_t value, int idx)
{
zassert_equal(gpio_port_set_masked_raw(port, mask, value), 0,
"Test point %d: failed to set physical port value", idx);
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}
static void port_set_masked_and_verify(struct device *port,
gpio_port_pins_t mask, gpio_port_value_t value, int idx)
{
zassert_equal(gpio_port_set_masked(port, mask, value), 0,
"Test point %d: failed to set logical port value", idx);
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}
static void port_set_bits_raw_and_verify(struct device *port,
gpio_port_pins_t pins, int idx)
{
zassert_equal(gpio_port_set_bits_raw(port, pins), 0,
"Test point %d: failed to set physical port value", idx);
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}
static void port_set_bits_and_verify(struct device *port,
gpio_port_pins_t pins, int idx)
{
zassert_equal(gpio_port_set_bits(port, pins), 0,
"Test point %d: failed to set logical port value", idx);
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}
static void port_clear_bits_raw_and_verify(struct device *port,
gpio_port_pins_t pins, int idx)
{
zassert_equal(gpio_port_clear_bits_raw(port, pins), 0,
"Test point %d: failed to set physical port value", idx);
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}
static void port_clear_bits_and_verify(struct device *port,
gpio_port_pins_t pins, int idx)
{
zassert_equal(gpio_port_clear_bits(port, pins), 0,
"Test point %d: failed to set logical port value", idx);
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}
static void port_set_clr_bits_raw(struct device *port,
gpio_port_pins_t set_pins, gpio_port_pins_t clear_pins, int idx)
{
zassert_equal(gpio_port_set_clr_bits_raw(port, set_pins, clear_pins), 0,
"Test point %d: failed to set physical port value", idx);
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}
static void port_set_clr_bits(struct device *port,
gpio_port_pins_t set_pins, gpio_port_pins_t clear_pins, int idx)
{
zassert_equal(gpio_port_set_clr_bits(port, set_pins, clear_pins), 0,
"Test point %d: failed to set logical port value", idx);
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}
/** @brief Verify gpio_port_toggle_bits function.
*
* - Verify that gpio_port_toggle_bits function changes pin state from active to
* inactive and vice versa.
*/
void test_gpio_port_toggle(void)
{
struct device *port;
gpio_port_value_t val_expected;
int ret;
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
port_set_bits_raw_and_verify(port, 1 << TEST_PIN, 0);
zassert_equal(gpio_port_get(port, &val_expected), 0,
"Failed to get logical port value");
for (int i = 0; i < 5; i++) {
ret = gpio_port_toggle_bits(port, 1 << TEST_PIN);
zassert_equal(ret, 0, "Failed to toggle pin value");
k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
val_expected ^= 1 << TEST_PIN;
port_get_raw_and_verify(port, val_expected, i);
}
}
void test_gpio_port_set_masked_get_raw(void)
{
struct device *port;
gpio_port_value_t val_expected;
int ret;
const gpio_port_value_t test_vector[] = {
0xEE11EE11,
0x11EE11EE,
TEST_GPIO_PORT_VALUE_MAX,
TEST_GPIO_PORT_VALUE_MAX,
0x00000000,
0x00000000,
0x55555555,
0xAAAAAAAA,
0x00000000,
0x00000000,
TEST_GPIO_PORT_VALUE_MAX,
TEST_GPIO_PORT_VALUE_MAX,
0x00000000,
};
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
ret = gpio_port_get_raw(port, &val_expected);
zassert_equal(ret, 0, "Failed to get physical port value");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
port_set_masked_raw_and_verify(port, 1 << TEST_PIN, test_vector[i], i);
val_expected &= ~(1 << TEST_PIN);
val_expected |= test_vector[i] & (1 << TEST_PIN);
port_get_raw_and_verify(port, val_expected, i);
}
}
void test_gpio_port_set_masked_get(void)
{
struct device *port;
gpio_port_value_t val_expected;
int ret;
const gpio_port_value_t test_vector[] = {
0xEE11EE11,
0x11EE11EE,
TEST_GPIO_PORT_VALUE_MAX,
TEST_GPIO_PORT_VALUE_MAX,
0x00000000,
0x00000000,
0x55555555,
0xAAAAAAAA,
0x00000000,
0x00000000,
TEST_GPIO_PORT_VALUE_MAX,
TEST_GPIO_PORT_VALUE_MAX,
0x00000000,
};
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
ret = gpio_port_get(port, &val_expected);
zassert_equal(ret, 0, "Failed to get logical port value");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
port_set_masked_and_verify(port, 1 << TEST_PIN, test_vector[i], i);
val_expected &= ~(1 << TEST_PIN);
val_expected |= test_vector[i] & (1 << TEST_PIN);
port_get_and_verify(port, val_expected, i);
}
}
void test_gpio_port_set_masked_get_active_high(void)
{
struct device *port;
gpio_port_value_t val_expected;
int ret;
const gpio_port_value_t test_vector[] = {
0xCC33CC33,
0x33CC33CC,
TEST_GPIO_PORT_VALUE_MAX,
TEST_GPIO_PORT_VALUE_MAX,
TEST_GPIO_PORT_VALUE_MAX,
0x00000000,
0x00000000,
0x00000000,
0x55555555,
0x00000000,
0xAAAAAAAA,
0x00000000,
TEST_GPIO_PORT_VALUE_MAX,
0x00000000,
};
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT |
GPIO_ACTIVE_HIGH);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
ret = gpio_port_get(port, &val_expected);
zassert_equal(ret, 0, "Failed to get logical port value");
TC_PRINT("Step 1: Set logical, get logical and physical port value\n");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
port_set_masked_and_verify(port, 1 << TEST_PIN, test_vector[i], i);
val_expected &= ~(1 << TEST_PIN);
val_expected |= test_vector[i] & (1 << TEST_PIN);
port_get_and_verify(port, val_expected, i);
port_get_raw_and_verify(port, val_expected, i);
}
TC_PRINT("Step 2: Set physical, get logical and physical port value\n");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
port_set_masked_raw_and_verify(port, 1 << TEST_PIN, test_vector[i], i);
val_expected &= ~(1 << TEST_PIN);
val_expected |= test_vector[i] & (1 << TEST_PIN);
port_get_and_verify(port, val_expected, i);
port_get_raw_and_verify(port, val_expected, i);
}
}
void test_gpio_port_set_masked_get_active_low(void)
{
struct device *port;
gpio_port_value_t val_expected, val_raw_expected;
int ret;
const gpio_port_value_t test_vector[] = {
0xCC33CC33,
0x33CC33CC,
TEST_GPIO_PORT_VALUE_MAX,
TEST_GPIO_PORT_VALUE_MAX,
TEST_GPIO_PORT_VALUE_MAX,
0x00000000,
0x00000000,
0x00000000,
0x55555555,
0x00000000,
0xAAAAAAAA,
0x00000000,
TEST_GPIO_PORT_VALUE_MAX,
0x00000000,
};
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT |
GPIO_ACTIVE_LOW);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
ret = gpio_port_get_raw(port, &val_raw_expected);
zassert_equal(ret, 0, "Failed to get physical port value");
ret = gpio_port_get(port, &val_expected);
zassert_equal(ret, 0, "Failed to get logical port value");
TC_PRINT("Step 1: Set logical, get logical and physical port value\n");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
port_set_masked_and_verify(port, 1 << TEST_PIN, test_vector[i], i);
val_raw_expected &= ~(1 << TEST_PIN);
val_raw_expected |= (test_vector[i] & (1 << TEST_PIN)) ^ (1 << TEST_PIN);
val_expected &= ~(1 << TEST_PIN);
val_expected |= test_vector[i] & (1 << TEST_PIN);
port_get_and_verify(port, val_expected, i);
port_get_raw_and_verify(port, val_raw_expected, i);
}
TC_PRINT("Step 2: Set physical, get logical and physical port value\n");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
port_set_masked_raw_and_verify(port, 1 << TEST_PIN, test_vector[i], i);
val_raw_expected &= ~(1 << TEST_PIN);
val_raw_expected |= test_vector[i] & (1 << TEST_PIN);
val_expected &= ~(1 << TEST_PIN);
val_expected |= (test_vector[i] & (1 << TEST_PIN)) ^ (1 << TEST_PIN);
port_get_and_verify(port, val_expected, i);
port_get_raw_and_verify(port, val_raw_expected, i);
}
}
void test_gpio_port_set_bits_clear_bits_raw(void)
{
struct device *port;
gpio_port_value_t val_expected;
int ret;
const gpio_port_value_t test_vector[][2] = {
/* set value, clear value */
{0xEE11EE11, 0xEE11EE11},
{0x11EE11EE, TEST_GPIO_PORT_VALUE_MAX},
{0x00000000, 0x55555555},
{TEST_GPIO_PORT_VALUE_MAX, 0xAAAAAAAA},
{TEST_GPIO_PORT_VALUE_MAX, TEST_GPIO_PORT_VALUE_MAX},
};
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
ret = gpio_port_get_raw(port, &val_expected);
zassert_equal(ret, 0, "Failed to get logical port value");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
port_set_bits_raw_and_verify(port, test_vector[i][0], i);
val_expected |= test_vector[i][0] & (1 << TEST_PIN);
port_get_raw_and_verify(port, val_expected, i);
port_clear_bits_raw_and_verify(port, test_vector[i][1], i);
val_expected &= ~(test_vector[i][1] & (1 << TEST_PIN));
port_get_raw_and_verify(port, val_expected, i);
}
}
void test_gpio_port_set_bits_clear_bits(void)
{
struct device *port;
gpio_port_value_t val_expected;
int ret;
const gpio_port_value_t test_vector[][2] = {
/* set value, clear value */
{TEST_GPIO_PORT_VALUE_MAX, 0xAAAAAAAA},
{0x00000000, TEST_GPIO_PORT_VALUE_MAX},
{0xCC33CC33, 0x33CC33CC},
{0x33CC33CC, 0x33CC33CC},
{0x00000000, 0x55555555},
};
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
ret = gpio_port_get(port, &val_expected);
zassert_equal(ret, 0, "Failed to get logical port value");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
port_set_bits_and_verify(port, test_vector[i][0], i);
val_expected |= test_vector[i][0] & (1 << TEST_PIN);
port_get_and_verify(port, val_expected, i);
port_clear_bits_and_verify(port, test_vector[i][1], i);
val_expected &= ~(test_vector[i][1] & (1 << TEST_PIN));
port_get_and_verify(port, val_expected, i);
}
}
void test_gpio_port_set_clr_bits_raw(void)
{
struct device *port;
gpio_port_value_t val_expected;
int ret;
const gpio_port_value_t test_vector[][2] = {
/* set value, clear value */
{0xEE11EE11, 0x11EE11EE},
{0x00000000, TEST_GPIO_PORT_VALUE_MAX},
{0x55555555, 0x00000000},
{TEST_GPIO_PORT_VALUE_MAX, 0x00000000},
{0xAAAAAAAA, 0x00000000},
{0x00000000, TEST_GPIO_PORT_VALUE_MAX},
};
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
ret = gpio_port_get_raw(port, &val_expected);
zassert_equal(ret, 0, "Failed to get logical port value");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
port_set_clr_bits_raw(port, test_vector[i][0], test_vector[i][1], i);
val_expected |= test_vector[i][0] & (1 << TEST_PIN);
val_expected &= ~(test_vector[i][1] & (1 << TEST_PIN));
port_get_raw_and_verify(port, val_expected, i);
}
}
void test_gpio_port_set_clr_bits(void)
{
struct device *port;
gpio_port_value_t val_expected;
int ret;
const gpio_port_value_t test_vector[][2] = {
/* set value, clear value */
{0xEE11EE11, 0x11EE11EE},
{0x00000000, TEST_GPIO_PORT_VALUE_MAX},
{0x55555555, 0x00000000},
{TEST_GPIO_PORT_VALUE_MAX, 0x00000000},
{0xAAAAAAAA, 0x00000000},
{0x00000000, TEST_GPIO_PORT_VALUE_MAX},
};
port = device_get_binding(TEST_DEV);
zassert_not_null(port, "device " TEST_DEV " not found");
TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);
ret = gpio_pin_configure(port, TEST_PIN, GPIO_OUTPUT | GPIO_INPUT);
if (ret == -ENOTSUP) {
TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "Failed to configure the pin");
ret = gpio_port_get(port, &val_expected);
zassert_equal(ret, 0, "Failed to get logical port value");
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
port_set_clr_bits(port, test_vector[i][0], test_vector[i][1], i);
val_expected |= test_vector[i][0] & (1 << TEST_PIN);
val_expected &= ~(test_vector[i][1] & (1 << TEST_PIN));
port_get_and_verify(port, val_expected, i);
}
}

View file

@ -0,0 +1,6 @@
tests:
peripheral.gpio:
tags: drivers gpio
depends_on: gpio
min_flash: 48
filter: DT_ALIAS_LED0_GPIOS_CONTROLLER