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