|  | /* | 
|  | * Copyright (c) 2018 Intel Corporation | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <kernel_structs.h> | 
|  | #include "wrapper.h" | 
|  |  | 
|  | #define DONT_CARE		(0) | 
|  | #define NSEC_PER_MSEC		(NSEC_PER_USEC * USEC_PER_MSEC) | 
|  |  | 
|  | /** | 
|  | * @brief Set the specified Thread Flags of a thread. | 
|  | */ | 
|  | uint32_t osThreadFlagsSet(osThreadId_t thread_id, uint32_t flags) | 
|  | { | 
|  | int key; | 
|  | struct cv2_thread *tid = (struct cv2_thread *)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 cv2_thread *tid; | 
|  |  | 
|  | if (k_is_in_isr()) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | tid = (struct cv2_thread *)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 cv2_thread *tid; | 
|  | int sig, key; | 
|  |  | 
|  | if (k_is_in_isr()) { | 
|  | return osFlagsErrorUnknown; | 
|  | } | 
|  |  | 
|  | if (flags & 0x80000000) { | 
|  | return osFlagsErrorParameter; | 
|  | } | 
|  |  | 
|  | tid = (struct cv2_thread *)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 cv2_thread *tid; | 
|  | int retval, key; | 
|  | u32_t sig; | 
|  | u32_t time_delta_ms, timeout_ms = __ticks_to_ms(timeout); | 
|  | u64_t time_stamp_start, hwclk_cycles_delta, time_delta_ns; | 
|  |  | 
|  | if (k_is_in_isr()) { | 
|  | return osFlagsErrorUnknown; | 
|  | } | 
|  |  | 
|  | if (flags & 0x80000000) { | 
|  | return osFlagsErrorParameter; | 
|  | } | 
|  |  | 
|  | tid = (struct cv2_thread *)osThreadGetId(); | 
|  | if (tid == NULL) { | 
|  | return osFlagsErrorUnknown; | 
|  | } | 
|  |  | 
|  | for (;;) { | 
|  |  | 
|  | time_stamp_start = (u64_t)k_cycle_get_32(); | 
|  |  | 
|  | 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, 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 == 1, | 
|  | "event signaled is not 1"); | 
|  |  | 
|  | /* Reset the states to facilitate the next trigger */ | 
|  | tid->poll_event.signal->signaled = 0; | 
|  | tid->poll_event.state = K_POLL_STATE_NOT_READY; | 
|  |  | 
|  | if (options & osFlagsWaitAll) { | 
|  | /* Check if all events we are waiting on have | 
|  | * been signalled | 
|  | */ | 
|  | if ((tid->signal_results & flags) == flags) { | 
|  | break; | 
|  | } | 
|  |  | 
|  | /* 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 = | 
|  | (u64_t)k_cycle_get_32() - time_stamp_start; | 
|  |  | 
|  | time_delta_ns = | 
|  | (u32_t)SYS_CLOCK_HW_CYCLES_TO_NS(hwclk_cycles_delta); | 
|  |  | 
|  | time_delta_ms =	(u32_t)time_delta_ns/NSEC_PER_MSEC; | 
|  |  | 
|  | if (timeout_ms > time_delta_ms) { | 
|  | timeout_ms -= time_delta_ms; | 
|  | } else { | 
|  | timeout_ms = 0; | 
|  | } | 
|  | } else { | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | sig = tid->signal_results; | 
|  | if (!(options & osFlagsNoClear)) { | 
|  |  | 
|  | /* Clear signal flags as the thread is ready now */ | 
|  | key = irq_lock(); | 
|  | tid->signal_results &= ~(flags); | 
|  | irq_unlock(key); | 
|  | } | 
|  |  | 
|  | return sig; | 
|  | } |