1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel_structs.h>
8 #include "wrapper.h"
9
10 #define DONT_CARE (0)
11
12 /**
13 * @brief Set the specified Thread Flags of a thread.
14 */
osThreadFlagsSet(osThreadId_t thread_id,uint32_t flags)15 uint32_t osThreadFlagsSet(osThreadId_t thread_id, uint32_t flags)
16 {
17 unsigned int key;
18 struct cv2_thread *tid = (struct cv2_thread *)thread_id;
19
20 if ((thread_id == NULL) || (is_cmsis_rtos_v2_thread(thread_id) == NULL)
21 || (flags & 0x80000000)) {
22 return osFlagsErrorParameter;
23 }
24
25 key = irq_lock();
26 tid->signal_results |= flags;
27 irq_unlock(key);
28
29 k_poll_signal_raise(&tid->poll_signal, DONT_CARE);
30
31 return tid->signal_results;
32 }
33
34 /**
35 * @brief Get the current Thread Flags of current running thread.
36 */
osThreadFlagsGet(void)37 uint32_t osThreadFlagsGet(void)
38 {
39 struct cv2_thread *tid;
40
41 if (k_is_in_isr()) {
42 return 0;
43 }
44
45 tid = (struct cv2_thread *)osThreadGetId();
46 if (tid == NULL) {
47 return 0;
48 } else {
49 return tid->signal_results;
50 }
51 }
52
53 /**
54 * @brief Clear the specified Thread Flags of current running thread.
55 */
osThreadFlagsClear(uint32_t flags)56 uint32_t osThreadFlagsClear(uint32_t flags)
57 {
58 struct cv2_thread *tid;
59 int sig, key;
60
61 if (k_is_in_isr()) {
62 return osFlagsErrorUnknown;
63 }
64
65 if (flags & 0x80000000) {
66 return osFlagsErrorParameter;
67 }
68
69 tid = (struct cv2_thread *)osThreadGetId();
70 if (tid == NULL) {
71 return osFlagsErrorUnknown;
72 }
73
74 key = irq_lock();
75 sig = tid->signal_results;
76 tid->signal_results &= ~(flags);
77 irq_unlock(key);
78
79 return sig;
80 }
81
82 /**
83 * @brief Wait for one or more Thread Flags of the current running thread to
84 * become signalled.
85 */
osThreadFlagsWait(uint32_t flags,uint32_t options,uint32_t timeout)86 uint32_t osThreadFlagsWait(uint32_t flags, uint32_t options, uint32_t timeout)
87 {
88 struct cv2_thread *tid;
89 int retval, key;
90 uint32_t sig;
91 uint32_t time_delta_ms, timeout_ms = k_ticks_to_ms_floor64(timeout);
92 uint64_t time_stamp_start, hwclk_cycles_delta, time_delta_ns;
93
94 if (k_is_in_isr()) {
95 return osFlagsErrorUnknown;
96 }
97
98 if (flags & 0x80000000) {
99 return osFlagsErrorParameter;
100 }
101
102 tid = (struct cv2_thread *)osThreadGetId();
103 if (tid == NULL) {
104 return osFlagsErrorUnknown;
105 }
106
107 for (;;) {
108
109 time_stamp_start = (uint64_t)k_cycle_get_32();
110
111 switch (timeout) {
112 case 0:
113 retval = k_poll(&tid->poll_event, 1, K_NO_WAIT);
114 break;
115 case osWaitForever:
116 retval = k_poll(&tid->poll_event, 1, K_FOREVER);
117 break;
118 default:
119 retval = k_poll(&tid->poll_event, 1,
120 K_MSEC(timeout_ms));
121 break;
122 }
123
124 switch (retval) {
125 case 0:
126 break;
127 case -EAGAIN:
128 return osFlagsErrorTimeout;
129 default:
130 return osFlagsErrorUnknown;
131 }
132
133 __ASSERT(tid->poll_event.state == K_POLL_STATE_SIGNALED,
134 "event state not signalled!");
135 __ASSERT(tid->poll_event.signal->signaled == 1U,
136 "event signaled is not 1");
137
138 /* Reset the states to facilitate the next trigger */
139 tid->poll_event.signal->signaled = 0U;
140 tid->poll_event.state = K_POLL_STATE_NOT_READY;
141
142 if (options & osFlagsWaitAll) {
143 /* Check if all events we are waiting on have
144 * been signalled
145 */
146 if ((tid->signal_results & flags) == flags) {
147 break;
148 }
149
150 /* If we need to wait on more signals, we need to
151 * adjust the timeout value accordingly based on
152 * the time that has already elapsed.
153 */
154 hwclk_cycles_delta =
155 (uint64_t)k_cycle_get_32() - time_stamp_start;
156
157 time_delta_ns =
158 (uint32_t)k_cyc_to_ns_floor64(hwclk_cycles_delta);
159
160 time_delta_ms = (uint32_t)time_delta_ns / NSEC_PER_MSEC;
161
162 if (timeout_ms > time_delta_ms) {
163 timeout_ms -= time_delta_ms;
164 } else {
165 timeout_ms = 0U;
166 }
167 } else {
168 break;
169 }
170 }
171
172 sig = tid->signal_results;
173 if (!(options & osFlagsNoClear)) {
174
175 /* Clear signal flags as the thread is ready now */
176 key = irq_lock();
177 tid->signal_results &= ~(flags);
178 irq_unlock(key);
179 }
180
181 return sig;
182 }
183