165 lines
3.8 KiB
C
165 lines
3.8 KiB
C
/*
|
|
* Copyright (c) 2018 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <kernel.h>
|
|
#include <cmsis_os.h>
|
|
|
|
#define NSEC_PER_MSEC (NSEC_PER_USEC * USEC_PER_MSEC)
|
|
#define MAX_VALID_SIGNAL_VAL ((1 << osFeature_Signals) - 1)
|
|
|
|
void *k_thread_other_custom_data_get(struct k_thread *thread_id)
|
|
{
|
|
return thread_id->custom_data;
|
|
}
|
|
|
|
/**
|
|
* @brief Set the specified Signal Flags of an active thread.
|
|
*/
|
|
int32_t osSignalSet(osThreadId thread_id, int32_t signals)
|
|
{
|
|
int sig, key;
|
|
|
|
if ((thread_id == NULL) || (!signals) ||
|
|
(signals & 0x80000000) || (signals > MAX_VALID_SIGNAL_VAL)) {
|
|
return 0x80000000;
|
|
}
|
|
|
|
osThreadDef_t *thread_def =
|
|
(osThreadDef_t *)k_thread_other_custom_data_get(
|
|
(struct k_thread *)thread_id);
|
|
|
|
key = irq_lock();
|
|
sig = thread_def->signal_results;
|
|
thread_def->signal_results |= signals;
|
|
irq_unlock(key);
|
|
|
|
k_poll_signal_raise(thread_def->poll_signal, signals);
|
|
|
|
return sig;
|
|
}
|
|
|
|
/**
|
|
* @brief Clear the specified Signal Flags of an active thread.
|
|
*/
|
|
int32_t osSignalClear(osThreadId thread_id, int32_t signals)
|
|
{
|
|
int sig, key;
|
|
|
|
if (k_is_in_isr() || (thread_id == NULL) || (!signals) ||
|
|
(signals & 0x80000000) || (signals > MAX_VALID_SIGNAL_VAL)) {
|
|
return 0x80000000;
|
|
}
|
|
|
|
osThreadDef_t *thread_def =
|
|
(osThreadDef_t *)k_thread_other_custom_data_get(
|
|
(struct k_thread *)thread_id);
|
|
|
|
key = irq_lock();
|
|
sig = thread_def->signal_results;
|
|
thread_def->signal_results &= ~(signals);
|
|
irq_unlock(key);
|
|
|
|
return sig;
|
|
}
|
|
|
|
/**
|
|
* @brief Wait for one or more Signal Flags to become signalled for the
|
|
* current running thread.
|
|
*/
|
|
osEvent osSignalWait(int32_t signals, uint32_t millisec)
|
|
{
|
|
int retval, key;
|
|
osEvent evt = {0};
|
|
uint32_t time_delta_ms, timeout = millisec;
|
|
uint64_t time_stamp_start, hwclk_cycles_delta, time_delta_ns;
|
|
|
|
if (k_is_in_isr()) {
|
|
evt.status = osErrorISR;
|
|
return evt;
|
|
}
|
|
|
|
/* Check if signals is within the permitted range */
|
|
if ((signals & 0x80000000) || (signals > MAX_VALID_SIGNAL_VAL)) {
|
|
evt.status = osErrorValue;
|
|
return evt;
|
|
}
|
|
|
|
osThreadDef_t *thread_def = k_thread_custom_data_get();
|
|
|
|
for (;;) {
|
|
|
|
time_stamp_start = (uint64_t)k_cycle_get_32();
|
|
|
|
switch (millisec) {
|
|
case 0:
|
|
retval = k_poll(thread_def->poll_event, 1, K_NO_WAIT);
|
|
break;
|
|
case osWaitForever:
|
|
retval = k_poll(thread_def->poll_event, 1, K_FOREVER);
|
|
break;
|
|
default:
|
|
retval = k_poll(thread_def->poll_event, 1,
|
|
K_MSEC(timeout));
|
|
break;
|
|
}
|
|
|
|
switch (retval) {
|
|
case 0:
|
|
evt.status = osEventSignal;
|
|
break;
|
|
case -EAGAIN:
|
|
if (millisec == 0U) {
|
|
evt.status = osOK;
|
|
} else {
|
|
evt.status = osEventTimeout;
|
|
}
|
|
return evt;
|
|
default:
|
|
evt.status = osErrorValue;
|
|
return evt;
|
|
}
|
|
|
|
__ASSERT(thread_def->poll_event->state
|
|
== K_POLL_STATE_SIGNALED,
|
|
"event state not signalled!");
|
|
__ASSERT(thread_def->poll_event->signal->signaled == 1,
|
|
"event signaled is not 1");
|
|
|
|
/* Reset the states to facilitate the next trigger */
|
|
thread_def->poll_event->signal->signaled = 0;
|
|
thread_def->poll_event->state = K_POLL_STATE_NOT_READY;
|
|
|
|
/* Check if all events we are waiting on have been signalled */
|
|
if ((thread_def->signal_results & signals) == signals) {
|
|
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 = (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 > time_delta_ms) {
|
|
timeout -= time_delta_ms;
|
|
} else {
|
|
timeout = 0U;
|
|
}
|
|
}
|
|
|
|
evt.value.signals = thread_def->signal_results;
|
|
|
|
/* Clear signal flags as the thread is ready now */
|
|
key = irq_lock();
|
|
thread_def->signal_results &= ~(signals);
|
|
irq_unlock(key);
|
|
|
|
return evt;
|
|
}
|