zephyr/tests/kernel/timer/timer_api/src/test_timer_api.c
Andrew Boie 65a9d2a94a kernel: make K_.*_INITIALIZER private to kernel
Upcoming memory protection features will be placing some additional
constraints on kernel objects:

- They need to reside in memory owned by the kernel and not the
application
- Certain kernel object validation schemes will require some run-time
initialization of all kernel objects before they can be used.

Per Ben these initializer macros were never intended to be public. It is
not forbidden to use them, but doing so requires care: the memory being
initialized must reside in kernel space, and extra runtime
initialization steps may need to be peformed before they are fully
usable as kernel objects. In particular, kernel subsystems or drivers
whose objects are already in kernel memory may still need to use these
macros if they define kernel objects as members of a larger data
structure.

It is intended that application developers instead use the
K_<object>_DEFINE macros, which will automatically put the object in the
right memory and add them to a section which can be iterated over at
boot to complete initiailization.

There was no K_WORK_DEFINE() macro for creating struct k_work objects,
this is now added.

k_poll_event and k_poll_signal are intended to be instatiated from
application memory and have not been changed.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-07-10 11:44:56 -07:00

275 lines
6.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "test_timer.h"
#include <ztest.h>
#define DURATION 100
#define PERIOD 50
#define EXPIRE_TIMES 4
static void duration_expire(struct k_timer *timer);
static void duration_stop(struct k_timer *timer);
/** TESTPOINT: init timer via K_TIMER_DEFINE */
K_TIMER_DEFINE(ktimer, duration_expire, duration_stop);
static struct k_timer timer;
static struct timer_data tdata;
#define TIMER_ASSERT(exp, tmr) \
do { \
if (!(exp)) { \
k_timer_stop(tmr); \
zassert_true(exp, NULL); \
} \
} while (0)
static void init_timer_data(void)
{
tdata.expire_cnt = 0;
tdata.stop_cnt = 0;
}
/* entry routines */
static void duration_expire(struct k_timer *timer)
{
/** TESTPOINT: expire function */
tdata.expire_cnt++;
if (tdata.expire_cnt == 1) {
TIMER_ASSERT(k_uptime_delta(&tdata.timestamp) >= DURATION,
timer);
} else {
TIMER_ASSERT(k_uptime_delta(&tdata.timestamp) >= PERIOD, timer);
}
tdata.timestamp = k_uptime_get();
if (tdata.expire_cnt >= EXPIRE_TIMES) {
k_timer_stop(timer);
}
}
static void duration_stop(struct k_timer *timer)
{
tdata.stop_cnt++;
}
static void period0_expire(struct k_timer *timer)
{
tdata.expire_cnt++;
}
static void status_expire(struct k_timer *timer)
{
/** TESTPOINT: status get upon timer expired */
TIMER_ASSERT(k_timer_status_get(timer) == 1, timer);
/** TESTPOINT: remaining get upon timer expired */
TIMER_ASSERT(k_timer_remaining_get(timer) >= PERIOD, timer);
if (tdata.expire_cnt >= EXPIRE_TIMES) {
k_timer_stop(timer);
}
}
static void busy_wait_ms(s32_t ms)
{
#ifdef CONFIG_TICKLESS_KERNEL
k_enable_sys_clock_always_on();
#endif
s32_t deadline = k_uptime_get() + ms;
volatile s32_t now = k_uptime_get();
while (now < deadline) {
now = k_uptime_get();
}
#ifdef CONFIG_TICKLESS_KERNEL
k_disable_sys_clock_always_on();
#endif
}
static void status_stop(struct k_timer *timer)
{
/** TESTPOINT: remaining get upon timer stopped */
TIMER_ASSERT(k_timer_remaining_get(timer) == 0, timer);
}
/* test cases */
void test_timer_duration_period(void)
{
init_timer_data();
/** TESTPOINT: init timer via k_timer_init */
k_timer_init(&timer, duration_expire, duration_stop);
k_timer_start(&timer, DURATION, PERIOD);
tdata.timestamp = k_uptime_get();
busy_wait_ms(DURATION + PERIOD * EXPIRE_TIMES + PERIOD / 2);
/** TESTPOINT: check expire and stop times */
TIMER_ASSERT(tdata.expire_cnt == EXPIRE_TIMES, &timer);
TIMER_ASSERT(tdata.stop_cnt == 1, &timer);
/* cleanup environemtn */
k_timer_stop(&timer);
}
void test_timer_period_0(void)
{
init_timer_data();
/** TESTPOINT: set period 0 */
k_timer_init(&timer, period0_expire, NULL);
k_timer_start(&timer, DURATION, 0);
tdata.timestamp = k_uptime_get();
busy_wait_ms(DURATION + 1);
/** TESTPOINT: ensure it is one-short timer */
TIMER_ASSERT(tdata.expire_cnt == 1, &timer);
TIMER_ASSERT(tdata.stop_cnt == 0, &timer);
/* cleanup environemtn */
k_timer_stop(&timer);
}
void test_timer_expirefn_null(void)
{
init_timer_data();
/** TESTPOINT: expire function NULL */
k_timer_init(&timer, NULL, duration_stop);
k_timer_start(&timer, DURATION, PERIOD);
busy_wait_ms(DURATION + PERIOD * EXPIRE_TIMES + PERIOD / 2);
k_timer_stop(&timer);
/** TESTPOINT: expire handler is not invoked */
TIMER_ASSERT(tdata.expire_cnt == 0, &timer);
/** TESTPOINT: stop handler is invoked */
TIMER_ASSERT(tdata.stop_cnt == 1, &timer);
/* cleanup environment */
k_timer_stop(&timer);
}
void test_timer_status_get(void)
{
init_timer_data();
k_timer_init(&timer, status_expire, status_stop);
k_timer_start(&timer, DURATION, PERIOD);
/** TESTPOINT: status get upon timer starts */
TIMER_ASSERT(k_timer_status_get(&timer) == 0, &timer);
/** TESTPOINT: remaining get upon timer starts */
TIMER_ASSERT(k_timer_remaining_get(&timer) >= DURATION / 2, &timer);
/* cleanup environment */
k_timer_stop(&timer);
}
void test_timer_status_get_anytime(void)
{
init_timer_data();
k_timer_init(&timer, NULL, NULL);
k_timer_start(&timer, DURATION, PERIOD);
busy_wait_ms(DURATION + PERIOD * (EXPIRE_TIMES - 1) + PERIOD / 2);
/** TESTPOINT: status get at any time */
TIMER_ASSERT(k_timer_status_get(&timer) == EXPIRE_TIMES, &timer);
/* cleanup environment */
k_timer_stop(&timer);
}
void test_timer_status_sync(void)
{
init_timer_data();
k_timer_init(&timer, duration_expire, duration_stop);
k_timer_start(&timer, DURATION, PERIOD);
for (int i = 0; i < EXPIRE_TIMES; i++) {
/** TESTPOINT: check timer not expire */
TIMER_ASSERT(tdata.expire_cnt == i, &timer);
/** TESTPOINT expired times returned by status sync */
TIMER_ASSERT(k_timer_status_sync(&timer) == 1, &timer);
/** TESTPOINT: check timer not expire */
TIMER_ASSERT(tdata.expire_cnt == (i + 1), &timer);
}
/* cleanup environment */
k_timer_stop(&timer);
}
void test_timer_k_define(void)
{
init_timer_data();
/** TESTPOINT: init timer via k_timer_init */
k_timer_start(&ktimer, DURATION, PERIOD);
tdata.timestamp = k_uptime_get();
busy_wait_ms(DURATION + PERIOD * EXPIRE_TIMES + PERIOD / 2);
/** TESTPOINT: check expire and stop times */
TIMER_ASSERT(tdata.expire_cnt == EXPIRE_TIMES, &ktimer);
TIMER_ASSERT(tdata.stop_cnt == 1, &ktimer);
/* cleanup environment */
k_timer_stop(&ktimer);
}
/* k_timer_user_data_set/get test */
static void user_data_timer_handler(struct k_timer *timer);
K_TIMER_DEFINE(timer0, user_data_timer_handler, NULL);
K_TIMER_DEFINE(timer1, user_data_timer_handler, NULL);
K_TIMER_DEFINE(timer2, user_data_timer_handler, NULL);
K_TIMER_DEFINE(timer3, user_data_timer_handler, NULL);
K_TIMER_DEFINE(timer4, user_data_timer_handler, NULL);
static struct k_timer *user_data_timer[5] = {
&timer0, &timer1, &timer2, &timer3, &timer4
};
static const intptr_t user_data[5] = { 0x1337, 0xbabe, 0xd00d, 0xdeaf, 0xfade };
static int user_data_correct[5] = { 0, 0, 0, 0, 0 };
static void user_data_timer_handler(struct k_timer *timer)
{
int timer_num = timer == user_data_timer[0] ? 0 :
timer == user_data_timer[1] ? 1 :
timer == user_data_timer[2] ? 2 :
timer == user_data_timer[3] ? 3 :
timer == user_data_timer[4] ? 4 : -1;
if (timer_num == -1) {
return;
}
intptr_t data_retrieved = (intptr_t)k_timer_user_data_get(timer);
user_data_correct[timer_num] = user_data[timer_num] == data_retrieved;
}
void test_timer_user_data(void)
{
int ii;
for (ii = 0; ii < 5; ii++) {
intptr_t check;
k_timer_user_data_set(user_data_timer[ii],
(void *)user_data[ii]);
check = (intptr_t)k_timer_user_data_get(user_data_timer[ii]);
zassert_true(check == user_data[ii], NULL);
}
for (ii = 0; ii < 5; ii++) {
k_timer_start(user_data_timer[ii], 50 + ii * 50, 0);
}
k_sleep(50 * ii + 50);
for (ii = 0; ii < 5; ii++) {
k_timer_stop(user_data_timer[ii]);
}
for (ii = 0; ii < 5; ii++) {
zassert_true(user_data_correct[ii], NULL);
}
}