blob: 8b84cd2e8eae939f0cc9d9bc4b6bcbe536a23825 [file] [log] [blame]
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/ztest.h>
#include <zephyr/kernel.h>
#include <cmsis_os2.h>
#include <zephyr/irq_offload.h>
#include <zephyr/kernel_structs.h>
#define TIMEOUT_TICKS (10)
#define FLAG1 (0x00000020)
#define FLAG2 (0x00000004)
#define FLAG (FLAG1 | FLAG2)
#define ISR_FLAG (0x50)
#define STACKSZ CONFIG_CMSIS_V2_THREAD_MAX_STACK_SIZE
static void thread1(void *arg)
{
uint32_t flags;
/* wait for FLAG1. It should return immediately as it is
* already triggered.
*/
flags = osThreadFlagsWait(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 = osThreadFlagsGet();
zassert_equal(flags & FLAG1, FLAG1, "");
/* Clear the Flag explicitly */
flags = osThreadFlagsClear(FLAG1);
zassert_not_equal(flags, osFlagsErrorParameter,
"ThreadFlagsClear failed");
/* wait for FLAG1. It should timeout here as the flag
* though triggered, gets cleared in the previous step.
*/
flags = osThreadFlagsWait(FLAG1, osFlagsWaitAny, TIMEOUT_TICKS);
zassert_equal(flags, osFlagsErrorTimeout, "ThreadFlagsWait failed");
}
static void thread2(void *arg)
{
uint32_t flags;
flags = osThreadFlagsWait(FLAG, osFlagsWaitAll, TIMEOUT_TICKS);
zassert_equal(flags & FLAG, FLAG,
"osThreadFlagsWait failed unexpectedly");
/* validate by passing invalid parameters */
zassert_equal(osThreadFlagsSet(NULL, 0), osFlagsErrorParameter,
"Invalid Thread Flags ID is unexpectedly working!");
zassert_equal(osThreadFlagsSet(osThreadGetId(), 0x80010000),
osFlagsErrorParameter,
"Thread with MSB set is set unexpectedly");
zassert_equal(osThreadFlagsClear(0x80010000), osFlagsErrorParameter,
"Thread with MSB set is cleared unexpectedly");
/* cannot wait for Flag mask with MSB set */
zassert_equal(osThreadFlagsWait(0x80010000, osFlagsWaitAny, 0),
osFlagsErrorParameter,
"ThreadFlagsWait passed unexpectedly");
}
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,
};
ZTEST(cmsis_thread_flags, test_thread_flags_no_wait_timeout)
{
osThreadId_t id1;
uint32_t flags;
id1 = osThreadNew(thread1, NULL, &thread1_attr);
zassert_true(id1 != NULL, "Failed creating thread1");
flags = osThreadFlagsSet(id1, FLAG1);
zassert_equal(flags & FLAG1, FLAG1, "");
/* Let id1 run to do the tests for Thread Flags */
osDelay(TIMEOUT_TICKS);
}
ZTEST(cmsis_thread_flags, test_thread_flags_signalled)
{
osThreadId_t id;
uint32_t flags;
id = osThreadNew(thread2, osThreadGetId(), &thread2_attr);
zassert_true(id != NULL, "Failed creating thread2");
flags = osThreadFlagsSet(id, FLAG1);
zassert_equal(flags & FLAG1, FLAG1, "");
/* Let id run to do the tests for Thread Flags */
osDelay(TIMEOUT_TICKS / 2);
flags = osThreadFlagsSet(id, FLAG2);
zassert_equal(flags & FLAG2, FLAG2, "");
/* z_thread has a higher priority over the other threads.
* Hence, this thread needs to be put to sleep for thread2
* to become the active thread.
*/
osDelay(TIMEOUT_TICKS / 2);
}
/* IRQ offload function handler to set Thread flag */
static void offload_function(const void *param)
{
int flags;
/* Make sure we're in IRQ context */
zassert_true(k_is_in_isr(), "Not in IRQ context!");
flags = osThreadFlagsSet((osThreadId_t)param, ISR_FLAG);
zassert_equal(flags & ISR_FLAG, ISR_FLAG,
"ThreadFlagsSet failed in ISR");
}
void test_thread_flags_from_isr(void *thread_id)
{
uint32_t flags;
/**TESTPOINT: Offload to IRQ context*/
irq_offload(offload_function, (const void *)osThreadGetId());
flags = osThreadFlagsWait(ISR_FLAG, osFlagsWaitAll, TIMEOUT_TICKS);
zassert_equal((flags & ISR_FLAG),
ISR_FLAG, "unexpected Thread flags value");
}
static K_THREAD_STACK_DEFINE(test_stack3, STACKSZ);
static osThreadAttr_t thread3_attr = {
.name = "Thread3",
.stack_mem = &test_stack3,
.stack_size = STACKSZ,
.priority = osPriorityHigh,
};
ZTEST(cmsis_thread_flags, test_thread_flags_isr)
{
osThreadId_t id;
id = osThreadNew(test_thread_flags_from_isr, osThreadGetId(),
&thread3_attr);
zassert_true(id != NULL, "Failed creating thread");
osDelay(TIMEOUT_TICKS);
}
ZTEST_SUITE(cmsis_thread_flags, NULL, NULL, NULL, NULL, NULL);