tests: drivers: counter: Extend basic api test with ZLI support
Modified test to handle case when counter handlers are called in ZLI interrupt context where kernel primitives cannot be used. In that case volatile counters are used to track number of handlers calls. Added configuration for nrf52840dk board where zli feature is enabled for all counters. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
0419ff72aa
commit
f923779e4d
|
@ -0,0 +1,14 @@
|
|||
CONFIG_COUNTER_TIMER0=y
|
||||
CONFIG_COUNTER_TIMER0_ZLI=y
|
||||
CONFIG_COUNTER_TIMER1=y
|
||||
CONFIG_COUNTER_TIMER1_ZLI=y
|
||||
CONFIG_COUNTER_TIMER2=y
|
||||
CONFIG_COUNTER_TIMER2_ZLI=y
|
||||
CONFIG_COUNTER_TIMER3=y
|
||||
CONFIG_COUNTER_TIMER3_ZLI=y
|
||||
CONFIG_COUNTER_TIMER4=y
|
||||
CONFIG_COUNTER_TIMER4_ZLI=y
|
||||
CONFIG_COUNTER_RTC0=y
|
||||
CONFIG_COUNTER_RTC0_ZLI=y
|
||||
CONFIG_COUNTER_RTC2=y
|
||||
CONFIG_COUNTER_RTC2_ZLI=y
|
|
@ -11,7 +11,9 @@
|
|||
LOG_MODULE_REGISTER(test);
|
||||
|
||||
static struct k_sem top_cnt_sem;
|
||||
static volatile uint32_t top_cnt;
|
||||
static struct k_sem alarm_cnt_sem;
|
||||
static volatile uint32_t alarm_cnt;
|
||||
|
||||
static void top_handler(const struct device *dev, void *user_data);
|
||||
|
||||
|
@ -94,6 +96,9 @@ typedef bool (*counter_capability_func_t)(const char *dev_name);
|
|||
static void counter_setup_instance(const char *dev_name)
|
||||
{
|
||||
k_sem_reset(&alarm_cnt_sem);
|
||||
if (!k_is_user_context()) {
|
||||
alarm_cnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void counter_tear_down_instance(const char *dev_name)
|
||||
|
@ -168,6 +173,12 @@ static void top_handler(const struct device *dev, void *user_data)
|
|||
{
|
||||
zassert_true(user_data == exp_user_data,
|
||||
"%s: Unexpected callback", dev->name);
|
||||
if (IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS)) {
|
||||
top_cnt++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
k_sem_give(&top_cnt_sem);
|
||||
}
|
||||
|
||||
|
@ -176,8 +187,9 @@ void test_set_top_value_with_alarm_instance(const char *dev_name)
|
|||
const struct device *dev;
|
||||
int err;
|
||||
uint32_t cnt;
|
||||
uint32_t top_value;
|
||||
uint32_t counter_period_us;
|
||||
uint32_t top_cnt;
|
||||
uint32_t top_handler_cnt;
|
||||
struct counter_top_cfg top_cfg = {
|
||||
.callback = top_handler,
|
||||
.user_data = exp_user_data,
|
||||
|
@ -185,6 +197,7 @@ void test_set_top_value_with_alarm_instance(const char *dev_name)
|
|||
};
|
||||
|
||||
k_sem_reset(&top_cnt_sem);
|
||||
top_cnt = 0;
|
||||
|
||||
dev = device_get_binding(dev_name);
|
||||
if (strcmp(dev_name, "RTC_0") == 0) {
|
||||
|
@ -206,8 +219,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 {
|
||||
top_cnt = counter_get_top_value(dev);
|
||||
err = (cnt < top_cnt) ? 0 : 1;
|
||||
top_value = counter_get_top_value(dev);
|
||||
err = (cnt < top_value) ? 0 : 1;
|
||||
}
|
||||
zassert_true(err == 0, "%s: Counter should progress", dev_name);
|
||||
|
||||
|
@ -217,10 +230,11 @@ void test_set_top_value_with_alarm_instance(const char *dev_name)
|
|||
|
||||
k_busy_wait(5.2*counter_period_us);
|
||||
|
||||
top_cnt = k_sem_count_get(&top_cnt_sem);
|
||||
zassert_true(top_cnt == 5U,
|
||||
top_handler_cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ?
|
||||
top_cnt : k_sem_count_get(&top_cnt_sem);
|
||||
zassert_true(top_handler_cnt == 5U,
|
||||
"%s: Unexpected number of turnarounds (%d).",
|
||||
dev_name, top_cnt);
|
||||
dev_name, top_handler_cnt);
|
||||
}
|
||||
|
||||
void test_set_top_value_with_alarm(void)
|
||||
|
@ -234,7 +248,7 @@ void test_set_top_value_without_alarm_instance(const char *dev_name)
|
|||
const struct device *dev;
|
||||
int err;
|
||||
uint32_t cnt;
|
||||
uint32_t top_cnt;
|
||||
uint32_t top_value;
|
||||
uint32_t counter_period_us;
|
||||
struct counter_top_cfg top_cfg = {
|
||||
.callback = NULL,
|
||||
|
@ -262,8 +276,8 @@ void test_set_top_value_without_alarm_instance(const char *dev_name)
|
|||
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;
|
||||
top_value = counter_get_top_value(dev);
|
||||
err = (cnt < top_value) ? 0 : 1;
|
||||
}
|
||||
zassert_true(err == 0, "%s: Counter should progress", dev_name);
|
||||
|
||||
|
@ -319,6 +333,10 @@ static void alarm_handler(const struct device *dev, uint8_t chan_id,
|
|||
"%s: Unexpected callback", dev->name);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS)) {
|
||||
alarm_cnt++;
|
||||
return;
|
||||
}
|
||||
zassert_true(k_is_in_isr(), "%s: Expected interrupt context",
|
||||
dev->name);
|
||||
k_sem_give(&alarm_cnt_sem);
|
||||
|
@ -329,7 +347,7 @@ void test_single_shot_alarm_instance(const char *dev_name, bool set_top)
|
|||
const struct device *dev;
|
||||
int err;
|
||||
uint32_t ticks;
|
||||
uint32_t alarm_cnt;
|
||||
uint32_t cnt;
|
||||
uint32_t counter_period_us;
|
||||
struct counter_top_cfg top_cfg = {
|
||||
.callback = top_handler,
|
||||
|
@ -353,6 +371,7 @@ void test_single_shot_alarm_instance(const char *dev_name, bool set_top)
|
|||
alarm_cfg.user_data = &alarm_cfg;
|
||||
|
||||
k_sem_reset(&alarm_cnt_sem);
|
||||
alarm_cnt = 0;
|
||||
|
||||
if (counter_get_num_of_channels(dev) < 1U) {
|
||||
/* Counter does not support any alarm */
|
||||
|
@ -383,14 +402,14 @@ void test_single_shot_alarm_instance(const char *dev_name, bool set_top)
|
|||
|
||||
k_busy_wait(2*(uint32_t)counter_ticks_to_us(dev, ticks));
|
||||
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(1, alarm_cnt,
|
||||
"%s: Expecting alarm callback", dev_name);
|
||||
cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ?
|
||||
alarm_cnt : k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(1, cnt, "%s: Expecting alarm callback", dev_name);
|
||||
|
||||
k_busy_wait(1.5*counter_ticks_to_us(dev, ticks));
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(1, alarm_cnt,
|
||||
"%s: Expecting alarm callback", dev_name);
|
||||
cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ?
|
||||
alarm_cnt : k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(1, cnt, "%s: Expecting alarm callback", dev_name);
|
||||
|
||||
err = counter_cancel_channel_alarm(dev, 0);
|
||||
zassert_equal(0, err, "%s: Counter disabling alarm failed", dev_name);
|
||||
|
@ -453,6 +472,13 @@ static void alarm_handler2(const struct device *dev, uint8_t chan_id,
|
|||
uint32_t counter,
|
||||
void *user_data)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS)) {
|
||||
clbk_data[alarm_cnt] = user_data;
|
||||
alarm_cnt++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
clbk_data[k_sem_count_get(&alarm_cnt_sem)] = user_data;
|
||||
k_sem_give(&alarm_cnt_sem);
|
||||
}
|
||||
|
@ -468,7 +494,7 @@ void test_multiple_alarms_instance(const char *dev_name)
|
|||
const struct device *dev;
|
||||
int err;
|
||||
uint32_t ticks;
|
||||
uint32_t alarm_cnt;
|
||||
uint32_t cnt;
|
||||
uint32_t counter_period_us;
|
||||
struct counter_top_cfg top_cfg = {
|
||||
.callback = top_handler,
|
||||
|
@ -498,6 +524,7 @@ void test_multiple_alarms_instance(const char *dev_name)
|
|||
alarm_cfg2.user_data = &alarm_cfg2;
|
||||
|
||||
k_sem_reset(&alarm_cnt_sem);
|
||||
alarm_cnt = 0;
|
||||
|
||||
if (counter_get_num_of_channels(dev) < 2U) {
|
||||
/* Counter does not support two alarms */
|
||||
|
@ -520,10 +547,11 @@ 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));
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(2, alarm_cnt,
|
||||
cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ?
|
||||
alarm_cnt : k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(2, cnt,
|
||||
"%s: Invalid number of callbacks %d (expected: %d)",
|
||||
dev_name, alarm_cnt, 2);
|
||||
dev_name, cnt, 2);
|
||||
|
||||
zassert_equal(&alarm_cfg2, clbk_data[0],
|
||||
"%s: Expected different order or callbacks",
|
||||
|
@ -562,7 +590,7 @@ void test_all_channels_instance(const char *dev_name)
|
|||
bool limit_reached = false;
|
||||
struct counter_alarm_cfg alarm_cfgs;
|
||||
uint32_t ticks;
|
||||
uint32_t alarm_cnt;
|
||||
uint32_t cnt;
|
||||
uint32_t counter_period_us;
|
||||
|
||||
if (strcmp(dev_name, "RTC_0") == 0) {
|
||||
|
@ -594,8 +622,9 @@ void test_all_channels_instance(const char *dev_name)
|
|||
}
|
||||
|
||||
k_busy_wait(1.5*counter_ticks_to_us(dev, ticks));
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(nchan, alarm_cnt,
|
||||
cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ?
|
||||
alarm_cnt : k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(nchan, cnt,
|
||||
"%s: Expecting alarm callback", dev_name);
|
||||
|
||||
for (int i = 0; i < nchan; i++) {
|
||||
|
@ -624,7 +653,7 @@ void test_all_channels(void)
|
|||
void test_late_alarm_instance(const char *dev_name)
|
||||
{
|
||||
int err;
|
||||
uint32_t alarm_cnt;
|
||||
uint32_t cnt;
|
||||
const struct device *dev = device_get_binding(dev_name);
|
||||
uint32_t tick_us = (uint32_t)counter_ticks_to_us(dev, 1);
|
||||
uint32_t guard = counter_us_to_ticks(dev, 200);
|
||||
|
@ -651,10 +680,11 @@ void test_late_alarm_instance(const char *dev_name)
|
|||
/* wait couple of ticks */
|
||||
k_busy_wait(5*tick_us);
|
||||
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(1, alarm_cnt,
|
||||
cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ?
|
||||
alarm_cnt : k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(1, cnt,
|
||||
"%s: Expected %d callbacks, got %d\n",
|
||||
dev_name, 1, alarm_cnt);
|
||||
dev_name, 1, cnt);
|
||||
|
||||
err = counter_get_value(dev, &(alarm_cfg.ticks));
|
||||
zassert_true(err == 0, "%s: Counter read failed (err: %d)", dev_name,
|
||||
|
@ -667,10 +697,11 @@ void test_late_alarm_instance(const char *dev_name)
|
|||
/* wait to ensure that tick+1 timeout will expire. */
|
||||
k_busy_wait(3*tick_us);
|
||||
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(2, alarm_cnt,
|
||||
cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ?
|
||||
alarm_cnt : k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(2, cnt,
|
||||
"%s: Expected %d callbacks, got %d\n",
|
||||
dev_name, 2, alarm_cnt);
|
||||
dev_name, 2, cnt);
|
||||
}
|
||||
|
||||
void test_late_alarm_error_instance(const char *dev_name)
|
||||
|
@ -739,7 +770,7 @@ void test_late_alarm_error(void)
|
|||
static void test_short_relative_alarm_instance(const char *dev_name)
|
||||
{
|
||||
int err;
|
||||
uint32_t alarm_cnt;
|
||||
uint32_t cnt;
|
||||
const struct device *dev = device_get_binding(dev_name);
|
||||
uint32_t tick_us = (uint32_t)counter_ticks_to_us(dev, 1);
|
||||
struct counter_alarm_cfg alarm_cfg = {
|
||||
|
@ -762,10 +793,11 @@ 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);
|
||||
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(i + 1, alarm_cnt,
|
||||
cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ?
|
||||
alarm_cnt : k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(i + 1, cnt,
|
||||
"%s: Expected %d callbacks, got %d\n",
|
||||
dev_name, i + 1, alarm_cnt);
|
||||
dev_name, i + 1, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -783,6 +815,7 @@ static bool short_relative_capable(const char *dev_name)
|
|||
.ticks = 1
|
||||
};
|
||||
int err;
|
||||
uint32_t cnt;
|
||||
bool ret;
|
||||
|
||||
if (single_channel_alarm_capable(dev_name) == false) {
|
||||
|
@ -796,6 +829,7 @@ static bool short_relative_capable(const char *dev_name)
|
|||
}
|
||||
|
||||
k_sem_reset(&alarm_cnt_sem);
|
||||
alarm_cnt = 0;
|
||||
err = counter_set_channel_alarm(dev, 0, &alarm_cfg);
|
||||
if (err != 0) {
|
||||
ret = false;
|
||||
|
@ -803,7 +837,9 @@ static bool short_relative_capable(const char *dev_name)
|
|||
}
|
||||
|
||||
k_busy_wait(counter_ticks_to_us(dev, 10));
|
||||
if (k_sem_count_get(&alarm_cnt_sem) == 1) {
|
||||
cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ?
|
||||
alarm_cnt : k_sem_count_get(&alarm_cnt_sem);
|
||||
if (cnt == 1) {
|
||||
ret = true;
|
||||
} else {
|
||||
ret = false;
|
||||
|
@ -812,6 +848,7 @@ static bool short_relative_capable(const char *dev_name)
|
|||
|
||||
end:
|
||||
k_sem_reset(&alarm_cnt_sem);
|
||||
alarm_cnt = 0;
|
||||
counter_stop(dev);
|
||||
k_busy_wait(1000);
|
||||
|
||||
|
@ -830,7 +867,7 @@ static void test_short_relative_alarm(void)
|
|||
static void test_cancelled_alarm_does_not_expire_instance(const char *dev_name)
|
||||
{
|
||||
int err;
|
||||
uint32_t alarm_cnt;
|
||||
uint32_t cnt;
|
||||
const struct device *dev = device_get_binding(dev_name);
|
||||
uint32_t us = 1000;
|
||||
uint32_t ticks = counter_us_to_ticks(dev, us);
|
||||
|
@ -878,10 +915,11 @@ 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);
|
||||
|
||||
alarm_cnt = k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(0, alarm_cnt,
|
||||
cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ?
|
||||
alarm_cnt : k_sem_count_get(&alarm_cnt_sem);
|
||||
zassert_equal(0, cnt,
|
||||
"%s: Expected %d callbacks, got %d (i:%d)\n",
|
||||
dev_name, 0, alarm_cnt, i);
|
||||
dev_name, 0, cnt, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,3 +5,10 @@ tests:
|
|||
min_ram: 16
|
||||
platform_exclude: nucleo_f302r8
|
||||
timeout: 400
|
||||
drivers.counter_nrf_zli:
|
||||
tags: drivers
|
||||
depends_on: counter
|
||||
platform_allow: nrf52840dk_nrf52840
|
||||
timeout: 400
|
||||
extra_args: >
|
||||
OVERLAY_CONFIG="zli.conf;boards/nrf52840dk_nrf52840_zli.conf"
|
||||
|
|
1
tests/drivers/counter/counter_basic_api/zli.conf
Normal file
1
tests/drivers/counter/counter_basic_api/zli.conf
Normal file
|
@ -0,0 +1 @@
|
|||
CONFIG_ZERO_LATENCY_IRQS=y
|
Loading…
Reference in a new issue