lib/cmsis_rtos_v1: Implement support for Signal Event APIs
Signals are used to trigger execution states between threads. These APIs provide functionalities like signal set, clear and wait. Signed-off-by: Rajavardhan Gundi <rajavardhan.gundi@intel.com>
This commit is contained in:
parent
f4999f7949
commit
b5df23e423
5 changed files with 188 additions and 1 deletions
|
@ -169,6 +169,9 @@ typedef struct os_thread_def {
|
||||||
uint32_t stacksize; ///< stack size requirements in bytes; 0 is default stack size
|
uint32_t stacksize; ///< stack size requirements in bytes; 0 is default stack size
|
||||||
void *stack_mem; ///< pointer to array of stack memory
|
void *stack_mem; ///< pointer to array of stack memory
|
||||||
struct k_thread *cm_thread; ///< pointer to k_thread structure
|
struct k_thread *cm_thread; ///< pointer to k_thread structure
|
||||||
|
struct k_poll_signal *poll_signal;
|
||||||
|
struct k_poll_event *poll_event;
|
||||||
|
int32_t signal_results;
|
||||||
} osThreadDef_t;
|
} osThreadDef_t;
|
||||||
|
|
||||||
/// Timer Definition structure contains timer parameters.
|
/// Timer Definition structure contains timer parameters.
|
||||||
|
@ -283,8 +286,10 @@ extern const osThreadDef_t os_thread_def_##name
|
||||||
#define osThreadDef(name, priority, instances, stacksz) \
|
#define osThreadDef(name, priority, instances, stacksz) \
|
||||||
static K_THREAD_STACK_ARRAY_DEFINE(stacks_##name, instances, CONFIG_CMSIS_THREAD_MAX_STACK_SIZE); \
|
static K_THREAD_STACK_ARRAY_DEFINE(stacks_##name, instances, CONFIG_CMSIS_THREAD_MAX_STACK_SIZE); \
|
||||||
static struct k_thread cm_thread_##name[instances]; \
|
static struct k_thread cm_thread_##name[instances]; \
|
||||||
|
static struct k_poll_signal wait_signal_##name; \
|
||||||
|
static struct k_poll_event wait_events_##name; \
|
||||||
static osThreadDef_t os_thread_def_##name = \
|
static osThreadDef_t os_thread_def_##name = \
|
||||||
{ (name), (priority), (instances), (stacksz), (void *)(stacks_##name), (cm_thread_##name)}
|
{ (name), (priority), (instances), (stacksz), (void *)(stacks_##name), (cm_thread_##name), (&wait_signal_##name), (&wait_events_##name), 0 }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Access a Thread definition.
|
/// Access a Thread definition.
|
||||||
|
|
|
@ -15,6 +15,7 @@ zephyr_library_sources_ifdef(
|
||||||
cmsis_mempool.c
|
cmsis_mempool.c
|
||||||
cmsis_mailq.c
|
cmsis_mailq.c
|
||||||
cmsis_msgq.c
|
cmsis_msgq.c
|
||||||
|
cmsis_signal.c
|
||||||
)
|
)
|
||||||
|
|
||||||
zephyr_library_link_libraries(CMSIS)
|
zephyr_library_link_libraries(CMSIS)
|
||||||
|
|
|
@ -13,6 +13,24 @@ config CMSIS_RTOS_V1
|
||||||
Zephyr.
|
Zephyr.
|
||||||
|
|
||||||
if CMSIS_RTOS_V1
|
if CMSIS_RTOS_V1
|
||||||
|
config THREAD_CUSTOM_DATA
|
||||||
|
bool
|
||||||
|
prompt "Thread custom data"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
This option allows each thread to store 32 bits of custom data,
|
||||||
|
which can be accessed using the k_thread_custom_data_xxx() APIs.
|
||||||
|
|
||||||
|
config POLL
|
||||||
|
bool
|
||||||
|
prompt "Async I/O Framework"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Asynchronous notification framework. Enable the k_poll() and
|
||||||
|
k_poll_signal() APIs. The former can wait on multiple events
|
||||||
|
concurrently, which can be either directly triggered or triggered by
|
||||||
|
the availability of some kernel objects (semaphores and fifos).
|
||||||
|
|
||||||
config CMSIS_MAX_THREAD_COUNT
|
config CMSIS_MAX_THREAD_COUNT
|
||||||
int
|
int
|
||||||
prompt "Maximum thread count in CMSIS RTOS application"
|
prompt "Maximum thread count in CMSIS RTOS application"
|
||||||
|
|
158
lib/cmsis_rtos_v1/cmsis_signal.c
Normal file
158
lib/cmsis_rtos_v1/cmsis_signal.c
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <kernel_structs.h>
|
||||||
|
#include <cmsis_os.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
osThreadDef_t *thread_def =
|
||||||
|
(osThreadDef_t *)k_thread_other_custom_data_get(
|
||||||
|
(struct k_thread *)thread_id);
|
||||||
|
|
||||||
|
if (_is_in_isr() || (thread_id == NULL) ||
|
||||||
|
(signals >= (1 << (osFeature_Signals + 1)))) {
|
||||||
|
return 0x80000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = irq_lock();
|
||||||
|
sig = thread_def->signal_results;
|
||||||
|
thread_def->signal_results |= signals;
|
||||||
|
irq_unlock(key);
|
||||||
|
|
||||||
|
k_poll_signal(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;
|
||||||
|
osThreadDef_t *thread_def =
|
||||||
|
(osThreadDef_t *)k_thread_other_custom_data_get(
|
||||||
|
(struct k_thread *)thread_id);
|
||||||
|
|
||||||
|
if (_is_in_isr() || (thread_id == NULL) ||
|
||||||
|
(signals >= (1 << (osFeature_Signals + 1)))) {
|
||||||
|
return 0x80000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
u32_t time_delta_ms, timeout = millisec;
|
||||||
|
u64_t time_stamp_start, time_delta_us;
|
||||||
|
int freq = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000000;
|
||||||
|
|
||||||
|
if (_is_in_isr()) {
|
||||||
|
evt.status = osErrorISR;
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if signals is within the permitted range */
|
||||||
|
if (signals >= (1 << (osFeature_Signals + 1))) {
|
||||||
|
evt.status = osErrorValue;
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
|
osThreadDef_t *thread_def = k_thread_custom_data_get();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
|
time_stamp_start = (u64_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, timeout);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (retval) {
|
||||||
|
case 0:
|
||||||
|
evt.status = osEventSignal;
|
||||||
|
break;
|
||||||
|
case -EAGAIN:
|
||||||
|
if (millisec == 0) {
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
time_delta_us =
|
||||||
|
((u64_t)k_cycle_get_32() - time_stamp_start)/freq;
|
||||||
|
time_delta_ms = (u32_t)(time_delta_us/1000);
|
||||||
|
|
||||||
|
if (timeout > time_delta_ms) {
|
||||||
|
timeout -= time_delta_ms;
|
||||||
|
} else {
|
||||||
|
timeout = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -62,10 +62,15 @@ osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *arg)
|
||||||
stacksz = CONFIG_CMSIS_THREAD_MAX_STACK_SIZE;
|
stacksz = CONFIG_CMSIS_THREAD_MAX_STACK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
k_poll_signal_init(thread_def->poll_signal);
|
||||||
|
k_poll_event_init(thread_def->poll_event, K_POLL_TYPE_SIGNAL,
|
||||||
|
K_POLL_MODE_NOTIFY_ONLY, thread_def->poll_signal);
|
||||||
|
|
||||||
cm_thread = thread_def->cm_thread;
|
cm_thread = thread_def->cm_thread;
|
||||||
atomic_dec((atomic_t *)&thread_def->instances);
|
atomic_dec((atomic_t *)&thread_def->instances);
|
||||||
stk_ptr = thread_def->stack_mem;
|
stk_ptr = thread_def->stack_mem;
|
||||||
prio = cmsis_to_zephyr_priority(thread_def->tpriority);
|
prio = cmsis_to_zephyr_priority(thread_def->tpriority);
|
||||||
|
k_thread_custom_data_set((void *)thread_def);
|
||||||
|
|
||||||
tid = k_thread_create(&cm_thread[thread_def->instances],
|
tid = k_thread_create(&cm_thread[thread_def->instances],
|
||||||
stk_ptr[thread_def->instances], stacksz,
|
stk_ptr[thread_def->instances], stacksz,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue