// Copyright 2020-2021 Beken // // 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. #pragma once #include #include #include #pragma once /** * @brief os enums defines * @defgroup os_defines os defines * @ingroup os * @{ */ #define RTOS_TAG "os" /**< OS log tag*/ #define RTOS_LOGI(...) BK_LOGI(RTOS_TAG, ##__VA_ARGS__) /**< Output OS Info log */ #define RTOS_LOGW(...) BK_LOGW(RTOS_TAG, ##__VA_ARGS__) /**< Output OS Warning log */ #define RTOS_LOGE(...) BK_LOGE(RTOS_TAG, ##__VA_ARGS__) /**< Output OS Error log */ #define RTOS_LOGD(...) BK_LOGD(RTOS_TAG, ##__VA_ARGS__) /**< Output OS Debug log */ /// os stop interrupt #define GLOBAL_INT_STOP (void)rtos_disable_int /// os declaration interrupt status #define GLOBAL_INT_DECLARATION() uint32_t irq_level /// os read interrupt status and disable interrupt #define GLOBAL_INT_DISABLE() irq_level = rtos_disable_int() /// os restore interrupt status #define GLOBAL_INT_RESTORE() rtos_enable_int(irq_level) #define RTOS_SUCCESS (1) /**< Return Success */ #define RTOS_FAILURE (0) /**< Return Failure */ #define BEKEN_DEFAULT_WORKER_PRIORITY (6) /**< Default Worker Priority */ #define BEKEN_APPLICATION_PRIORITY (7) /**< Application Task Priority */ #define NanosecondsPerSecond 1000000000UUL /**< Nanoseconds Per Second */ #define MicrosecondsPerSecond 1000000UL /**< Microseconds Per Second */ #define MillisecondsPerSecond 1000 /**< Milliseconds Per Second */ #define BEKEN_NEVER_TIMEOUT (0xFFFFFFFF) /**< Never Timeout */ #define BEKEN_WAIT_FOREVER (0xFFFFFFFF) /**< Wait Forever */ #define BEKEN_NO_WAIT (0) /**< No Wait */ #define NANOSECONDS 1000000UL /**< Nanoseconds Per Milliseconds */ #define MICROSECONDS 1000 /**< Microseconds Per Milliseconds */ #define MILLISECONDS (1) /**< One Milliseconds */ #define SECONDS (1000) /**< Milliseconds Per Second */ #define MINUTES (60 * SECONDS) /**< Milliseconds Per MINUTES */ #define HOURS (60 * MINUTES) /**< Milliseconds Per HOURS */ #define DAYS (24 * HOURS) /**< Milliseconds Per DAYS */ #define BEKEN_MAGIC_WORD (0xBABA7231) /**< Beken Magic word */ typedef int bk_err_t; /**< Return error code */ typedef void *beken_thread_arg_t; /**< Thread argument pointer type */ typedef uint8_t beken_bool_t; /**< Bool type */ typedef uint32_t beken_time_t; /**< Time value in milliseconds */ typedef uint32_t beken_utc_time_t; /**< UTC Time in seconds */ typedef uint64_t beken_utc_time_ms_t; /**< UTC Time in milliseconds */ typedef uint32_t beken_event_flags_t; /**< Event flag type */ typedef void *beken_semaphore_t; /**< OS Semaphore handle pointer */ typedef void *beken_mutex_t; /**< OS Mutex handle pointer */ typedef void *beken_thread_t; /**< OS Thread handle pointer */ typedef void *beken_queue_t; /**< OS Queue handle pointer */ typedef void *beken_event_t; /**< OS Event handle pointer */ /// timer callback function type with one parameter typedef void (*timer_handler_t)(void *); /// timer callback function type with two parameters typedef void (*timer_2handler_t)(void *Larg, void *Rarg); /// event callback function type with one parameter typedef bk_err_t(*event_handler_t)(void *arg); /// OS Thread entry function type typedef void (*beken_thread_function_t)(beken_thread_arg_t arg); /// OS Event wait options typedef enum { WAIT_FOR_ANY_EVENT, /**< Wait for any event */ WAIT_FOR_ALL_EVENTS, /**< Wait for all event */ } beken_event_flags_wait_option_t; /** * @} */ #define os_printf bk_printf /**< OS printf, will be replace with RTOS_LOGI later */ #define os_null_printf bk_null_printf /**< OS drop print string */ #define rtos_init_semaphore_adv rtos_init_semaphore_ex /**< To be replace with rtos_init_semaphore_ex */ #define rtos_get_sema_count rtos_get_semaphore_count /**< To be replace with rtos_get_semaphore_count */ /** * @brief os struct defines * @defgroup os_structs structs in os * @ingroup os * @{ */ /// OS timer handle struct type typedef struct { void *handle; /**< OS timer handle pointer */ timer_handler_t function; /**< OS timer handle callback function */ void *arg; /**< OS timer handle callback argument */ } beken_timer_t; /// OS worker thread handle struct type typedef struct { beken_thread_t thread; /**< OS thread handle */ beken_queue_t event_queue; /**< OS event queue */ } beken_worker_thread_t; /// OS timer event struct type typedef struct { event_handler_t function; /**< OS event callback function */ void *arg; /**< OS event callback argument */ beken_timer_t timer; /**< OS timer handle */ beken_worker_thread_t *thread; /**< OS work thread handle */ } beken_timed_event_t; /// OS timer handle struct type typedef struct { void *handle; /**< OS timer handle pointer */ timer_2handler_t function; /**< OS timer handle callback function */ void *left_arg; /**< OS timer handle callback first argument */ void *right_arg; /**< OS timer handle callback second argument */ uint32_t beken_magic; /**< OS timer magic word */ } beken2_timer_t; /** * @} */ /** * @brief os API * @defgroup os_apis os API group * @ingroup os * @{ */ /** @brief Enter a critical session, all interrupts are disabled * * @return irq flags */ uint32_t rtos_enter_critical(void); /** @brief Exit a critical session, all interrupts are enabled * @param flags : irq flags * * @return none */ void rtos_exit_critical(uint32_t flags); /** @brief Get system time value in milliseconds * * @param time_ptr : the pointer of time value in milliseconds * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t beken_time_get_time(beken_time_t *time_ptr); /** @defgroup BEKEN_RTOS_Thread _BK_ RTOS Thread Management Functions * @brief Provide thread creation, delete, suspend, resume, and other RTOS management API * @verbatim * _BK_ thread priority table * * +----------+-----------------+ * | Priority | Thread | * |----------|-----------------| * | 0 | _BK_ | Highest priority * | 1 | Network | * | 2 | | * | 3 | Network worker | * | 4 | | * | 5 | Default Library | * | | Default worker | * | 6 | | * | 7 | Application | * | 8 | | * | 9 | Idle | Lowest priority * +----------+-----------------+ * @endverbatim * @{ */ /** @brief Creates and starts a new thread,the task will be dynamically created in sram * * @note Do not call this API when interrupts are disabled (may cause the system * to enter a deadlock or abnormal status) * * @param thread : Pointer to variable that will receive the thread handle (can be null) * @param priority : A priority number. The adaptation layer uniformly managers priorities. * For the application layer,the lower the configured number,the higher * the task priority.Currently supports ten priority levels from 0 to 9. * recommended that the application layer use priorities from 6 to 8. * @param name : a text name for the thread (can be null) * @param function : the main thread function * @param stack_size : stack size for this thread,size is in bytes,for example if the stack_size * is defined as 2048,then 2048bytes will be allocated for stack storage. * @param arg : argument which will be passed to thread function * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_create_sram_thread(beken_thread_t *thread, uint8_t priority, const char *name, beken_thread_function_t function, uint32_t stack_size, beken_thread_arg_t arg); /** @brief Creates and starts a new thread on psram * * @note Do not call this API when interrupts are disabled (may cause the system * to enter a deadlock or abnormal status) * * @param thread : Pointer to variable that will receive the thread handle (can be null) * @param priority : A priority number.he adaptation layer uniformly managers priorities. * For the application layer,the lower the configured number,the higher * the task priority.Currently supports ten priority levels from 0 to 9. * recommended that the application layer use priorities from 6 to 8. * @param name : a text name for the thread (can be null) * @param function : the main thread function * @param stack_size : stack size for this thread,size is in bytes,for example if the stack_size * is defined as 2048,then 2048bytes will be allocated for stack storage. * @param arg : argument which will be passed to thread function * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_create_psram_thread(beken_thread_t *thread, uint8_t priority, const char *name, beken_thread_function_t function, uint32_t stack_size, beken_thread_arg_t arg); /** @brief Creates and starts a new thread,the task will be dynamically created in sram(default) * * @note Do not call this API when interrupts are disabled (may cause the system * to enter a deadlock or abnormal status) * * @param thread : Pointer to variable that will receive the thread handle (can be null) * @param priority : A priority number. The adaptation layer uniformly managers priorities. * For the application layer,the lower the configured number,the higher * the task priority.Currently supports ten priority levels from 0 to 9. * recommended that the application layer use priorities from 6 to 8. * @param name : a text name for the thread (can be null) * @param function : the main thread function * @param stack_size : stack size for this thread,size is in bytes,for example if the stack_size * is defined as 2048,then 2048bytes will be allocated for stack storage. * @param arg : argument which will be passed to thread function * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_create_thread(beken_thread_t *thread, uint8_t priority, const char *name, beken_thread_function_t function, uint32_t stack_size, beken_thread_arg_t arg); /** @brief Deletes a terminated thread * * @note If you want to delete the task itself,do not call this API when the interrupts * is disables(may cause the system to enter a deadlock or abnormal status)) * * @param thread : the handle of the thread to delete, , NULL is the current thread * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_delete_thread(beken_thread_t *thread); /** @brief Suspend a thread * * @note If you want to suspend the task itself,do not call this API when interrupts * are disabled (may cause the system to enter a deadlock or abnormal status) * * @param thread : the handle of the thread to suspend, NULL is the current thread * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ void rtos_suspend_thread(beken_thread_t *thread); /** @brief Suspend all other thread * * @param none * * @return none */ void rtos_suspend_all_thread(void); /** @brief resume a thread * * @note If you want to resume the task not itself,do not call this API when interrupts * are disabled (may cause the system to enter a deadlock or abnormal status) * * @param thread : the handle of the thread to resume, NULL is the current thread * * @return none */ void rtos_resume_thread(beken_thread_t* thread); /** @brief Rresume all other thread * * @param none * * @return none */ void rtos_resume_all_thread(void); /** @brief Sleeps until another thread has terminated * * @note do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @Details Causes the current thread to sleep until the specified other thread * has terminated. If the processor is heavily loaded with higher priority * tasks, this thread may not wake until significantly after the thread termination. * * @param thread : the handle of the other thread which will terminate * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_thread_join(beken_thread_t *thread); /** @brief Forcibly wakes another thread * * @note do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @Details Causes the specified thread to wake from suspension. This will usually * cause an error or timeout in that thread, since the task it was waiting on * is not complete. * * @param thread : the handle of the other thread which will be removed from the * block state. * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_thread_force_awake(beken_thread_t *thread); /** @brief Checks if a thread is the current thread * * @Details Checks if a specified thread is the currently running thread * * @param thread : the handle of the other thread against which the current thread * will be compared * * @return true : specified thread is the current thread * @return false : specified thread is not currently running */ bool rtos_is_current_thread(beken_thread_t *thread); /** @brief Get current thread handler * * @return Current RTOS thread handler */ beken_thread_t *rtos_get_current_thread(void); /** @brief Suspend current thread for a specific time * * @note do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @param seconds : A time interval (Unit: seconds) * * @return None. */ void rtos_thread_sleep(uint32_t seconds); /** @brief Suspend current thread for a specific time * * @note do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @param milliseconds : A time interval (Unit: millisecond) * * @return None. */ void rtos_thread_msleep(uint32_t milliseconds); /** @brief Suspend current thread for a specific time * * @note do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @param num_ms : A time interval (Unit: millisecond) * * @return kNoErr. */ bk_err_t rtos_delay_milliseconds(uint32_t num_ms); /** * @} */ /** @defgroup BEKEN_RTOS_SEM _BK_ RTOS Semaphore Functions * @brief Provide management APIs for semaphore such as init,set,get and dinit. * @{ */ /** @brief Initialises a counting semaphore and set count to 0 * * @param semaphore : a pointer to the semaphore handle to be initialised * @param max_count : the max count number of this semaphore * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_init_semaphore(beken_semaphore_t *semaphore, int max_count); /** @brief Initialises a counting semaphore and set count to init count * * @param semaphore : a pointer to the semaphore handle to be initialised * @param max_count : the max count number of this semaphore * @param init_count : the init count number of this semaphore * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_init_semaphore_ex(beken_semaphore_t *semaphore, int max_count, int init_count); /** @brief Set (post/put/increment) a semaphore * * @note This API can be called in task context and interrupt context. * * @param semaphore : a pointer to the semaphore handle to be set * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_set_semaphore(beken_semaphore_t *semaphore); /** @brief Get (wait/decrement) a semaphore * * @note Do not call this API when interrupts are disabled (may cause the system * to enter a deadlock or abnormal status) * * @Details Attempts to get (wait/decrement) a semaphore. If semaphore is at zero already, * then the calling thread will be suspended until another thread sets the * semaphore with @ref rtos_set_semaphore * * @param semaphore : a pointer to the semaphore handle * @param timeout_ms: the number of milliseconds to wait before returning * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_get_semaphore(beken_semaphore_t *semaphore, uint32_t timeout_ms); /** @brief get current semaphore count * * @param semaphore : a pointer to the semaphore handle to be set * * @return kNoErr : current semaphore count */ int rtos_get_semaphore_count(beken_semaphore_t *semaphore); /** @brief De-initialise a semaphore * * @Details Deletes a semaphore created with @ref rtos_init_semaphore * * @param semaphore : a pointer to the semaphore handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_deinit_semaphore(beken_semaphore_t *semaphore); /** * @} */ /** @defgroup BEKEN_RTOS_MUTEX _BK_ RTOS Mutex Functions * @brief Provide management APIs for Mutex such as init,lock,unlock and dinit. * @{ */ /** @brief Initialises a mutex * * @Details A mutex is different to a semaphore in that a thread that already holds * the lock on the mutex can request the lock again (nested) without causing * it to be suspended. * * @param mutex : a pointer to the mutex handle to be initialised * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_init_mutex(beken_mutex_t *mutex); /** @brief Obtains the lock on a mutex * * @Details Attempts to obtain the lock on a mutex. If the lock is already held * by another thead, the calling thread will not be suspended until the mutex * lock is released by the other thread. * * @param mutex : a pointer to the mutex handle to be locked * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_trylock_mutex(beken_mutex_t *mutex); /** @brief Obtains the lock on a mutex * * @note do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @Details Attempts to obtain the lock on a mutex. If the lock is already held * by another thead, the calling thread will be suspended until the mutex * lock is released by the other thread. * * @param mutex : a pointer to the mutex handle to be locked * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_lock_mutex(beken_mutex_t *mutex); /** @brief Releases the lock on a mutex * * @note do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @Details Releases a currently held lock on a mutex. If another thread * is waiting on the mutex lock, then it will be resumed. * * @param mutex : a pointer to the mutex handle to be unlocked * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_unlock_mutex(beken_mutex_t *mutex); /** @brief De-initialise a mutex * * @Details Deletes a mutex created with @ref rtos_init_mutex * * @param mutex : a pointer to the mutex handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_deinit_mutex(beken_mutex_t *mutex); /** @brief Obtains the lock on a mutex * * @Details Attempts to obtain the lock on a mutex. If the lock is already held * by another thead, the calling thread will be suspended until the mutex * lock is released by the other thread or timeout. * * @param mutex : a pointer to the mutex handle to be locked * @param timeout_ms : timeout for get lock * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_lock_mutex_timeout( beken_mutex_t* mutex, uint32_t timeout_ms); /** @brief Creates a new recursive mutex type semaphore instance * * @param mutex : a pointer to the new recursive mutex handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_init_recursive_mutex( beken_mutex_t* mutex ); /** @brief Obtains the lock on a recursive mutex (A mutex * used recursively can be 'taken' repeatedly by the owner) * * @note do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @param mutex : a pointer to the new recursive mutex handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_lock_recursive_mutex( beken_mutex_t* mutex ); /** @brief Releases the lock on a recursive mutex (A mutex * used recursively can be 'taken' repeatedly by the owner) * * @note do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @param mutex : a pointer to the new recursive mutex handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_unlock_recursive_mutex( beken_mutex_t* mutex ); /** @brief De-initialise a recursive mutex * * @Details Deletes a mutex created with @ref rtos_init_recursive_mutex * * @param mutex : a pointer to the recursive mutex handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_deinit_recursive_mutex( beken_mutex_t* mutex ); /** * @} */ /** @defgroup BEKEN_RTOS_QUEUE _BK_ RTOS FIFO Queue Functions * @brief Provide management APIs for FIFO such as init,push,pop and dinit. * @{ */ /** @brief Initialises a FIFO queue * * @param queue : a pointer to the queue handle to be initialised * @param name : a text string name for the queue (NULL is allowed) * @param message_size : size in bytes of objects that will be held in the queue * @param number_of_messages : depth of the queue - i.e. max number of objects in the queue * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_init_queue(beken_queue_t *queue, const char *name, uint32_t message_size, uint32_t number_of_messages); /** @brief Post an item to the back of a queue. The item is queued by copy, not by * reference * * @note This API can be called in task context and interrupt context. However when * calling this API in task context,the interrupt cannot be turned off(may cause * the system to enter a deadlock or abnormal status) * * @param queue : a pointer to the queue handle * @param message : the object to be added to the queue. Size is assumed to be * the size specified in @ref rtos_init_queue * @param timeout_ms: the number of milliseconds to wait before returning * * @return kNoErr : on success. * @return kGeneralErr : if an error or timeout occurred */ bk_err_t rtos_push_to_queue(beken_queue_t *queue, void *message, uint32_t timeout_ms); /** @brief Post an item to the front of a queue. The item is queued by copy, not by * reference. * * @note This API can be called in task context and interrupt context. However when * calling this API in task context,the interrupt cannot be turned off(may cause * the system to enter a deadlock or abnormal status) * * @param queue : a pointer to the queue handle * @param message : the object to be added to the queue. Size is assumed to be * the size specified in @ref rtos_init_queue * @param timeout_ms: the number of milliseconds to wait before returning * * @return kNoErr : on success. * @return kGeneralErr : if an error or timeout occurred */ bk_err_t rtos_push_to_queue_front(beken_queue_t *queue, void *message, uint32_t timeout_ms); /** @brief Pops an object off a queue * * @note do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @param queue : a pointer to the queue handle * @param message : pointer to a buffer that will receive the object being * popped off the queue. Size is assumed to be * the size specified in @ref rtos_init_queue , hence * you must ensure the buffer is long enough or memory * corruption will result * @param timeout_ms: the number of milliseconds to wait before returning * * @return kNoErr : on success. * @return kGeneralErr : if an error or timeout occurred */ bk_err_t rtos_pop_from_queue(beken_queue_t *queue, void *message, uint32_t timeout_ms); /** @brief De-initialise a queue created with @ref rtos_init_queue * * @param queue : a pointer to the queue handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_deinit_queue(beken_queue_t *queue); /** @brief Check if a queue is empty * * @param queue : a pointer to the queue handle * * @return true : queue is empty. * @return false : queue is not empty. */ bool rtos_is_queue_empty(beken_queue_t *queue); /** @brief Check if a queue is full * * @param queue : a pointer to the queue handle * * @return true : queue is empty. * @return false : queue is not empty. */ bool rtos_is_queue_full(beken_queue_t *queue); /** @brief Reset queue * * @param queue : a pointer to the queue handle * * @return true : reset ok. * @return false : reset fail. */ bool rtos_reset_queue(beken_queue_t *queue); /** @defgroup BEKEN_RTOS_EVENT _BK_ RTOS Event Functions * @{ */ /** Create a new event group * * @param event_flags : pointer to a event handle which will be initialised * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_init_event_flags( beken_event_t* event_flags ); /** block to wait for one or more bits to be set within a * previously created event group. * * @note do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @param event_flags : pointer to a event handle which will be initialised * @param flags_to_wait_for : A bitwise value that indicates the bit or bits to test * inside the event group. For example, to wait for bit 0 * and/or bit 2 set flags_to_wait_for to 0x05. To wait for * bits 0 and/or bit 1 and/or bit 2 set flags_to_wait_for to 0x07. Etc. * @param clear_set_flags : If clear_set_flags is set to pdTRUE then any bits within * flags_to_wait_for that are set within the event group will * be cleared before returns * @param wait_option : If it is set to WAIT_FOR_ALL_EVENTS then will return when * either all the bits in flags_to_wait_for are set or the * specified block time expires. If it is set to WAIT_FOR_ANY_EVENT * then will return when any one of the bits set in flags_to_wait_for * is set or the specified block time expires. The block time is specified * by the timeout_ms parameter. * @param timeout_ms : the time period between function calls in milliseconds * * @return The value of the event group at the time either the bits being waited * for became set, or the block time expired. */ beken_event_flags_t rtos_wait_for_event_flags( beken_event_t* event_flags, uint32_t flags_to_wait_for, beken_bool_t clear_set_flags, beken_event_flags_wait_option_t wait_option, uint32_t timeout_ms ); /** Set bits within an event group. * * @note This API can be called in task context and interrupt context. * * @param event_flags : pointer to a event handle which will be initialised * @param flags_to_set : A bitwise value that indicates the bit or bits to set. * For example, to set bit 3 only, set flags_to_set to 0x08. * To set bit 3 and bit 0 set flags_to_set to 0x09. * */ void rtos_set_event_flags( beken_event_t* event_flags, uint32_t flags_to_set ); /** Clear bits within an event group. * * @note This API can be called in task context and interrupt context. * * @param event_flags : pointer to a event handle which will be initialised * @param flags_to_clear :A bitwise value that indicates the bit or bits to clear * in the event group. For example, to clear bit 3 only, * set flags_to_clear to 0x08. To clear bit 3 and bit 0 set * flags_to_clear to 0x09. * * @return The value of the event group before the specified bits were cleared * */ beken_event_flags_t rtos_clear_event_flags( beken_event_t* event_flags, uint32_t flags_to_clear ); /** Atomically set bits within an event group, then wait for a combination of * bits to be set within the same event group. This functionality is typically * used to synchronise multiple tasks, where each task has to wait for the other * tasks to reach a synchronisation point before proceeding. * * @note do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @param event_flags : pointer to a event handle which will be initialised * @param flags_to_set : The bits to set in the event group before determining * if, and possibly waiting for, all the bits specified by * the timeout_ms parameter are set. * @param flags_to_wait_for : A bitwise value that indicates the bit or bits to test * inside the event group. For example, to wait for bit 0 and bit 2 * flags_to_wait_for to 0x05. To wait for bits 0 and bit 1 and bit 2 set * flags_to_wait_for to 0x07. Etc. * @param timeout_ms : the time period between function calls in milliseconds * * @return The value of the event group at the time either the bits being waited * for became set, or the block time expired. */ beken_event_flags_t rtos_sync_event_flags( beken_event_t* event_flags, uint32_t flags_to_set, uint32_t flags_to_wait_for, uint32_t timeout_ms); /** Delete an event group that was previously created by a call to * rtos_init_event_flags(). Tasks that are blocked on the event group will be * unblocked and obtain 0 as the event group's value. * * @param event_flags : pointer to a event handle which will be initialised * * @return kNoErr : on success. * @return kParamErr : if an error occurred */ bk_err_t rtos_deinit_event_flags( beken_event_t* event_flags ); /** @defgroup BEKEN_RTOS_TIMER _BK_ RTOS Timer Functions * @brief Provide management APIs for timer such as init,start,stop,reload and dinit. * @{ */ /** * @brief Gets time in miiliseconds since RTOS start * * @note: Since this is only 32 bits, it will roll over every 49 days, 17 hours. * * @returns Time in milliseconds since RTOS started. */ uint32_t rtos_get_time(void); /** @defgroup BEKEN_RTOS_TIMER _BK_ RTOS Timer Functions * @brief Provide management APIs for timer such as init,start,stop,reload and dinit. * @{ */ /** * @brief Gets time in miiliseconds since RTOS start * * @note: Since this is only 32 bits, it will roll over every 49 days, 17 hours. * * @returns Time in milliseconds since RTOS started. */ uint32_t beken_ms_per_tick(void); /** * @brief Initialize a RTOS periodic timer * * @note Timer does not start running until @ref beken_start_timer is called * and the timer will execute periodically * * @param timer : a pointer to the timer handle to be initialised * @param time_ms : Timer period in milliseconds * @param function : the callback handler function that is called each time the * timer expires * @param arg : an argument that will be passed to the callback function * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_init_timer(beken_timer_t *timer, uint32_t time_ms, timer_handler_t function, void *arg); /** @brief Starts a RTOS periodic timer * * @note Timer must have been previously initialised with @ref rtos_init_timer * This API can be called in task context and interrupt context. However when * calling this API in task context,the interrupt cannot be turned off(may cause * the system to enter a deadlock or abnormal status) * * @param timer : a pointer to the timer handle to start * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_start_timer(beken_timer_t *timer); /** @brief Stops a running RTOS periodic timer * * @note Timer must have been previously started with @ref rtos_init_timer. * This API can be called in task context and interrupt context. However when * calling this API in task context,the interrupt cannot be turned off(may cause * the system to enter a deadlock or abnormal status) * * @param timer : a pointer to the timer handle to stop * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_stop_timer(beken_timer_t *timer); /** @brief Reloads a RTOS periodic timer that has expired * * @note This is usually called in the timer callback handler, to * reschedule the timer for the next period. * This API can be called in task context and interrupt context. However when * calling this API in task context,the interrupt cannot be turned off(may cause * the system to enter a deadlock or abnormal status) * * @param timer : a pointer to the timer handle to reload * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_reload_timer(beken_timer_t *timer); /** @brief De-initialise a RTOS periodic timer * * @note Deletes a RTOS timer created with @ref rtos_init_timer. * do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @param timer : a pointer to the RTOS timer handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_deinit_timer(beken_timer_t *timer); /** @brief Check if an RTOS periodic timer is init * * @param timer : a pointer to the RTOS timer handle * * @return true : if init. * @return false : if not init */ bool rtos_is_timer_init(beken_timer_t *timer); /** @brief Check if an RTOS periodic timer is running * * @param timer : a pointer to the RTOS timer handle * * @return true : if running. * @return false : if not running */ bool rtos_is_timer_running(beken_timer_t *timer); /** * @brief Initialize a RTOS oneshot timer * * @note Timer does not start running until @ref rtos_start_oneshot_timer is called * and the timer will only execute once * * @param timer : a pointer to the timer handle to be initialised * @param time_ms : Timer period in milliseconds * @param function : the callback handler function that is called each time the * timer expires * @param larg : an argument that will be passed to the callback function * @param rarg : an argument that will be passed to the callback function * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_init_oneshot_timer(beken2_timer_t *timer, uint32_t time_ms, timer_2handler_t function, void *larg, void *rarg); /** @brief De-initialise a RTOS rtos_init_oneshot_timer timer * * @note Deletes a RTOS timer created with @ref rtos_init_oneshot_timer. * do not call this API when interrupts are disabled (may cause the * system to enter a deadlock or abnormal status) * * @param timer : a pointer to the RTOS timer handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_deinit_oneshot_timer(beken2_timer_t *timer); /** @brief start a RTOS oneshot timer * * @note Timer must have been previously started with @ref rtos_init_oneshot_timer. * This API can be called in task context and interrupt context. However when * calling this API in task context,the interrupt cannot be turned off(may cause * the system to enter a deadlock or abnormal status) * * @param timer : a pointer to the RTOS timer handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_start_oneshot_timer(beken2_timer_t *timer); /** @brief stop a RTOS oneshot timer * * @note Timer must have been previously started with @ref rtos_init_oneshot_timer. * This API can be called in task context and interrupt context. However when * calling this API in task context,the interrupt cannot be turned off(may cause * the system to enter a deadlock or abnormal status) * * @param timer : a pointer to the RTOS timer handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_stop_oneshot_timer(beken2_timer_t *timer); /** @brief Check if an RTOS oneshot timer is running * * @param timer : a pointer to the RTOS timer handle * * @return true : if running. * @return false : if not running */ bool rtos_is_oneshot_timer_running(beken2_timer_t *timer); /** @brief Check if an RTOS oneshot timer is initialised * * @param timer : a pointer to the RTOS timer handle * * @return true : if initialised * @return false : if not initialised */ bool rtos_is_oneshot_timer_init(beken2_timer_t *timer); /** @brief re-starts a oneshot timer * * @note Timer must have been previously started with @ref rtos_init_oneshot_timer. * This API can be called in task context and interrupt context. However when * calling this API in task context,the interrupt cannot be turned off(may cause * the system to enter a deadlock or abnormal status) * * @param timer : a pointer to the RTOS timer handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_oneshot_reload_timer(beken2_timer_t *timer); /** @brief changes the period of a oneshot timer * * @note Timer must have been previously started with @ref rtos_init_oneshot_timer. * This API can be called in task context and interrupt context. However when * calling this API in task context,the interrupt cannot be turned off(may cause * the system to enter a deadlock or abnormal status) * * @param timer : a pointer to the RTOS timer handle * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_change_period(beken_timer_t *timer, uint32_t time_ms); /** @brief changes the period of a oneshot timer then re-start it * * @note Timer must have been previously started with @ref rtos_init_oneshot_timer. * This API can be called in task context and interrupt context. However when * calling this API in task context,the interrupt cannot be turned off(may cause * the system to enter a deadlock or abnormal status) * * @param timer : a pointer to the RTOS timer handle * @param time_ms : Timer period in milliseconds * @param function : the callback handler function that is called each time the * timer expires * @param larg : an argument that will be passed to the callback function * @param rarg : an argument that will be passed to the callback function * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_oneshot_reload_timer_ex(beken2_timer_t *timer, uint32_t time_ms, timer_2handler_t function, void *larg, void *rarg); /** @brief Returns the time in ticks at which the timer will expire * * @param timer : a pointer to the RTOS timer handle * * @return If the timer is running then the time in ticks at which the timer * will next expire is returned. If the timer is not running then the return * value is undefined. */ uint32_t rtos_get_timer_expiry_time(beken_timer_t *timer); /** @defgroup BEKEN_RTOS_SYSTEM _BK_ RTOS system Functions * @brief Provide management APIs for system such as memory interrupt etc. * @{ */ /** @brief Starts the real time kernel tick processing. After calling the kernel * has control over which tasks are executed and when. */ void rtos_start_scheduler(void); /** @brief check if the rtos scheduler is running or not * */ bool rtos_is_scheduler_started(void); /** @brief get the name of the currently used OS * */ char *rtos_get_name(void); /** @brief get the version of the currently used OS * */ char *rtos_get_version(void); /** @brief get the total heap size * * @return the amount of total heap space available on the system */ size_t rtos_get_total_heap_size(void); /** @brief get the free heap size * * @return the amount of left heap space available on the system */ size_t rtos_get_free_heap_size(void); /** @brief get the minimum heap size * * @return the minimum value remaining during the system heap * space usage */ size_t rtos_get_minimum_free_heap_size(void); /** @brief get the total heap size in psram * * @return the amount of total heap space in psram */ size_t rtos_get_psram_total_heap_size(void); /** @brief get the free heap size * * @return the amount of left heap space in psram */ size_t rtos_get_psram_free_heap_size(void); /** @brief get the minimum heap size in psram * * @return the minimum value remaining in psram during * the system heap space usage */ size_t rtos_get_psram_minimum_free_heap_size(void); /** @brief get the os tick count * * @return The count of ticks since vTaskStartScheduler was called. */ uint32_t rtos_get_tick_count(void); /** @brief disable interrupts and return the current interrupt status * * @note disable interrupt support nesting * * @return the current interrupt status */ uint32_t rtos_disable_int(void); /** @brief enable previously disabled interrupts * * @note this API needs to be used with @ref rtos_disable_int * * @param int_level : saved interrupt status * * @return the current interrupt status */ void rtos_enable_int(uint32_t int_level); /** @brief disable interrupts and return the current interrupt status * * @note disable interrupt support nesting. * This API has the same functionality as @ref rtos_disable_int * * @return the current interrupt status */ uint32_t rtos_before_sleep(void); /** @brief enable previously disabled interrupts * * @note This API has the same functionality as @ref rtos_enable_int * * @param int_level : saved interrupt status * * @return the current interrupt status */ void rtos_after_sleep(uint32_t int_level); /** @brief Check if system in interrupt context * * @return true : if in interrupt context * @return false : if not in interrupt context */ bool rtos_is_in_interrupt_context(void); /** @brief Check if local irq is disabled * * @return true : if irq is disabled * @return false : if irq is not disabled */ bool rtos_local_irq_disabled(void); /** @brief Check if the current scheduler is in suspended state * * @return true : the scheduler is in suspended state * @return false : the scheduler is not in suspended state */ bool rtos_is_scheduler_suspended(void); /** @brief disable interrupts and the run in an infinite loop * */ void rtos_shutdown(void); #if (CONFIG_FREERTOS_SMP_TEMP) /*TODO: Enhanced implementation of cohesion*/ #ifndef portGET_CORE_ID #define portGET_CORE_ID() (*((volatile uint32_t *)(0x20000000))) /*CPU_ID_ADDR = 0x20000000*/ #endif static inline int rtos_get_core_id(void) { return portGET_CORE_ID(); } /** @brief Creates and starts a new thread with affinity * * @param thread : Pointer to variable that will receive the thread handle (can be null) * @param affinity : Core affinity, bitmap of cores, -1 stands for all cores. * @param priority : A priority number. * @param name : a text name for the thread (can be null) * @param function : the main thread function * @param stack_size : stack size for this thread * @param arg : argument which will be passed to thread function * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_create_thread_with_affinity( beken_thread_t *thread, uint32_t affinity, uint8_t priority, const char* name, beken_thread_function_t function, uint32_t stack_size, beken_thread_arg_t arg ); /** @brief Creates and starts a new smp thread * * @param thread : Pointer to variable that will receive the thread handle (can be null) * @param priority : A priority number. * @param name : a text name for the thread (can be null) * @param function : the main thread function * @param stack_size : stack size for this thread * @param arg : argument which will be passed to thread function * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_smp_create_thread( beken_thread_t* thread, uint8_t priority, const char* name, beken_thread_function_t function, uint32_t stack_size, beken_thread_arg_t arg ); /** @brief Creates and starts a new thread specify to run on cpu0 * * @param thread : Pointer to variable that will receive the thread handle (can be null) * @param priority : A priority number. * @param name : a text name for the thread (can be null) * @param function : the main thread function * @param stack_size : stack size for this thread * @param arg : argument which will be passed to thread function * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_core0_create_thread( beken_thread_t* thread, uint8_t priority, const char* name, beken_thread_function_t function, uint32_t stack_size, beken_thread_arg_t arg ); #if (CONFIG_CPU_CNT > 1) /** @brief Creates and starts a new thread specify to run on cpu1 * * @param thread : Pointer to variable that will receive the thread handle (can be null) * @param priority : A priority number. * @param name : a text name for the thread (can be null) * @param function : the main thread function * @param stack_size : stack size for this thread * @param arg : argument which will be passed to thread function * * @return kNoErr : on success. * @return kGeneralErr : if an error occurred */ bk_err_t rtos_core1_create_thread( beken_thread_t* thread, uint8_t priority, const char* name, beken_thread_function_t function, uint32_t stack_size, beken_thread_arg_t arg ); #endif /* * Lots of our codes use `GLOBAL_INT_DISABLE` to make the code excuted in critical section. * But in SMP, disable local CPU irq is insufficient. So here `GLOBAL_INT_DISABLE' * is redefined to `rtos_enter_critical'. * * In further, codes may explicitly use `rtos_enter_critical' instead of `GLOBAL_INT_DISABLE', * and `GLOBAL_INT_DISABLE' still represents disable local cpu irq. * * And a global spin lock may be defined, for example, global_spin_lock. and redefine * GLOBAL_INT_DISABLE and GLOBAL_INT_RESTORE as the following: * volatile spinlock_t global_spin_lock = SPIN_LOCK_FREE; * #define GLOBAL_INT_DISABLE() spin_lock_irqsave(&global_spin_lock, irq_level) * #define GLOBAL_INT_RESTORE() spin_unlock_irqrestore(&global_spin_lock, irq_level) * refer: portSET_INTERRUPT_MASK_FROM_ISR and portCLEAR_INTERRUPT_MASK_FROM_ISR */ #undef GLOBAL_INT_DISABLE #define GLOBAL_INT_DISABLE() do { irq_level = rtos_enter_critical(); } while (0) #undef GLOBAL_INT_RESTORE #define GLOBAL_INT_RESTORE() do { rtos_exit_critical(irq_level); } while (0) #endif