Fix issues detected by checkpatch Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
440 lines
10 KiB
C
440 lines
10 KiB
C
/*
|
|
* Copyright (c) 2021 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/ztest.h>
|
|
#include <wait_q.h>
|
|
|
|
#define DELAY K_MSEC(50)
|
|
#define SHORT_TIMEOUT K_MSEC(100)
|
|
#define LONG_TIMEOUT K_MSEC(1000)
|
|
|
|
#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
|
|
|
|
static struct k_thread treceiver;
|
|
static struct k_thread textra1;
|
|
static struct k_thread textra2;
|
|
|
|
static K_THREAD_STACK_DEFINE(sreceiver, STACK_SIZE);
|
|
static K_THREAD_STACK_DEFINE(sextra1, STACK_SIZE);
|
|
static K_THREAD_STACK_DEFINE(sextra2, STACK_SIZE);
|
|
|
|
static K_EVENT_DEFINE(test_event);
|
|
static K_EVENT_DEFINE(sync_event);
|
|
|
|
static K_SEM_DEFINE(receiver_sem, 0, 1);
|
|
static K_SEM_DEFINE(sync_sem, 0, 1);
|
|
|
|
volatile static uint32_t test_events;
|
|
|
|
static void entry_extra1(void *p1, void *p2, void *p3)
|
|
{
|
|
uint32_t events;
|
|
|
|
events = k_event_wait_all(&sync_event, 0x33, true, K_FOREVER);
|
|
|
|
k_event_post(&test_event, events);
|
|
}
|
|
|
|
static void entry_extra2(void *p1, void *p2, void *p3)
|
|
{
|
|
uint32_t events;
|
|
|
|
events = k_event_wait(&sync_event, 0x3300, true, K_FOREVER);
|
|
|
|
k_event_post(&test_event, events);
|
|
}
|
|
/**
|
|
* @ingroup kernel_event_tests
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* Test the k_event_init() API.
|
|
*
|
|
* This is a white-box test to verify that the k_event_init() API initializes
|
|
* the fields of a k_event structure as expected.
|
|
*/
|
|
ZTEST(events_api, test_k_event_init)
|
|
{
|
|
static struct k_event event;
|
|
struct k_thread *thread;
|
|
|
|
k_event_init(&event);
|
|
|
|
/*
|
|
* The type of wait queue used by the event may vary depending upon
|
|
* which kernel features have been enabled. As such, the most flexible
|
|
* useful check is to verify that the waitq is empty.
|
|
*/
|
|
|
|
|
|
thread = z_waitq_head(&event.wait_q);
|
|
|
|
zassert_is_null(thread, NULL);
|
|
zassert_true(event.events == 0);
|
|
}
|
|
|
|
static void receive_existing_events(void)
|
|
{
|
|
/*
|
|
* Sync point 1-1 : test_event contains events 0x1234.
|
|
* Test for events 0x2448 (no waiting)--expect an error
|
|
*/
|
|
|
|
k_sem_take(&sync_sem, K_FOREVER);
|
|
test_events = k_event_wait(&test_event, 0x2448, false, K_NO_WAIT);
|
|
k_sem_give(&receiver_sem);
|
|
|
|
/*
|
|
* Sync point 1-2 : test_event still contains event 0x1234.
|
|
* Test for events 0x2448 (with waiting)--expect an error
|
|
*/
|
|
|
|
k_sem_take(&sync_sem, K_FOREVER);
|
|
test_events = k_event_wait(&test_event, 0x2448, false, SHORT_TIMEOUT);
|
|
k_sem_give(&receiver_sem);
|
|
|
|
/*
|
|
* Sync point 1-3: test_event still contains event 0x1234.
|
|
* Test for events 0x1235 (no waiting)--expect an error
|
|
*/
|
|
|
|
k_sem_take(&sync_sem, K_FOREVER);
|
|
test_events = k_event_wait_all(&test_event, 0x1235, false, K_NO_WAIT);
|
|
k_sem_give(&receiver_sem);
|
|
|
|
/*
|
|
* Sync point 1-4: test_event still contains event 0x1234.
|
|
* Test for events 0x1235 (no waiting)--expect an error
|
|
*/
|
|
|
|
k_sem_take(&sync_sem, K_FOREVER);
|
|
test_events = k_event_wait_all(&test_event, 0x1235, false, K_NO_WAIT);
|
|
k_sem_give(&receiver_sem);
|
|
|
|
/*
|
|
* Sync point 1-5: test_event still contains event 0x1234.
|
|
* Test for events 0x0235. Expect 0x0234 to be returned.
|
|
*/
|
|
|
|
k_sem_take(&sync_sem, K_FOREVER);
|
|
test_events = k_event_wait(&test_event, 0x0235, false, K_NO_WAIT);
|
|
k_sem_give(&receiver_sem);
|
|
|
|
/*
|
|
* Sync point 1-6: test_event still contains event 0x1234.
|
|
* Test for events 0x1234. Expect 0x1234 to be returned.
|
|
*/
|
|
|
|
k_sem_take(&sync_sem, K_FOREVER);
|
|
test_events = k_event_wait_all(&test_event, 0x1234, false, K_NO_WAIT);
|
|
k_sem_give(&receiver_sem);
|
|
}
|
|
|
|
static void reset_on_wait(void)
|
|
{
|
|
/* Sync point 2-1 */
|
|
|
|
k_sem_take(&sync_sem, K_FOREVER);
|
|
test_events = k_event_wait_all(&test_event, 0x1234, true,
|
|
SHORT_TIMEOUT);
|
|
k_sem_give(&receiver_sem);
|
|
|
|
/* Sync point 2-2 */
|
|
|
|
k_sem_take(&sync_sem, K_FOREVER);
|
|
test_events = k_event_wait(&test_event, 0x120000, true,
|
|
SHORT_TIMEOUT);
|
|
k_sem_give(&receiver_sem);
|
|
|
|
/* Sync point 2-3 */
|
|
|
|
k_sem_take(&sync_sem, K_FOREVER);
|
|
test_events = k_event_wait_all(&test_event, 0x248001, true,
|
|
SHORT_TIMEOUT);
|
|
k_sem_give(&receiver_sem);
|
|
|
|
/* Sync point 2-4 */
|
|
|
|
k_sem_take(&sync_sem, K_FOREVER);
|
|
test_events = k_event_wait(&test_event, 0x123458, true,
|
|
SHORT_TIMEOUT);
|
|
k_sem_give(&receiver_sem);
|
|
}
|
|
|
|
/**
|
|
* receiver helper task
|
|
*/
|
|
|
|
static void receiver(void *p1, void *p2, void *p3)
|
|
{
|
|
receive_existing_events();
|
|
|
|
reset_on_wait();
|
|
}
|
|
|
|
/**
|
|
* Works with receive_existing_events() to test the waiting for events
|
|
* when some events have already been sent. No additional events are sent
|
|
* to the event object during this block of testing.
|
|
*/
|
|
static void test_receive_existing_events(void)
|
|
{
|
|
int rv;
|
|
|
|
/*
|
|
* Sync point 1-1.
|
|
* K_NO_WAIT, k_event_wait(), no matches
|
|
*/
|
|
|
|
k_sem_give(&sync_sem);
|
|
rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
|
|
zassert_true(rv == 0);
|
|
zassert_true(test_events == 0);
|
|
|
|
/*
|
|
* Sync point 1-2.
|
|
* Short timeout, k_event_wait(), no expected matches
|
|
*/
|
|
|
|
k_sem_give(&sync_sem);
|
|
rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
|
|
zassert_true(rv == 0);
|
|
zassert_true(test_events == 0);
|
|
|
|
/*
|
|
* Sync point 1-3.
|
|
* K_NO_WAIT, k_event_wait_all(), incomplete match
|
|
*/
|
|
|
|
k_sem_give(&sync_sem);
|
|
rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
|
|
zassert_true(rv == 0);
|
|
zassert_true(test_events == 0);
|
|
|
|
/*
|
|
* Sync point 1-4.
|
|
* Short timeout, k_event_wait_all(), incomplete match
|
|
*/
|
|
|
|
k_sem_give(&sync_sem);
|
|
rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
|
|
zassert_true(rv == 0);
|
|
zassert_true(test_events == 0);
|
|
|
|
/*
|
|
* Sync point 1-5.
|
|
* Short timeout, k_event_wait_all(), incomplete match
|
|
*/
|
|
|
|
k_sem_give(&sync_sem);
|
|
rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
|
|
zassert_true(rv == 0);
|
|
zassert_true(test_events == 0x234);
|
|
|
|
/*
|
|
* Sync point 1-6.
|
|
* Short timeout, k_event_wait_all(), incomplete match
|
|
*/
|
|
|
|
k_sem_give(&sync_sem);
|
|
rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
|
|
zassert_true(rv == 0);
|
|
zassert_true(test_events == 0x1234);
|
|
}
|
|
|
|
/**
|
|
* Works with reset_on_wait() to verify that the events stored in the
|
|
* event object are reset at the appropriate time.
|
|
*/
|
|
|
|
static void test_reset_on_wait(void)
|
|
{
|
|
int rv;
|
|
|
|
/*
|
|
* Sync point 2-1. Reset events before receive.
|
|
* Short timeout, k_event_wait_all(), incomplete match
|
|
*/
|
|
|
|
k_sem_give(&sync_sem);
|
|
k_sleep(DELAY); /* Give receiver thread time to run */
|
|
k_event_post(&test_event, 0x123);
|
|
rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
|
|
zassert_true(rv == 0);
|
|
zassert_true(test_events == 0);
|
|
zassert_true(test_event.events == 0x123);
|
|
|
|
/*
|
|
* Sync point 2-2. Reset events before receive.
|
|
* Short timeout, k_event_wait(), no matches
|
|
*/
|
|
|
|
k_sem_give(&sync_sem);
|
|
k_sleep(DELAY);
|
|
k_event_post(&test_event, 0x248);
|
|
rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
|
|
zassert_true(rv == 0);
|
|
zassert_true(test_events == 0);
|
|
zassert_true(test_event.events == 0x248);
|
|
|
|
/*
|
|
* Sync point 2-3. Reset events before receive.
|
|
* Short timeout, k_event_wait_all(), complete match
|
|
*/
|
|
|
|
k_sem_give(&sync_sem);
|
|
k_sleep(DELAY);
|
|
k_event_post(&test_event, 0x248021);
|
|
rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
|
|
zassert_true(rv == 0);
|
|
zassert_true(test_events == 0x248001);
|
|
zassert_true(test_event.events == 0x248021);
|
|
|
|
/*
|
|
* Sync point 2-4. Reset events before receive.
|
|
* Short timeout, k_event_wait(), partial match
|
|
*/
|
|
|
|
k_sem_give(&sync_sem);
|
|
k_sleep(DELAY);
|
|
k_event_post(&test_event, 0x123456);
|
|
rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
|
|
zassert_true(rv == 0);
|
|
zassert_true(test_events == 0x123450);
|
|
zassert_true(test_event.events == 0x123456);
|
|
|
|
k_event_set(&test_event, 0x0); /* Reset events */
|
|
k_sem_give(&sync_sem);
|
|
}
|
|
|
|
void test_wake_multiple_threads(void)
|
|
{
|
|
uint32_t events;
|
|
|
|
/*
|
|
* The extra threads are expected to be waiting on <sync_event>
|
|
* Wake them both up.
|
|
*/
|
|
|
|
k_event_set(&sync_event, 0xfff);
|
|
|
|
/*
|
|
* The extra threads send back the events they received. Wait
|
|
* for all of them.
|
|
*/
|
|
|
|
events = k_event_wait_all(&test_event, 0x333, false, SHORT_TIMEOUT);
|
|
|
|
zassert_true(events == 0x333);
|
|
}
|
|
|
|
/**
|
|
* Test basic k_event_post() and k_event_set() APIs.
|
|
*
|
|
* Tests the basic k_event_post() and k_event_set() APIs. This does not
|
|
* involve waking or receiving events.
|
|
*/
|
|
|
|
ZTEST(events_api, test_event_deliver)
|
|
{
|
|
static struct k_event event;
|
|
uint32_t events;
|
|
uint32_t events_mask;
|
|
uint32_t previous;
|
|
|
|
k_event_init(&event);
|
|
|
|
zassert_equal(k_event_test(&event, ~0), 0);
|
|
|
|
/*
|
|
* Verify k_event_post() and k_event_set() update the
|
|
* events stored in the event object as expected.
|
|
*/
|
|
|
|
events = 0xAAAA;
|
|
previous = k_event_post(&event, events);
|
|
zassert_equal(previous, 0x0000);
|
|
zassert_equal(k_event_test(&event, ~0), events);
|
|
|
|
events |= 0x55555ABC;
|
|
previous = k_event_post(&event, events);
|
|
zassert_equal(previous, events & 0xAAAA);
|
|
zassert_equal(k_event_test(&event, ~0), events);
|
|
|
|
events = 0xAAAA0000;
|
|
previous = k_event_set(&event, events);
|
|
zassert_equal(previous, 0xAAAA | 0x55555ABC);
|
|
zassert_equal(k_event_test(&event, ~0), events);
|
|
|
|
/*
|
|
* Verify k_event_set_masked() update the events
|
|
* stored in the event object as expected
|
|
*/
|
|
events = 0x33333333;
|
|
(void)k_event_set(&event, events);
|
|
zassert_equal(k_event_test(&event, ~0), events);
|
|
|
|
events_mask = 0x11111111;
|
|
previous = k_event_set_masked(&event, 0, events_mask);
|
|
zassert_equal(previous, 0x11111111);
|
|
zassert_equal(k_event_test(&event, ~0), 0x22222222);
|
|
|
|
events_mask = 0x22222222;
|
|
previous = k_event_set_masked(&event, 0, events_mask);
|
|
zassert_equal(previous, 0x22222222);
|
|
zassert_equal(k_event_test(&event, ~0), 0);
|
|
|
|
events = 0x22222222;
|
|
events_mask = 0x22222222;
|
|
previous = k_event_set_masked(&event, events, events_mask);
|
|
zassert_equal(previous, 0x00000000);
|
|
zassert_equal(k_event_test(&event, ~0), events);
|
|
|
|
events = 0x11111111;
|
|
events_mask = 0x33333333;
|
|
previous = k_event_set_masked(&event, events, events_mask);
|
|
zassert_equal(previous, 0x22222222);
|
|
zassert_equal(k_event_test(&event, ~0), events);
|
|
}
|
|
|
|
/**
|
|
* Test delivery and reception of events.
|
|
*
|
|
* Testing both the delivery and reception of events involves the use of
|
|
* multiple threads and uses the following event related APIs:
|
|
* k_event_post(), k_event_set(), k_event_wait() and k_event_wait_all().
|
|
*/
|
|
|
|
ZTEST(events_api, test_event_receive)
|
|
{
|
|
|
|
/* Create helper threads */
|
|
|
|
k_event_set(&test_event, 0x1234);
|
|
|
|
(void) k_thread_create(&treceiver, sreceiver, STACK_SIZE,
|
|
receiver, NULL, NULL, NULL,
|
|
K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
|
|
|
|
(void) k_thread_create(&textra1, sextra1, STACK_SIZE,
|
|
entry_extra1, NULL, NULL, NULL,
|
|
K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
|
|
|
|
(void) k_thread_create(&textra2, sextra2, STACK_SIZE,
|
|
entry_extra2, NULL, NULL, NULL,
|
|
K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
|
|
|
|
test_receive_existing_events();
|
|
|
|
test_reset_on_wait();
|
|
|
|
test_wake_multiple_threads();
|
|
}
|
|
/**
|
|
* @}
|
|
*/
|