diff --git a/include/cmsis_rtos_v1/cmsis_os.h b/include/cmsis_rtos_v1/cmsis_os.h index 842ee96f67c..9da629dc10a 100644 --- a/include/cmsis_rtos_v1/cmsis_os.h +++ b/include/cmsis_rtos_v1/cmsis_os.h @@ -169,6 +169,9 @@ typedef struct os_thread_def { uint32_t stacksize; ///< stack size requirements in bytes; 0 is default stack size void *stack_mem; ///< pointer to array of stack memory 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; /// Timer Definition structure contains timer parameters. @@ -283,8 +286,10 @@ extern const osThreadDef_t os_thread_def_##name #define osThreadDef(name, priority, instances, stacksz) \ 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_poll_signal wait_signal_##name; \ +static struct k_poll_event wait_events_##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 /// Access a Thread definition. diff --git a/lib/cmsis_rtos_v1/CMakeLists.txt b/lib/cmsis_rtos_v1/CMakeLists.txt index c4fd2fc6f96..8318284b7f2 100644 --- a/lib/cmsis_rtos_v1/CMakeLists.txt +++ b/lib/cmsis_rtos_v1/CMakeLists.txt @@ -15,6 +15,7 @@ zephyr_library_sources_ifdef( cmsis_mempool.c cmsis_mailq.c cmsis_msgq.c + cmsis_signal.c ) zephyr_library_link_libraries(CMSIS) diff --git a/lib/cmsis_rtos_v1/Kconfig b/lib/cmsis_rtos_v1/Kconfig index 5a630168026..c7f7abd608e 100644 --- a/lib/cmsis_rtos_v1/Kconfig +++ b/lib/cmsis_rtos_v1/Kconfig @@ -13,6 +13,24 @@ config CMSIS_RTOS_V1 Zephyr. 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 int prompt "Maximum thread count in CMSIS RTOS application" diff --git a/lib/cmsis_rtos_v1/cmsis_signal.c b/lib/cmsis_rtos_v1/cmsis_signal.c new file mode 100644 index 00000000000..9756739c220 --- /dev/null +++ b/lib/cmsis_rtos_v1/cmsis_signal.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +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; +} diff --git a/lib/cmsis_rtos_v1/cmsis_thread.c b/lib/cmsis_rtos_v1/cmsis_thread.c index b3788ff25a6..0e247b3bd16 100644 --- a/lib/cmsis_rtos_v1/cmsis_thread.c +++ b/lib/cmsis_rtos_v1/cmsis_thread.c @@ -62,10 +62,15 @@ osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *arg) 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; atomic_dec((atomic_t *)&thread_def->instances); stk_ptr = thread_def->stack_mem; 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], stk_ptr[thread_def->instances], stacksz,