/***********************************************************************************************//** * \file cyabs_rtos_rtxv5.c * * \brief * Implementation for CMSIS RTOS v2 abstraction * *************************************************************************************************** * \copyright * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or * an affiliate of Cypress Semiconductor Corporation * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **************************************************************************************************/ #include #include #include #if defined(__cplusplus) extern "C" { #endif #define CY_RTOS_THREAD_FLAG 0x01 /****************************************************** * Error Converter ******************************************************/ // Last received error status static cy_rtos_error_t dbgErr; //-------------------------------------------------------------------------------------------------- // cy_rtos_last_error //-------------------------------------------------------------------------------------------------- cy_rtos_error_t cy_rtos_last_error(void) { return dbgErr; } //-------------------------------------------------------------------------------------------------- // error_converter // // Converts internal error type to external error type //-------------------------------------------------------------------------------------------------- static cy_rslt_t error_converter(cy_rtos_error_t internalError) { cy_rslt_t value; switch (internalError) { case osOK: value = CY_RSLT_SUCCESS; break; case osErrorTimeout: value = CY_RTOS_TIMEOUT; break; case osErrorParameter: value = CY_RTOS_BAD_PARAM; break; case osErrorNoMemory: value = CY_RTOS_NO_MEMORY; break; case osError: case osErrorResource: case osErrorISR: default: value = CY_RTOS_GENERAL_ERROR; break; } // Update the last known error status dbgErr = internalError; return value; } //-------------------------------------------------------------------------------------------------- // convert_ms_to_ticks //-------------------------------------------------------------------------------------------------- static uint32_t convert_ms_to_ticks(cy_time_t timeout_ms) { if (timeout_ms == CY_RTOS_NEVER_TIMEOUT) { return osWaitForever; } else if (timeout_ms == 0) { return 0; } else { // Get number of ticks per second uint32_t tick_freq = osKernelGetTickFreq(); uint32_t ticks = (uint32_t)(((uint64_t)timeout_ms * tick_freq) / 1000); if (ticks == 0) { ticks = 1; } else if (ticks >= UINT32_MAX) { // if ticks if more than 32 bits, change ticks to max possible value that isn't // osWaitForever. ticks = UINT32_MAX - 1; } return ticks; } } /****************************************************** * Threads ******************************************************/ cy_rslt_t cy_rtos_create_thread(cy_thread_t* thread, cy_thread_entry_fn_t entry_function, const char* name, void* stack, uint32_t stack_size, cy_thread_priority_t priority, cy_thread_arg_t arg) { cy_rslt_t status = CY_RSLT_SUCCESS; osThreadAttr_t attr; if ((thread == NULL) || (stack_size < CY_RTOS_MIN_STACK_SIZE)) { status = CY_RTOS_BAD_PARAM; } else if ((stack != NULL) && (0 != (((uint32_t)stack) & CY_RTOS_ALIGNMENT_MASK))) { status = CY_RTOS_ALIGNMENT_ERROR; } else { attr.name = name; attr.attr_bits = osThreadJoinable; attr.cb_size = osRtxThreadCbSize; attr.stack_size = stack_size; attr.priority = (osPriority_t)priority; attr.tz_module = 0; attr.reserved = 0; // Allocate stack if NULL was passed if ((uint32_t*)stack == NULL) { // Note: 1 malloc so that it can be freed with 1 call when terminating uint32_t cb_mem_pad = (~osRtxThreadCbSize + 1) & CY_RTOS_ALIGNMENT_MASK; attr.cb_mem = malloc(osRtxThreadCbSize + cb_mem_pad + stack_size); if (attr.cb_mem != NULL) { attr.stack_mem = (uint32_t*)((uint32_t)attr.cb_mem + osRtxThreadCbSize + cb_mem_pad); } } else { attr.cb_mem = malloc(osRtxThreadCbSize); attr.stack_mem = stack; } if (attr.cb_mem == NULL) { status = CY_RTOS_NO_MEMORY; } else { CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); CY_ASSERT(((uint32_t)attr.stack_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); *thread = osThreadNew((osThreadFunc_t)entry_function, arg, &attr); CY_ASSERT((*thread == attr.cb_mem) || (*thread == NULL)); status = (*thread == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS; } } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_exit_thread //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_exit_thread(void) { // This does not have a return statement because the osThreadExit() function * does not return // so the return statement would be unreachable and causes a * warning for IAR compiler. osThreadExit(); } //-------------------------------------------------------------------------------------------------- // cy_rtos_terminate_thread //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_terminate_thread(cy_thread_t* thread) { cy_rslt_t status; cy_rtos_error_t statusInternal; if (thread == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osThreadTerminate(*thread); status = error_converter(statusInternal); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_is_thread_running //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_is_thread_running(cy_thread_t* thread, bool* running) { cy_rslt_t status = CY_RSLT_SUCCESS; if ((thread == NULL) || (running == NULL)) { status = CY_RTOS_BAD_PARAM; } else { *running = (osThreadGetState(*thread) == osThreadRunning) ? true : false; } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_get_thread_state //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_get_thread_state(cy_thread_t* thread, cy_thread_state_t* state) { cy_rslt_t status = CY_RSLT_SUCCESS; if ((thread == NULL) || (state == NULL)) { status = CY_RTOS_BAD_PARAM; } else { switch (osThreadGetState(*thread)) { case osThreadInactive: *state = CY_THREAD_STATE_INACTIVE; break; case osThreadReady: *state = CY_THREAD_STATE_READY; break; case osThreadRunning: *state = CY_THREAD_STATE_RUNNING; break; case osThreadBlocked: *state = CY_THREAD_STATE_BLOCKED; break; case osThreadTerminated: *state = CY_THREAD_STATE_TERMINATED; break; case osThreadError: case osThreadReserved: default: *state = CY_THREAD_STATE_UNKNOWN; break; } } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_join_thread //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_join_thread(cy_thread_t* thread) { cy_rslt_t status; cy_rtos_error_t statusInternal; if (thread == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osThreadJoin(*thread); status = error_converter(statusInternal); if (status == CY_RSLT_SUCCESS) { free(*thread); *thread = NULL; } } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_get_thread_handle //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_get_thread_handle(cy_thread_t* thread) { cy_rslt_t status = CY_RSLT_SUCCESS; if (thread == NULL) { status = CY_RTOS_BAD_PARAM; } else { *thread = osThreadGetId(); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_wait_thread_notification //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_wait_thread_notification(cy_time_t timeout_ms) { uint32_t ret; cy_rslt_t status = CY_RSLT_SUCCESS; ret = osThreadFlagsWait(CY_RTOS_THREAD_FLAG, osFlagsWaitAll, convert_ms_to_ticks(timeout_ms)); if (ret & osFlagsError) { status = (ret == osFlagsErrorTimeout) ? CY_RTOS_TIMEOUT : CY_RTOS_GENERAL_ERROR; // Update the last known error status dbgErr = (cy_rtos_error_t)ret; } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_set_thread_notification //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_set_thread_notification(cy_thread_t* thread, bool in_isr) { cy_rslt_t status = CY_RSLT_SUCCESS; uint32_t ret; (void)in_isr; if (thread == NULL) { status = CY_RTOS_BAD_PARAM; } else { /* According to the description of CMSIS-RTOS v2 * osThreadFlagsSet() can be called inside ISR */ ret = osThreadFlagsSet(*thread, CY_RTOS_THREAD_FLAG); if (ret & osFlagsError) { status = CY_RTOS_GENERAL_ERROR; // Update the last known error status dbgErr = (cy_rtos_error_t)ret; } } return status; } /****************************************************** * Mutexes ******************************************************/ cy_rslt_t cy_rtos_init_mutex2(cy_mutex_t* mutex, bool recursive) { cy_rslt_t status; osMutexAttr_t attr; if (mutex == NULL) { status = CY_RTOS_BAD_PARAM; } else { attr.name = NULL; attr.attr_bits = osMutexPrioInherit; if (recursive) { attr.attr_bits |= osMutexRecursive; } attr.cb_mem = malloc(osRtxMutexCbSize); attr.cb_size = osRtxMutexCbSize; if (attr.cb_mem == NULL) { status = CY_RTOS_NO_MEMORY; } else { CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); *mutex = osMutexNew(&attr); CY_ASSERT((*mutex == attr.cb_mem) || (*mutex == NULL)); status = (*mutex == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS; } } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_get_mutex //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_get_mutex(cy_mutex_t* mutex, cy_time_t timeout_ms) { cy_rslt_t status; cy_rtos_error_t statusInternal; if (mutex == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osMutexAcquire(*mutex, timeout_ms); status = error_converter(statusInternal); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_set_mutex //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_set_mutex(cy_mutex_t* mutex) { cy_rslt_t status; cy_rtos_error_t statusInternal; if (mutex == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osMutexRelease(*mutex); status = error_converter(statusInternal); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_deinit_mutex //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_deinit_mutex(cy_mutex_t* mutex) { cy_rslt_t status; cy_rtos_error_t statusInternal; if (mutex == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osMutexDelete(*mutex); status = error_converter(statusInternal); if (status == CY_RSLT_SUCCESS) { free(*mutex); *mutex = NULL; } } return status; } /****************************************************** * Semaphores ******************************************************/ cy_rslt_t cy_rtos_init_semaphore(cy_semaphore_t* semaphore, uint32_t maxcount, uint32_t initcount) { cy_rslt_t status; osSemaphoreAttr_t attr; if (semaphore == NULL) { status = CY_RTOS_BAD_PARAM; } else { attr.name = NULL; attr.attr_bits = 0U; attr.cb_mem = malloc(osRtxSemaphoreCbSize); attr.cb_size = osRtxSemaphoreCbSize; if (attr.cb_mem == NULL) { status = CY_RTOS_NO_MEMORY; } else { CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); *semaphore = osSemaphoreNew(maxcount, initcount, &attr); CY_ASSERT((*semaphore == attr.cb_mem) || (*semaphore == NULL)); status = (*semaphore == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS; } } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_get_semaphore //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_get_semaphore(cy_semaphore_t* semaphore, cy_time_t timeout_ms, bool in_isr) { cy_rslt_t status = CY_RSLT_SUCCESS; cy_rtos_error_t statusInternal; // Based on documentation when osSemaphoreAcquire is called from ISR timeout must be zero. // https://www.keil.com/pack/doc/CMSIS/RTOS2/html/group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b if ((semaphore == NULL) || (in_isr && (timeout_ms != 0))) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osSemaphoreAcquire(*semaphore, timeout_ms); status = error_converter(statusInternal); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_set_semaphore //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t* semaphore, bool in_isr) { cy_rslt_t status = CY_RSLT_SUCCESS; cy_rtos_error_t statusInternal; (void)in_isr; // Unused parameter in this implementation if (semaphore == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osSemaphoreRelease(*semaphore); status = error_converter(statusInternal); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_get_count_semaphore //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_get_count_semaphore(cy_semaphore_t* semaphore, size_t* count) { cy_rslt_t status; if ((semaphore == NULL) || (count == NULL)) { status = CY_RTOS_BAD_PARAM; } else { *count = osSemaphoreGetCount(*semaphore); status = CY_RSLT_SUCCESS; } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_deinit_semaphore //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t* semaphore) { cy_rslt_t status; cy_rtos_error_t statusInternal; if (semaphore == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osSemaphoreDelete(*semaphore); status = error_converter(statusInternal); if (status == CY_RSLT_SUCCESS) { free(*semaphore); *semaphore = NULL; } } return status; } /****************************************************** * Events ******************************************************/ #define CY_RTOS_EVENT_ERRORFLAG 0x80000000UL #define CY_RTOS_EVENT_FLAGS 0x7FFFFFFFUL //-------------------------------------------------------------------------------------------------- // cy_rtos_init_event //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_init_event(cy_event_t* event) { cy_rslt_t status; osEventFlagsAttr_t attr; if (event == NULL) { status = CY_RTOS_BAD_PARAM; } else { attr.name = NULL; attr.attr_bits = 0U; attr.cb_mem = malloc(osRtxEventFlagsCbSize); attr.cb_size = osRtxEventFlagsCbSize; if (attr.cb_mem == NULL) { status = CY_RTOS_NO_MEMORY; } else { CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); *event = osEventFlagsNew(&attr); CY_ASSERT((*event == attr.cb_mem) || (*event == NULL)); status = (*event == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS; } } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_setbits_event //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_setbits_event(cy_event_t* event, uint32_t bits, bool in_isr) { cy_rslt_t status = CY_RSLT_SUCCESS; cy_rtos_error_t statusInternal; (void)in_isr; // Unused parameter in this implementation if (event == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = (osStatus_t)osEventFlagsSet(*event, bits); if ((statusInternal & CY_RTOS_EVENT_ERRORFLAG) != 0UL) { status = error_converter(statusInternal); } } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_clearbits_event //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_clearbits_event(cy_event_t* event, uint32_t bits, bool in_isr) { cy_rslt_t status = CY_RSLT_SUCCESS; cy_rtos_error_t statusInternal; (void)in_isr; // Unused parameter in this implementation if (event == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = (osStatus_t)osEventFlagsClear(*event, bits); if ((statusInternal & CY_RTOS_EVENT_ERRORFLAG) != 0UL) { status = error_converter(statusInternal); } } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_getbits_event //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_getbits_event(cy_event_t* event, uint32_t* bits) { cy_rslt_t status = CY_RSLT_SUCCESS; if ((event == NULL) || (bits == NULL)) { status = CY_RTOS_BAD_PARAM; } else { *bits = osEventFlagsGet(*event); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_waitbits_event //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_waitbits_event(cy_event_t* event, uint32_t* bits, bool clear, bool all, cy_time_t timeout) { cy_rslt_t status = CY_RSLT_SUCCESS; cy_rtos_error_t statusInternal; uint32_t flagOption; if ((event == NULL) || (bits == NULL)) { status = CY_RTOS_BAD_PARAM; } else { flagOption = (all) ? osFlagsWaitAll : osFlagsWaitAny; if (!clear) { flagOption |= osFlagsNoClear; } statusInternal = (osStatus_t)osEventFlagsWait(*event, *bits, flagOption, timeout); if ((statusInternal & CY_RTOS_EVENT_ERRORFLAG) == 0UL) { *bits = statusInternal; } else { status = error_converter(statusInternal); } } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_deinit_event //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_deinit_event(cy_event_t* event) { cy_rslt_t status; cy_rtos_error_t statusInternal; if (event == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osEventFlagsDelete(*event); status = error_converter(statusInternal); if (status == CY_RSLT_SUCCESS) { free(*event); *event = NULL; } } return status; } /****************************************************** * Queues ******************************************************/ cy_rslt_t cy_rtos_init_queue(cy_queue_t* queue, size_t length, size_t itemsize) { cy_rslt_t status; osMessageQueueAttr_t attr; if (queue == NULL) { status = CY_RTOS_BAD_PARAM; } else { attr.name = NULL; attr.attr_bits = 0U; attr.cb_size = osRtxMessageQueueCbSize; uint32_t blockSize = ((itemsize + 3U) & ~3UL) + sizeof(osRtxMessage_t); attr.mq_size = blockSize * length; // Note: 1 malloc for both so that they can be freed with 1 call uint32_t cb_mem_pad = (8 - (osRtxMessageQueueCbSize & 0x07)) & 0x07; attr.cb_mem = malloc(osRtxMessageQueueCbSize + cb_mem_pad + attr.mq_size); if (attr.cb_mem != NULL) { attr.mq_mem = (uint32_t*)((uint32_t)attr.cb_mem + osRtxMessageQueueCbSize + cb_mem_pad); } if (attr.cb_mem == NULL) { status = CY_RTOS_NO_MEMORY; } else { CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); CY_ASSERT(((uint32_t)attr.mq_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); *queue = osMessageQueueNew(length, itemsize, &attr); CY_ASSERT((*queue == attr.cb_mem) || (*queue == NULL)); status = (*queue == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS; } } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_put_queue //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_put_queue(cy_queue_t* queue, const void* item_ptr, cy_time_t timeout_ms, bool in_isr) { cy_rslt_t status; cy_rtos_error_t statusInternal; if ((queue == NULL) || (item_ptr == NULL)) { status = CY_RTOS_BAD_PARAM; } else { // Not allowed to be called in ISR if timeout != 0 if ((!in_isr) || (in_isr && (timeout_ms == 0U))) { statusInternal = osMessageQueuePut(*queue, (uint8_t*)item_ptr, 0u, timeout_ms); } else { statusInternal = osErrorISR; } status = error_converter(statusInternal); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_get_queue //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_get_queue(cy_queue_t* queue, void* item_ptr, cy_time_t timeout_ms, bool in_isr) { cy_rslt_t status; cy_rtos_error_t statusInternal; if ((queue == NULL) || (item_ptr == NULL)) { status = CY_RTOS_BAD_PARAM; } else { // Not allowed to be called in ISR if timeout != 0 if ((!in_isr) || (in_isr && (timeout_ms == 0U))) { statusInternal = osMessageQueueGet(*queue, (uint8_t*)item_ptr, 0u, timeout_ms); } else { statusInternal = osErrorISR; } status = error_converter(statusInternal); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_count_queue //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_count_queue(cy_queue_t* queue, size_t* num_waiting) { cy_rslt_t status = CY_RSLT_SUCCESS; if ((queue == NULL) || (num_waiting == NULL)) { status = CY_RTOS_BAD_PARAM; } else { *num_waiting = osMessageQueueGetCount(*queue); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_space_queue //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_space_queue(cy_queue_t* queue, size_t* num_spaces) { cy_rslt_t status = CY_RSLT_SUCCESS; if ((queue == NULL) || (num_spaces == NULL)) { status = CY_RTOS_BAD_PARAM; } else { *num_spaces = osMessageQueueGetSpace(*queue); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_reset_queue //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_reset_queue(cy_queue_t* queue) { cy_rslt_t status; cy_rtos_error_t statusInternal; if (queue == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osMessageQueueReset(*queue); status = error_converter(statusInternal); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_deinit_queue //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_deinit_queue(cy_queue_t* queue) { cy_rslt_t status; cy_rtos_error_t statusInternal; if (queue == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osMessageQueueDelete(*queue); status = error_converter(statusInternal); if (status == CY_RSLT_SUCCESS) { free(*queue); *queue = NULL; } } return status; } /****************************************************** * Timers ******************************************************/ cy_rslt_t cy_rtos_init_timer(cy_timer_t* timer, cy_timer_trigger_type_t type, cy_timer_callback_t fun, cy_timer_callback_arg_t arg) { cy_rslt_t status; osTimerAttr_t attr; if (timer == NULL) { status = CY_RTOS_BAD_PARAM; } else { attr.name = NULL; attr.attr_bits = 0U; attr.cb_mem = malloc(osRtxTimerCbSize); attr.cb_size = osRtxTimerCbSize; if (attr.cb_mem == NULL) { status = CY_RTOS_NO_MEMORY; } else { osTimerType_t osTriggerType = (CY_TIMER_TYPE_PERIODIC == type) ? osTimerPeriodic : osTimerOnce; CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); *timer = osTimerNew((osTimerFunc_t)fun, osTriggerType, (void*)arg, &attr); CY_ASSERT((*timer == attr.cb_mem) || (*timer == NULL)); status = (*timer == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS; } } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_start_timer //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_start_timer(cy_timer_t* timer, cy_time_t num_ms) { cy_rslt_t status; cy_rtos_error_t statusInternal; if (timer == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osTimerStart(*timer, convert_ms_to_ticks(num_ms)); status = error_converter(statusInternal); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_stop_timer //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_stop_timer(cy_timer_t* timer) { cy_rslt_t status; cy_rtos_error_t statusInternal; if (timer == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osTimerStop(*timer); status = error_converter(statusInternal); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_is_running_timer //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_is_running_timer(cy_timer_t* timer, bool* state) { cy_rslt_t status = CY_RSLT_SUCCESS; if ((timer == NULL) || (state == NULL)) { status = CY_RTOS_BAD_PARAM; } else { *state = osTimerIsRunning(*timer); } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_deinit_timer //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_deinit_timer(cy_timer_t* timer) { cy_rslt_t status; cy_rtos_error_t statusInternal; if (timer == NULL) { status = CY_RTOS_BAD_PARAM; } else { statusInternal = osTimerDelete(*timer); status = error_converter(statusInternal); if (status == CY_RSLT_SUCCESS) { free(*timer); *timer = NULL; } } return status; } /****************************************************** * Time ******************************************************/ cy_rslt_t cy_rtos_get_time(cy_time_t* tval) { cy_rslt_t status = CY_RSLT_SUCCESS; uint32_t tick_freq; if (tval == NULL) { status = CY_RTOS_BAD_PARAM; } else { // Get Number of ticks per second tick_freq = osKernelGetTickFreq(); // Convert ticks count to time in milliseconds if (tick_freq != 0) { *tval = (cy_time_t)((osKernelGetTickCount() * 1000LL) / tick_freq); } else { status = CY_RTOS_GENERAL_ERROR; } } return status; } //-------------------------------------------------------------------------------------------------- // cy_rtos_delay_milliseconds //-------------------------------------------------------------------------------------------------- cy_rslt_t cy_rtos_delay_milliseconds(cy_time_t num_ms) { cy_rslt_t status; cy_rtos_error_t statusInternal; statusInternal = osDelay(num_ms); status = error_converter(statusInternal); return status; } #if defined(__cplusplus) } #endif