Skip to content

Commit fedbe50

Browse files
peter-mitsiskartben
authored andcommitted
portability: cmsis: Base Event Flags on k_event
Updates the implementation of the osEventFlags APIs to use Zephyr kernel events instead of polling. Fixes #92899 Signed-off-by: Peter Mitsis <[email protected]>
1 parent 9cf0d66 commit fedbe50

File tree

5 files changed

+107
-113
lines changed

5 files changed

+107
-113
lines changed

include/zephyr/portability/cmsis_types.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,7 @@ struct cmsis_rtos_msgq_cb {
102102
* event flag control block. Control block is initiazed within `osEventFlagsNew()`.
103103
*/
104104
struct cmsis_rtos_event_cb {
105-
struct k_poll_signal poll_signal;
106-
struct k_poll_event poll_event;
107-
uint32_t signal_results;
105+
struct k_event z_event;
108106
bool is_cb_dynamic_allocation;
109107
const char *name;
110108
};

subsys/portability/cmsis_rtos_v2/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ config CMSIS_RTOS_V2
99
depends on THREAD_MONITOR
1010
depends on INIT_STACKS
1111
depends on NUM_PREEMPT_PRIORITIES >= 56
12+
select EVENTS
1213
help
1314
This enables CMSIS RTOS v2 API support. This is an OS-integration
1415
layer which allows applications using CMSIS RTOS V2 APIs to build

subsys/portability/cmsis_rtos_v2/event_flags.c

Lines changed: 40 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,9 @@ osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr)
4343
return NULL;
4444
}
4545
memset(events, 0, sizeof(struct cmsis_rtos_event_cb));
46-
events->is_cb_dynamic_allocation = attr->cb_mem == NULL;
47-
48-
k_poll_signal_init(&events->poll_signal);
49-
k_poll_event_init(&events->poll_event, K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY,
50-
&events->poll_signal);
51-
events->signal_results = 0U;
5246

47+
k_event_init(&events->z_event);
48+
events->is_cb_dynamic_allocation = (attr->cb_mem == NULL);
5349
events->name = (attr->name == NULL) ? init_event_flags_attrs.name : attr->name;
5450

5551
return (osEventFlagsId_t)events;
@@ -61,19 +57,13 @@ osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr)
6157
uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags)
6258
{
6359
struct cmsis_rtos_event_cb *events = (struct cmsis_rtos_event_cb *)ef_id;
64-
unsigned int key;
65-
6660
if ((ef_id == NULL) || (flags & osFlagsError)) {
6761
return osFlagsErrorParameter;
6862
}
6963

70-
key = irq_lock();
71-
events->signal_results |= flags;
72-
irq_unlock(key);
64+
k_event_post(&events->z_event, flags);
7365

74-
k_poll_signal_raise(&events->poll_signal, DONT_CARE);
75-
76-
return events->signal_results;
66+
return k_event_test(&events->z_event, 0xFFFFFFFF);
7767
}
7868

7969
/**
@@ -82,19 +72,16 @@ uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags)
8272
uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags)
8373
{
8474
struct cmsis_rtos_event_cb *events = (struct cmsis_rtos_event_cb *)ef_id;
85-
unsigned int key;
86-
uint32_t sig;
75+
uint32_t rv;
8776

8877
if ((ef_id == NULL) || (flags & osFlagsError)) {
8978
return osFlagsErrorParameter;
9079
}
9180

92-
key = irq_lock();
93-
sig = events->signal_results;
94-
events->signal_results &= ~(flags);
95-
irq_unlock(key);
81+
rv = k_event_test(&events->z_event, 0xFFFFFFFF);
82+
k_event_clear(&events->z_event, flags);
9683

97-
return sig;
84+
return rv;
9885
}
9986

10087
/**
@@ -104,101 +91,44 @@ uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t optio
10491
uint32_t timeout)
10592
{
10693
struct cmsis_rtos_event_cb *events = (struct cmsis_rtos_event_cb *)ef_id;
107-
int retval, key;
108-
uint32_t sig;
109-
k_timeout_t poll_timeout;
110-
uint64_t time_stamp_start, ticks_elapsed;
111-
bool flags_are_set;
112-
113-
/* Can be called from ISRs only if timeout is set to 0 */
114-
if (timeout > 0 && k_is_in_isr()) {
94+
uint32_t rv;
95+
k_timeout_t event_timeout;
96+
97+
/*
98+
* Return unknown error if called from ISR with a non-zero timeout
99+
* or if flags is zero.
100+
*/
101+
if (((timeout > 0U) && k_is_in_isr()) || (flags == 0U)) {
115102
return osFlagsErrorUnknown;
116103
}
117104

118105
if ((ef_id == NULL) || (flags & osFlagsError)) {
119106
return osFlagsErrorParameter;
120107
}
121108

122-
time_stamp_start = (uint64_t)k_uptime_ticks();
123-
124-
for (;;) {
125-
126-
flags_are_set = false;
127-
128-
key = irq_lock();
129-
130-
if (options & osFlagsWaitAll) {
131-
/* Check if all events we are waiting on have
132-
* been signalled
133-
*/
134-
if ((events->signal_results & flags) == flags) {
135-
flags_are_set = true;
136-
}
137-
} else {
138-
/* Check if any of events we are waiting on have
139-
* been signalled
140-
*/
141-
if (events->signal_results & flags) {
142-
flags_are_set = true;
143-
}
144-
}
145-
146-
if (flags_are_set) {
147-
sig = events->signal_results;
148-
149-
if (!(options & osFlagsNoClear)) {
150-
/* Clear signal flags as the thread is ready now */
151-
events->signal_results &= ~(flags);
152-
}
153-
154-
irq_unlock(key);
155-
156-
break;
157-
}
158-
159-
/* Reset the states to facilitate the next trigger */
160-
events->poll_event.signal->signaled = 0U;
161-
events->poll_event.state = K_POLL_STATE_NOT_READY;
162-
163-
irq_unlock(key);
164-
165-
if (timeout == 0) {
166-
return osFlagsErrorTimeout;
167-
} else if (timeout == osWaitForever) {
168-
poll_timeout = Z_FOREVER;
169-
} else {
170-
/* If we need to wait on more signals, we need to
171-
* adjust the timeout value accordingly based on
172-
* the time that has already elapsed.
173-
*/
174-
ticks_elapsed = (uint64_t)k_uptime_ticks() - time_stamp_start;
175-
176-
if (ticks_elapsed < (uint64_t)timeout) {
177-
poll_timeout = Z_TIMEOUT_TICKS(
178-
(k_ticks_t)(timeout - (uint32_t)ticks_elapsed));
179-
} else {
180-
return osFlagsErrorTimeout;
181-
}
182-
}
183-
184-
retval = k_poll(&events->poll_event, 1, poll_timeout);
185-
186-
if (retval == -EAGAIN) {
187-
/* k_poll signaled timeout. */
188-
return osFlagsErrorTimeout;
189-
} else if (retval != 0) {
190-
return osFlagsErrorUnknown;
191-
}
192-
193-
/* retval is zero.
194-
* k_poll found some raised signal then loop again and check flags.
195-
*/
196-
__ASSERT(events->poll_event.state == K_POLL_STATE_SIGNALED,
197-
"event state not signalled!");
198-
__ASSERT(events->poll_event.signal->signaled == 1U, "event signaled is not 1");
199-
}
200-
201-
return sig;
109+
if (timeout == osWaitForever) {
110+
event_timeout = K_FOREVER;
111+
} else if (timeout == 0U) {
112+
event_timeout = K_NO_WAIT;
113+
} else {
114+
event_timeout = K_TICKS(timeout);
115+
}
116+
117+
if ((options & osFlagsWaitAll) != 0) {
118+
rv = k_event_wait_all(&events->z_event, flags, false, event_timeout);
119+
} else {
120+
rv = k_event_wait(&events->z_event, flags, false, event_timeout);
121+
}
122+
123+
if ((options & osFlagsNoClear) == 0) {
124+
k_event_clear(&events->z_event, flags);
125+
}
126+
127+
if (rv != 0U) {
128+
return rv;
129+
}
130+
131+
return (timeout == 0U) ? osFlagsErrorResource : osFlagsErrorTimeout;
202132
}
203133

204134
/**
@@ -226,7 +156,7 @@ uint32_t osEventFlagsGet(osEventFlagsId_t ef_id)
226156
return 0;
227157
}
228158

229-
return events->signal_results;
159+
return k_event_test(&events->z_event, 0xFFFFFFFF);
230160
}
231161

232162
/**

tests/subsys/portability/cmsis_rtos_v2/prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ CONFIG_CMSIS_V2_THREAD_DYNAMIC_MAX_COUNT=10
1616
CONFIG_CMSIS_V2_THREAD_MAX_STACK_SIZE=1024
1717
CONFIG_CMSIS_V2_THREAD_DYNAMIC_STACK_SIZE=1024
1818
CONFIG_MP_MAX_NUM_CPUS=1
19+
CONFIG_EVENTS=y

tests/subsys/portability/cmsis_rtos_v2/src/event_flags.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,4 +232,68 @@ ZTEST(cmsis_event_flags, test_event_flags_static_allocation)
232232

233233
zassert_true(osEventFlagsDelete(evt_id) == osOK, "EventFlagsDelete failed");
234234
}
235+
236+
static K_THREAD_STACK_DEFINE(test_wait_stack1, STACKSZ);
237+
static osThreadAttr_t thread_wait_attr1 = {
238+
.name = "ThrWait1",
239+
.stack_mem = &test_wait_stack1,
240+
.stack_size = STACKSZ,
241+
.priority = osPriorityHigh,
242+
};
243+
244+
static K_THREAD_STACK_DEFINE(test_wait_stack2, STACKSZ);
245+
static osThreadAttr_t thread_wait_attr2 = {
246+
.name = "ThrWait2",
247+
.stack_mem = &test_wait_stack2,
248+
.stack_size = STACKSZ,
249+
.priority = osPriorityHigh,
250+
};
251+
252+
static osEventFlagsAttr_t event_wait_attrs = {
253+
.name = "MyEvent",
254+
.attr_bits = 0,
255+
.cb_mem = NULL,
256+
.cb_size = 0,
257+
};
258+
259+
static void thread_wait1(void *arg)
260+
{
261+
osEventFlagsWait(evt_id, FLAG2, osFlagsWaitAny, osWaitForever);
262+
}
263+
264+
static void thread_wait2(void *arg)
265+
{
266+
osEventFlagsWait(evt_id, FLAG1, osFlagsWaitAny, osWaitForever);
267+
}
268+
269+
/*
270+
* This test creates two threads that wait on the event flags. It previously
271+
* discovered that it would fail on the old CMSIS V2 implementation of event
272+
* flags that used polling. This test has been added to show that it no longer
273+
* fails.
274+
*/
275+
ZTEST(cmsis_event_flags, test_concurrent_wait)
276+
{
277+
evt_id = osEventFlagsNew(&event_wait_attrs);
278+
279+
/* Create 2 waiting threads */
280+
osThreadId_t id1 = osThreadNew(thread_wait1, evt_id, &thread_wait_attr1);
281+
osThreadId_t id2 = osThreadNew(thread_wait2, evt_id, &thread_wait_attr2);
282+
283+
zassert_true(id1 != NULL, "Failed creating thread1");
284+
zassert_true(id2 != NULL, "Failed creating thread2");
285+
osDelay(10);
286+
287+
int flags1 = osEventFlagsSet(evt_id, FLAG1);
288+
int flags2 = osEventFlagsSet(evt_id, FLAG2);
289+
290+
osThreadJoin(id1);
291+
osThreadJoin(id2);
292+
293+
zassert_true(flags1 & FLAG1, "");
294+
zassert_true(flags2 & FLAG2, "");
295+
296+
osEventFlagsDelete(evt_id);
297+
}
298+
235299
ZTEST_SUITE(cmsis_event_flags, NULL, NULL, NULL, NULL, NULL);

0 commit comments

Comments
 (0)