1 /*
2  * Copyright (c) 2017 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_os.h>
10 
11 #include <zephyr/irq_offload.h>
12 #include <zephyr/kernel_structs.h>
13 
14 #define TIMEOUT		(100)
15 #define SIGNAL1		(0x00000020)
16 #define SIGNAL2		(0x00000004)
17 #define SIGNAL		(SIGNAL1 | SIGNAL2)
18 
19 #define SIGNAL_FLAG 0x00000001
20 #define ISR_SIGNAL 0x50
21 
22 #define SIGNAL_ALL_FLAGS ((1 << osFeature_Signals) - 1)
23 #define SIGNAL_OUTOFLIMIT_FLAG ((1 << (osFeature_Signals + 1))-1)
24 
Thread_1(void const * arg)25 void Thread_1(void const *arg)
26 {
27 	int signals = osSignalSet((osThreadId)arg, SIGNAL1);
28 
29 	zassert_not_equal(signals, 0x80000000, "");
30 }
31 
Thread_2(void const * arg)32 void Thread_2(void const *arg)
33 {
34 	int signals = osSignalSet((osThreadId)arg, SIGNAL2);
35 
36 	zassert_not_equal(signals, 0x80000000, "");
37 }
38 
test_multiple_signal_flags(void const * thread_id)39 void test_multiple_signal_flags(void const *thread_id)
40 {
41 	int max_signal_cnt = osFeature_Signals;
42 	int signals, sig_cnt;
43 
44 	for (sig_cnt = 0; sig_cnt < max_signal_cnt; sig_cnt++) {
45 		/* create unique signal flags to set one flag at a time */
46 		int32_t signal_each_flag = SIGNAL_FLAG << sig_cnt;
47 		/* check if each signal flag is set properly */
48 		signals = osSignalSet((osThreadId)thread_id, signal_each_flag);
49 		zassert_not_equal(signals, 0x80000000,
50 				  "Setting each signal flag failed");
51 	}
52 	/* clear all the bits to check next scenario */
53 	signals = osSignalClear((osThreadId)thread_id, SIGNAL_ALL_FLAGS);
54 	zassert_not_equal(signals, 0x80000000, "");
55 
56 	/* signal all the available flags at one shot */
57 	signals = osSignalSet((osThreadId)thread_id, SIGNAL_ALL_FLAGS);
58 	zassert_not_equal(signals, 0x80000000,
59 					  "Signal flags maximum limit failed");
60 	/* clear all the bits to check next scenario */
61 	signals = osSignalClear((osThreadId)thread_id, SIGNAL_ALL_FLAGS);
62 	zassert_not_equal(signals, 0x80000000, "");
63 
64 	/* signal invalid flag to validate permissible flag limit */
65 	signals = osSignalSet((osThreadId)thread_id, SIGNAL_OUTOFLIMIT_FLAG);
66 	zassert_equal(signals, 0x80000000, "Signal flags set unexpectedly");
67 }
68 
69 osThreadDef(Thread_1, osPriorityHigh, 3, 0);
70 osThreadDef(Thread_2, osPriorityHigh, 1, 0);
71 
ZTEST(cmsis_signal,test_signal_events_no_wait)72 ZTEST(cmsis_signal, test_signal_events_no_wait)
73 {
74 	osThreadId id1;
75 	osEvent evt;
76 
77 	id1 = osThreadCreate(osThread(Thread_1), osThreadGetId());
78 	zassert_true(id1 != NULL, "Thread creation failed");
79 
80 	/* Let id1 run to trigger SIGNAL1 */
81 	osDelay(10);
82 
83 	/* wait for SIGNAL1. It should return immediately as it is
84 	 * already triggered.
85 	 */
86 	evt = osSignalWait(SIGNAL1, 0);
87 	zassert_equal(evt.status, osEventSignal, "");
88 	zassert_equal((evt.value.signals & SIGNAL1), SIGNAL1, "");
89 	osThreadTerminate(id1);
90 }
91 
ZTEST(cmsis_signal,test_signal_events_timeout)92 ZTEST(cmsis_signal, test_signal_events_timeout)
93 {
94 	osThreadId id1;
95 	int signals;
96 	osEvent evt;
97 
98 	id1 = osThreadCreate(osThread(Thread_1), osThreadGetId());
99 	zassert_true(id1 != NULL, "Thread creation failed");
100 
101 	/* Let id1 run to trigger SIGNAL1 */
102 	osDelay(10);
103 
104 	signals = osSignalClear(osThreadGetId(), SIGNAL1);
105 	zassert_not_equal(signals, 0x80000000, "signal clear failed");
106 
107 	/* wait for SIGNAL1. It should timeout here as the signal
108 	 * though triggered, gets cleared in the previous step.
109 	 */
110 	evt = osSignalWait(SIGNAL1, TIMEOUT);
111 	zassert_equal(evt.status, osEventTimeout, "signal timeout failed");
112 	osThreadTerminate(id1);
113 }
114 
ZTEST(cmsis_signal,test_signal_events_signalled)115 ZTEST(cmsis_signal, test_signal_events_signalled)
116 {
117 	osThreadId id1, id2;
118 	osEvent evt;
119 	int signals;
120 
121 	id1 = osThreadCreate(osThread(Thread_1), osThreadGetId());
122 	zassert_true(id1 != NULL, "Thread creation failed");
123 
124 	id2 = osThreadCreate(osThread(Thread_2), osThreadGetId());
125 	zassert_true(id2 != NULL, "Thread creation failed");
126 
127 	/* wait for multiple signals */
128 	evt = osSignalWait(SIGNAL, TIMEOUT);
129 	zassert_equal(evt.status, osEventSignal,
130 		      "wait signal returned unexpected error");
131 	zassert_equal((evt.value.signals & SIGNAL), SIGNAL,
132 		      "wait signal failed unexpectedly");
133 
134 	signals = osSignalClear(osThreadGetId(), SIGNAL);
135 	zassert_not_equal(signals, 0x80000000, "clear signal failed");
136 
137 	/* Set any single signal */
138 	signals = osSignalSet(osThreadGetId(), SIGNAL1);
139 	zassert_not_equal(signals, 0x80000000, "set any signal failed");
140 
141 	/* wait for any single signal flag */
142 	evt = osSignalWait(0, TIMEOUT);
143 	zassert_equal(evt.status, osEventSignal, "wait for single flag failed");
144 	zassert_equal(evt.value.signals, SIGNAL1,
145 				  "wait single flag returned invalid value");
146 
147 	/* validate by passing invalid parameters */
148 	zassert_equal(osSignalSet(NULL, 0), 0x80000000,
149 				  "NULL signal set unexpectedly");
150 	zassert_equal(osSignalClear(NULL, 0), 0x80000000,
151 				  "NULL signal cleared unexpectedly");
152 	/* cannot wait for Flag mask with MSB set */
153 	zassert_equal(osSignalWait((int32_t)0x80010000, 0).status, osErrorValue,
154 				  "signal wait passed unexpectedly");
155 	zassert_equal(osSignalSet(osThreadGetId(), (int32_t)0x80010000),
156 				  0x80000000, "signal set unexpectedly");
157 	zassert_equal(osSignalClear(osThreadGetId(), (int32_t)0x80010000),
158 				    0x80000000, "signal cleared unexpectedly");
159 
160 	test_multiple_signal_flags(osThreadGetId());
161 }
162 
163 /* IRQ offload function handler to set signal flag */
offload_function(const void * param)164 static void offload_function(const void *param)
165 {
166 	osThreadId tid = (osThreadId)param;
167 	int signals;
168 
169 	/* Make sure we're in IRQ context */
170 	zassert_true(k_is_in_isr(), "Not in IRQ context!");
171 
172 	signals = osSignalSet(tid, ISR_SIGNAL);
173 	zassert_not_equal(signals, 0x80000000, "signal set failed in ISR");
174 }
175 
test_signal_from_isr(void const * thread_id)176 void test_signal_from_isr(void const *thread_id)
177 {
178 	/**TESTPOINT: Offload to IRQ context*/
179 	irq_offload(offload_function, (const void *)thread_id);
180 }
181 
182 osThreadDef(test_signal_from_isr, osPriorityHigh, 1, 0);
183 
ZTEST(cmsis_signal,test_signal_events_isr)184 ZTEST(cmsis_signal, test_signal_events_isr)
185 {
186 	osThreadId id;
187 	osEvent evt;
188 
189 	id = osThreadCreate(osThread(test_signal_from_isr), osThreadGetId());
190 	zassert_true(id != NULL, "Thread creation failed");
191 	evt = osSignalWait(ISR_SIGNAL, TIMEOUT);
192 	zassert_equal(evt.status, osEventSignal,
193 		      "signal wait failed unexpectedly");
194 	zassert_equal((evt.value.signals & ISR_SIGNAL),
195 		       ISR_SIGNAL, "unexpected signal wait value");
196 }
197 ZTEST_SUITE(cmsis_signal, NULL, NULL, NULL, NULL, NULL);
198