tests/cmsis_rtos_v2: Introduce tests to make use of Thread APIs
Some test programs to illustrate the usage of thread APIs.
Signed-off-by: Rajavardhan Gundi <rajavardhan.gundi@intel.com>
diff --git a/tests/cmsis_rtos_v2/CMakeLists.txt b/tests/cmsis_rtos_v2/CMakeLists.txt
new file mode 100644
index 0000000..341d23e
--- /dev/null
+++ b/tests/cmsis_rtos_v2/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.8.2)
+include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
+project(NONE)
+
+target_include_directories(app PRIVATE $ENV{ZEPHYR_BASE}/include/cmsis_rtos_v2)
+FILE(GLOB app_sources src/*.c)
+target_sources(app PRIVATE ${app_sources})
diff --git a/tests/cmsis_rtos_v2/prj.conf b/tests/cmsis_rtos_v2/prj.conf
new file mode 100644
index 0000000..d196cf6
--- /dev/null
+++ b/tests/cmsis_rtos_v2/prj.conf
@@ -0,0 +1,10 @@
+CONFIG_ZTEST=y
+CONFIG_CMSIS_RTOS_V2=y
+CONFIG_NUM_PREEMPT_PRIORITIES=56
+CONFIG_HEAP_MEM_POOL_SIZE=256
+CONFIG_POLL=y
+CONFIG_THREAD_NAME=y
+CONFIG_THREAD_STACK_INFO=y
+CONFIG_THREAD_MONITOR=y
+CONFIG_IRQ_OFFLOAD=y
+CONFIG_INIT_STACKS=y
diff --git a/tests/cmsis_rtos_v2/src/main.c b/tests/cmsis_rtos_v2/src/main.c
new file mode 100644
index 0000000..4cdd71c
--- /dev/null
+++ b/tests/cmsis_rtos_v2/src/main.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <ztest.h>
+#include <kernel.h>
+#include <cmsis_os2.h>
+
+extern void test_thread_apis(void);
+extern void test_thread_prio(void);
+
+void test_main(void)
+{
+ ztest_test_suite(test_cmsis_v2_apis,
+ ztest_unit_test(test_thread_apis),
+ ztest_unit_test(test_thread_prio));
+
+ ztest_run_test_suite(test_cmsis_v2_apis);
+}
diff --git a/tests/cmsis_rtos_v2/src/thread_apis.c b/tests/cmsis_rtos_v2/src/thread_apis.c
new file mode 100644
index 0000000..de9574c
--- /dev/null
+++ b/tests/cmsis_rtos_v2/src/thread_apis.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <ztest.h>
+#include <kernel.h>
+#include <cmsis_os2.h>
+
+#define STACKSZ 512
+
+/* This is used to check the thread yield functionality between 2 threads */
+static int thread_yield_check;
+
+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 void thread1(void *argument)
+{
+ osStatus_t status;
+ osThreadId_t thread_id;
+ const char *name;
+
+ thread_id = osThreadGetId();
+ zassert_true(thread_id != NULL, "Failed getting Thread ID");
+
+ name = osThreadGetName(thread_id);
+ zassert_true(strcmp(thread1_attr.name, name) == 0,
+ "Failed getting Thread name");
+
+ /* This thread starts off at a high priority (same as thread2) */
+ thread_yield_check++;
+ zassert_equal(thread_yield_check, 1, NULL);
+
+ /* Yield to thread2 which is of same priority */
+ status = osThreadYield();
+ zassert_true(status == osOK, "Error doing thread yield");
+
+ /* thread_yield_check should now be 2 as it was incremented
+ * in thread2.
+ */
+ zassert_equal(thread_yield_check, 2, NULL);
+
+ osThreadExit();
+}
+
+static void thread2(void *argument)
+{
+ u32_t i, num_threads, max_num_threads = 5;
+ osThreadId_t *thread_array;
+
+ /* By now thread1 would have set thread_yield_check to 1 and would
+ * have yielded the CPU. Incrementing it over here would essentially
+ * confirm that the yield was indeed executed.
+ */
+ thread_yield_check++;
+
+ thread_array = k_calloc(max_num_threads, sizeof(osThreadId_t));
+ num_threads = osThreadEnumerate(thread_array, max_num_threads);
+ zassert_equal(num_threads, 2,
+ "Incorrect number of cmsis rtos v2 threads");
+
+ for (i = 0; i < num_threads; i++) {
+ zassert_true(
+ osThreadGetStackSize(thread_array[i]) <= STACKSZ,
+ "stack size allocated is not what is expected");
+
+ zassert_true(
+ osThreadGetStackSpace(thread_array[i]) <= STACKSZ - 4,
+ "stack size remaining is not what is expected");
+ }
+
+ zassert_equal(osThreadGetState(thread_array[1]), osThreadReady,
+ "Thread not in ready state");
+ zassert_equal(osThreadGetState(thread_array[0]), osThreadRunning,
+ "Thread not in running state");
+
+ zassert_equal(osThreadSuspend(thread_array[1]), osOK, "");
+ zassert_equal(osThreadGetState(thread_array[1]), osThreadBlocked,
+ "Thread not in blocked state");
+
+ zassert_equal(osThreadResume(thread_array[1]), osOK, "");
+ zassert_equal(osThreadGetState(thread_array[1]), osThreadReady,
+ "Thread not in ready state");
+
+ k_free(thread_array);
+
+ /* Yield back to thread1 which is of same priority */
+ osThreadYield();
+}
+
+void test_thread_apis(void)
+{
+ osThreadId_t id1;
+ osThreadId_t id2;
+
+ id1 = osThreadNew(thread1, NULL, &thread1_attr);
+ zassert_true(id1 != NULL, "Failed creating thread1");
+
+ id2 = osThreadNew(thread2, NULL, &thread2_attr);
+ zassert_true(id2 != NULL, "Failed creating thread2");
+
+ zassert_equal(osThreadGetCount(), 2,
+ "Incorrect number of cmsis rtos v2 threads");
+
+ do {
+ osDelay(100);
+ } while (thread_yield_check != 2);
+}
+
+static osPriority_t OsPriorityInvalid = 60;
+
+/* This is used to indicate the completion of processing for thread3 */
+static int thread3_state;
+
+static K_THREAD_STACK_DEFINE(test_stack3, STACKSZ);
+static osThreadAttr_t thread3_attr = {
+ .name = "Thread3",
+ .stack_mem = &test_stack3,
+ .stack_size = STACKSZ,
+ .priority = osPriorityNormal,
+};
+
+static void thread3(void *argument)
+{
+ osStatus_t status;
+ osPriority_t rv;
+ osThreadId_t id = osThreadGetId();
+ osPriority_t prio = osThreadGetPriority(id);
+
+ /* Lower the priority of the current thread */
+ osThreadSetPriority(id, osPriorityBelowNormal);
+ rv = osThreadGetPriority(id);
+ zassert_equal(rv, osPriorityBelowNormal,
+ "Expected priority to be changed to %d, not %d",
+ (int)osPriorityBelowNormal, (int)rv);
+
+ /* Increase the priority of the current thread */
+ osThreadSetPriority(id, osPriorityAboveNormal);
+ rv = osThreadGetPriority(id);
+ zassert_equal(rv, osPriorityAboveNormal,
+ "Expected priority to be changed to %d, not %d",
+ (int)osPriorityAboveNormal, (int)rv);
+
+ /* Restore the priority of the current thread */
+ osThreadSetPriority(id, prio);
+ rv = osThreadGetPriority(id);
+ zassert_equal(rv, prio,
+ "Expected priority to be changed to %d, not %d",
+ (int)prio, (int)rv);
+
+ /* Try to set unsupported priority and assert failure */
+ status = osThreadSetPriority(id, OsPriorityInvalid);
+ zassert_true(status == osErrorParameter,
+ "Something's wrong with osThreadSetPriority!");
+
+ /* Indication that thread3 is done with its processing */
+ thread3_state = 1;
+
+ /* Keep looping till it gets killed */
+ do {
+ osDelay(100);
+ } while (1);
+}
+
+void test_thread_prio(void)
+{
+ osStatus_t status;
+ osThreadId_t id3;
+
+ id3 = osThreadNew(thread3, NULL, &thread3_attr);
+ zassert_true(id3 != NULL, "Failed creating thread3");
+
+ /* Keep delaying 10 milliseconds to ensure thread3 is done with
+ * its execution. It loops at the end and is terminated here.
+ */
+ do {
+ osDelay(10);
+ } while (thread3_state == 0);
+
+ status = osThreadTerminate(id3);
+ zassert_true(status == osOK, "Error terminating thread3");
+
+ /* Try to set priority to inactive thread and assert failure */
+ status = osThreadSetPriority(id3, osPriorityNormal);
+ zassert_true(status == osErrorResource,
+ "Something's wrong with osThreadSetPriority!");
+
+ /* Try to terminate inactive thread and assert failure */
+ status = osThreadTerminate(id3);
+ zassert_true(status == osErrorResource,
+ "Something's wrong with osThreadTerminate!");
+
+ thread3_state = 0;
+}
diff --git a/tests/cmsis_rtos_v2/testcase.yaml b/tests/cmsis_rtos_v2/testcase.yaml
new file mode 100644
index 0000000..76af3f9
--- /dev/null
+++ b/tests/cmsis_rtos_v2/testcase.yaml
@@ -0,0 +1,5 @@
+tests:
+ portability.cmsis_rtos_v2:
+ tags: cmsis_rtos_v2
+ min_ram: 32
+ min_flash: 34