tests: drivers: counter: add user mode test
Add a single counter API test case (not using callbacks) running in user mode. Convert the existing test setup to use semaphores for counting events to be able to utilize the same test setup and teardown functionality in both user and supervisor mode tests. Most of the counter API basic test suite still needs to run in supervisor mode due the use of callback functions. Signed-off-by: Henrik Brix Andersen <henrik@brixandersen.dk>
This commit is contained in:
parent
0f60477667
commit
cf64c6bcca
2 changed files with 112 additions and 50 deletions
|
@ -1,5 +1,6 @@
|
|||
CONFIG_COUNTER=y
|
||||
CONFIG_BT=n
|
||||
CONFIG_ZTEST=y
|
||||
CONFIG_TEST_USERSPACE=y
|
||||
CONFIG_LOG=y
|
||||
CONFIG_COUNTER_LOG_LEVEL_DBG=y
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(test);
|
||||
|
||||
static volatile u32_t top_cnt;
|
||||
static volatile u32_t alarm_cnt;
|
||||
static struct k_sem top_cnt_sem;
|
||||
static struct k_sem alarm_cnt_sem;
|
||||
|
||||
static void top_handler(struct device *dev, void *user_data);
|
||||
|
||||
|
@ -26,7 +26,7 @@ void *exp_user_data = (void *)199;
|
|||
struct counter_alarm_cfg alarm_cfg;
|
||||
struct counter_alarm_cfg alarm_cfg2;
|
||||
|
||||
const char *devices[] = {
|
||||
static const char * const devices[] = {
|
||||
#ifdef CONFIG_COUNTER_TIMER0
|
||||
/* Nordic TIMER0 may be reserved for Bluetooth */
|
||||
DT_NORDIC_NRF_TIMER_TIMER_0_LABEL,
|
||||
|
@ -78,7 +78,7 @@ typedef bool (*counter_capability_func_t)(const char *dev_name);
|
|||
|
||||
static void counter_setup_instance(const char *dev_name)
|
||||
{
|
||||
alarm_cnt = 0U;
|
||||
k_sem_reset(&alarm_cnt_sem);
|
||||
}
|
||||
|
||||
static void counter_tear_down_instance(const char *dev_name)
|
||||
|
@ -147,7 +147,7 @@ static void top_handler(struct device *dev, void *user_data)
|
|||
{
|
||||
zassert_true(user_data == exp_user_data,
|
||||
"%s: Unexpected callback", dev->config->name);
|
||||
top_cnt++;
|
||||
k_sem_give(&top_cnt_sem);
|
||||
}
|
||||
|
||||
void test_set_top_value_with_alarm_instance(const char *dev_name)
|
||||
|
@ -155,14 +155,14 @@ void test_set_top_value_with_alarm_instance(const char *dev_name)
|
|||
struct device *dev;
|
||||
int err;
|
||||
u32_t cnt;
|
||||
u32_t tmp_top_cnt;
|
||||
u32_t top_cnt;
|
||||
struct counter_top_cfg top_cfg = {
|
||||
.callback = top_handler,
|
||||
.user_data = exp_user_data,
|
||||
.flags = 0
|
||||
};
|
||||
|
||||
top_cnt = 0U;
|
||||
k_sem_reset(&top_cnt_sem);
|
||||
|
||||
dev = device_get_binding(dev_name);
|
||||
top_cfg.ticks = counter_us_to_ticks(dev, COUNTER_PERIOD_US);
|
||||
|
@ -175,8 +175,8 @@ void test_set_top_value_with_alarm_instance(const char *dev_name)
|
|||
if (counter_is_counting_up(dev)) {
|
||||
err = (cnt > 0) ? 0 : 1;
|
||||
} else {
|
||||
tmp_top_cnt = counter_get_top_value(dev);
|
||||
err = (cnt < tmp_top_cnt) ? 0 : 1;
|
||||
top_cnt = counter_get_top_value(dev);
|
||||
err = (cnt < top_cnt) ? 0 : 1;
|
||||
}
|
||||
zassert_true(err == 0, "%s: Counter should progress", dev_name);
|
||||
|
||||
|
@ -186,10 +186,10 @@ void test_set_top_value_with_alarm_instance(const char *dev_name)
|
|||
|
||||
k_busy_wait(5.2*COUNTER_PERIOD_US);
|
||||
|
||||
tmp_top_cnt = top_cnt; /* to avoid passing volatile to the macro */
|
||||
zassert_true(tmp_top_cnt == 5U,
|
||||
top_cnt = k_sem_count_get(&top_cnt_sem);
|
||||
zassert_true(top_cnt == 5U,
|
||||
"%s: Unexpected number of turnarounds (%d).",
|
||||
dev_name, tmp_top_cnt);
|
||||
dev_name, top_cnt);
|
||||
}
|
||||
|
||||
void test_set_top_value_with_alarm(void)
|
||||
|
@ -198,6 +198,49 @@ void test_set_top_value_with_alarm(void)
|
|||
set_top_value_capable);
|
||||
}
|
||||
|
||||
void test_set_top_value_without_alarm_instance(const char *dev_name)
|
||||
{
|
||||
struct device *dev;
|
||||
int err;
|
||||
u32_t cnt;
|
||||
u32_t top_cnt;
|
||||
struct counter_top_cfg top_cfg = {
|
||||
.callback = NULL,
|
||||
.user_data = NULL,
|
||||
.flags = 0
|
||||
};
|
||||
|
||||
dev = device_get_binding(dev_name);
|
||||
top_cfg.ticks = counter_us_to_ticks(dev, COUNTER_PERIOD_US);
|
||||
err = counter_start(dev);
|
||||
zassert_equal(0, err, "%s: Counter failed to start", dev_name);
|
||||
|
||||
k_busy_wait(5000);
|
||||
|
||||
cnt = counter_read(dev);
|
||||
if (counter_is_counting_up(dev)) {
|
||||
err = (cnt > 0) ? 0 : 1;
|
||||
} else {
|
||||
top_cnt = counter_get_top_value(dev);
|
||||
err = (cnt < top_cnt) ? 0 : 1;
|
||||
}
|
||||
zassert_true(err == 0, "%s: Counter should progress", dev_name);
|
||||
|
||||
err = counter_set_top_value(dev, &top_cfg);
|
||||
zassert_equal(0, err, "%s: Counter failed to set top value (err: %d)",
|
||||
dev_name, err);
|
||||
|
||||
zassert_true(counter_get_top_value(dev) == top_cfg.ticks,
|
||||
"%s: new top value not in use.",
|
||||
dev_name);
|
||||
}
|
||||
|
||||
void test_set_top_value_without_alarm(void)
|
||||
{
|
||||
test_all_instances(test_set_top_value_without_alarm_instance,
|
||||
set_top_value_capable);
|
||||
}
|
||||
|
||||
static void alarm_handler(struct device *dev, u8_t chan_id, u32_t counter,
|
||||
void *user_data)
|
||||
{
|
||||
|
@ -220,7 +263,7 @@ static void alarm_handler(struct device *dev, u8_t chan_id, u32_t counter,
|
|||
|
||||
zassert_true(k_is_in_isr(), "%s: Expected interrupt context",
|
||||
dev->config->name);
|
||||
alarm_cnt++;
|
||||
k_sem_give(&alarm_cnt_sem);
|
||||
}
|
||||
|
||||
void test_single_shot_alarm_instance(const char *dev_name, bool set_top)
|
||||
|
@ -228,7 +271,7 @@ void test_single_shot_alarm_instance(const char *dev_name, bool set_top)
|
|||
struct device *dev;
|
||||
int err;
|
||||
u32_t ticks;
|
||||
u32_t tmp_alarm_cnt;
|
||||
u32_t alarm_cnt;
|
||||
struct counter_top_cfg top_cfg = {
|
||||
.callback = top_handler,
|
||||
.user_data = exp_user_data,
|
||||
|
@ -243,7 +286,7 @@ void test_single_shot_alarm_instance(const char *dev_name, bool set_top)
|
|||
alarm_cfg.callback = alarm_handler;
|
||||
alarm_cfg.user_data = &alarm_cfg;
|
||||
|
||||
alarm_cnt = 0U;
|
||||
k_sem_reset(&alarm_cnt_sem);
|
||||
|
||||
if (counter_get_num_of_channels(dev) < 1U) {
|
||||
/* Counter does not support any alarm */
|
||||
|
@ -274,13 +317,13 @@ void test_single_shot_alarm_instance(const char *dev_name, bool set_top)
|
|||
|
||||
k_busy_wait(2*(u32_t)counter_ticks_to_us(dev, ticks));
|
||||
|
||||
tmp_alarm_cnt = alarm_cnt; /* to avoid passing volatile to the macro */
|
||||
zassert_equal(1, tmp_alarm_cnt,
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(1, alarm_cnt,
|
||||
"%s: Expecting alarm callback", dev_name);
|
||||
|
||||
k_busy_wait(1.5*counter_ticks_to_us(dev, ticks));
|
||||
tmp_alarm_cnt = alarm_cnt; /* to avoid passing volatile to the macro */
|
||||
zassert_equal(1, tmp_alarm_cnt,
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(1, alarm_cnt,
|
||||
"%s: Expecting alarm callback", dev_name);
|
||||
|
||||
err = counter_cancel_channel_alarm(dev, 0);
|
||||
|
@ -337,8 +380,8 @@ static void *clbk_data[10];
|
|||
static void alarm_handler2(struct device *dev, u8_t chan_id, u32_t counter,
|
||||
void *user_data)
|
||||
{
|
||||
clbk_data[alarm_cnt] = user_data;
|
||||
alarm_cnt++;
|
||||
clbk_data[k_sem_count_get(&alarm_cnt_sem)] = user_data;
|
||||
k_sem_give(&alarm_cnt_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -352,7 +395,7 @@ void test_multiple_alarms_instance(const char *dev_name)
|
|||
struct device *dev;
|
||||
int err;
|
||||
u32_t ticks;
|
||||
u32_t tmp_alarm_cnt;
|
||||
u32_t alarm_cnt;
|
||||
struct counter_top_cfg top_cfg = {
|
||||
.callback = top_handler,
|
||||
.user_data = exp_user_data,
|
||||
|
@ -373,7 +416,7 @@ void test_multiple_alarms_instance(const char *dev_name)
|
|||
alarm_cfg2.callback = alarm_handler2;
|
||||
alarm_cfg2.user_data = &alarm_cfg2;
|
||||
|
||||
alarm_cnt = 0U;
|
||||
k_sem_reset(&alarm_cnt_sem);
|
||||
|
||||
if (counter_get_num_of_channels(dev) < 2U) {
|
||||
/* Counter does not support two alarms */
|
||||
|
@ -396,10 +439,10 @@ void test_multiple_alarms_instance(const char *dev_name)
|
|||
zassert_equal(0, err, "%s: Counter set alarm failed", dev_name);
|
||||
|
||||
k_busy_wait(1.2*counter_ticks_to_us(dev, ticks * 2U));
|
||||
tmp_alarm_cnt = alarm_cnt; /* to avoid passing volatile to the macro */
|
||||
zassert_equal(2, tmp_alarm_cnt,
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(2, alarm_cnt,
|
||||
"%s: Invalid number of callbacks %d (expected: %d)",
|
||||
dev_name, tmp_alarm_cnt, 2);
|
||||
dev_name, alarm_cnt, 2);
|
||||
|
||||
zassert_equal(&alarm_cfg2, clbk_data[0],
|
||||
"%s: Expected different order or callbacks",
|
||||
|
@ -438,7 +481,7 @@ void test_all_channels_instance(const char *dev_name)
|
|||
bool limit_reached = false;
|
||||
struct counter_alarm_cfg alarm_cfgs;
|
||||
u32_t ticks;
|
||||
u32_t tmp_alarm_cnt;
|
||||
u32_t alarm_cnt;
|
||||
|
||||
dev = device_get_binding(dev_name);
|
||||
ticks = counter_us_to_ticks(dev, COUNTER_PERIOD_US);
|
||||
|
@ -464,8 +507,8 @@ void test_all_channels_instance(const char *dev_name)
|
|||
}
|
||||
|
||||
k_busy_wait(1.5*counter_ticks_to_us(dev, ticks));
|
||||
tmp_alarm_cnt = alarm_cnt; /* to avoid passing volatile to the macro */
|
||||
zassert_equal(nchan, tmp_alarm_cnt,
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(nchan, alarm_cnt,
|
||||
"%s: Expecting alarm callback", dev_name);
|
||||
|
||||
for (int i = 0; i < nchan; i++) {
|
||||
|
@ -494,7 +537,7 @@ void test_all_channels(void)
|
|||
void test_late_alarm_instance(const char *dev_name)
|
||||
{
|
||||
int err;
|
||||
u32_t tmp_alarm_cnt;
|
||||
u32_t alarm_cnt;
|
||||
struct device *dev = device_get_binding(dev_name);
|
||||
u32_t tick_us = (u32_t)counter_ticks_to_us(dev, 1);
|
||||
u32_t guard = counter_us_to_ticks(dev, 200);
|
||||
|
@ -521,10 +564,10 @@ void test_late_alarm_instance(const char *dev_name)
|
|||
/* wait couple of ticks */
|
||||
k_busy_wait(5*tick_us);
|
||||
|
||||
tmp_alarm_cnt = alarm_cnt; /* to avoid passing volatile to the macro */
|
||||
zassert_equal(1, tmp_alarm_cnt,
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(1, alarm_cnt,
|
||||
"%s: Expected %d callbacks, got %d\n",
|
||||
dev_name, 1, tmp_alarm_cnt);
|
||||
dev_name, 1, alarm_cnt);
|
||||
|
||||
alarm_cfg.ticks = counter_read(dev);
|
||||
err = counter_set_channel_alarm(dev, 0, &alarm_cfg);
|
||||
|
@ -534,10 +577,10 @@ void test_late_alarm_instance(const char *dev_name)
|
|||
/* wait to ensure that tick+1 timeout will expire. */
|
||||
k_busy_wait(3*tick_us);
|
||||
|
||||
tmp_alarm_cnt = alarm_cnt; /* to avoid passing volatile to the macro */
|
||||
zassert_equal(2, tmp_alarm_cnt,
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(2, alarm_cnt,
|
||||
"%s: Expected %d callbacks, got %d\n",
|
||||
dev_name, 2, tmp_alarm_cnt);
|
||||
dev_name, 2, alarm_cnt);
|
||||
}
|
||||
|
||||
void test_late_alarm_error_instance(const char *dev_name)
|
||||
|
@ -603,7 +646,7 @@ void test_late_alarm_error(void)
|
|||
static void test_short_relative_alarm_instance(const char *dev_name)
|
||||
{
|
||||
int err;
|
||||
u32_t tmp_alarm_cnt;
|
||||
u32_t alarm_cnt;
|
||||
struct device *dev = device_get_binding(dev_name);
|
||||
u32_t tick_us = (u32_t)counter_ticks_to_us(dev, 1);
|
||||
struct counter_alarm_cfg alarm_cfg = {
|
||||
|
@ -626,11 +669,10 @@ static void test_short_relative_alarm_instance(const char *dev_name)
|
|||
/* wait to ensure that tick+1 timeout will expire. */
|
||||
k_busy_wait(3*tick_us);
|
||||
|
||||
/* to avoid passing volatile to the macro */
|
||||
tmp_alarm_cnt = alarm_cnt;
|
||||
zassert_equal(i + 1, tmp_alarm_cnt,
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(i + 1, alarm_cnt,
|
||||
"%s: Expected %d callbacks, got %d\n",
|
||||
dev_name, i + 1, tmp_alarm_cnt);
|
||||
dev_name, i + 1, alarm_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -660,7 +702,7 @@ static bool short_relative_capable(const char *dev_name)
|
|||
goto end;
|
||||
}
|
||||
|
||||
alarm_cnt = 0;
|
||||
k_sem_reset(&alarm_cnt_sem);
|
||||
err = counter_set_channel_alarm(dev, 0, &alarm_cfg);
|
||||
if (err != 0) {
|
||||
ret = false;
|
||||
|
@ -668,7 +710,7 @@ static bool short_relative_capable(const char *dev_name)
|
|||
}
|
||||
|
||||
k_busy_wait(counter_ticks_to_us(dev, 10));
|
||||
if (alarm_cnt == 1) {
|
||||
if (k_sem_count_get(&alarm_cnt_sem) == 1) {
|
||||
ret = true;
|
||||
} else {
|
||||
ret = false;
|
||||
|
@ -676,7 +718,7 @@ static bool short_relative_capable(const char *dev_name)
|
|||
}
|
||||
|
||||
end:
|
||||
alarm_cnt = 0;
|
||||
k_sem_reset(&alarm_cnt_sem);
|
||||
counter_stop(dev);
|
||||
k_busy_wait(1000);
|
||||
|
||||
|
@ -695,7 +737,7 @@ static void test_short_relative_alarm(void)
|
|||
static void test_cancelled_alarm_does_not_expire_instance(const char *dev_name)
|
||||
{
|
||||
int err;
|
||||
u32_t tmp_alarm_cnt;
|
||||
u32_t alarm_cnt;
|
||||
struct device *dev = device_get_binding(dev_name);
|
||||
u32_t us = 1000;
|
||||
u32_t ticks = counter_us_to_ticks(dev, us);
|
||||
|
@ -736,11 +778,10 @@ static void test_cancelled_alarm_does_not_expire_instance(const char *dev_name)
|
|||
zassert_equal(0, err, "%s: Failed to cancel an alarm (err: %d)",
|
||||
dev_name, err);
|
||||
|
||||
/* to avoid passing volatile to the macro */
|
||||
tmp_alarm_cnt = alarm_cnt;
|
||||
zassert_equal(0, tmp_alarm_cnt,
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(0, alarm_cnt,
|
||||
"%s: Expected %d callbacks, got %d\n",
|
||||
dev_name, 0, tmp_alarm_cnt);
|
||||
dev_name, 0, alarm_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -801,13 +842,30 @@ void test_cancelled_alarm_does_not_expire(void)
|
|||
|
||||
void test_main(void)
|
||||
{
|
||||
struct device *dev;
|
||||
int i;
|
||||
|
||||
/* Give required clocks some time to stabilize. In particular, nRF SoCs
|
||||
* need such delay for the Xtal LF clock source to start and for this
|
||||
* test to use the correct timing.
|
||||
*/
|
||||
k_busy_wait(USEC_PER_MSEC * 300);
|
||||
|
||||
k_sem_init(&top_cnt_sem, 0, UINT_MAX);
|
||||
k_object_access_grant(&top_cnt_sem, k_current_get());
|
||||
|
||||
k_sem_init(&alarm_cnt_sem, 0, UINT_MAX);
|
||||
k_object_access_grant(&alarm_cnt_sem, k_current_get());
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(devices); i++) {
|
||||
dev = device_get_binding(devices[i]);
|
||||
zassert_not_null(dev, "Unable to get counter device %s",
|
||||
devices[i]);
|
||||
k_object_access_grant(dev, k_current_get());
|
||||
}
|
||||
|
||||
ztest_test_suite(test_counter,
|
||||
/* Uses callbacks, run in supervisor mode */
|
||||
ztest_unit_test(test_set_top_value_with_alarm),
|
||||
ztest_unit_test(test_single_shot_alarm_notop),
|
||||
ztest_unit_test(test_single_shot_alarm_top),
|
||||
|
@ -816,7 +874,10 @@ void test_main(void)
|
|||
ztest_unit_test(test_late_alarm),
|
||||
ztest_unit_test(test_late_alarm_error),
|
||||
ztest_unit_test(test_short_relative_alarm),
|
||||
ztest_unit_test(test_cancelled_alarm_does_not_expire)
|
||||
ztest_unit_test(test_cancelled_alarm_does_not_expire),
|
||||
|
||||
/* No callbacks, run in usermode */
|
||||
ztest_user_unit_test(test_set_top_value_without_alarm)
|
||||
);
|
||||
ztest_run_test_suite(test_counter);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue