| /***********************************************************************************************//** |
| * \file cyabs_rtos_zephyr.c |
| * |
| * \brief |
| * Implementation for Zephyr RTOS abstraction |
| * |
| *************************************************************************************************** |
| * \copyright |
| * Copyright 2018-2022 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 <stdlib.h> |
| #include <string.h> |
| #include <cy_utils.h> |
| #include <cyabs_rtos.h> |
| |
| #if defined(__cplusplus) |
| extern "C" { |
| #endif |
| |
| |
| /* |
| * Error Converter |
| */ |
| |
| /* Last received error status */ |
| static cy_rtos_error_t dbgErr; |
| |
| cy_rtos_error_t cy_rtos_last_error(void) |
| { |
| return dbgErr; |
| } |
| |
| /* 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 0: |
| value = CY_RSLT_SUCCESS; |
| break; |
| |
| case -EAGAIN: |
| value = CY_RTOS_TIMEOUT; |
| break; |
| |
| case -EINVAL: |
| value = CY_RTOS_BAD_PARAM; |
| break; |
| |
| case -ENOMEM: |
| value = CY_RTOS_NO_MEMORY; |
| break; |
| |
| default: |
| value = CY_RTOS_GENERAL_ERROR; |
| break; |
| } |
| |
| /* Update the last known error status */ |
| dbgErr = internalError; |
| |
| return value; |
| } |
| |
| static void free_thead_obj(cy_thread_t *thread) |
| { |
| /* Free allocated stack buffer */ |
| if ((*thread)->memptr != NULL) { |
| k_free((*thread)->memptr); |
| } |
| |
| /* Free object */ |
| k_free(*thread); |
| } |
| |
| |
| /* |
| * Threads |
| */ |
| |
| static void thread_entry_function_wrapper(void *p1, void *p2, void *p3) |
| { |
| CY_UNUSED_PARAMETER(p3); |
| ((cy_thread_entry_fn_t)p2)(p1); |
| } |
| |
| 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; |
| cy_rtos_error_t status_internal = 0; |
| |
| 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 { |
| void *stack_alloc = NULL; |
| k_tid_t my_tid = NULL; |
| |
| /* Allocate cy_thread_t object */ |
| *thread = k_malloc(sizeof(k_thread_wrapper_t)); |
| |
| /* Allocate stack if NULL was passed */ |
| if ((uint32_t *)stack == NULL) { |
| stack_alloc = k_aligned_alloc(Z_KERNEL_STACK_OBJ_ALIGN, |
| Z_KERNEL_STACK_SIZE_ADJUST(stack_size)); |
| |
| /* Store pointer to allocated stack, |
| * NULL if not allocated by cy_rtos_thread_create (passed by application). |
| */ |
| (*thread)->memptr = stack_alloc; |
| } else { |
| stack_alloc = stack; |
| (*thread)->memptr = NULL; |
| } |
| |
| if (stack_alloc == NULL) { |
| status = CY_RTOS_NO_MEMORY; |
| } else { |
| /* Create thread */ |
| my_tid = k_thread_create(&(*thread)->z_thread, stack_alloc, stack_size, |
| thread_entry_function_wrapper, |
| (cy_thread_arg_t)arg, (void *)entry_function, NULL, |
| priority, 0, K_NO_WAIT); |
| |
| /* Set thread name */ |
| status_internal = k_thread_name_set(my_tid, name); |
| /* NOTE: k_thread_name_set returns -ENOSYS if thread name |
| * configuration option not enabled. |
| */ |
| } |
| |
| if ((my_tid == NULL) || ((status_internal != 0) && (status_internal != -ENOSYS))) { |
| status = CY_RTOS_GENERAL_ERROR; |
| |
| /* Free allocated thread object and stack buffer */ |
| free_thead_obj(thread); |
| } |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_exit_thread(void) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (k_is_in_isr()) { |
| status = CY_RTOS_GENERAL_ERROR; |
| } else { |
| cy_thread_t thread = (cy_thread_t)k_current_get(); |
| |
| /* Abort thread */ |
| k_thread_abort((k_tid_t)&(thread)->z_thread); |
| |
| CODE_UNREACHABLE; |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_terminate_thread(cy_thread_t *thread) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (thread == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else if (k_is_in_isr()) { |
| status = CY_RTOS_GENERAL_ERROR; |
| } else { |
| /* Abort thread */ |
| k_thread_abort((k_tid_t)&(*thread)->z_thread); |
| |
| /* Free allocated stack buffer */ |
| if ((*thread)->memptr != NULL) { |
| k_free((*thread)->memptr); |
| } |
| } |
| |
| return status; |
| } |
| |
| 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 = (k_current_get() == &(*thread)->z_thread) ? true : false; |
| } |
| |
| return status; |
| } |
| 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 { |
| if (k_is_in_isr()) { |
| *state = CY_THREAD_STATE_UNKNOWN; |
| } else if (k_current_get() == &(*thread)->z_thread) { |
| *state = CY_THREAD_STATE_RUNNING; |
| } |
| if (((*thread)->z_thread.base.thread_state & _THREAD_DEAD) != 0) { |
| *state = CY_THREAD_STATE_TERMINATED; |
| } else { |
| switch ((*thread)->z_thread.base.thread_state) { |
| case _THREAD_DUMMY: |
| *state = CY_THREAD_STATE_UNKNOWN; |
| break; |
| |
| case _THREAD_PRESTART: |
| *state = CY_THREAD_STATE_INACTIVE; |
| break; |
| |
| case _THREAD_SUSPENDED: |
| case _THREAD_PENDING: |
| *state = CY_THREAD_STATE_BLOCKED; |
| break; |
| |
| case _THREAD_QUEUED: |
| *state = CY_THREAD_STATE_READY; |
| break; |
| |
| default: |
| *state = CY_THREAD_STATE_UNKNOWN; |
| break; |
| } |
| } |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_join_thread(cy_thread_t *thread) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| cy_rtos_error_t status_internal; |
| |
| if (thread == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| if (*thread != NULL) { |
| /* Sleep until a thread exits */ |
| status_internal = k_thread_join(&(*thread)->z_thread, K_FOREVER); |
| status = error_converter(status_internal); |
| |
| if (status == CY_RSLT_SUCCESS) { |
| /* Free allocated thread object and stack buffer */ |
| free_thead_obj(thread); |
| } |
| } |
| } |
| |
| return status; |
| } |
| |
| 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 = (cy_thread_t)k_current_get(); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_wait_thread_notification(cy_time_t timeout_ms) |
| { |
| cy_rtos_error_t status_internal; |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (timeout_ms == CY_RTOS_NEVER_TIMEOUT) { |
| status_internal = k_sleep(K_FOREVER); |
| } else { |
| status_internal = k_msleep((int32_t)timeout_ms); |
| if (status_internal == 0) { |
| status = CY_RTOS_TIMEOUT; |
| } |
| } |
| |
| if ((status_internal < 0) && (status_internal != K_TICKS_FOREVER)) { |
| status = error_converter(status_internal); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_thread_set_notification(cy_thread_t *thread, bool in_isr) |
| { |
| CY_UNUSED_PARAMETER(in_isr); |
| |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (thread == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| k_wakeup(&(*thread)->z_thread); |
| } |
| |
| return status; |
| } |
| |
| |
| /* |
| * Mutexes |
| */ |
| |
| cy_rslt_t cy_rtos_init_mutex2(cy_mutex_t *mutex, bool recursive) |
| { |
| cy_rtos_error_t status_internal; |
| cy_rslt_t status; |
| |
| /* Non recursive mutex is not supported by Zephyr */ |
| CY_UNUSED_PARAMETER(recursive); |
| |
| if (mutex == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Initialize a mutex object */ |
| status_internal = k_mutex_init(mutex); |
| status = error_converter(status_internal); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_get_mutex(cy_mutex_t *mutex, cy_time_t timeout_ms) |
| { |
| cy_rtos_error_t status_internal; |
| cy_rslt_t status; |
| |
| if (mutex == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else if (k_is_in_isr()) { |
| /* Mutexes may not be locked in ISRs */ |
| status = CY_RTOS_GENERAL_ERROR; |
| } else { |
| /* Convert timeout value */ |
| k_timeout_t k_timeout = |
| (timeout_ms == CY_RTOS_NEVER_TIMEOUT) ? K_FOREVER : K_MSEC(timeout_ms); |
| |
| /* Lock a mutex */ |
| status_internal = k_mutex_lock(mutex, k_timeout); |
| status = error_converter(status_internal); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_set_mutex(cy_mutex_t *mutex) |
| { |
| cy_rtos_error_t status_internal; |
| cy_rslt_t status; |
| |
| if (mutex == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else if (k_is_in_isr()) { |
| /* Mutexes may not be unlocked in ISRs */ |
| status = CY_RTOS_GENERAL_ERROR; |
| } else { |
| /* Unlock a mutex */ |
| status_internal = k_mutex_unlock(mutex); |
| status = error_converter(status_internal); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_deinit_mutex(cy_mutex_t *mutex) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (mutex == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Force unlock mutex, do not care about return */ |
| (void)k_mutex_unlock(mutex); |
| } |
| |
| return status; |
| } |
| |
| |
| /* |
| * Semaphores |
| */ |
| |
| cy_rslt_t cy_rtos_init_semaphore(cy_semaphore_t *semaphore, uint32_t maxcount, uint32_t initcount) |
| { |
| cy_rtos_error_t status_internal; |
| cy_rslt_t status; |
| |
| if (semaphore == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Initialize a semaphore object */ |
| status_internal = k_sem_init(semaphore, initcount, maxcount); |
| status = error_converter(status_internal); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_get_semaphore(cy_semaphore_t *semaphore, cy_time_t timeout_ms, bool in_isr) |
| { |
| CY_UNUSED_PARAMETER(in_isr); |
| |
| cy_rtos_error_t status_internal; |
| cy_rslt_t status; |
| |
| if (semaphore == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Convert timeout value */ |
| k_timeout_t k_timeout; |
| |
| if (k_is_in_isr()) { |
| /* NOTE: Based on Zephyr documentation when k_sem_take |
| * is called from ISR timeout must be set to K_NO_WAIT. |
| */ |
| k_timeout = K_NO_WAIT; |
| } else if (timeout_ms == CY_RTOS_NEVER_TIMEOUT) { |
| k_timeout = K_FOREVER; |
| } else { |
| k_timeout = K_MSEC(timeout_ms); |
| } |
| |
| /* Take a semaphore */ |
| status_internal = k_sem_take(semaphore, k_timeout); |
| status = error_converter(status_internal); |
| |
| if (k_is_in_isr() && (status_internal == -EBUSY)) { |
| status = CY_RSLT_SUCCESS; |
| } |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t *semaphore, bool in_isr) |
| { |
| CY_UNUSED_PARAMETER(in_isr); |
| |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (semaphore == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Give a semaphore */ |
| k_sem_give(semaphore); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_get_count_semaphore(cy_semaphore_t *semaphore, size_t *count) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if ((semaphore == NULL) || (count == NULL)) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| *count = k_sem_count_get(semaphore); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t *semaphore) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (semaphore == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| k_sem_reset(semaphore); |
| } |
| |
| return status; |
| } |
| |
| |
| /* |
| * Events |
| */ |
| |
| cy_rslt_t cy_rtos_init_event(cy_event_t *event) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (event == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Initialize an event object */ |
| k_event_init(event); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_setbits_event(cy_event_t *event, uint32_t bits, bool in_isr) |
| { |
| CY_UNUSED_PARAMETER(in_isr); |
| |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (event == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Post the new bits */ |
| k_event_post(event, bits); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_clearbits_event(cy_event_t *event, uint32_t bits, bool in_isr) |
| { |
| CY_UNUSED_PARAMETER(in_isr); |
| |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (event == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| uint32_t current_bits; |
| |
| /* Reads events value */ |
| status = cy_rtos_getbits_event(event, ¤t_bits); |
| |
| /* Set masked value */ |
| k_event_set(event, (~bits & current_bits)); |
| } |
| |
| return status; |
| } |
| |
| 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 { |
| /* NOTE: Zephyr does not provide function for get bits, |
| * retrieve it from event object. |
| */ |
| *bits = event->events; |
| } |
| |
| return status; |
| } |
| |
| 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; |
| |
| if ((event == NULL) || (bits == NULL)) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| uint32_t wait_for = *bits; |
| k_timeout_t k_timeout = |
| (timeout == CY_RTOS_NEVER_TIMEOUT) ? K_FOREVER : K_MSEC(timeout); |
| |
| if (all) { |
| /* Wait for all of the specified events */ |
| *bits = k_event_wait_all(event, wait_for, false, k_timeout); |
| } else { |
| /* Wait for any of the specified events */ |
| *bits = k_event_wait(event, wait_for, false, k_timeout); |
| } |
| |
| /* Check timeout */ |
| status = (*bits == 0) ? CY_RTOS_TIMEOUT : CY_RSLT_SUCCESS; |
| |
| /* Return full current events */ |
| cy_rtos_getbits_event(event, bits); |
| |
| /* Crear bits if required */ |
| if ((status == CY_RSLT_SUCCESS) && (clear == true)) { |
| cy_rtos_clearbits_event(event, wait_for, false); |
| } |
| } |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_deinit_event(cy_event_t *event) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (event != NULL) { |
| /* Clear event */ |
| k_event_set(event, 0); |
| } else { |
| status = CY_RTOS_BAD_PARAM; |
| } |
| return status; |
| } |
| |
| |
| /* |
| * Queues |
| */ |
| |
| cy_rslt_t cy_rtos_init_queue(cy_queue_t *queue, size_t length, size_t itemsize) |
| { |
| cy_rtos_error_t status_internal; |
| cy_rslt_t status; |
| |
| if (queue == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Initialize a message queue */ |
| status_internal = k_msgq_alloc_init(queue, itemsize, length); |
| status = error_converter(status_internal); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_put_queue(cy_queue_t *queue, const void *item_ptr, cy_time_t timeout_ms, |
| bool in_isr) |
| { |
| CY_UNUSED_PARAMETER(in_isr); |
| |
| cy_rtos_error_t status_internal; |
| cy_rslt_t status; |
| |
| if ((queue == NULL) || (item_ptr == NULL)) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Convert timeout value */ |
| k_timeout_t k_timeout; |
| |
| if (k_is_in_isr()) { |
| k_timeout = K_NO_WAIT; |
| } else if (timeout_ms == CY_RTOS_NEVER_TIMEOUT) { |
| k_timeout = K_FOREVER; |
| } else { |
| k_timeout = K_MSEC(timeout_ms); |
| } |
| |
| /* Send a message to a message queue */ |
| status_internal = k_msgq_put(queue, item_ptr, k_timeout); |
| status = error_converter(status_internal); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_get_queue(cy_queue_t *queue, void *item_ptr, cy_time_t timeout_ms, bool in_isr) |
| { |
| CY_UNUSED_PARAMETER(in_isr); |
| |
| cy_rtos_error_t status_internal; |
| cy_rslt_t status; |
| |
| if ((queue == NULL) || (item_ptr == NULL)) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Convert timeout value */ |
| k_timeout_t k_timeout; |
| |
| if (k_is_in_isr()) { |
| k_timeout = K_NO_WAIT; |
| } else if (timeout_ms == CY_RTOS_NEVER_TIMEOUT) { |
| k_timeout = K_FOREVER; |
| } else { |
| k_timeout = K_MSEC(timeout_ms); |
| } |
| |
| /* Receive a message from a message queue */ |
| status_internal = k_msgq_get(queue, item_ptr, k_timeout); |
| status = error_converter(status_internal); |
| } |
| |
| return status; |
| } |
| |
| 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 { |
| /* Get the number of messages in a message queue */ |
| *num_waiting = k_msgq_num_used_get(queue); |
| } |
| |
| return status; |
| } |
| |
| 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 { |
| /* Get the amount of free space in a message queue */ |
| *num_spaces = k_msgq_num_free_get(queue); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_reset_queue(cy_queue_t *queue) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (queue == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Reset a message queue */ |
| k_msgq_purge(queue); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_deinit_queue(cy_queue_t *queue) |
| { |
| cy_rtos_error_t status_internal; |
| cy_rslt_t status; |
| |
| if (queue == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Reset a message queue */ |
| status = cy_rtos_reset_queue(queue); |
| |
| if (status == CY_RSLT_SUCCESS) { |
| /* Release allocated buffer for a queue */ |
| status_internal = k_msgq_cleanup(queue); |
| status = error_converter(status_internal); |
| } |
| } |
| |
| return status; |
| } |
| |
| |
| /* |
| * Timers |
| */ |
| static void zephyr_timer_event_handler(struct k_timer *timer) |
| { |
| cy_timer_t *_timer = (cy_timer_t *)timer; |
| |
| ((cy_timer_callback_t)_timer->callback_function)( |
| (cy_timer_callback_arg_t)_timer->arg); |
| } |
| |
| 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 = CY_RSLT_SUCCESS; |
| |
| if ((timer == NULL) || (fun == NULL)) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| timer->callback_function = (void *)fun; |
| timer->trigger_type = (uint32_t)type; |
| timer->arg = (void *)arg; |
| |
| k_timer_init(&timer->z_timer, zephyr_timer_event_handler, NULL); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_start_timer(cy_timer_t *timer, cy_time_t num_ms) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (timer == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| if ((cy_timer_trigger_type_t)timer->trigger_type == CY_TIMER_TYPE_ONCE) { |
| /* Called once only */ |
| k_timer_start(&timer->z_timer, K_MSEC(num_ms), K_NO_WAIT); |
| } else { |
| /* Called periodically until stopped */ |
| k_timer_start(&timer->z_timer, K_MSEC(num_ms), K_MSEC(num_ms)); |
| } |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_stop_timer(cy_timer_t *timer) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (timer == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Stop timer */ |
| k_timer_stop(&timer->z_timer); |
| } |
| |
| return status; |
| } |
| |
| 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 { |
| /* Check if running */ |
| *state = (k_timer_remaining_get(&timer->z_timer) != 0u); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_deinit_timer(cy_timer_t *timer) |
| { |
| cy_rslt_t status; |
| |
| if (timer == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| bool running; |
| |
| /* Get current timer state */ |
| status = cy_rtos_is_running_timer(timer, &running); |
| |
| /* Check if running */ |
| if ((status == CY_RSLT_SUCCESS) && (running)) { |
| /* Stop timer */ |
| status = cy_rtos_stop_timer(timer); |
| } |
| } |
| |
| return status; |
| } |
| |
| |
| /* |
| * Time |
| */ |
| |
| cy_rslt_t cy_rtos_get_time(cy_time_t *tval) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (tval == NULL) { |
| status = CY_RTOS_BAD_PARAM; |
| } else { |
| /* Get system uptime (32-bit version) */ |
| *tval = k_uptime_get_32(); |
| } |
| |
| return status; |
| } |
| |
| cy_rslt_t cy_rtos_delay_milliseconds(cy_time_t num_ms) |
| { |
| cy_rslt_t status = CY_RSLT_SUCCESS; |
| |
| if (k_is_in_isr()) { |
| status = CY_RTOS_GENERAL_ERROR; |
| } else { |
| k_msleep(num_ms); |
| } |
| |
| return status; |
| } |
| |
| #if defined(__cplusplus) |
| } |
| #endif |