tests: add gpio driver test case

the commit include 5 ztest cases, cover the basic gpio APIs
including callback relevant and pin read/write functions.
It proves workable on intel quark c1000 and
arduino 101 platform

Change-Id: Iab30aa841cfa440c1f773b5a8c5ce0d68346c353
Signed-off-by: jing wang <jing.j.wang@intel.com>
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
jing wang 2016-12-08 14:47:29 +08:00 committed by Anas Nashif
commit b008914e42
9 changed files with 499 additions and 0 deletions

View file

@ -0,0 +1,4 @@
BOARD ?= quark_se_c1000_devboard
CONF_FILE = prj.conf
include ${ZEPHYR_BASE}/Makefile.inc

View file

@ -0,0 +1,3 @@
CONFIG_GPIO=y
CONFIG_ZTEST=y
CONFIG_NEWLIB_LIBC=y

View file

@ -0,0 +1,2 @@
include $(ZEPHYR_BASE)/tests/Makefile.test
obj-y = main.o test_callback_trigger.o test_callback_manage.o test_pin_rw.o

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @addtogroup t_driver_gpio
* @{
* @defgroup t_gpio_basic_api test_gpio_basic_api
* @}
*
* Setup: loop PIN_OUT with PIN_IN on the target board
*
* quark_se_c1000_devboard - x86
* --------------------
*
* 1. PIN_OUT is GPIO_15
* 2. PIN_IN is GPIO_16
*
* quark_se_c1000_ss_devboard - arc
* --------------------
*
* 1. PIN_OUT is GPIO_SS_12
* 2. PIN_IN is GPIO_SS_13
*
* arduino_101 - x86
* --------------------
*
* 1. PIN_OUT is GPIO_16
* 2. PIN_IN is GPIO_19
*/
#include "test_gpio.h"
void test_main(void)
{
ztest_test_suite(gpio_basic_test,
ztest_unit_test(test_gpio_pin_read_write),
ztest_unit_test(test_gpio_callback_edge_high),
ztest_unit_test(test_gpio_callback_edge_low),
ztest_unit_test(test_gpio_callback_level_high),
ztest_unit_test(test_gpio_callback_add_remove),
ztest_unit_test(test_gpio_callback_enable_disable),
ztest_unit_test(test_gpio_callback_level_high));
ztest_run_test_suite(gpio_basic_test);
}

View file

@ -0,0 +1,172 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @addtogroup t_gpio_basic_api
* @{
* @defgroup t_gpio_callback_manage test_gpio_callback_manage
* @brief TestPurpose: verify zephyr gpio callback add/remvoe and enable/disable
* @}
*/
#include "test_gpio.h"
static struct drv_data cb_data[2];
static int cb_cnt[2];
static void callback_1(struct device *dev,
struct gpio_callback *gpio_cb, uint32_t pins)
{
TC_PRINT("%s triggered: %d\n", __func__, ++cb_cnt[0]);
}
static void callback_2(struct device *dev,
struct gpio_callback *gpio_cb, uint32_t pins)
{
TC_PRINT("%s triggered: %d\n", __func__, ++cb_cnt[1]);
}
static void init_callback(struct device *dev)
{
gpio_pin_disable_callback(dev, PIN_IN);
gpio_pin_disable_callback(dev, PIN_OUT);
/* 1. set PIN_OUT */
gpio_pin_configure(dev, PIN_OUT, GPIO_DIR_OUT);
gpio_pin_write(dev, PIN_OUT, 0);
/* 2. configure PIN_IN callback and trigger condition */
gpio_pin_configure(dev, PIN_IN,
GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | \
GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE);
gpio_init_callback(&cb_data[0].gpio_cb, callback_1, BIT(PIN_IN));
gpio_add_callback(dev, &cb_data[0].gpio_cb);
gpio_init_callback(&cb_data[1].gpio_cb, callback_2, BIT(PIN_IN));
gpio_add_callback(dev, &cb_data[1].gpio_cb);
}
static void trigger_callback(struct device *dev, int enable_cb)
{
gpio_pin_write(dev, PIN_OUT, 0);
k_sleep(100);
cb_cnt[0] = 0;
cb_cnt[1] = 0;
if (enable_cb == 1) {
gpio_pin_enable_callback(dev, PIN_IN);
} else {
gpio_pin_disable_callback(dev, PIN_IN);
}
k_sleep(100);
gpio_pin_write(dev, PIN_OUT, 1);
k_sleep(1000);
}
static int test_callback_add_remove(void)
{
struct device *dev = device_get_binding(DEV_NAME);
/* SetUp: initialize environment */
init_callback(dev);
/* 3. enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
trigger_callback(dev, 1);
/*= checkpoint: check callback is triggered =*/
if (cb_cnt[0] != 1 || cb_cnt[1] != 1) {
TC_ERROR("not trigger callback correctly\n");
goto err_exit;
}
/* 4. remove callback_1 */
gpio_remove_callback(dev, &cb_data[0].gpio_cb);
trigger_callback(dev, 1);
/*= checkpoint: check callback is triggered =*/
if (cb_cnt[0] != 0 || cb_cnt[1] != 1) {
TC_ERROR("not trigger callback correctly\n");
goto err_exit;
}
/* 5. remove callback_2 */
gpio_remove_callback(dev, &cb_data[1].gpio_cb);
trigger_callback(dev, 1);
/*= checkpoint: check callback is triggered =*/
if (cb_cnt[0] != 0 || cb_cnt[1] != 0) {
TC_ERROR("not trigger callback correctly\n");
goto err_exit;
}
return TC_PASS;
err_exit:
gpio_remove_callback(dev, &cb_data[0].gpio_cb);
gpio_remove_callback(dev, &cb_data[1].gpio_cb);
return TC_FAIL;
}
static int test_callback_enable_disable(void)
{
struct device *dev = device_get_binding(DEV_NAME);
/* SetUp: initialize environment */
init_callback(dev);
/* 3. enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
trigger_callback(dev, 1);
/*= checkpoint: check callback is triggered =*/
if (cb_cnt[0] != 1 || cb_cnt[1] != 1) {
TC_ERROR("not trigger callback correctly\n");
goto err_exit;
}
/* 4. disable callback */
trigger_callback(dev, 0);
/*= checkpoint: check callback is triggered =*/
if (cb_cnt[0] != 0 || cb_cnt[1] != 0) {
TC_ERROR("not trigger callback correctly\n");
goto err_exit;
}
/* 5. enable callback again */
trigger_callback(dev, 1);
/*= checkpoint: check callback is triggered =*/
if (cb_cnt[0] != 1 || cb_cnt[1] != 1) {
TC_ERROR("not trigger callback correctly\n");
goto err_exit;
}
gpio_remove_callback(dev, &cb_data[0].gpio_cb);
gpio_remove_callback(dev, &cb_data[1].gpio_cb);
return TC_PASS;
err_exit:
gpio_remove_callback(dev, &cb_data[0].gpio_cb);
gpio_remove_callback(dev, &cb_data[1].gpio_cb);
return TC_FAIL;
}
void test_gpio_callback_add_remove(void)
{
assert_true(
test_callback_add_remove() == TC_PASS, NULL);
}
void test_gpio_callback_enable_disable(void)
{
assert_true(
test_callback_enable_disable() == TC_PASS, NULL);
}

View file

@ -0,0 +1,146 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @addtogroup t_gpio_basic_api
* @{
* @defgroup t_gpio_callback_trigger test_gpio_callback_trigger
* @brief TestPurpose: verify zephyr gpio callback triggered
* under different INT modes
* @}
*/
#include "test_gpio.h"
static struct drv_data data;
static int cb_cnt;
static int pin_num(uint32_t pins)
{
int ret = 0;
while (pins >>= 1) {
ret++;
}
return ret;
}
static void callback(struct device *dev,
struct gpio_callback *gpio_cb, uint32_t pins)
{
/*= checkpoint: pins should be marked with correct pin number bit =*/
assert_true(pin_num(pins) == PIN_IN, NULL);
TC_PRINT("callback triggered: %d\n", ++cb_cnt);
if (cb_cnt >= MAX_INT_CNT) {
struct drv_data *drv_data = CONTAINER_OF(gpio_cb,
struct drv_data, gpio_cb);
gpio_pin_write(dev, PIN_OUT,
(drv_data->mode & GPIO_INT_ACTIVE_HIGH) ? 0 : 1);
}
}
static int test_callback(int mode)
{
struct device *dev = device_get_binding(DEV_NAME);
gpio_pin_disable_callback(dev, PIN_IN);
gpio_pin_disable_callback(dev, PIN_OUT);
/* 1. set PIN_OUT to initial state */
if (gpio_pin_configure(dev, PIN_OUT, GPIO_DIR_OUT) != 0) {
TC_ERROR("PIN_OUT config fail\n");
return TC_FAIL;
}
if (gpio_pin_write(dev, PIN_OUT,
(mode & GPIO_INT_ACTIVE_HIGH) ? 0 : 1) != 0) {
TC_ERROR("set PIN_OUT init voltage fail\n");
return TC_FAIL;
}
/* 2. configure PIN_IN callback and trigger condition */
if (gpio_pin_configure(dev, PIN_IN,
GPIO_DIR_IN | GPIO_INT | mode | GPIO_INT_DEBOUNCE) != 0) {
TC_ERROR("config PIN_IN fail");
goto err_exit;
}
struct drv_data *drv_data = &data;
drv_data->mode = mode;
gpio_init_callback(&drv_data->gpio_cb, callback, BIT(PIN_IN));
if (gpio_add_callback(dev, &drv_data->gpio_cb) != 0) {
TC_ERROR("set PIN_IN callback fail\n");
return TC_FAIL;
}
/* 3. enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
cb_cnt = 0;
gpio_pin_enable_callback(dev, PIN_IN);
k_sleep(100);
gpio_pin_write(dev, PIN_OUT, (mode & GPIO_INT_ACTIVE_HIGH) ? 1 : 0);
k_sleep(1000);
/*= checkpoint: check callback is triggered =*/
TC_PRINT("check enabled callback\n");
if (mode & GPIO_INT_EDGE) {
if (cb_cnt != 1) {
TC_ERROR("not trigger callback correctly\n");
goto err_exit;
}
}
if (mode & GPIO_INT_LEVEL) {
if (cb_cnt != MAX_INT_CNT) {
TC_ERROR("not trigger callback correctly\n");
goto err_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_edge_high(void)
{
assert_true(
test_callback(GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH) == TC_PASS,
NULL);
}
void test_gpio_callback_edge_low(void)
{
assert_true(
test_callback(GPIO_INT_EDGE | GPIO_INT_ACTIVE_LOW) == TC_PASS,
NULL);
}
void test_gpio_callback_level_high(void)
{
assert_true(
test_callback(GPIO_INT_LEVEL | GPIO_INT_ACTIVE_HIGH) == TC_PASS,
NULL);
}
void test_gpio_callback_level_low(void)
{
assert_true(
test_callback(GPIO_INT_LEVEL | GPIO_INT_ACTIVE_LOW) == TC_PASS,
NULL);
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2015-2016 Intel Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __TEST_GPIO_H__
#define __TEST_GPIO_H__
#include <zephyr.h>
#include <gpio.h>
#include <misc/util.h>
#include <ztest.h>
#if defined(CONFIG_BOARD_QUARK_SE_C1000_DEVBOARD)
#define DEV_NAME CONFIG_GPIO_QMSI_0_NAME
#define PIN_OUT 15 /* GPIO15_I2S_RXD */
#define PIN_IN 16 /* GPIO16_I2S_RSCK */
#elif defined(CONFIG_BOARD_QUARK_SE_C1000_DEVBOARD_SS)
#define DEV_NAME CONFIG_GPIO_QMSI_SS_0_NAME
#define PIN_OUT 4 /* GPIO_SS_AIN_12 */
#define PIN_IN 5 /* GPIO_SS_AIN_13 */
#elif defined(CONFIG_BOARD_ARDUINO_101)
#define DEV_NAME CONFIG_GPIO_QMSI_0_NAME
#define PIN_OUT 16 /* IO8 */
#define PIN_IN 19 /* IO4 */
#endif
#define MAX_INT_CNT 3
struct drv_data {
struct gpio_callback gpio_cb;
int mode;
int index;
};
void test_gpio_pin_read_write(void);
void test_gpio_callback_edge_high(void);
void test_gpio_callback_edge_low(void);
void test_gpio_callback_level_high(void);
void test_gpio_callback_level_low(void);
void test_gpio_callback_add_remove(void);
void test_gpio_callback_enable_disable(void);
#endif /* __TEST_GPIO_H__ */

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @addtogroup t_gpio_basic_api
* @{
* @defgroup t_gpio_basic_read_write test_gpio_basic_read_write
* @brief TestPurpose: verify zephyr gpio read and write correctly
* @}
*/
#include <stdlib.h>
#include "test_gpio.h"
void test_gpio_pin_read_write(void)
{
struct device *dev = device_get_binding(DEV_NAME);
/* set PIN_OUT as writer */
TC_PRINT("device=%s, pin1=%d, pin2=%d\n", DEV_NAME, PIN_OUT, PIN_IN);
gpio_pin_configure(dev, PIN_OUT, GPIO_DIR_OUT);
/* set PIN_IN as reader */
gpio_pin_configure(dev, PIN_IN, GPIO_DIR_IN);
gpio_pin_disable_callback(dev, PIN_IN);
uint32_t val_write, val_read = 0;
int i = 0;
while (i++ < 32) {
val_write = rand() % 2;
assert_true(gpio_pin_write(dev, PIN_OUT, val_write) == 0,
"write data fail");
TC_PRINT("write: %lu\n", val_write);
k_sleep(100);
assert_true(gpio_pin_read(dev, PIN_IN, &val_read) == 0,
"read data fail");
TC_PRINT("read: %lu\n", val_read);
/*= checkpoint: compare write and read value =*/
assert_true(val_write == val_read,
"Inconsistent GPIO read/write value");
}
}

View file

@ -0,0 +1,5 @@
[test_dma]
tags = drivers
build_only = true
arch_whitelist = x86 arc
platform_whitelist = quark_se_c1000_devboard quark_se_c1000_ss_devboard arduino_101