lib: cmsis_rtos_v2: Fix timing and logic for osEventFlagsWait.
Consistently use ticks for timing purposes. Fix retry logic. Check flags when osFlagsWaitAll is not set. Fixes #31103 Signed-off-by: Artur Lipowski <Artur.Lipowski@hidglobal.com>
This commit is contained in:
parent
a71fec83bd
commit
3b269bb033
1 changed files with 65 additions and 59 deletions
|
@ -18,8 +18,7 @@ static const osEventFlagsAttr_t init_event_flags_attrs = {
|
||||||
.cb_size = 0,
|
.cb_size = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DONT_CARE (0)
|
#define DONT_CARE (0)
|
||||||
#define NSEC_PER_MSEC (NSEC_PER_USEC * USEC_PER_MSEC)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create and Initialize an Event Flags object.
|
* @brief Create and Initialize an Event Flags object.
|
||||||
|
@ -37,7 +36,7 @@ osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k_mem_slab_alloc(&cv2_event_flags_slab, (void **)&events, K_MSEC(100))
|
if (k_mem_slab_alloc(&cv2_event_flags_slab, (void **)&events, K_MSEC(100))
|
||||||
== 0) {
|
== 0) {
|
||||||
memset(events, 0, sizeof(struct cv2_event_flags));
|
memset(events, 0, sizeof(struct cv2_event_flags));
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -66,7 +65,7 @@ uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags)
|
||||||
struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
|
struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
|
||||||
int key;
|
int key;
|
||||||
|
|
||||||
if ((ef_id == NULL) || (flags & 0x80000000)) {
|
if ((ef_id == NULL) || (flags & osFlagsError)) {
|
||||||
return osFlagsErrorParameter;
|
return osFlagsErrorParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +87,7 @@ uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags)
|
||||||
int key;
|
int key;
|
||||||
uint32_t sig;
|
uint32_t sig;
|
||||||
|
|
||||||
if ((ef_id == NULL) || (flags & 0x80000000)) {
|
if ((ef_id == NULL) || (flags & osFlagsError)) {
|
||||||
return osFlagsErrorParameter;
|
return osFlagsErrorParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,91 +108,98 @@ uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags,
|
||||||
struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
|
struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
|
||||||
int retval, key;
|
int retval, key;
|
||||||
uint32_t sig;
|
uint32_t sig;
|
||||||
uint32_t time_delta_ms, timeout_ms = k_ticks_to_ms_floor64(timeout);
|
k_timeout_t poll_timeout;
|
||||||
uint64_t time_stamp_start, hwclk_cycles_delta, time_delta_ns;
|
uint64_t time_stamp_start, ticks_elapsed;
|
||||||
|
bool flags_are_set;
|
||||||
|
|
||||||
/* Can be called from ISRs only if timeout is set to 0 */
|
/* Can be called from ISRs only if timeout is set to 0 */
|
||||||
if (timeout > 0 && k_is_in_isr()) {
|
if (timeout > 0 && k_is_in_isr()) {
|
||||||
return osFlagsErrorUnknown;
|
return osFlagsErrorUnknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ef_id == NULL) || (flags & 0x80000000)) {
|
if ((ef_id == NULL) || (flags & osFlagsError)) {
|
||||||
return osFlagsErrorParameter;
|
return osFlagsErrorParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_stamp_start = (uint64_t)k_uptime_ticks();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
time_stamp_start = (uint64_t)k_cycle_get_32();
|
flags_are_set = false;
|
||||||
|
|
||||||
switch (timeout) {
|
key = irq_lock();
|
||||||
case 0:
|
|
||||||
retval = k_poll(&events->poll_event, 1, K_NO_WAIT);
|
if (options & osFlagsWaitAll) {
|
||||||
break;
|
/* Check if all events we are waiting on have
|
||||||
case osWaitForever:
|
* been signalled
|
||||||
retval = k_poll(&events->poll_event, 1, K_FOREVER);
|
*/
|
||||||
break;
|
if ((events->signal_results & flags) == flags) {
|
||||||
default:
|
flags_are_set = true;
|
||||||
retval = k_poll(&events->poll_event, 1,
|
}
|
||||||
K_MSEC(timeout_ms));
|
} else {
|
||||||
break;
|
/* Check if any of events we are waiting on have
|
||||||
|
* been signalled
|
||||||
|
*/
|
||||||
|
if (events->signal_results & flags) {
|
||||||
|
flags_are_set = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (retval) {
|
if (flags_are_set) {
|
||||||
case 0:
|
sig = events->signal_results;
|
||||||
break;
|
|
||||||
case -EAGAIN:
|
|
||||||
return osFlagsErrorTimeout;
|
|
||||||
default:
|
|
||||||
return osFlagsErrorUnknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
__ASSERT(events->poll_event.state == K_POLL_STATE_SIGNALED,
|
if (!(options & osFlagsNoClear)) {
|
||||||
"event state not signalled!");
|
/* Clear signal flags as the thread is ready now */
|
||||||
__ASSERT(events->poll_event.signal->signaled == 1U,
|
events->signal_results &= ~(flags);
|
||||||
"event signaled is not 1");
|
}
|
||||||
|
|
||||||
|
irq_unlock(key);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset the states to facilitate the next trigger */
|
/* Reset the states to facilitate the next trigger */
|
||||||
events->poll_event.signal->signaled = 0U;
|
events->poll_event.signal->signaled = 0U;
|
||||||
events->poll_event.state = K_POLL_STATE_NOT_READY;
|
events->poll_event.state = K_POLL_STATE_NOT_READY;
|
||||||
|
|
||||||
if (options & osFlagsWaitAll) {
|
irq_unlock(key);
|
||||||
|
|
||||||
/* Check if all events we are waiting on have
|
|
||||||
* been signalled
|
|
||||||
*/
|
|
||||||
if ((events->signal_results & flags) == flags) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (timeout == 0) {
|
||||||
|
return osFlagsErrorTimeout;
|
||||||
|
} else if (timeout == osWaitForever) {
|
||||||
|
poll_timeout = Z_FOREVER;
|
||||||
|
} else {
|
||||||
/* If we need to wait on more signals, we need to
|
/* If we need to wait on more signals, we need to
|
||||||
* adjust the timeout value accordingly based on
|
* adjust the timeout value accordingly based on
|
||||||
* the time that has already elapsed.
|
* the time that has already elapsed.
|
||||||
*/
|
*/
|
||||||
hwclk_cycles_delta =
|
ticks_elapsed =
|
||||||
(uint64_t)k_cycle_get_32() - time_stamp_start;
|
(uint64_t)k_uptime_ticks() - time_stamp_start;
|
||||||
|
|
||||||
time_delta_ns =
|
if (ticks_elapsed < (uint64_t)timeout) {
|
||||||
(uint32_t)k_cyc_to_ns_floor64(hwclk_cycles_delta);
|
poll_timeout = Z_TIMEOUT_TICKS((k_ticks_t)(
|
||||||
|
timeout - (uint32_t)ticks_elapsed));
|
||||||
time_delta_ms = (uint32_t)time_delta_ns / NSEC_PER_MSEC;
|
|
||||||
|
|
||||||
if (timeout_ms > time_delta_ms) {
|
|
||||||
timeout_ms -= time_delta_ms;
|
|
||||||
} else {
|
} else {
|
||||||
timeout_ms = 0U;
|
return osFlagsErrorTimeout;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sig = events->signal_results;
|
retval = k_poll(&events->poll_event, 1, poll_timeout);
|
||||||
if (!(options & osFlagsNoClear)) {
|
|
||||||
|
|
||||||
/* Clear signal flags as the thread is ready now */
|
if (retval == -EAGAIN) {
|
||||||
key = irq_lock();
|
/* k_poll signaled timeout. */
|
||||||
events->signal_results &= ~(flags);
|
return osFlagsErrorTimeout;
|
||||||
irq_unlock(key);
|
} else if (retval != 0) {
|
||||||
|
return osFlagsErrorUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* retval is zero.
|
||||||
|
* k_poll found some raised signal then loop again and check flags.
|
||||||
|
*/
|
||||||
|
__ASSERT(events->poll_event.state == K_POLL_STATE_SIGNALED,
|
||||||
|
"event state not signalled!");
|
||||||
|
__ASSERT(events->poll_event.signal->signaled == 1U,
|
||||||
|
"event signaled is not 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
return sig;
|
return sig;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue