diff --git a/tests/drivers/counter/counter_basic_api/prj.conf b/tests/drivers/counter/counter_basic_api/prj.conf index f3051dd7427..95b674a1ee8 100644 --- a/tests/drivers/counter/counter_basic_api/prj.conf +++ b/tests/drivers/counter/counter_basic_api/prj.conf @@ -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 diff --git a/tests/drivers/counter/counter_basic_api/src/test_counter.c b/tests/drivers/counter/counter_basic_api/src/test_counter.c index 89eb85cf827..57fa9378491 100644 --- a/tests/drivers/counter/counter_basic_api/src/test_counter.c +++ b/tests/drivers/counter/counter_basic_api/src/test_counter.c @@ -10,8 +10,8 @@ #include 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); }