blob: 99e65d8b2cc9d70131c70b8b234244c98b6286b5 [file] [log] [blame]
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
#include <kernel.h>
#include <cmsis_os2.h>
#include <irq_offload.h>
#include <kernel_structs.h>
#define TIMEOUT_TICKS (100)
#define FLAG1 (0x00000020)
#define FLAG2 (0x00000004)
#define FLAG (FLAG1 | FLAG2)
#define ISR_FLAG 0x50
#define STACKSZ CONFIG_CMSIS_V2_THREAD_MAX_STACK_SIZE
osEventFlagsId_t evt_id;
static void thread1(void *arg)
{
int flags = osEventFlagsSet((osEventFlagsId_t)arg, FLAG1);
zassert_equal(flags & FLAG1, FLAG1, "");
}
static void thread2(void *arg)
{
int flags = osEventFlagsSet((osEventFlagsId_t)arg, FLAG2);
/* Please note that as soon as the last flag that a thread is waiting
* on is set, the control shifts to that thread and that thread may
* choose to clear the flags as part of its osEventFlagsWait operation.
* In this test case, the main thread is waiting for FLAG1 and FLAG2.
* FLAG1 gets set first and then FLAG2 gets set. As soon as FLAG2 gets
* set, control shifts to the waiting thread where osEventFlagsWait
* clears FLAG1 and FLAG2 internally. When this thread eventually gets
* scheduled we should hence check if FLAG2 is cleared.
*/
zassert_equal(flags & FLAG2, 0, "");
}
static K_THREAD_STACK_DEFINE(test_stack1, STACKSZ);
static osThreadAttr_t thread1_attr = {
.name = "Thread1",
.stack_mem = &test_stack1,
.stack_size = STACKSZ,
.priority = osPriorityHigh,
};
static K_THREAD_STACK_DEFINE(test_stack2, STACKSZ);
static osThreadAttr_t thread2_attr = {
.name = "Thread2",
.stack_mem = &test_stack2,
.stack_size = STACKSZ,
.priority = osPriorityHigh,
};
static osEventFlagsAttr_t event_flags_attrs = {
.name = "MyEvent",
.attr_bits = 0,
.cb_mem = NULL,
.cb_size = 0,
};
void test_event_flags_no_wait_timeout(void)
{
osThreadId_t id1;
u32_t flags;
const char *name;
osEventFlagsId_t dummy_id = NULL;
evt_id = osEventFlagsNew(&event_flags_attrs);
zassert_true(evt_id != NULL, "Failed creating event flags");
name = osEventFlagsGetName(dummy_id);
zassert_true(name == NULL,
"Invalid event Flags ID is unexpectedly working!");
name = osEventFlagsGetName(evt_id);
zassert_true(strcmp(event_flags_attrs.name, name) == 0,
"Error getting event_flags object name");
id1 = osThreadNew(thread1, evt_id, &thread1_attr);
zassert_true(id1 != NULL, "Failed creating thread1");
/* Let id1 run to trigger FLAG1 */
osDelay(2);
/* wait for FLAG1. It should return immediately as it is
* already triggered.
*/
flags = osEventFlagsWait(evt_id, FLAG1,
osFlagsWaitAny | osFlagsNoClear, 0);
zassert_equal(flags & FLAG1, FLAG1, "");
/* Since the flags are not cleared automatically in the previous step,
* we should be able to get the same flags upon query below.
*/
flags = osEventFlagsGet(evt_id);
zassert_equal(flags & FLAG1, FLAG1, "");
flags = osEventFlagsGet(dummy_id);
zassert_true(flags == 0U,
"Invalid event Flags ID is unexpectedly working!");
/* Clear the Flag explicitly */
flags = osEventFlagsClear(evt_id, FLAG1);
zassert_not_equal(flags, osFlagsErrorParameter, "Event clear failed");
/* wait for FLAG1. It should timeout here as the event
* though triggered, gets cleared in the previous step.
*/
flags = osEventFlagsWait(evt_id, FLAG1, osFlagsWaitAny, TIMEOUT_TICKS);
zassert_equal(flags, osFlagsErrorTimeout, "EventFlagsWait failed");
}
void test_event_flags_signalled(void)
{
osThreadId_t id1, id2;
u32_t flags;
id1 = osThreadNew(thread1, evt_id, &thread1_attr);
zassert_true(id1 != NULL, "Failed creating thread1");
id2 = osThreadNew(thread2, evt_id, &thread2_attr);
zassert_true(id2 != NULL, "Failed creating thread2");
/* wait for multiple flags. The flags will be cleared automatically
* upon being set since "osFlagsNoClear" is not opted for.
*/
flags = osEventFlagsWait(evt_id, FLAG, osFlagsWaitAll, TIMEOUT_TICKS);
zassert_equal(flags & FLAG, FLAG,
"osEventFlagsWait failed unexpectedly");
/* set any single flag */
flags = osEventFlagsSet(evt_id, FLAG1);
zassert_equal(flags & FLAG1, FLAG1, "set any flag failed");
flags = osEventFlagsWait(evt_id, FLAG1, osFlagsWaitAny, TIMEOUT_TICKS);
zassert_equal(flags & FLAG1, FLAG1,
"osEventFlagsWait failed unexpectedly");
/* validate by passing invalid parameters */
zassert_equal(osEventFlagsSet(NULL, 0), osFlagsErrorParameter,
"Invalid event Flags ID is unexpectedly working!");
zassert_equal(osEventFlagsSet(evt_id, 0x80010000),
osFlagsErrorParameter,
"Event with MSB set is set unexpectedly");
zassert_equal(osEventFlagsClear(NULL, 0), osFlagsErrorParameter,
"Invalid event Flags ID is unexpectedly working!");
zassert_equal(osEventFlagsClear(evt_id, 0x80010000),
osFlagsErrorParameter,
"Event with MSB set is cleared unexpectedly");
/* cannot wait for Flag mask with MSB set */
zassert_equal(osEventFlagsWait(evt_id, 0x80010000, osFlagsWaitAny, 0),
osFlagsErrorParameter,
"EventFlagsWait passed unexpectedly");
}
/* IRQ offload function handler to set event flag */
static void offload_function(void *param)
{
int flags;
/* Make sure we're in IRQ context */
zassert_true(k_is_in_isr(), "Not in IRQ context!");
flags = osEventFlagsSet((osEventFlagsId_t)param, ISR_FLAG);
zassert_equal(flags & ISR_FLAG, ISR_FLAG,
"EventFlagsSet failed in ISR");
}
void test_event_from_isr(void *event_id)
{
/**TESTPOINT: Offload to IRQ context*/
irq_offload(offload_function, (void *)event_id);
}
static K_THREAD_STACK_DEFINE(test_stack3, STACKSZ);
static osThreadAttr_t thread3_attr = {
.name = "Thread3",
.stack_mem = &test_stack3,
.stack_size = STACKSZ,
.priority = osPriorityHigh,
};
void test_event_flags_isr(void)
{
osThreadId_t id;
int flags;
osEventFlagsId_t dummy_id = NULL;
id = osThreadNew(test_event_from_isr, evt_id, &thread3_attr);
zassert_true(id != NULL, "Failed creating thread");
flags = osEventFlagsWait(dummy_id, ISR_FLAG,
osFlagsWaitAll, TIMEOUT_TICKS);
zassert_true(flags == osFlagsErrorParameter,
"Invalid event Flags ID is unexpectedly working!");
flags = osEventFlagsWait(evt_id, ISR_FLAG,
osFlagsWaitAll, TIMEOUT_TICKS);
zassert_equal((flags & ISR_FLAG),
ISR_FLAG, "unexpected event flags value");
zassert_true(osEventFlagsDelete(dummy_id) == osErrorResource,
"Invalid event Flags ID is unexpectedly working!");
zassert_true(osEventFlagsDelete(evt_id) == osOK,
"EventFlagsDelete failed");
}