lib/cmsis_rtos_v2: Implement support for Event Flag APIs
Events are used to trigger execution states between threads. These APIs provide functionalities like event set, clear and wait. Signed-off-by: Rajavardhan Gundi <rajavardhan.gundi@intel.com>
This commit is contained in:
parent
ff911f7fdf
commit
fa499b353d
@ -13,6 +13,7 @@ zephyr_library_sources_ifdef(
|
||||
semaphore.c
|
||||
mempool.c
|
||||
msgq.c
|
||||
event_flags.c
|
||||
)
|
||||
|
||||
zephyr_library_link_libraries(CMSIS)
|
||||
|
||||
@ -66,4 +66,11 @@ config CMSIS_V2_MSGQ_MAX_COUNT
|
||||
range 0 255
|
||||
help
|
||||
Mention maximum number of message queues in CMSIS RTOS V2 compliant application.
|
||||
|
||||
config CMSIS_V2_EVT_FLAGS_MAX_COUNT
|
||||
int "Maximum event flags count in CMSIS RTOS V2 application"
|
||||
default 5
|
||||
range 0 255
|
||||
help
|
||||
Mention maximum number of event flags in CMSIS RTOS V2 compliant application.
|
||||
endif
|
||||
|
||||
244
lib/cmsis_rtos_v2/event_flags.c
Normal file
244
lib/cmsis_rtos_v2/event_flags.c
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <kernel_structs.h>
|
||||
#include "wrapper.h"
|
||||
|
||||
K_MEM_SLAB_DEFINE(cv2_event_flags_slab, sizeof(struct cv2_event_flags),
|
||||
CONFIG_CMSIS_V2_EVT_FLAGS_MAX_COUNT, 4);
|
||||
|
||||
static const osEventFlagsAttr_t init_event_flags_attrs = {
|
||||
.name = "ZephyrEvent",
|
||||
.attr_bits = 0,
|
||||
.cb_mem = NULL,
|
||||
.cb_size = 0,
|
||||
};
|
||||
|
||||
#define DONT_CARE (0)
|
||||
#define NSEC_PER_MSEC (NSEC_PER_USEC * USEC_PER_MSEC)
|
||||
|
||||
/**
|
||||
* @brief Create and Initialize an Event Flags object.
|
||||
*/
|
||||
osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr)
|
||||
{
|
||||
struct cv2_event_flags *events;
|
||||
|
||||
if (k_is_in_isr()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (attr == NULL) {
|
||||
attr = &init_event_flags_attrs;
|
||||
}
|
||||
|
||||
if (k_mem_slab_alloc(&cv2_event_flags_slab, (void **)&events, 100)
|
||||
== 0) {
|
||||
memset(events, 0, sizeof(struct cv2_event_flags));
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
k_poll_signal_init(&events->poll_signal);
|
||||
k_poll_event_init(&events->poll_event, K_POLL_TYPE_SIGNAL,
|
||||
K_POLL_MODE_NOTIFY_ONLY, &events->poll_signal);
|
||||
events->signal_results = 0;
|
||||
memcpy(events->name, attr->name, 16);
|
||||
|
||||
return (osEventFlagsId_t)events;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the specified Event Flags.
|
||||
*/
|
||||
uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags)
|
||||
{
|
||||
struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
|
||||
int key;
|
||||
|
||||
if ((ef_id == NULL) || (flags & 0x80000000)) {
|
||||
return osFlagsErrorParameter;
|
||||
}
|
||||
|
||||
key = irq_lock();
|
||||
events->signal_results |= flags;
|
||||
irq_unlock(key);
|
||||
|
||||
k_poll_signal_raise(&events->poll_signal, DONT_CARE);
|
||||
|
||||
return events->signal_results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the specified Event Flags.
|
||||
*/
|
||||
uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags)
|
||||
{
|
||||
struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
|
||||
int key;
|
||||
u32_t sig;
|
||||
|
||||
if ((ef_id == NULL) || (flags & 0x80000000)) {
|
||||
return osFlagsErrorParameter;
|
||||
}
|
||||
|
||||
key = irq_lock();
|
||||
sig = events->signal_results;
|
||||
events->signal_results &= ~(flags);
|
||||
irq_unlock(key);
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for one or more Event Flags to become signaled.
|
||||
*/
|
||||
uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags,
|
||||
uint32_t options, uint32_t timeout)
|
||||
{
|
||||
struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
|
||||
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;
|
||||
|
||||
/* Can be called from ISRs only if timeout is set to 0 */
|
||||
if (timeout > 0 && k_is_in_isr()) {
|
||||
return osFlagsErrorUnknown;
|
||||
}
|
||||
|
||||
if ((ef_id == NULL) || (flags & 0x80000000)) {
|
||||
return osFlagsErrorParameter;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
||||
time_stamp_start = (u64_t)k_cycle_get_32();
|
||||
|
||||
switch (timeout) {
|
||||
case 0:
|
||||
retval = k_poll(&events->poll_event, 1, K_NO_WAIT);
|
||||
break;
|
||||
case osWaitForever:
|
||||
retval = k_poll(&events->poll_event, 1, K_FOREVER);
|
||||
break;
|
||||
default:
|
||||
retval = k_poll(&events->poll_event, 1, timeout_ms);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (retval) {
|
||||
case 0:
|
||||
break;
|
||||
case -EAGAIN:
|
||||
return osFlagsErrorTimeout;
|
||||
default:
|
||||
return osFlagsErrorUnknown;
|
||||
}
|
||||
|
||||
__ASSERT(events->poll_event.state == K_POLL_STATE_SIGNALED,
|
||||
"event state not signalled!");
|
||||
__ASSERT(events->poll_event.signal->signaled == 1,
|
||||
"event signaled is not 1");
|
||||
|
||||
/* Reset the states to facilitate the next trigger */
|
||||
events->poll_event.signal->signaled = 0;
|
||||
events->poll_event.state = K_POLL_STATE_NOT_READY;
|
||||
|
||||
if (options & osFlagsWaitAll) {
|
||||
|
||||
/* Check if all events we are waiting on have
|
||||
* been signalled
|
||||
*/
|
||||
if ((events->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 = events->signal_results;
|
||||
if (!(options & osFlagsNoClear)) {
|
||||
|
||||
/* Clear signal flags as the thread is ready now */
|
||||
key = irq_lock();
|
||||
events->signal_results &= ~(flags);
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get name of an Event Flags object.
|
||||
*/
|
||||
const char *osEventFlagsGetName(osEventFlagsId_t ef_id)
|
||||
{
|
||||
struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
|
||||
|
||||
if (!k_is_in_isr() && (ef_id != NULL)) {
|
||||
return events->name;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current Event Flags.
|
||||
*/
|
||||
uint32_t osEventFlagsGet(osEventFlagsId_t ef_id)
|
||||
{
|
||||
struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
|
||||
|
||||
if (ef_id == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return events->signal_results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delete an Event Flags object.
|
||||
*/
|
||||
osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id)
|
||||
{
|
||||
struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
|
||||
|
||||
if (ef_id == NULL) {
|
||||
return osErrorResource;
|
||||
}
|
||||
|
||||
if (k_is_in_isr()) {
|
||||
return osErrorISR;
|
||||
}
|
||||
|
||||
/* The status code "osErrorParameter" (the value of the parameter
|
||||
* ef_id is incorrect) is not supported in Zephyr.
|
||||
*/
|
||||
|
||||
k_mem_slab_free(&cv2_event_flags_slab, (void *)&events);
|
||||
|
||||
return osOK;
|
||||
}
|
||||
@ -55,6 +55,13 @@ struct cv2_msgq {
|
||||
char name[16];
|
||||
};
|
||||
|
||||
struct cv2_event_flags {
|
||||
struct k_poll_signal poll_signal;
|
||||
struct k_poll_event poll_event;
|
||||
u32_t signal_results;
|
||||
char name[16];
|
||||
};
|
||||
|
||||
extern osThreadId_t get_cmsis_thread_id(k_tid_t tid);
|
||||
extern void *is_cmsis_rtos_v2_thread(void *thread_id);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user