| /* |
| * Copyright (c) 2017-2022, Arm Limited. All rights reserved. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| * |
| */ |
| |
| #include "thread.h" |
| #include "os_wrapper/mutex.h" |
| #include "semaphore.h" |
| #include "delay.h" |
| |
| #include "cmsis_os2.h" |
| |
| #include "tfm_nsid_manager.h" |
| #ifdef TFM_NS_MANAGE_NSID |
| #include "tfm_nsid_map_table.h" |
| #endif |
| |
| /* This is an example OS abstraction layer for CMSIS-RTOSv2 */ |
| |
| void *os_wrapper_thread_new(const char *name, int32_t stack_size, |
| os_wrapper_thread_func func, void *arg, |
| uint32_t priority) |
| { |
| osThreadAttr_t task_attribs = { |
| .tz_module = ((TZ_ModuleId_t)TFM_DEFAULT_NSID) |
| }; |
| |
| /* By default, the thread starts as osThreadDetached */ |
| if (stack_size != OS_WRAPPER_DEFAULT_STACK_SIZE) { |
| task_attribs.stack_size = stack_size; |
| } |
| task_attribs.name = name; |
| task_attribs.priority = (osPriority_t) priority; |
| |
| #ifdef TFM_NS_MANAGE_NSID |
| task_attribs.tz_module = (TZ_ModuleId_t)nsid_mgr_get_thread_nsid(name); |
| #endif |
| |
| return (void *)osThreadNew(func, arg, &task_attribs); |
| } |
| |
| void *os_wrapper_semaphore_create(uint32_t max_count, uint32_t initial_count, |
| const char *name) |
| { |
| osSemaphoreAttr_t sema_attrib = {0}; |
| |
| sema_attrib.name = name; |
| |
| return (void *)osSemaphoreNew(max_count, initial_count, &sema_attrib); |
| } |
| |
| uint32_t os_wrapper_semaphore_acquire(void *handle, uint32_t timeout) |
| { |
| osStatus_t status; |
| |
| status = osSemaphoreAcquire((osSemaphoreId_t)handle, |
| (timeout == OS_WRAPPER_WAIT_FOREVER) ? |
| osWaitForever : timeout); |
| if (status != osOK) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| uint32_t os_wrapper_semaphore_release(void *handle) |
| { |
| osStatus_t status; |
| |
| status = osSemaphoreRelease((osSemaphoreId_t)handle); |
| if (status != osOK) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| uint32_t os_wrapper_semaphore_delete(void *handle) |
| { |
| osStatus_t status; |
| |
| status = osSemaphoreDelete((osSemaphoreId_t)handle); |
| if (status != osOK) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| void *os_wrapper_mutex_create(void) |
| { |
| const osMutexAttr_t attr = { |
| .name = NULL, |
| .attr_bits = osMutexPrioInherit, /* Priority inheritance is recommended |
| * to enable if it is supported. |
| * For recursive mutex and the ability |
| * of auto release when owner being |
| * terminated is not required. |
| */ |
| .cb_mem = NULL, |
| .cb_size = 0U |
| }; |
| |
| return (void *)osMutexNew(&attr); |
| } |
| |
| uint32_t os_wrapper_mutex_acquire(void *handle, uint32_t timeout) |
| { |
| osStatus_t status = osOK; |
| |
| if (!handle) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| status = osMutexAcquire((osMutexId_t)handle, |
| (timeout == OS_WRAPPER_WAIT_FOREVER) ? |
| osWaitForever : timeout); |
| if (status != osOK) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| uint32_t os_wrapper_mutex_release(void *handle) |
| { |
| osStatus_t status = osOK; |
| |
| if (!handle) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| status = osMutexRelease((osMutexId_t)handle); |
| if (status != osOK) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| uint32_t os_wrapper_mutex_delete(void *handle) |
| { |
| osStatus_t status = osOK; |
| |
| if (!handle) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| status = osMutexDelete((osMutexId_t)handle); |
| if (status != osOK) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| void *os_wrapper_thread_get_handle(void) |
| { |
| return (void *)osThreadGetId(); |
| } |
| |
| uint32_t os_wrapper_thread_get_priority(void *handle, uint32_t *priority) |
| { |
| osPriority_t prio; |
| |
| prio = osThreadGetPriority((osThreadId_t)handle); |
| if (prio == osPriorityError) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| *priority = (uint32_t)prio; |
| |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| void os_wrapper_thread_exit(void) |
| { |
| osThreadExit(); |
| } |
| |
| uint32_t os_wrapper_thread_set_flag(void *handle, uint32_t flags) |
| { |
| uint32_t ret; |
| |
| ret = osThreadFlagsSet((osThreadId_t)handle, flags); |
| if (ret & osFlagsError) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| /* |
| * According to the description of CMSIS-RTOS v2 Thread Flags, |
| * osThreadFlagsSet() can be called inside Interrupt Service Routine. |
| */ |
| uint32_t os_wrapper_thread_set_flag_isr(void *handle, uint32_t flags) |
| { |
| uint32_t ret; |
| |
| ret = osThreadFlagsSet((osThreadId_t)handle, flags); |
| if (ret & osFlagsError) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| uint32_t os_wrapper_thread_wait_flag(uint32_t flags, uint32_t timeout) |
| { |
| uint32_t ret; |
| |
| ret = osThreadFlagsWait(flags, osFlagsWaitAll, |
| (timeout == OS_WRAPPER_WAIT_FOREVER) ? |
| osWaitForever : timeout); |
| if (ret & osFlagsError) { |
| return OS_WRAPPER_ERROR; |
| } |
| |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| uint32_t os_wrapper_get_tick(void) |
| { |
| return osKernelGetTickCount(); |
| } |
| |
| void *os_wrapper_msg_queue_create(size_t msg_size, uint8_t msg_count) |
| { |
| osMessageQueueId_t mq_id; |
| |
| mq_id = osMessageQueueNew(msg_count, msg_size, NULL); |
| |
| return (void *)mq_id; |
| } |
| |
| int32_t os_wrapper_msg_queue_send(void *mq_handle, |
| const void *msg_ptr) |
| { |
| osStatus_t status; |
| |
| status = osMessageQueuePut(mq_handle, msg_ptr, 0, 0); |
| if (status == osOK) { |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| return OS_WRAPPER_ERROR; |
| } |
| |
| int32_t os_wrapper_msg_queue_receive(void *mq_handle, |
| void *msg_ptr) |
| { |
| osStatus_t status; |
| |
| status = osMessageQueueGet(mq_handle, msg_ptr, NULL, osWaitForever); |
| if (status == osOK) { |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| return OS_WRAPPER_ERROR; |
| } |
| |
| int32_t os_wrapper_delay(uint32_t ticks) |
| { |
| osStatus_t status; |
| |
| status = osDelay(ticks); |
| if (status == osOK) { |
| return OS_WRAPPER_SUCCESS; |
| } |
| |
| return OS_WRAPPER_ERROR; |
| } |