// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // // 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. #ifndef _ESPOS_SCHEDULER_H_ #define _ESPOS_SCHEDULER_H_ #include #include "espos_types.h" #include "espos_errno.h" #include "espos_spinlock.h" #ifdef __cplusplus extern "C" { #endif /** * ESPOS state */ typedef enum espos_stat { ESPOS_IS_NOT_STARTED = 0, ESPOS_IS_RUNNING, ESPOS_IS_SUSPENDED } espos_stat_t; /************************************ internal function ************************************/ /** * @brief enter ESPOS system critical state * * @param spinlock spinlock handle point * * @return critical state temple variable(used by "espos_exit_critical") */ espos_critical_t _espos_enter_critical(espos_spinlock_t *spinlock); /** * @brief exit ESPOS system critical state * * @param spinlock spinlock handle point * @param tmp critical state temple variable(created by "espos_enter_critical") * * @return none */ void _espos_exit_critical(espos_spinlock_t *spinlock, espos_critical_t tmp); /*******************************************************************************************/ /** * @brief initialize ESPOS system * * @return the result * 0 : successful * -ENOMEM : no enough memory */ esp_err_t espos_init(void); /** * @brief start ESPOS system * * @return the result * 0 : successful * -EPERM : failed (it will never happen in a general way) */ esp_err_t espos_start(void); /** * @brief get espos system state * * @return the state * ESPOS_IS_NOT_STARTED : ESPOS is not started * ESPOS_IS_RUNNING : ESPOS is running * ESPOS_IS_SUSPENDED : ESPOS is suspended */ espos_stat_t espos_sched_state_get(void); #if ESPOS_PROCESSORS_NUM > 1u /** * @brief start ESPOS system CPU port * * @param port CPU port ID * * @return the result * 0 : successful * -EPERM : failed (it will never happen in a general way) */ esp_err_t espos_start_port(int port); /** * @brief declare espos critical temp data */ #define espos_declare_critical(t) espos_critical_t t /** * @brief enter ESPOS system critical state * * @param sl spinlock handle * @param t critical state * * @return critical state temple variable(used by "espos_exit_critical") */ #define espos_enter_critical(t, sl) (t) = _espos_enter_critical(&(sl)) /** * @brief exit ESPOS system critical state * * @param t critical state temple variable(created by "espos_enter_critical") * @param sl spinlock handle point * * @return none */ #define espos_exit_critical(t, sl) _espos_exit_critical(&(sl), t) /** * @brief OS internal function enter ESPOS system critical state * * @param sl spinlock handle * @param t critical state * * @return critical state temple variable(used by "espos_exit_critical") * * @note: ESPOS is application level OS API, so it means all APIs call internal * real OS's function, so if OS's or its core hardware's functions want * to call ESPOS, loop nesting will occur, so we should tell ESPOS it's * at OS internal state now. */ #define espos_os_enter_critical(t, sl) \ espos_os_enter(); \ (t) = _espos_enter_critical(&(sl)) /** * @brief OS internal function exit ESPOS system critical state * * @param t critical state temple variable(created by "espos_enter_critical") * @param sl spinlock handle point * * @return none * * @note: ESPOS is application level OS API, so it means all APIs call internal * real OS's function, so if OS's or its core hardware's functions want * to call ESPOS, loop nesting will occur, so we should tell ESPOS it's * at OS internal state now. */ #define espos_os_exit_critical(t, sl) \ _espos_exit_critical(&(sl), t); \ espos_os_exit() #else /** * @brief start ESPOS system CPU port * * @param port CPU port ID * * @return the result * -ENODEV : no device */ static inline esp_err_t espos_start_port(int port) { return -ENODEV; } /** * @brief declare espos critical temp data */ #define espos_declare_critical(t) espos_critical_t t /** * @brief enter ESPOS system critical state * * @param sl no mean * @param t critical state * * @return critical state temple variable(used by "espos_exit_critical") */ #define espos_enter_critical(t, sl) (t) = _espos_enter_critical(NULL) /** * @brief exit ESPOS system critical state * * @param t critical state temple variable(created by "espos_enter_critical") * @param sl no mean * * @return none */ #define espos_exit_critical(t, sl) _espos_exit_critical(NULL, t) /** * @brief OS internal function enter ESPOS system critical state * * @param sl no mean * @param t critical state * * @return critical state temple variable(used by "espos_exit_critical") * * @note: ESPOS is application level OS API, so it means all APIs call internal * real OS's function, so if OS's or its core hardware's functions want * to call ESPOS, loop nesting will occur, so we should tell ESPOS it's * at OS internal state now. */ #define espos_os_enter_critical(t, sl) \ espos_os_enter(); \ (t) = _espos_enter_critical(NULL) /** * @brief OS internal function exit ESPOS system critical state * * @param t critical state temple variable(created by "espos_enter_critical") * @param sl no mean * * @return none * * @note: ESPOS is application level OS API, so it means all APIs call internal * real OS's function, so if OS's or its core hardware's functions want * to call ESPOS, loop nesting will occur, so we should tell ESPOS it's * at OS internal state now. */ #define espos_os_exit_critical(t, sl) \ _espos_exit_critical(NULL, t); \ espos_os_exit() #endif /** * @brief suspend the local CPU core preempt and the current task * owned by local CPU core will not be preempted * * @return the result * 0 : successful * -EAGAIN : preempt suspending maximum number is reached, and fail to do it * -EINTR : you do this at interrupt state, and it is not supported * * @note the function can be used nested */ esp_err_t espos_preempt_suspend_local(void); /** * @brief resume the local CPU core preempt * * @return the result * 0 : successful * -EAGAIN : preempt resuming maximum number is reached, and fail to do it * -EINTR : you do this at interrupt state, and it is not supported * * @note the function can be used nested */ esp_err_t espos_preempt_resume_local(void); /** * @brief enter system interrupt server, the function must be used after entering hardware interrupt * * @return the result * 0 : successful * -EAGAIN : nested count is reached * * @note the function can be used nested */ esp_err_t espos_isr_enter (void); /** * @brief exit system interrupt server, the function must be used before exiting hardware interrupt * * @return none * * @note the function can be used nested */ void espos_isr_exit(void); /** * @brief check if the CPU is at ISR state * * @param none * * @return true if the CPU is at ISR state or false */ bool espos_in_isr(void); /** * @brief mark it enters real OS interal function * * @return the result * 0 : successful * -EAGAIN : nested count is reached * * @note the function can be used nested */ esp_err_t espos_os_enter(void); /** * @brief remove mark it enters real OS interal function * * @param none * * @return none */ void espos_os_exit(void); /** * @brief check if the function is at real OS internal fucntion * * @param none * * @return true if the CPU is at real OS internal fucntion or false */ bool espos_os_isr(void); size_t espos_get_free_heap_size(void); #ifdef __cplusplus } #endif #endif