The osFlagsWaitAny option is not handled correctly. It returns once any flag at all is set, whereas it is supposed to only return once one of the flags specified in flags is set. Signed-off-by: Utsav Munendra <utsavm@meta.com>
184 lines
3.8 KiB
C
184 lines
3.8 KiB
C
/*
|
|
* Copyright (c) 2018 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/kernel_structs.h>
|
|
#include <zephyr/portability/cmsis_types.h>
|
|
#include "wrapper.h"
|
|
|
|
#define DONT_CARE (0)
|
|
|
|
/**
|
|
* @brief Set the specified Thread Flags of a thread.
|
|
*/
|
|
uint32_t osThreadFlagsSet(osThreadId_t thread_id, uint32_t flags)
|
|
{
|
|
unsigned int key;
|
|
struct cmsis_rtos_thread_cb *tid = (struct cmsis_rtos_thread_cb *)thread_id;
|
|
|
|
if ((thread_id == NULL) || (is_cmsis_rtos_v2_thread(thread_id) == NULL) ||
|
|
(flags & 0x80000000)) {
|
|
return osFlagsErrorParameter;
|
|
}
|
|
|
|
key = irq_lock();
|
|
tid->signal_results |= flags;
|
|
irq_unlock(key);
|
|
|
|
k_poll_signal_raise(&tid->poll_signal, DONT_CARE);
|
|
|
|
return tid->signal_results;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the current Thread Flags of current running thread.
|
|
*/
|
|
uint32_t osThreadFlagsGet(void)
|
|
{
|
|
struct cmsis_rtos_thread_cb *tid;
|
|
|
|
if (k_is_in_isr()) {
|
|
return 0;
|
|
}
|
|
|
|
tid = (struct cmsis_rtos_thread_cb *)osThreadGetId();
|
|
if (tid == NULL) {
|
|
return 0;
|
|
} else {
|
|
return tid->signal_results;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Clear the specified Thread Flags of current running thread.
|
|
*/
|
|
uint32_t osThreadFlagsClear(uint32_t flags)
|
|
{
|
|
struct cmsis_rtos_thread_cb *tid;
|
|
int sig, key;
|
|
|
|
if (k_is_in_isr()) {
|
|
return osFlagsErrorUnknown;
|
|
}
|
|
|
|
if (flags & 0x80000000) {
|
|
return osFlagsErrorParameter;
|
|
}
|
|
|
|
tid = (struct cmsis_rtos_thread_cb *)osThreadGetId();
|
|
if (tid == NULL) {
|
|
return osFlagsErrorUnknown;
|
|
}
|
|
|
|
key = irq_lock();
|
|
sig = tid->signal_results;
|
|
tid->signal_results &= ~(flags);
|
|
irq_unlock(key);
|
|
|
|
return sig;
|
|
}
|
|
|
|
/**
|
|
* @brief Wait for one or more Thread Flags of the current running thread to
|
|
* become signalled.
|
|
*/
|
|
uint32_t osThreadFlagsWait(uint32_t flags, uint32_t options, uint32_t timeout)
|
|
{
|
|
struct cmsis_rtos_thread_cb *tid;
|
|
int retval, key;
|
|
uint32_t sig;
|
|
uint32_t time_delta_ms, timeout_ms = k_ticks_to_ms_floor64(timeout);
|
|
uint64_t time_stamp_start, hwclk_cycles_delta, time_delta_ns;
|
|
|
|
if (k_is_in_isr()) {
|
|
return osFlagsErrorUnknown;
|
|
}
|
|
|
|
if (flags & 0x80000000) {
|
|
return osFlagsErrorParameter;
|
|
}
|
|
|
|
tid = (struct cmsis_rtos_thread_cb *)osThreadGetId();
|
|
if (tid == NULL) {
|
|
return osFlagsErrorUnknown;
|
|
}
|
|
|
|
for (;;) {
|
|
|
|
time_stamp_start = (uint64_t)k_cycle_get_32();
|
|
|
|
sig = tid->signal_results & flags;
|
|
|
|
if (options & osFlagsWaitAll) {
|
|
/* Check if all events we are waiting on have
|
|
* been signalled
|
|
*/
|
|
if (sig == flags) {
|
|
break;
|
|
}
|
|
} else {
|
|
/* Check if any events we are waiting on have
|
|
* been signalled
|
|
*/
|
|
if (sig != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (timeout) {
|
|
case 0:
|
|
retval = k_poll(&tid->poll_event, 1, K_NO_WAIT);
|
|
break;
|
|
case osWaitForever:
|
|
retval = k_poll(&tid->poll_event, 1, K_FOREVER);
|
|
break;
|
|
default:
|
|
retval = k_poll(&tid->poll_event, 1, K_MSEC(timeout_ms));
|
|
break;
|
|
}
|
|
|
|
switch (retval) {
|
|
case 0:
|
|
break;
|
|
case -EAGAIN:
|
|
return osFlagsErrorTimeout;
|
|
default:
|
|
return osFlagsErrorUnknown;
|
|
}
|
|
|
|
__ASSERT(tid->poll_event.state == K_POLL_STATE_SIGNALED,
|
|
"event state not signalled!");
|
|
__ASSERT(tid->poll_event.signal->signaled == 1U, "event signaled is not 1");
|
|
|
|
/* Reset the states to facilitate the next trigger */
|
|
tid->poll_event.signal->signaled = 0U;
|
|
tid->poll_event.state = K_POLL_STATE_NOT_READY;
|
|
|
|
/* If we need to wait on more signals, we need to
|
|
* adjust the timeout value accordingly based on
|
|
* the time that has already elapsed.
|
|
*/
|
|
hwclk_cycles_delta = (uint64_t)k_cycle_get_32() - time_stamp_start;
|
|
|
|
time_delta_ns = (uint32_t)k_cyc_to_ns_floor64(hwclk_cycles_delta);
|
|
|
|
time_delta_ms = (uint32_t)time_delta_ns / NSEC_PER_MSEC;
|
|
|
|
if (timeout_ms > time_delta_ms) {
|
|
timeout_ms -= time_delta_ms;
|
|
} else {
|
|
timeout_ms = 0U;
|
|
}
|
|
}
|
|
|
|
if (!(options & osFlagsNoClear)) {
|
|
/* Clear signal flags as the thread is ready now */
|
|
key = irq_lock();
|
|
tid->signal_results &= ~(sig);
|
|
irq_unlock(key);
|
|
}
|
|
|
|
return sig;
|
|
}
|