| /* |
| * 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 = k_ticks_to_ms_floor64(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 == 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 (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)k_cyc_to_ns_floor64(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 = 0U; |
| } |
| } 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; |
| } |