1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/kernel.h>
9 #include <cmsis_os2.h>
10
11 #include <zephyr/irq_offload.h>
12 #include <zephyr/kernel_structs.h>
13
14 #define TIMEOUT_TICKS (10)
15 #define FLAG1 (0x00000020)
16 #define FLAG2 (0x00000004)
17 #define FLAG (FLAG1 | FLAG2)
18 #define ISR_FLAG (0x50)
19 #define STACKSZ CONFIG_CMSIS_V2_THREAD_MAX_STACK_SIZE
20
thread1(void * arg)21 static void thread1(void *arg)
22 {
23 uint32_t flags;
24
25 /* wait for FLAG1. It should return immediately as it is
26 * already triggered.
27 */
28 flags = osThreadFlagsWait(FLAG1, osFlagsWaitAny | osFlagsNoClear, 0);
29 zassert_equal(flags & FLAG1, FLAG1, "");
30
31 /* Since the flags are not cleared automatically in the previous step,
32 * we should be able to get the same flags upon query below.
33 */
34 flags = osThreadFlagsGet();
35 zassert_equal(flags & FLAG1, FLAG1, "");
36
37 /* Clear the Flag explicitly */
38 flags = osThreadFlagsClear(FLAG1);
39 zassert_not_equal(flags, osFlagsErrorParameter, "ThreadFlagsClear failed");
40
41 /* wait for FLAG1. It should timeout here as the flag
42 * though triggered, gets cleared in the previous step.
43 */
44 flags = osThreadFlagsWait(FLAG1, osFlagsWaitAny, TIMEOUT_TICKS);
45 zassert_equal(flags, osFlagsErrorTimeout, "ThreadFlagsWait failed");
46 }
47
thread2(void * arg)48 static void thread2(void *arg)
49 {
50 uint32_t flags;
51
52 flags = osThreadFlagsWait(FLAG, osFlagsWaitAll, TIMEOUT_TICKS);
53 zassert_equal(flags & FLAG, FLAG, "osThreadFlagsWait failed unexpectedly");
54
55 /* validate by passing invalid parameters */
56 zassert_equal(osThreadFlagsSet(NULL, 0), osFlagsErrorParameter,
57 "Invalid Thread Flags ID is unexpectedly working!");
58 zassert_equal(osThreadFlagsSet(osThreadGetId(), 0x80010000), osFlagsErrorParameter,
59 "Thread with MSB set is set unexpectedly");
60
61 zassert_equal(osThreadFlagsClear(0x80010000), osFlagsErrorParameter,
62 "Thread with MSB set is cleared unexpectedly");
63
64 /* cannot wait for Flag mask with MSB set */
65 zassert_equal(osThreadFlagsWait(0x80010000, osFlagsWaitAny, 0), osFlagsErrorParameter,
66 "ThreadFlagsWait passed unexpectedly");
67 }
68
69 static K_THREAD_STACK_DEFINE(test_stack1, STACKSZ);
70 static osThreadAttr_t thread1_attr = {
71 .name = "Thread1",
72 .stack_mem = &test_stack1,
73 .stack_size = STACKSZ,
74 .priority = osPriorityHigh,
75 };
76
77 static K_THREAD_STACK_DEFINE(test_stack2, STACKSZ);
78 static osThreadAttr_t thread2_attr = {
79 .name = "Thread2",
80 .stack_mem = &test_stack2,
81 .stack_size = STACKSZ,
82 .priority = osPriorityHigh,
83 };
84
ZTEST(cmsis_thread_flags,test_thread_flags_no_wait_timeout)85 ZTEST(cmsis_thread_flags, test_thread_flags_no_wait_timeout)
86 {
87 osThreadId_t id1;
88 uint32_t flags;
89
90 id1 = osThreadNew(thread1, NULL, &thread1_attr);
91 zassert_true(id1 != NULL, "Failed creating thread1");
92
93 flags = osThreadFlagsSet(id1, FLAG1);
94 zassert_equal(flags & FLAG1, FLAG1, "");
95
96 /* Let id1 run to do the tests for Thread Flags */
97 osDelay(TIMEOUT_TICKS);
98 }
99
ZTEST(cmsis_thread_flags,test_thread_flags_signalled)100 ZTEST(cmsis_thread_flags, test_thread_flags_signalled)
101 {
102 osThreadId_t id;
103 uint32_t flags;
104
105 id = osThreadNew(thread2, osThreadGetId(), &thread2_attr);
106 zassert_true(id != NULL, "Failed creating thread2");
107
108 flags = osThreadFlagsSet(id, FLAG1);
109 zassert_equal(flags & FLAG1, FLAG1, "");
110
111 /* Let id run to do the tests for Thread Flags */
112 osDelay(TIMEOUT_TICKS / 2);
113
114 flags = osThreadFlagsSet(id, FLAG2);
115 zassert_equal(flags & FLAG2, FLAG2, "");
116
117 /* z_thread has a higher priority over the other threads.
118 * Hence, this thread needs to be put to sleep for thread2
119 * to become the active thread.
120 */
121 osDelay(TIMEOUT_TICKS / 2);
122 }
123
124 /* IRQ offload function handler to set Thread flag */
offload_function(const void * param)125 static void offload_function(const void *param)
126 {
127 int flags;
128
129 /* Make sure we're in IRQ context */
130 zassert_true(k_is_in_isr(), "Not in IRQ context!");
131
132 flags = osThreadFlagsSet((osThreadId_t)param, ISR_FLAG);
133 zassert_equal(flags & ISR_FLAG, ISR_FLAG, "ThreadFlagsSet failed in ISR");
134 }
135
test_thread_flags_from_isr(void * thread_id)136 void test_thread_flags_from_isr(void *thread_id)
137 {
138 uint32_t flags;
139
140 /**TESTPOINT: Offload to IRQ context*/
141 irq_offload(offload_function, (const void *)osThreadGetId());
142
143 flags = osThreadFlagsWait(ISR_FLAG, osFlagsWaitAll, TIMEOUT_TICKS);
144 zassert_equal((flags & ISR_FLAG), ISR_FLAG, "unexpected Thread flags value");
145 }
146
147 static K_THREAD_STACK_DEFINE(test_stack3, STACKSZ);
148 static osThreadAttr_t thread3_attr = {
149 .name = "Thread3",
150 .stack_mem = &test_stack3,
151 .stack_size = STACKSZ,
152 .priority = osPriorityHigh,
153 };
154
ZTEST(cmsis_thread_flags,test_thread_flags_isr)155 ZTEST(cmsis_thread_flags, test_thread_flags_isr)
156 {
157 osThreadId_t id;
158
159 id = osThreadNew(test_thread_flags_from_isr, osThreadGetId(), &thread3_attr);
160 zassert_true(id != NULL, "Failed creating thread");
161
162 osDelay(TIMEOUT_TICKS);
163 }
164 ZTEST_SUITE(cmsis_thread_flags, NULL, NULL, NULL, NULL, NULL);
165