freertos: Update Xtensa port files to support FreeRTOS SMP

This commit updates the copied Xtensa port to support the new porting interfaces
of the FreeRTOS SMP kernel. These modifications are mainly contained in

- FreeRTOSConfig.h
- FreeRTOSConfig_smp.h
- portmacro.h
- port.c

Some porting interfaces have changed in FreeRTOS SMP. In order to allow building
with IDF, compatibility interfaces have been added.
This commit is contained in:
Darian Leung 2022-02-24 21:54:53 +08:00
parent 163ddc3818
commit 37c270b337
10 changed files with 1165 additions and 994 deletions

View File

@ -0,0 +1,318 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef FREERTOS_CONFIG_SMP_H
#define FREERTOS_CONFIG_SMP_H
#include "sdkconfig.h"
/*
This file get's pulled into assembly sources. Therefore, some includes need to be wrapped in #ifndef __ASSEMBLER__
*/
#ifndef __ASSEMBLER__
#include <assert.h> //For configASSERT()
#endif /* def __ASSEMBLER__ */
/* Required for configuration-dependent settings. */
#include "xtensa_config.h"
/* -------------------------------------------- Xtensa Additional Config ----------------------------------------------
* - Provide Xtensa definitions usually given by -D option when building with xt-make (see readme_xtensa.txt)
* - xtensa_rtos.h and xtensa_timer.h will default some of these values
* - XT_SIMULATOR configXT_SIMULATOR
* - XT_BOARD configXT_BOARD
* - XT_CLOCK_FREQ Should not be defined as we are using XT_BOARD mode
* - XT_TICK_PER_SEC Defaults to configTICK_RATE_HZ
* - XT_TIMER_INDEX Defaults to configXT_TIMER_INDEX
* - XT_INTEXC_HOOKS Defaults to configXT_INTEXC_HOOKS
* - XT_USE_OVLY We don't define this (unused)
* - XT_USE_SWPRI We don't define this (unused)
* ------------------------------------------------------------------------------------------------------------------ */
#define configXT_SIMULATOR 0
#define configXT_BOARD 1 /* Board mode */
#if CONFIG_FREERTOS_CORETIMER_0
#define configXT_TIMER_INDEX 0
#elif CONFIG_FREERTOS_CORETIMER_1
#define configXT_TIMER_INDEX 1
#endif
#define configXT_INTEXC_HOOKS 0
#define configBENCHMARK 0
/* ------------------------------------------------ ESP-IDF Additions --------------------------------------------------
*
* ------------------------------------------------------------------------------------------------------------------ */
/* The Xtensa port uses a separate interrupt stack. Adjust the stack size
* to suit the needs of your specific application.
* Size needs to be aligned to the stack increment, since the location of
* the stack for the 2nd CPU will be calculated using configISR_STACK_SIZE.
*/
#define configSTACK_ALIGNMENT 16
#ifndef configISR_STACK_SIZE
#define configISR_STACK_SIZE ((CONFIG_FREERTOS_ISR_STACKSIZE + configSTACK_ALIGNMENT - 1) & (~(configSTACK_ALIGNMENT - 1)))
#endif
/* ----------------------------------------------------- Helpers -------------------------------------------------------
* - Macros that the FreeRTOS configuration macros depend on
* ------------------------------------------------------------------------------------------------------------------ */
/* Higher stack checker modes cause overhead on each function call */
#if CONFIG_STACK_CHECK_ALL || CONFIG_STACK_CHECK_STRONG
#define STACK_OVERHEAD_CHECKER 256
#else
#define STACK_OVERHEAD_CHECKER 0
#endif
/* with optimizations disabled, scheduler uses additional stack */
#if CONFIG_COMPILER_OPTIMIZATION_NONE
#define STACK_OVERHEAD_OPTIMIZATION 320
#else
#define STACK_OVERHEAD_OPTIMIZATION 0
#endif
/* apptrace mdule increases minimum stack usage */
#if CONFIG_APPTRACE_ENABLE
#define STACK_OVERHEAD_APPTRACE 1280
#else
#define STACK_OVERHEAD_APPTRACE 0
#endif
/* Stack watchpoint decreases minimum usable stack size by up to 60 bytes.
See FreeRTOS FREERTOS_WATCHPOINT_END_OF_STACK option in Kconfig. */
#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
#define STACK_OVERHEAD_WATCHPOINT 60
#else
#define STACK_OVERHEAD_WATCHPOINT 0
#endif
#define configSTACK_OVERHEAD_TOTAL ( \
STACK_OVERHEAD_CHECKER + \
STACK_OVERHEAD_OPTIMIZATION + \
STACK_OVERHEAD_APPTRACE + \
STACK_OVERHEAD_WATCHPOINT \
)
/* ----------------------------------------------------- Helpers -------------------------------------------------------
* - Macros that the FreeRTOS configuration macros depend on
* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------- FreeRTOS Config ---------------------------------------------------
* - All Vanilla FreeRTOS configuration goes into this section
* - Keep this section in-sync with the corresponding version of single-core upstream version of FreeRTOS
* - Don't put any SMP or ESP-IDF exclusive FreeRTOS configurations here. Those go into the next section
* - Not all FreeRTOS configuration are listed. Some configurations have default values set in FreeRTOS.h thus don't
* need to be explicitly defined.
* ------------------------------------------------------------------------------------------------------------------ */
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html
*----------------------------------------------------------*/
// ------------------ Scheduler Related --------------------
#define configUSE_PREEMPTION 1
#define configUSE_TASK_PREEMPTION_DISABLE 1
#define configUSE_TICKLESS_IDLE 0
#define configCPU_CLOCK_HZ (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000)
#define configTICK_RATE_HZ CONFIG_FREERTOS_HZ
#define configMAX_PRIORITIES ( 25 ) //This has impact on speed of search for highest priority
#define configMINIMAL_STACK_SIZE ( 768 + configSTACK_OVERHEAD_TOTAL )
#define configUSE_TIME_SLICING 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0 //Todo: Check this
#define configKERNEL_INTERRUPT_PRIORITY 1 //Todo: This currently isn't used anywhere
#define configMAX_API_CALL_INTERRUPT_PRIORITY XCHAL_EXCM_LEVEL
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 //SMP currently does not support optimized selection
// -------------------- FreeRTOS SMP -----------------------
#ifdef CONFIG_FREERTOS_UNICORE
#define configNUM_CORES 1
#else
#define configNUM_CORES 2
#endif
#define configUSE_CORE_AFFINITY 1
#define configRUN_MULTIPLE_PRIORITIES 1
#define configUSE_MINIMAL_IDLE_HOOK 1
// ------------- Synchronization Primitives ----------------
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_QUEUE_SETS 1
#define configQUEUE_REGISTRY_SIZE CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE
#define configUSE_TASK_NOTIFICATIONS 1
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 1
// ----------------------- System --------------------------
#define configMAX_TASK_NAME_LEN CONFIG_FREERTOS_MAX_TASK_NAME_LEN
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS
#define configSTACK_DEPTH_TYPE uint32_t
#define configUSE_NEWLIB_REENTRANT 1
#define configENABLE_BACKWARD_COMPATIBILITY 0
#define configASSERT(a) assert(a)
#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1
// ----------------------- Memory -------------------------
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 1
//We define the heap to span all of the non-statically-allocated shared RAM. ToDo: Make sure there
//is some space left for the app and main cpu when running outside of a thread.
#define configTOTAL_HEAP_SIZE (&_heap_end - &_heap_start)//( ( size_t ) (64 * 1024) )
#define configAPPLICATION_ALLOCATED_HEAP 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 //Todo: Check this
// ------------------------ Hooks --------------------------
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1
#if CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE
#define configCHECK_FOR_STACK_OVERFLOW 0
#elif CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL
#define configCHECK_FOR_STACK_OVERFLOW 1
#elif CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY
#define configCHECK_FOR_STACK_OVERFLOW 2
#endif
#define configRECORD_STACK_HIGH_ADDRESS 1
// ------------------- Run-time Stats ----------------------
#ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
#define configGENERATE_RUN_TIME_STATS 1 /* Used by vTaskGetRunTimeStats() */
#endif
#ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY
#define configUSE_TRACE_FACILITY 1 /* Used by uxTaskGetSystemState(), and other trace facility functions */
#endif
#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
#define configUSE_STATS_FORMATTING_FUNCTIONS 1 /* Used by vTaskList() */
#endif
// -------------------- Co-routines -----------------------
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
// ------------------- Software Timer ----------------------
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY
#define configTIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH
#define configTIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH
// -------------------- API Includes -----------------------
#define configENABLE_BACKWARD_COMPATIBILITY 0
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_xTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
#define INCLUDE_xTaskAbortDelay 1
#define INCLUDE_xSemaphoreGetMutexHolder 1
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_uxTaskGetStackHighWaterMark2 0
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTaskResumeFromISR 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
// -------------------- Trace Macros -----------------------
/*
For trace macros.
Note: Include trace macros here and not above as trace macros are dependent on some of the FreeRTOS configs
*/
#ifndef __ASSEMBLER__
#if CONFIG_SYSVIEW_ENABLE
#include "SEGGER_SYSVIEW_FreeRTOS.h"
#undef INLINE // to avoid redefinition
#endif //CONFIG_SYSVIEW_ENABLE
#endif /* def __ASSEMBLER__ */
/*
Default values for trace macros added by ESP-IDF and are not part of Vanilla FreeRTOS
*/
#ifndef traceISR_EXIT
#define traceISR_EXIT()
#endif
#ifndef traceISR_ENTER
#define traceISR_ENTER(_n_)
#endif
/* ------------------------------------------------ IDF Compatibility --------------------------------------------------
* - We need these in order for ESP-IDF to compile
* ------------------------------------------------------------------------------------------------------------------ */
#define portNUM_PROCESSORS configNUM_CORES
#ifdef CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID
#define configTASKLIST_INCLUDE_COREID 1
#endif
#define configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS 1
#ifndef __ASSEMBLER__
#if CONFIG_APPTRACE_SV_ENABLE
extern uint32_t port_switch_flag[];
#define os_task_switch_is_pended(_cpu_) (port_switch_flag[_cpu_])
#else
#define os_task_switch_is_pended(_cpu_) (false)
#endif
#endif
// ---------------------- Features -------------------------
#ifdef CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT
#define configENABLE_TASK_SNAPSHOT 1
#else
#define configENABLE_TASK_SNAPSHOT 0
#endif
/* These currently aren't required, but could be useful additions in the future */
#if 0
#ifndef configIDLE_TASK_STACK_SIZE
#define configIDLE_TASK_STACK_SIZE CONFIG_FREERTOS_IDLE_TASK_STACKSIZE
#endif
#if CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER
#define configCHECK_MUTEX_GIVEN_BY_OWNER 1
#else
#define configCHECK_MUTEX_GIVEN_BY_OWNER 0
#endif
#ifndef __ASSEMBLER__
#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP
extern void vPortCleanUpTCB ( void *pxTCB );
#define portCLEAN_UP_TCB( pxTCB ) vPortCleanUpTCB( pxTCB )
#endif
#endif
#endif //0
// -------------------- Compatibility ----------------------
// backward compatibility for 4.4
#define xTaskRemoveFromUnorderedEventList vTaskRemoveFromUnorderedEventList
#endif /* FREERTOS_CONFIG_SMP_H */

View File

@ -1,98 +1,37 @@
/*
* SPDX-FileCopyrightText: 2017 Amazon.com, Inc. or its affiliates
* SPDX-FileCopyrightText: 2015-2019 Cadence Design Systems, Inc.
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: MIT
*
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
*/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#ifndef __ASSEMBLER__
#pragma once
#include "sdkconfig.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdarg.h>
#include <xtensa/config/core.h>
#include <xtensa/hal.h> /* required for xthal_get_ccount. [refactor-todo] use cpu_hal instead */
#include <xtensa/xtruntime.h> /* required for XTOS_SET_INTLEVEL. [refactor-todo] add common intr functions to esp_hw_support */
#include "spinlock.h"
#include "xtensa/xtruntime.h"
#include "xtensa/config/core.h"
#include "xtensa/config/core-isa.h"
#include "xtensa/config/specreg.h"
#include "xt_instr_macros.h"
#include "soc/spinlock.h"
#include "portbenchmark.h"
#include "esp_macro.h"
#include "hal/cpu_hal.h"
#include "esp_private/crosscore_int.h"
#include "esp_macro.h"
#include "esp_attr.h"
#include "esp_timer.h" /* required for esp_timer_get_time. [refactor-todo] make this common between archs */
#include "esp_newlib.h" /* required for esp_reent_init() in tasks.c */
#include "esp_heap_caps.h"
#include "esp_rom_sys.h"
#include "esp_system.h" /* required by esp_get_...() functions in portable.h. [refactor-todo] Update portable.h */
#include "portbenchmark.h"
/* [refactor-todo] These includes are not directly used in this file. They are kept into to prevent a breaking change. Remove these. */
#include <limits.h>
#include <xtensa/config/system.h>
#include <xtensa/xtensa_api.h>
/*
Note: We should not include any FreeRTOS headers (directly or indirectly) here as this will create a reverse dependency
- FreeRTOS pulls in "portmacro.h" via
- source.c <- FreeRTOS.h <- portable.h <- portmacro.h
- If we need types of task.h (such as TaskHandle_t), best put the feature somewhere else
- Be careful as some parts of C Standard Library Headers will pull in FreeRTOS headers
*/
#ifdef __cplusplus
extern "C" {
#endif
/* --------------------------------------------------- Port Types ------------------------------------------------------
* - Port specific types.
* - The settings in this file configure FreeRTOS correctly for the given hardware and compiler.
@ -124,88 +63,23 @@ typedef uint32_t TickType_t;
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/* ----------------------------------------------- Port Configurations -------------------------------------------------
* - Configurations values supplied by each port
* - Required by FreeRTOS
* ------------------------------------------------------------------------------------------------------------------ */
#define portCRITICAL_NESTING_IN_TCB 0
#define portCRITICAL_NESTING_IN_TCB 1
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 4
#define portNOP() XT_NOP()
#define portNOP() XT_NOP() //Todo: Check if XT_NOP exists
/* ---------------------------------------------- Forward Declarations -------------------------------------------------
* - Forward declarations of all the port functions and macros need to implement the FreeRTOS porting interface
* - These must come before definition/declaration of the FreeRTOS porting interface
* ------------------------------------------------------------------------------------------------------------------ */
// --------------------- Interrupts ------------------------
/**
* @brief Checks if the current core is in an ISR context
*
* - ISR context consist of Low/Mid priority ISR, or time tick ISR
* - High priority ISRs aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
*
* @note [refactor-todo] Check if this should be inlined
* @return
* - pdTRUE if in ISR
* - pdFALSE otherwise
*/
BaseType_t xPortInIsrContext(void);
/**
* @brief Asserts if in ISR context
*
* - Asserts on xPortInIsrContext() internally
*
* @note [refactor-todo] Check if this API is still required
* @note [refactor-todo] Check if this should be inlined
*/
void vPortAssertIfInISR(void);
/**
* @brief Check if in ISR context from High priority ISRs
*
* - Called from High priority ISR
* - Checks if the previous context (before high priority interrupt) was in ISR context (meaning low/med priority)
*
* @note [refactor-todo] Check if this should be inlined
* @return
* - pdTRUE if in previous in ISR context
* - pdFALSE otherwise
*/
BaseType_t xPortInterruptedFromISRContext(void);
/**
* @brief Disable interrupts in a nested manner (meant to be called from ISRs)
*
* @warning Only applies to current CPU.
* @return UBaseType_t Previous interrupt level
*/
static inline UBaseType_t xPortSetInterruptMaskFromISR(void);
/**
* @brief Reenable interrupts in a nested manner (meant to be called from ISRs)
*
* @warning Only applies to current CPU.
* @param prev_level Previous interrupt level
*/
static inline void vPortClearInterruptMaskFromISR(UBaseType_t prev_level);
/* ---------------------- Spinlocks ------------------------
* - Modifications made to critical sections to support SMP
* - See "Critical Sections & Disabling Interrupts" in docs/api-guides/freertos-smp.rst for more details
* - Remark: For the ESP32, portENTER_CRITICAL and portENTER_CRITICAL_ISR both alias vPortEnterCritical, meaning that
* either function can be called both from ISR as well as task context. This is not standard FreeRTOS
* behaviorr; please keep this in mind if you need any compatibility with other FreeRTOS implementations.
* @note [refactor-todo] Check if these comments are still true
* ------------------------------------------------------ */
// ---------------------- Spinlocks ------------------------
typedef spinlock_t portMUX_TYPE; /**< Spinlock type used by FreeRTOS critical sections */
#define portMUX_INITIALIZER_UNLOCKED SPINLOCK_INITIALIZER /**< Spinlock initializer */
@ -214,364 +88,124 @@ typedef spinlock_t portMUX_TYPE; /**< Spi
#define portMUX_TRY_LOCK SPINLOCK_NO_WAIT /**< Try to acquire the spinlock a single time only. [refactor-todo] check if this is still required */
#define portMUX_INITIALIZE(mux) spinlock_initialize(mux) /*< Initialize a spinlock to its unlocked state */
// ----------------------- Memory --------------------------
// --------------------- Interrupts ------------------------
BaseType_t xPortCheckIfInISR(void);
// ------------------ Critical Sections --------------------
/**
* @brief Enter a SMP critical section with a timeout
*
* This function enters an SMP critical section by disabling interrupts then
* taking a spinlock with a specified timeout.
*
* This function can be called in a nested manner.
*
* @note This function is made non-inline on purpose to reduce code size
* @param mux Spinlock
* @param timeout Timeout to wait for spinlock in number of CPU cycles.
* Use portMUX_NO_TIMEOUT to wait indefinitely
* Use portMUX_TRY_LOCK to only getting the spinlock a single time
* @retval pdPASS Critical section entered (spinlock taken)
* @retval pdFAIL If timed out waiting for spinlock (will not occur if using portMUX_NO_TIMEOUT)
*/
BaseType_t xPortEnterCriticalTimeout(portMUX_TYPE *mux, BaseType_t timeout);
UBaseType_t uxPortEnterCriticalFromISR( void );
void vPortExitCriticalFromISR( UBaseType_t level );
/**
* @brief Enter a SMP critical section
*
* This function enters an SMP critical section by disabling interrupts then
* taking a spinlock with an unlimited timeout.
*
* This function can be called in a nested manner
*
* @param[in] mux Spinlock
*/
static inline void __attribute__((always_inline)) vPortEnterCritical(portMUX_TYPE *mux);
/*
These are always called with interrupts already disabled. We simply need to get/release the spinlocks
*/
/**
* @brief Exit a SMP critical section
*
* This function can be called in a nested manner. On the outer most level of nesting, this function will:
*
* - Release the spinlock
* - Restore the previous interrupt level before the critical section was entered
*
* If still nesting, this function simply decrements a critical nesting count
*
* @note This function is made non-inline on purpose to reduce code size
* @param[in] mux Spinlock
*/
void vPortExitCritical(portMUX_TYPE *mux);
extern portMUX_TYPE port_xTaskLock;
extern portMUX_TYPE port_xISRLock;
/**
* @brief FreeRTOS Compliant version of xPortEnterCriticalTimeout()
*
* Compliant version of xPortEnterCriticalTimeout() will ensure that this is
* called from a task context only. An abort is called otherwise.
*
* @note This function is made non-inline on purpose to reduce code size
*
* @param mux Spinlock
* @param timeout Timeout
* @return BaseType_t
*/
BaseType_t xPortEnterCriticalTimeoutCompliance(portMUX_TYPE *mux, BaseType_t timeout);
/**
* @brief FreeRTOS compliant version of vPortEnterCritical()
*
* Compliant version of vPortEnterCritical() will ensure that this is
* called from a task context only. An abort is called otherwise.
*
* @param[in] mux Spinlock
*/
static inline void __attribute__((always_inline)) vPortEnterCriticalCompliance(portMUX_TYPE *mux);
/**
* @brief FreeRTOS compliant version of vPortExitCritical()
*
* Compliant version of vPortExitCritical() will ensure that this is
* called from a task context only. An abort is called otherwise.
*
* @note This function is made non-inline on purpose to reduce code size
* @param[in] mux Spinlock
*/
void vPortExitCriticalCompliance(portMUX_TYPE *mux);
/**
* @brief Safe version of enter critical timeout
*
* Safe version of enter critical will automatically select between
* portTRY_ENTER_CRITICAL() and portTRY_ENTER_CRITICAL_ISR()
*
* @param mux Spinlock
* @param timeout Timeout
* @return BaseType_t
*/
static inline BaseType_t __attribute__((always_inline)) xPortEnterCriticalTimeoutSafe(portMUX_TYPE *mux, BaseType_t timeout);
/**
* @brief Safe version of enter critical
*
* Safe version of enter critical will automatically select between
* portENTER_CRITICAL() and portENTER_CRITICAL_ISR()
*
* @param[in] mux Spinlock
*/
static inline void __attribute__((always_inline)) vPortEnterCriticalSafe(portMUX_TYPE *mux);
/**
* @brief Safe version of exit critical
*
* Safe version of enter critical will automatically select between
* portEXIT_CRITICAL() and portEXIT_CRITICAL_ISR()
*
* @param[in] mux Spinlock
*/
static inline void __attribute__((always_inline)) vPortExitCriticalSafe(portMUX_TYPE *mux);
void vPortTakeLock( portMUX_TYPE *lock );
void vPortReleaseLock( portMUX_TYPE *lock );
// ---------------------- Yielding -------------------------
/**
* @brief Perform a solicited context switch
*
* - Defined in portasm.S
*
* @note [refactor-todo] The rest of ESP-IDF should call taskYield() instead
*/
void vPortYield( void );
static inline void __attribute__((always_inline)) vPortYieldCore( BaseType_t xCoreID );
static inline void __attribute__((always_inline)) vPortYieldFromISR( void );
/**
* @brief Yields the other core
*
* - Send an interrupt to another core in order to make the task running on it yield for a higher-priority task.
* - Can be used to yield current core as well
*
* @note [refactor-todo] Put this into private macros as its only called from task.c and is not public API
* @param coreid ID of core to yield
*/
void vPortYieldOtherCore(BaseType_t coreid);
/**
* @brief Checks if the current core can yield
*
* - A core cannot yield if its in an ISR or in a critical section
*
* @note [refactor-todo] See if this can be separated from port macro
* @return true Core can yield
* @return false Core cannot yield
*/
static inline bool IRAM_ATTR xPortCanYield(void);
// ------------------- Hook Functions ----------------------
/**
* @brief Hook function called on entry to tickless idle
*
* - Implemented in pm_impl.c
*
* @param xExpectedIdleTime Expected idle time
*/
void vApplicationSleep(TickType_t xExpectedIdleTime);
#define portYIELD_FROM_ISR_CHECK(x) ({ \
if ( (x) == pdTRUE ) { \
vPortYieldFromISR(); \
} \
})
#define portYIELD_FROM_ISR_NO_CHECK() vPortYieldFromISR()
// ----------------------- System --------------------------
/**
* @brief Get the tick rate per second
*
* @note [refactor-todo] make this inline
* @return uint32_t Tick rate in Hz
*/
uint32_t xPortGetTickRateHz(void);
static inline BaseType_t __attribute__((always_inline)) xPortGetCoreID( void );
/**
* @brief Set a watchpoint to watch the last 32 bytes of the stack
*
* Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack watchpoint
* around.
*
* @param pxStackStart Pointer to the start of the stack
*/
void vPortSetStackWatchpoint( void *pxStackStart );
/**
* @brief Get the current core's ID
*
* @note [refactor-todo] IDF should call a FreeRTOS like macro instead of port function directly
* @return BaseType_t Core ID
*/
static inline BaseType_t IRAM_ATTR xPortGetCoreID(void);
/**
* @brief Wrapper for atomic compare-and-set instruction
*
* This subroutine will atomically compare *addr to 'compare'. If *addr == compare, *addr is set to *set. *set is
* updated with the previous value of *addr (either 'compare' or some other value.)
*
* @warning From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the "bitwise inverse" of
* the old mem if the mem wasn't written. This doesn't seem to happen on the ESP32 (portMUX assertions would
* fail).
*
* @note [refactor-todo] Check if this can be deprecated
* @note [refactor-todo] Check if this function should be renamed (due to void return type)
*
* @param[inout] addr Pointer to target address
* @param[in] compare Compare value
* @param[inout] set Pointer to set value
*/
static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set);
/**
* @brief Wrapper for atomic compare-and-set instruction in external RAM
*
* Atomic compare-and-set but the target address is placed in external RAM
*
* @note [refactor-todo] Check if this can be deprecated
*
* @param[inout] addr Pointer to target address
* @param[in] compare Compare value
* @param[inout] set Pointer to set value
*/
static inline void __attribute__((always_inline)) uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set);
/* ------------------------------------------- FreeRTOS Porting Interface ----------------------------------------------
* - Contains all the mappings of the macros required by FreeRTOS
* - Most come after forward declare as porting macros map to declared functions
* - Maps to forward declared functions
/* ----------------------------------------- FreeRTOS SMP Porting Interface --------------------------------------------
* - Contains all the mappings of the macros required by FreeRTOS SMP
* - Must come after forward declare as some porting macros map to declared functions
* ------------------------------------------------------------------------------------------------------------------ */
// ----------------------- Memory --------------------------
/**
* @brief Task memory allocation macros
*
* @note Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force the stack
* memory to always be internal.
* @note [refactor-todo] Update portable.h to match v10.4.3 to use new malloc prototypes
*/
#define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
#define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
#define pvPortMallocTcbMem(size) heap_caps_malloc(size, portTcbMemoryCaps)
#define pvPortMallocStackMem(size) heap_caps_malloc(size, portStackMemoryCaps)
// --------------------- Interrupts ------------------------
/**
* - Only applies to current core
* - These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level.
*
* @note [refactor-todo] replace XTOS_SET_INTLEVEL with more efficient version, if any?
*/
#define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0)
#define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0)
#define portDISABLE_INTERRUPTS() ({ \
unsigned int prev_level = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); \
portbenchmarkINTERRUPT_DISABLE(); \
prev_level; \
})
/**
* ISR versions to enable/disable interrupts
*/
#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMaskFromISR()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(prev_level) vPortClearInterruptMaskFromISR(prev_level)
#define portENABLE_INTERRUPTS() ({ \
portbenchmarkINTERRUPT_RESTORE(0); \
XTOS_SET_INTLEVEL(0); \
})
#define portASSERT_IF_IN_ISR() vPortAssertIfInISR()
/*
Note: XTOS_RESTORE_INTLEVEL() will overwrite entire PS register on XEA2. So we need ot make the value INTLEVEL field ourselves
*/
#define portRESTORE_INTERRUPTS(x) ({ \
unsigned int ps_reg; \
RSR(PS, ps_reg); \
ps_reg = (ps_reg & ~XCHAL_PS_INTLEVEL_MASK); \
ps_reg |= ((x << XCHAL_PS_INTLEVEL_SHIFT) & XCHAL_PS_INTLEVEL_MASK); \
XTOS_RESTORE_INTLEVEL(ps_reg); \
})
// ------------------ Critical Sections --------------------
/**
* @brief FreeRTOS critical section macros
*
* - Added a spinlock argument for SMP
* - Can be nested
* - Compliance versions will assert if regular critical section API is used in ISR context
* - Safe versions can be called from either contexts
*/
#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
#define portTRY_ENTER_CRITICAL(mux, timeout) xPortEnterCriticalTimeoutCompliance(mux, timeout)
#define portENTER_CRITICAL(mux) vPortEnterCriticalCompliance(mux)
#define portEXIT_CRITICAL(mux) vPortExitCriticalCompliance(mux)
#else
#define portTRY_ENTER_CRITICAL(mux, timeout) xPortEnterCriticalTimeout(mux, timeout)
#define portENTER_CRITICAL(mux) vPortEnterCritical(mux)
#define portEXIT_CRITICAL(mux) vPortExitCritical(mux)
#endif /* CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE */
#define portGET_TASK_LOCK() vPortTakeLock(&port_xTaskLock)
#define portRELEASE_TASK_LOCK() vPortReleaseLock(&port_xTaskLock)
#define portGET_ISR_LOCK() vPortTakeLock(&port_xISRLock)
#define portRELEASE_ISR_LOCK() vPortReleaseLock(&port_xISRLock)
#define portTRY_ENTER_CRITICAL_ISR(mux, timeout) xPortEnterCriticalTimeout(mux, timeout)
#define portENTER_CRITICAL_ISR(mux) vPortEnterCritical(mux)
#define portEXIT_CRITICAL_ISR(mux) vPortExitCritical(mux)
//Critical sections used by FreeRTOS SMP
extern void vTaskEnterCritical( void );
extern void vTaskExitCritical( void );
#define portENTER_CRITICAL_SMP() vTaskEnterCritical();
#define portEXIT_CRITICAL_SMP() vTaskExitCritical();
#define portTRY_ENTER_CRITICAL_SAFE(mux, timeout) xPortEnterCriticalTimeoutSafe(mux)
#define portENTER_CRITICAL_SAFE(mux) vPortEnterCriticalSafe(mux)
#define portEXIT_CRITICAL_SAFE(mux) vPortExitCriticalSafe(mux)
#define portENTER_CRITICAL(...) CHOOSE_MACRO_VA_ARG(_0, ##__VA_ARGS__, portENTER_CRITICAL_IDF, portENTER_CRITICAL_SMP)(__VA_ARGS__)
#define portEXIT_CRITICAL(...) CHOOSE_MACRO_VA_ARG(_0, ##__VA_ARGS__, portEXIT_CRITICAL_IDF, portEXIT_CRITICAL_SMP)(__VA_ARGS__)
#define portSET_INTERRUPT_MASK_FROM_ISR() ({ \
unsigned int cur_level; \
RSR(PS, cur_level); \
cur_level = (cur_level & XCHAL_PS_INTLEVEL_MASK) >> XCHAL_PS_INTLEVEL_SHIFT; \
vTaskEnterCritical(); \
cur_level; \
})
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) ({ \
vTaskExitCritical(); \
portRESTORE_INTERRUPTS(x); \
})
// ---------------------- Yielding -------------------------
#define portYIELD() vPortYield()
#define portYIELD() vPortYield()
#define portYIELD_FROM_ISR(...) CHOOSE_MACRO_VA_ARG(_0, ##__VA_ARGS__, portYIELD_FROM_ISR_CHECK, portYIELD_FROM_ISR_NO_CHECK)(__VA_ARGS__)
#define portYIELD_CORE(x) vPortYieldCore(x)
extern void _frxt_setup_switch( void ); //Defined in portasm.S
// ----------------------- System --------------------------
#define portYIELD_FROM_ISR_NO_ARG() ({ \
traceISR_EXIT_TO_SCHEDULER(); \
_frxt_setup_switch(); \
})
#define portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken) ({ \
if (xHigherPriorityTaskWoken == pdTRUE) { \
traceISR_EXIT_TO_SCHEDULER(); \
_frxt_setup_switch(); \
} \
})
/**
* @note The macro below could be used when passing a single argument, or without any argument,
* it was developed to support both usages of portYIELD inside of an ISR. Any other usage form
* might result in undesired behavior
*/
#if defined(__cplusplus) && (__cplusplus > 201703L)
#define portYIELD_FROM_ISR(...) CHOOSE_MACRO_VA_ARG(_0 __VA_OPT__(,) ##__VA_ARGS__, portYIELD_FROM_ISR_ARG, portYIELD_FROM_ISR_NO_ARG)(__VA_ARGS__)
#else
#define portYIELD_FROM_ISR(...) CHOOSE_MACRO_VA_ARG(_0, ##__VA_ARGS__, portYIELD_FROM_ISR_ARG, portYIELD_FROM_ISR_NO_ARG)(__VA_ARGS__)
#endif
/* Yielding within an API call (when interrupts are off), means the yield should be delayed
until interrupts are re-enabled.
To do this, we use the "cross-core" interrupt as a trigger to yield on this core when interrupts are re-enabled.This
is the same interrupt & code path which is used to trigger a yield between CPUs, although in this case the yield is
happening on the same CPU.
*/
#define portYIELD_WITHIN_API() esp_crosscore_int_send_yield(xPortGetCoreID())
// ------------------- Hook Functions ----------------------
#define portSUPPRESS_TICKS_AND_SLEEP(idleTime) vApplicationSleep(idleTime)
#define portGET_CORE_ID() xPortGetCoreID()
#define portCHECK_IF_IN_ISR() xPortCheckIfInISR()
// ------------------- Run Time Stats ----------------------
//Timers are already configured, so nothing to do for configuration of run time stats timer
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
/**
* - Fine resolution uses ccount
* - ALT is coarse and uses esp_timer
* @note [refactor-todo] Make fine and alt timers mutually exclusive
*/
#define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount()
//We define get run time counter value regardless because the rest of ESP-IDF uses it
#define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount()
#ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER
#define portALT_GET_RUN_TIME_COUNTER_VALUE(x) do {x = (uint32_t)esp_timer_get_time();} while(0)
#define portALT_GET_RUN_TIME_COUNTER_VALUE(x) ({x = (uint32_t)esp_timer_get_time();})
#endif
// -------------- Optimized Task Selection -----------------
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */
#if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice.
#endif
/* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( ( uxReadyPriorities ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* --------------------------------------------- Inline Implementations ------------------------------------------------
* - Implementation of inline functions of the forward declares
* - Should come after forward declare and FreeRTOS Porting interface, as implementation may use both.
@ -580,99 +214,33 @@ extern void _frxt_setup_switch( void ); //Defined in portasm.S
// --------------------- Interrupts ------------------------
static inline UBaseType_t __attribute__((always_inline)) xPortSetInterruptMaskFromISR(void)
{
UBaseType_t prev_int_level = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);
portbenchmarkINTERRUPT_DISABLE();
return prev_int_level;
}
static inline void __attribute__((always_inline)) vPortClearInterruptMaskFromISR(UBaseType_t prev_level)
{
portbenchmarkINTERRUPT_RESTORE(prev_level);
XTOS_RESTORE_JUST_INTLEVEL((int) prev_level);
}
// ------------------ Critical Sections --------------------
static inline void __attribute__((always_inline)) vPortEnterCritical(portMUX_TYPE *mux)
{
xPortEnterCriticalTimeout(mux, portMUX_NO_TIMEOUT);
}
static inline void __attribute__((always_inline)) vPortEnterCriticalCompliance(portMUX_TYPE *mux)
{
xPortEnterCriticalTimeoutCompliance(mux, portMUX_NO_TIMEOUT);
}
static inline BaseType_t __attribute__((always_inline)) xPortEnterCriticalTimeoutSafe(portMUX_TYPE *mux, BaseType_t timeout)
{
BaseType_t ret;
if (xPortInIsrContext()) {
ret = portTRY_ENTER_CRITICAL_ISR(mux, timeout);
} else {
ret = portTRY_ENTER_CRITICAL(mux, timeout);
}
return ret;
}
static inline void __attribute__((always_inline)) vPortEnterCriticalSafe(portMUX_TYPE *mux)
{
xPortEnterCriticalTimeoutSafe(mux, portMUX_NO_TIMEOUT);
}
static inline void __attribute__((always_inline)) vPortExitCriticalSafe(portMUX_TYPE *mux)
{
if (xPortInIsrContext()) {
portEXIT_CRITICAL_ISR(mux);
} else {
portEXIT_CRITICAL(mux);
}
}
// ---------------------- Yielding -------------------------
static inline bool IRAM_ATTR xPortCanYield(void)
extern void _frxt_setup_switch( void ); //Defined in portasm.S
static inline void __attribute__((always_inline)) vPortYieldCore( BaseType_t xCoreID )
{
uint32_t ps_reg = 0;
esp_crosscore_int_send_yield( xCoreID );
}
//Get the current value of PS (processor status) register
RSR(PS, ps_reg);
/*
* intlevel = (ps_reg & 0xf);
* excm = (ps_reg >> 4) & 0x1;
* CINTLEVEL is max(excm * EXCMLEVEL, INTLEVEL), where EXCMLEVEL is 3.
* However, just return true, only intlevel is zero.
*/
return ((ps_reg & PS_INTLEVEL_MASK) == 0);
static inline void __attribute__((always_inline)) vPortYieldFromISR( void )
{
//traceISR_EXIT_TO_SCHEDULER();
_frxt_setup_switch();
}
// ----------------------- System --------------------------
static inline BaseType_t IRAM_ATTR xPortGetCoreID(void)
static inline BaseType_t __attribute__((always_inline)) xPortGetCoreID( void )
{
return (BaseType_t) cpu_hal_get_core_id();
}
static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
{
compare_and_set_native(addr, compare, set);
}
static inline void __attribute__((always_inline)) uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
{
#ifdef CONFIG_SPIRAM
compare_and_set_extram(addr, compare, set);
#endif
}
/* ------------------------------------------------------ Misc ---------------------------------------------------------
* - Miscellaneous porting macros
* - These are not port of the FreeRTOS porting interface, but are used by other FreeRTOS dependent components
* - These are not part of the FreeRTOS porting interface, but are used by other FreeRTOS dependent components
* - [refactor-todo] Remove dependency on MPU wrappers by modifying TCB
* ------------------------------------------------------------------------------------------------------------------ */
@ -717,60 +285,144 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMOR
void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings );
#endif
// -------------------- Heap Related -----------------------
/**
* @brief Checks if a given piece of memory can be used to store a task's TCB
*
* - Defined in port_common.c
*
* @param ptr Pointer to memory
* @return true Memory can be used to store a TCB
* @return false Otherwise
*/
bool xPortCheckValidTCBMem(const void *ptr);
/**
* @brief Checks if a given piece of memory can be used to store a task's stack
*
* - Defined in port_common.c
*
* @param ptr Pointer to memory
* @return true Memory can be used to store a task stack
* @return false Otherwise
*/
bool xPortcheckValidStackMem(const void *ptr);
#define portVALID_TCB_MEM(ptr) xPortCheckValidTCBMem(ptr)
#define portVALID_STACK_MEM(ptr) xPortcheckValidStackMem(ptr)
// --------------------- App-Trace -------------------------
#if CONFIG_APPTRACE_SV_ENABLE
extern uint32_t port_switch_flag[];
#define os_task_switch_is_pended(_cpu_) (port_switch_flag[_cpu_])
#else
#define os_task_switch_is_pended(_cpu_) (false)
#endif
// --------------------- Debugging -------------------------
#if CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION
#define UNTESTED_FUNCTION() { esp_rom_printf("Untested FreeRTOS function %s\r\n", __FUNCTION__); configASSERT(false); } while(0)
#else
#define UNTESTED_FUNCTION()
#endif
/* ---------------------------------------------------- Deprecate ------------------------------------------------------
* - Pull in header containing deprecated macros here
/* ------------------------------------------------ IDF Compatibility --------------------------------------------------
* - These macros and functions need to be defined for IDF to compile
* ------------------------------------------------------------------------------------------------------------------ */
#include "portmacro_deprecated.h"
// --------------------- Interrupts ------------------------
static inline BaseType_t xPortInIsrContext(void)
{
//Just call the FreeRTOS port interface version
return xPortCheckIfInISR();
}
BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void);
static inline UBaseType_t xPortSetInterruptMaskFromISR(void)
{
UBaseType_t prev_int_level = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);
portbenchmarkINTERRUPT_DISABLE();
return prev_int_level;
}
static inline void vPortClearInterruptMaskFromISR(UBaseType_t prev_level)
{
portbenchmarkINTERRUPT_RESTORE(prev_level);
XTOS_RESTORE_JUST_INTLEVEL((int) prev_level);
}
// ---------------------- Spinlocks ------------------------
static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
{
compare_and_set_native(addr, compare, set);
}
static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
{
#if defined(CONFIG_SPIRAM)
compare_and_set_extram(addr, compare, set);
#endif
}
static inline bool __attribute__((always_inline)) vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout)
{
return (spinlock_acquire(mux, timeout));
}
static inline void __attribute__((always_inline)) vPortCPUReleaseMutex(portMUX_TYPE *mux)
{
spinlock_release(mux);
}
// ------------------ Critical Sections --------------------
BaseType_t xPortEnterCriticalTimeout(portMUX_TYPE *lock, BaseType_t timeout);
static inline void __attribute__((always_inline)) vPortEnterCriticalIDF(portMUX_TYPE *lock)
{
xPortEnterCriticalTimeout(lock, portMUX_NO_TIMEOUT);
}
void vPortExitCriticalIDF(portMUX_TYPE *lock);
/*
In case any IDF libs called the port critical functions directly instead of through the macros.
The will just call the vPort...CriticalIDF() functions
*/
void vPortEnterCritical(portMUX_TYPE *lock);
void vPortExitCritical(portMUX_TYPE *lock);
//IDF task critical sections
#define portTRY_ENTER_CRITICAL(lock, timeout) xPortEnterCriticalTimeout(lock, timeout)
#define portENTER_CRITICAL_IDF(lock) vPortEnterCriticalIDF(lock)
#define portEXIT_CRITICAL_IDF(lock) vPortExitCriticalIDF(lock)
//IDF ISR critical sections
#define portTRY_ENTER_CRITICAL_ISR(lock, timeout) xPortEnterCriticalTimeout(lock, timeout)
#define portENTER_CRITICAL_ISR(lock) vPortEnterCriticalIDF(lock)
#define portEXIT_CRITICAL_ISR(lock) vPortExitCriticalIDF(lock)
//IDF safe critical sections (they're the same)
#define portENTER_CRITICAL_SAFE(lock) vPortEnterCriticalIDF(lock)
#define portEXIT_CRITICAL_SAFE(lock) vPortExitCriticalIDF(lock)
// ---------------------- Yielding -------------------------
static inline bool IRAM_ATTR xPortCanYield(void)
{
uint32_t ps_reg = 0;
//Get the current value of PS (processor status) register
RSR(PS, ps_reg);
/*
* intlevel = (ps_reg & 0xf);
* excm = (ps_reg >> 4) & 0x1;
* CINTLEVEL is max(excm * EXCMLEVEL, INTLEVEL), where EXCMLEVEL is 3.
* However, just return true, only intlevel is zero.
*/
return ((ps_reg & PS_INTLEVEL_MASK) == 0);
}
// ----------------------- System --------------------------
void vPortSetStackWatchpoint(void *pxStackStart);
#define portVALID_TCB_MEM(ptr) (esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr))
#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
#define portVALID_STACK_MEM(ptr) (esp_ptr_byte_accessible(ptr))
#else
#define portVALID_STACK_MEM(ptr) (esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr))
#endif
#define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
#define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
// --------------- Compatibility Includes ------------------
/*
ESP-IDF currently does not have a "Include what you use" policy. A lot of files implicitly pull in API through
portmacro.h. Therefore, we need to keep these headers around for now to allow the rest of IDF to compile.
[refactor-todo] Clean up ESP-IDF inclusion dependencies and add a inclusion check.
*/
#include <stdlib.h>
#include <stdbool.h>
#include <stdarg.h>
#include <xtensa/hal.h>
#include "esp_attr.h"
#include "esp_timer.h"
#include "esp_newlib.h"
#include "esp_heap_caps.h"
#include "esp_rom_sys.h"
#include "esp_system.h"
#include "portbenchmark.h"
#include <limits.h>
#include <xtensa/config/system.h>
#include <xtensa/xtensa_api.h>
#ifdef __cplusplus
}
#endif
#endif // __ASSEMBLER__
#endif /* PORTMACRO_H */

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -17,7 +17,7 @@
*
* @deprecated This function is deprecated. Call portSET_INTERRUPT_MASK_FROM_ISR() instead
*/
static inline __attribute__((deprecated)) UBaseType_t portENTER_CRITICAL_NESTED(void) {
static inline __attribute__((always_inline, deprecated)) UBaseType_t portENTER_CRITICAL_NESTED(void) {
return portSET_INTERRUPT_MASK_FROM_ISR();
}
@ -28,7 +28,7 @@ static inline __attribute__((deprecated)) UBaseType_t portENTER_CRITICAL_NESTED(
*
* @deprecated This function is deprecated. Call portCLEAR_INTERRUPT_MASK_FROM_ISR() instead
*/
static inline void __attribute__((deprecated)) portEXIT_CRITICAL_NESTED(UBaseType_t prev_level)
static inline void __attribute__((always_inline, deprecated)) portEXIT_CRITICAL_NESTED(UBaseType_t prev_level)
{
portCLEAR_INTERRUPT_MASK_FROM_ISR(prev_level);
}
@ -43,7 +43,7 @@ static inline void __attribute__((deprecated)) portEXIT_CRITICAL_NESTED(UBaseTyp
* @deprecated This function is deprecated. Call spinlock_initialize() instead
* @param[in] mux Spinlock
*/
static inline void __attribute__((deprecated)) __attribute__((always_inline)) vPortCPUInitializeMutex(portMUX_TYPE *mux)
static inline void __attribute__((always_inline, deprecated)) vPortCPUInitializeMutex(portMUX_TYPE *mux)
{
spinlock_initialize(mux);
}
@ -56,7 +56,7 @@ static inline void __attribute__((deprecated)) __attribute__((always_inline)) vP
* @deprecated This function is deprecated. Call spinlock_acquire() instead
* @param[in] mux Spinlock
*/
static inline void __attribute__((deprecated)) __attribute__((always_inline)) vPortCPUAcquireMutex(portMUX_TYPE *mux)
static inline void __attribute__((always_inline, deprecated)) vPortCPUAcquireMutex(portMUX_TYPE *mux)
{
spinlock_acquire(mux, portMUX_NO_TIMEOUT);
}

View File

@ -1,2 +1,7 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* This header file has been moved, please include <xtensa/xtensa_api.h> in future */
#include <xtensa/xtensa_api.h>

View File

@ -1,2 +1,7 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* This header file has been moved, please include <xtensa/xtensa_context.h> in future */
#include <xtensa/xtensa_context.h>

View File

@ -1,94 +1,323 @@
/*
* SPDX-FileCopyrightText: 2017 Amazon.com, Inc. or its affiliates
* SPDX-FileCopyrightText: 2015-2019 Cadence Design Systems, Inc.
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: MIT
*
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
*/
/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <xtensa/config/core.h>
#include <xtensa/xtensa_context.h>
#include "soc/soc_caps.h"
#include "esp_private/crosscore_int.h"
#include "FreeRTOS.h"
#include "task.h" //For vApplicationStackOverflowHook
#include "portmacro.h"
#include "spinlock.h"
#include "xt_instr_macros.h"
#include "xtensa/xtensa_context.h"
#include "xtensa/corebits.h"
#include "xtensa/config/core.h"
#include "xtensa/config/core-isa.h"
#include "xtensa/xtruntime.h"
#include "esp_heap_caps.h"
#include "esp_system.h"
#include "esp_task.h"
#include "esp_log.h"
#include "esp_int_wdt.h"
#ifdef CONFIG_APPTRACE_ENABLE
#include "esp_app_trace.h" /* Required for esp_apptrace_init. [refactor-todo] */
#endif
#include "FreeRTOS.h" /* This pulls in portmacro.h */
#include "task.h" /* Required for TaskHandle_t, tskNO_AFFINITY, and vTaskStartScheduler */
#include "port_systick.h"
#include "esp_cpu.h"
#include "esp_rom_sys.h"
#include "esp_int_wdt.h"
#include "esp_task_wdt.h"
#include "esp_heap_caps_init.h"
#include "esp_private/startup_internal.h" /* Required by g_spiram_ok. [refactor-todo] for g_spiram_ok */
#include "esp32/spiram.h" /* Required by esp_spiram_reserve_dma_pool() */
#ifdef CONFIG_APPTRACE_ENABLE
#include "esp_app_trace.h"
#endif
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
#include "esp_gdbstub.h" /* Required by esp_gdbstub_init() */
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
_Static_assert(tskNO_AFFINITY == CONFIG_FREERTOS_NO_AFFINITY, "incorrect tskNO_AFFINITY value");
/*
OS state variables
*/
volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0};
unsigned int port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit
//FreeRTOS SMP Locks
portMUX_TYPE port_xTaskLock = portMUX_INITIALIZER_UNLOCKED;
portMUX_TYPE port_xISRLock = portMUX_INITIALIZER_UNLOCKED;
/* ---------------------------------------------------- Variables ------------------------------------------------------
*
/* ------------------------------------------------ IDF Compatibility --------------------------------------------------
* - These need to be defined for IDF to compile
* ------------------------------------------------------------------------------------------------------------------ */
static const char *TAG = "cpu_start"; /* [refactor-todo]: might be appropriate to change in the future, but for now maintain the same log output */
extern volatile int port_xSchedulerRunning[portNUM_PROCESSORS];
unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit
BaseType_t port_uxCriticalNesting[portNUM_PROCESSORS] = {0};
BaseType_t port_uxOldInterruptState[portNUM_PROCESSORS] = {0};
// --------------------- Interrupts ------------------------
BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void)
{
return (port_interruptNesting[xPortGetCoreID()] != 0);
}
// ------------------ Critical Sections --------------------
/*
Variables used by IDF critical sections only (SMP tracks critical nesting inside TCB now)
[refactor-todo] Figure out how IDF critical sections will be merged with SMP FreeRTOS critical sections
*/
BaseType_t port_uxCriticalNestingIDF[portNUM_PROCESSORS] = {0};
BaseType_t port_uxCriticalOldInterruptStateIDF[portNUM_PROCESSORS] = {0};
BaseType_t xPortEnterCriticalTimeout(portMUX_TYPE *lock, BaseType_t timeout)
{
/* Interrupts may already be disabled (if this function is called in nested
* manner). However, there's no atomic operation that will allow us to check,
* thus we have to disable interrupts again anyways.
*
* However, if this is call is NOT nested (i.e., the first call to enter a
* critical section), we will save the previous interrupt level so that the
* saved level can be restored on the last call to exit the critical.
*/
BaseType_t xOldInterruptLevel = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);
if (!spinlock_acquire(lock, timeout)) {
//Timed out attempting to get spinlock. Restore previous interrupt level and return
XTOS_RESTORE_JUST_INTLEVEL((int) xOldInterruptLevel);
return pdFAIL;
}
//Spinlock acquired. Increment the IDF critical nesting count.
BaseType_t coreID = xPortGetCoreID();
BaseType_t newNesting = port_uxCriticalNestingIDF[coreID] + 1;
port_uxCriticalNestingIDF[coreID] = newNesting;
//If this is the first entry to a critical section. Save the old interrupt level.
if ( newNesting == 1 ) {
port_uxCriticalOldInterruptStateIDF[coreID] = xOldInterruptLevel;
}
return pdPASS;
}
void vPortExitCriticalIDF(portMUX_TYPE *lock)
{
/* This function may be called in a nested manner. Therefore, we only need
* to reenable interrupts if this is the last call to exit the critical. We
* can use the nesting count to determine whether this is the last exit call.
*/
spinlock_release(lock);
BaseType_t coreID = xPortGetCoreID();
BaseType_t nesting = port_uxCriticalNestingIDF[coreID];
if (nesting > 0) {
nesting--;
port_uxCriticalNestingIDF[coreID] = nesting;
//This is the last exit call, restore the saved interrupt level
if ( nesting == 0 ) {
XTOS_RESTORE_JUST_INTLEVEL((int) port_uxCriticalOldInterruptStateIDF[coreID]);
}
}
}
/*
In case any IDF libs called the port critical functions directly instead of through the macros.
Just inline call the IDF versions
*/
void vPortEnterCritical(portMUX_TYPE *lock)
{
vPortEnterCriticalIDF(lock);
}
void vPortExitCritical(portMUX_TYPE *lock)
{
vPortExitCriticalIDF(lock);
}
// ----------------------- System --------------------------
#define STACK_WATCH_POINT_NUMBER (SOC_CPU_WATCHPOINTS_NUM - 1)
void vPortSetStackWatchpoint( void *pxStackStart )
{
//Set watchpoint 1 to watch the last 32 bytes of the stack.
//Unfortunately, the Xtensa watchpoints can't set a watchpoint on a random [base - base+n] region because
//the size works by masking off the lowest address bits. For that reason, we futz a bit and watch the lowest 32
//bytes of the stack we can actually watch. In general, this can cause the watchpoint to be triggered at most
//28 bytes early. The value 32 is chosen because it's larger than the stack canary, which in FreeRTOS is 20 bytes.
//This way, we make sure we trigger before/when the stack canary is corrupted, not after.
int addr = (int)pxStackStart;
addr = (addr + 31) & (~31);
esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, 32, ESP_CPU_WATCHPOINT_STORE);
}
// ---------------------- Tick Timer -----------------------
extern void _frxt_tick_timer_init(void);
extern void _xt_tick_divisor_init(void);
/**
* @brief Initialize CCONT timer to generate the tick interrupt
*
*/
void vPortSetupTimer(void)
{
/* Init the tick divisor value */
_xt_tick_divisor_init();
_frxt_tick_timer_init();
}
// --------------------- App Start-up ----------------------
static const char *TAG = "cpu_start";
extern void app_main(void);
static void main_task(void* args)
{
#if !CONFIG_FREERTOS_UNICORE
// Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack
while (port_xSchedulerRunning[1] == 0) {
;
}
#endif
// [refactor-todo] check if there is a way to move the following block to esp_system startup
heap_caps_enable_nonos_stack_heaps();
// Now we have startup stack RAM available for heap, enable any DMA pool memory
#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
if (g_spiram_ok) {
esp_err_t r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
if (r != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool (error 0x%x)", r);
abort();
}
}
#endif
//Initialize task wdt if configured to do so
#ifdef CONFIG_ESP_TASK_WDT_PANIC
ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, true));
#elif CONFIG_ESP_TASK_WDT
ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false));
#endif
//Add IDLE 0 to task wdt
#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
if(idle_0 != NULL){
ESP_ERROR_CHECK(esp_task_wdt_add(idle_0));
}
#endif
//Add IDLE 1 to task wdt
#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
if(idle_1 != NULL){
ESP_ERROR_CHECK(esp_task_wdt_add(idle_1));
}
#endif
app_main();
vTaskDelete(NULL);
}
void esp_startup_start_app_common(void)
{
#if CONFIG_ESP_INT_WDT
esp_int_wdt_init();
//Initialize the interrupt watch dog for CPU0.
esp_int_wdt_cpu_init();
#endif
esp_crosscore_int_init();
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
esp_gdbstub_init();
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
TaskHandle_t main_task_hdl;
portDISABLE_INTERRUPTS();
portBASE_TYPE res = xTaskCreatePinnedToCore(main_task, "main",
ESP_TASK_MAIN_STACK, NULL,
ESP_TASK_MAIN_PRIO, &main_task_hdl, ESP_TASK_MAIN_CORE);
#if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 )
//We only need to set affinity when using dual core with affinities supported
vTaskCoreAffinitySet(main_task_hdl, 1 << 1);
#endif
portENABLE_INTERRUPTS();
assert(res == pdTRUE);
(void)res;
}
void esp_startup_start_app_other_cores(void)
{
// For now, we only support up to two core: 0 and 1.
if (xPortGetCoreID() >= 2) {
abort();
}
// Wait for FreeRTOS initialization to finish on PRO CPU
while (port_xSchedulerRunning[0] == 0) {
;
}
#if CONFIG_APPTRACE_ENABLE
// [refactor-todo] move to esp_system initialization
esp_err_t err = esp_apptrace_init();
assert(err == ESP_OK && "Failed to init apptrace module on APP CPU!");
#endif
#if CONFIG_ESP_INT_WDT
//Initialize the interrupt watch dog for CPU1.
esp_int_wdt_cpu_init();
#endif
esp_crosscore_int_init();
ESP_EARLY_LOGI(TAG, "Starting scheduler on APP CPU.");
xPortStartScheduler();
abort(); /* Only get to here if FreeRTOS somehow very broken */
}
void esp_startup_start_app(void)
{
#if !CONFIG_ESP_INT_WDT
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
assert(!soc_has_cache_lock_bug() && "ESP32 Rev 3 + Dual Core + PSRAM requires INT WDT enabled in project config!");
#endif
#endif
esp_startup_start_app_common();
ESP_EARLY_LOGI(TAG, "Starting scheduler on PRO CPU.");
vTaskStartScheduler();
}
/* ---------------------------------------------- Port Implementations -------------------------------------------------
* Implementations of Porting Interface functions
* ------------------------------------------------------------------------------------------------------------------ */
// --------------------- Interrupts ------------------------
BaseType_t xPortCheckIfInISR(void)
{
//Disable interrupts so that reading port_interruptNesting is atomic
BaseType_t ret;
unsigned int prev_int_level = portDISABLE_INTERRUPTS();
ret = (port_interruptNesting[xPortGetCoreID()] != 0) ? pdTRUE : pdFALSE;
portRESTORE_INTERRUPTS(prev_int_level);
return ret;
}
// ------------------ Critical Sections --------------------
void vPortTakeLock( portMUX_TYPE *lock )
{
spinlock_acquire( lock, portMUX_NO_TIMEOUT);
}
void vPortReleaseLock( portMUX_TYPE *lock )
{
spinlock_release( lock );
}
// ---------------------- Yielding -------------------------
// ----------------------- System --------------------------
/* ------------------------------------------------ FreeRTOS Portable --------------------------------------------------
* - Provides implementation for functions required by FreeRTOS
@ -97,7 +326,6 @@ BaseType_t port_uxOldInterruptState[portNUM_PROCESSORS] = {0};
// ----------------- Scheduler Start/End -------------------
/* Defined in xtensa_context.S */
extern void _xt_coproc_init(void);
BaseType_t xPortStartScheduler( void )
@ -124,11 +352,81 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void )
{
/* It is unlikely that the Xtensa port will get stopped. If required simply
disable the tick interrupt here. */
abort();
;
}
// ----------------------- Memory --------------------------
#define FREERTOS_SMP_MALLOC_CAPS (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
void *pvPortMalloc( size_t xSize )
{
return heap_caps_malloc(xSize, FREERTOS_SMP_MALLOC_CAPS);
}
void vPortFree( void * pv )
{
heap_caps_free(pv);
}
void vPortInitialiseBlocks( void )
{
; //Does nothing, heap is initialized separately in ESP-IDF
}
size_t xPortGetFreeHeapSize( void )
{
return esp_get_free_heap_size();
}
#if( configSTACK_ALLOCATION_FROM_SEPARATE_HEAP == 1 )
void *pvPortMallocStack( size_t xSize )
{
return NULL;
}
void vPortFreeStack( void *pv )
{
}
#endif
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize )
{
StaticTask_t *pxTCBBufferTemp;
StackType_t *pxStackBufferTemp;
//Allocate TCB and stack buffer in internal memory
pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
pxStackBufferTemp = pvPortMalloc(CONFIG_FREERTOS_IDLE_TASK_STACKSIZE);
assert(pxTCBBufferTemp != NULL);
assert(pxStackBufferTemp != NULL);
//Write back pointers
*ppxIdleTaskTCBBuffer = pxTCBBufferTemp;
*ppxIdleTaskStackBuffer = pxStackBufferTemp;
*pulIdleTaskStackSize = CONFIG_FREERTOS_IDLE_TASK_STACKSIZE;
}
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize )
{
StaticTask_t *pxTCBBufferTemp;
StackType_t *pxStackBufferTemp;
//Allocate TCB and stack buffer in internal memory
pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
pxStackBufferTemp = pvPortMalloc(configTIMER_TASK_STACK_DEPTH);
assert(pxTCBBufferTemp != NULL);
assert(pxStackBufferTemp != NULL);
//Write back pointers
*ppxTimerTaskTCBBuffer = pxTCBBufferTemp;
*ppxTimerTaskStackBuffer = pxStackBufferTemp;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
#endif //( configSUPPORT_STATIC_ALLOCATION == 1 )
// ------------------------ Stack --------------------------
// User exception dispatcher when exiting
@ -146,10 +444,17 @@ static void vPortTaskWrapper(TaskFunction_t pxCode, void *pvParameters)
}
#endif
#if portUSING_MPU_WRAPPERS
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
#if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged )
#else
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged )
#endif
{
StackType_t *sp, *tp;
@ -254,115 +559,37 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
return sp;
}
// -------------------- Tick Handler -----------------------
extern void esp_vApplicationIdleHook(void);
extern void esp_vApplicationTickHook(void);
/* ---------------------------------------------- Port Implementations -------------------------------------------------
*
* ------------------------------------------------------------------------------------------------------------------ */
// --------------------- Interrupts ------------------------
BaseType_t xPortInIsrContext(void)
BaseType_t xPortSysTickHandler(void)
{
unsigned int irqStatus;
portbenchmarkIntLatency();
traceISR_ENTER(SYSTICK_INTR_ID);
BaseType_t ret;
irqStatus = portSET_INTERRUPT_MASK_FROM_ISR();
ret = (port_interruptNesting[xPortGetCoreID()] != 0);
portCLEAR_INTERRUPT_MASK_FROM_ISR(irqStatus);
return ret;
}
void vPortAssertIfInISR(void)
{
configASSERT(xPortInIsrContext());
}
BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void)
{
return (port_interruptNesting[xPortGetCoreID()] != 0);
}
// ------------------ Critical Sections --------------------
BaseType_t __attribute__((optimize("-O3"))) xPortEnterCriticalTimeout(portMUX_TYPE *mux, BaseType_t timeout)
{
/* Interrupts may already be disabled (if this function is called in nested
* manner). However, there's no atomic operation that will allow us to check,
* thus we have to disable interrupts again anyways.
*
* However, if this is call is NOT nested (i.e., the first call to enter a
* critical section), we will save the previous interrupt level so that the
* saved level can be restored on the last call to exit the critical.
*/
BaseType_t xOldInterruptLevel = portSET_INTERRUPT_MASK_FROM_ISR();
if (!spinlock_acquire(mux, timeout)) {
//Timed out attempting to get spinlock. Restore previous interrupt level and return
portCLEAR_INTERRUPT_MASK_FROM_ISR(xOldInterruptLevel);
return pdFAIL;
}
//Spinlock acquired. Increment the critical nesting count.
BaseType_t coreID = xPortGetCoreID();
BaseType_t newNesting = port_uxCriticalNesting[coreID] + 1;
port_uxCriticalNesting[coreID] = newNesting;
//If this is the first entry to a critical section. Save the old interrupt level.
if ( newNesting == 1 ) {
port_uxOldInterruptState[coreID] = xOldInterruptLevel;
}
return pdPASS;
}
void __attribute__((optimize("-O3"))) vPortExitCritical(portMUX_TYPE *mux)
{
/* This function may be called in a nested manner. Therefore, we only need
* to reenable interrupts if this is the last call to exit the critical. We
* can use the nesting count to determine whether this is the last exit call.
*/
spinlock_release(mux);
BaseType_t coreID = xPortGetCoreID();
BaseType_t nesting = port_uxCriticalNesting[coreID];
if (nesting > 0) {
nesting--;
port_uxCriticalNesting[coreID] = nesting;
//This is the last exit call, restore the saved interrupt level
if ( nesting == 0 ) {
portCLEAR_INTERRUPT_MASK_FROM_ISR(port_uxOldInterruptState[coreID]);
}
}
}
BaseType_t xPortEnterCriticalTimeoutCompliance(portMUX_TYPE *mux, BaseType_t timeout)
{
BaseType_t ret;
if (!xPortInIsrContext()) {
ret = xPortEnterCriticalTimeout(mux, timeout);
if (portGET_CORE_ID() == 0) {
//Only Core 0 calls xTaskIncrementTick();
ret = xTaskIncrementTick();
} else {
esp_rom_printf("port*_CRITICAL called from ISR context. Aborting!\n");
abort();
ret = pdFAIL;
//Manually call the IDF tick hooks
esp_vApplicationTickHook();
ret = pdFALSE;
}
if(ret != pdFALSE) {
portYIELD_FROM_ISR();
} else {
traceISR_EXIT();
}
return ret;
}
void vPortExitCriticalCompliance(portMUX_TYPE *mux)
{
if (!xPortInIsrContext()) {
vPortExitCritical(mux);
} else {
esp_rom_printf("port*_CRITICAL called from ISR context. Aborting!\n");
abort();
}
}
// ---------------------- Yielding -------------------------
void vPortYieldOtherCore( BaseType_t coreid )
{
esp_crosscore_int_send_yield( coreid );
}
// ------------------- Hook Functions ----------------------
#include <stdlib.h>
#if ( configCHECK_FOR_STACK_OVERFLOW > 0 )
void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
{
#define ERR_STR1 "***ERROR*** A stack overflow in task "
@ -377,30 +604,28 @@ void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, c
}
esp_system_abort(buf);
}
#endif
// ----------------------- System --------------------------
uint32_t xPortGetTickRateHz(void)
#if ( configUSE_TICK_HOOK > 0 )
void vApplicationTickHook( void )
{
return (uint32_t)configTICK_RATE_HZ;
esp_vApplicationTickHook();
}
#endif
#define STACK_WATCH_AREA_SIZE 32
#define STACK_WATCH_POINT_NUMBER (SOC_CPU_WATCHPOINTS_NUM - 1)
void vPortSetStackWatchpoint( void *pxStackStart )
#if ( configUSE_IDLE_HOOK == 1 )
void vApplicationIdleHook( void )
{
//Set watchpoint 1 to watch the last 32 bytes of the stack.
//Unfortunately, the Xtensa watchpoints can't set a watchpoint on a random [base - base+n] region because
//the size works by masking off the lowest address bits. For that reason, we futz a bit and watch the lowest 32
//bytes of the stack we can actually watch. In general, this can cause the watchpoint to be triggered at most
//28 bytes early. The value 32 is chosen because it's larger than the stack canary, which in FreeRTOS is 20 bytes.
//This way, we make sure we trigger before/when the stack canary is corrupted, not after.
int addr = (int)pxStackStart;
addr = (addr + 31) & (~31);
esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, 32, ESP_CPU_WATCHPOINT_STORE);
esp_vApplicationIdleHook();
}
#endif
#if ( configUSE_MINIMAL_IDLE_HOOK == 1 )
void vApplicationMinimalIdleHook( void )
{
esp_vApplicationIdleHook();
}
#endif
/* ---------------------------------------------- Misc Implementations -------------------------------------------------
*
@ -432,53 +657,3 @@ void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings )
_xt_coproc_release( xMPUSettings->coproc_area );
}
#endif /* portUSING_MPU_WRAPPERS */
// --------------------- App Start-up ----------------------
#if !CONFIG_FREERTOS_UNICORE
void esp_startup_start_app_other_cores(void)
{
// For now, we only support up to two core: 0 and 1.
if (xPortGetCoreID() >= 2) {
abort();
}
// Wait for FreeRTOS initialization to finish on PRO CPU
while (port_xSchedulerRunning[0] == 0) {
;
}
#if CONFIG_APPTRACE_ENABLE
// [refactor-todo] move to esp_system initialization
esp_err_t err = esp_apptrace_init();
assert(err == ESP_OK && "Failed to init apptrace module on APP CPU!");
#endif
#if CONFIG_ESP_INT_WDT
//Initialize the interrupt watch dog for CPU1.
esp_int_wdt_cpu_init();
#endif
esp_crosscore_int_init();
ESP_EARLY_LOGI(TAG, "Starting scheduler on APP CPU.");
xPortStartScheduler();
abort(); /* Only get to here if FreeRTOS somehow very broken */
}
#endif // !CONFIG_FREERTOS_UNICORE
extern void esp_startup_start_app_common(void);
void esp_startup_start_app(void)
{
#if !CONFIG_ESP_INT_WDT
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
assert(!soc_has_cache_lock_bug() && "ESP32 Rev 3 + Dual Core + PSRAM requires INT WDT enabled in project config!");
#endif
#endif
esp_startup_start_app_common();
ESP_LOGI(TAG, "Starting scheduler on PRO CPU.");
vTaskStartScheduler();
}

View File

@ -34,7 +34,7 @@
#define TOPOFSTACK_OFFS 0x00 /* StackType_t *pxTopOfStack */
#define CP_TOPOFSTACK_OFFS 0x04 /* xMPU_SETTINGS.coproc_area */
.extern pxCurrentTCB
.extern pxCurrentTCBs
/*
*******************************************************************************
@ -125,11 +125,11 @@ _frxt_int_enter:
s32i a2, a3, 0 /* save nesting count */
bnei a2, 1, .Lnested /* !=0 before incr, so nested */
movi a2, pxCurrentTCB
movi a2, pxCurrentTCBs
addx4 a2, a4, a2
l32i a2, a2, 0 /* a2 = current TCB */
beqz a2, 1f
s32i a1, a2, TOPOFSTACK_OFFS /* pxCurrentTCB->pxTopOfStack = SP */
s32i a1, a2, TOPOFSTACK_OFFS /* pxCurrentTCBs->pxTopOfStack = SP */
movi a1, port_IntStack+configISR_STACK_SIZE /* a1 = top of intr stack for CPU 0 */
movi a2, configISR_STACK_SIZE /* add configISR_STACK_SIZE * cpu_num to arrive at top of stack for cpu_num */
mull a2, a4, a2
@ -198,11 +198,11 @@ _frxt_int_exit:
#endif
#endif
movi a2, pxCurrentTCB
movi a2, pxCurrentTCBs
addx4 a2, a4, a2
l32i a2, a2, 0 /* a2 = current TCB */
beqz a2, 1f /* no task ? go to dispatcher */
l32i a1, a2, TOPOFSTACK_OFFS /* SP = pxCurrentTCB->pxTopOfStack */
l32i a1, a2, TOPOFSTACK_OFFS /* SP = pxCurrentTCBs->pxTopOfStack */
movi a2, port_switch_flag /* address of switch flag */
addx4 a2, a4, a2 /* point to flag for this cpu */
@ -410,7 +410,7 @@ _frxt_tick_timer_init:
* If restoring a task that was preempted, restores all state including the task's CPENABLE.
*
* Entry:
* pxCurrentTCB points to the TCB of the task to suspend,
* pxCurrentTCBs points to the TCB of the task to suspend,
* Because it is tail-called without a true function entrypoint, it needs no 'entry' instruction.
*
* Exit:
@ -424,15 +424,18 @@ _frxt_tick_timer_init:
.align 4
_frxt_dispatch:
/* vTaskSwitchContext(xCoreID) now expects xCoreID as an argument, so the assembly calls below have been modified */
#ifdef __XTENSA_CALL0_ABI__
getcoreid a2 // vTaskSwitchContext requires xCoreID as the first argument
call0 vTaskSwitchContext // Get next TCB to resume
movi a2, pxCurrentTCB
getcoreid a3
getcoreid a3 // Get xCoreID again because a2 wasn't preserved over the call
movi a2, pxCurrentTCBs
addx4 a2, a3, a2
#else
getcoreid a6 // vTaskSwitchContext requires xCoreID as the first argument
call4 vTaskSwitchContext // Get next TCB to resume
movi a2, pxCurrentTCB
getcoreid a3
movi a2, pxCurrentTCBs
getcoreid a3 // Get xCoreID again because a6 wasn't preserved over the call
addx4 a2, a3, a2
#endif
l32i a3, a2, 0
@ -471,7 +474,7 @@ _frxt_dispatch:
#if XCHAL_CP_NUM > 0
/* Restore CPENABLE from task's co-processor save area. */
movi a3, pxCurrentTCB /* cp_state = */
movi a3, pxCurrentTCBs /* cp_state = */
getcoreid a2
addx4 a3, a2, a3
l32i a3, a3, 0
@ -512,7 +515,7 @@ _frxt_dispatch:
* then tail-calls the dispatcher _frxt_dispatch() to perform the actual context switch
*
* At Entry:
* pxCurrentTCB points to the TCB of the task to suspend
* pxCurrentTCBs points to the TCB of the task to suspend
* Callable from C (obeys ABI conventions on entry).
*
* Does not return to caller.
@ -560,17 +563,17 @@ vPortYield:
call0 _xt_coproc_savecs
#endif
movi a2, pxCurrentTCB
movi a2, pxCurrentTCBs
getcoreid a3
addx4 a2, a3, a2
l32i a2, a2, 0 /* a2 = pxCurrentTCB */
l32i a2, a2, 0 /* a2 = pxCurrentTCBs */
movi a3, 0
s32i a3, sp, XT_SOL_EXIT /* 0 to flag as solicited frame */
s32i sp, a2, TOPOFSTACK_OFFS /* pxCurrentTCB->pxTopOfStack = SP */
s32i sp, a2, TOPOFSTACK_OFFS /* pxCurrentTCBs->pxTopOfStack = SP */
#if XCHAL_CP_NUM > 0
/* Clear CPENABLE, also in task's co-processor state save area. */
l32i a2, a2, CP_TOPOFSTACK_OFFS /* a2 = pxCurrentTCB->cp_state */
l32i a2, a2, CP_TOPOFSTACK_OFFS /* a2 = pxCurrentTCBs->cp_state */
movi a3, 0
wsr a3, CPENABLE
beqz a2, 1f
@ -592,8 +595,8 @@ vPortYield:
* _frxt_dispatch() to perform the actual context switch.
*
* At Entry:
* Interrupted task context has been saved in an interrupt stack frame at pxCurrentTCB->pxTopOfStack.
* pxCurrentTCB points to the TCB of the task to suspend,
* Interrupted task context has been saved in an interrupt stack frame at pxCurrentTCBs->pxTopOfStack.
* pxCurrentTCBs points to the TCB of the task to suspend,
* Callable from C (obeys ABI conventions on entry).
*
* At Exit:
@ -611,7 +614,7 @@ vPortYieldFromInt:
#if XCHAL_CP_NUM > 0
/* Save CPENABLE in task's co-processor save area, and clear CPENABLE. */
movi a3, pxCurrentTCB /* cp_state = */
movi a3, pxCurrentTCBs /* cp_state = */
getcoreid a2
addx4 a3, a2, a3
l32i a3, a3, 0
@ -665,9 +668,9 @@ _frxt_task_coproc_state:
l32i a15, a15, 0
bnez a15, 1f
movi a15, pxCurrentTCB
movi a15, pxCurrentTCBs
addx4 a15, a3, a15
l32i a15, a15, 0 /* && pxCurrentTCB != 0) { */
l32i a15, a15, 0 /* && pxCurrentTCBs != 0) { */
beqz a15, 2f
l32i a15, a15, CP_TOPOFSTACK_OFFS

View File

@ -108,7 +108,7 @@
Please change this when the tcb structure is changed
*/
#define TASKTCB_XCOREID_OFFSET (0x38+configMAX_TASK_NAME_LEN+3)&~3
.extern pxCurrentTCB
.extern pxCurrentTCBs
/*
--------------------------------------------------------------------------------
@ -924,10 +924,10 @@ _xt_coproc_exc:
/* FPU operations are incompatible with non-pinned tasks. If we have a FPU operation
here, to keep the entire thing from crashing, it's better to pin the task to whatever
core we're running on now. */
movi a2, pxCurrentTCB
movi a2, pxCurrentTCBs
getcoreid a3
addx4 a2, a3, a2
l32i a2, a2, 0 /* a2 = start of pxCurrentTCB[cpuid] */
l32i a2, a2, 0 /* a2 = start of pxCurrentTCBs[cpuid] */
addi a2, a2, TASKTCB_XCOREID_OFFSET /* offset to xCoreID in tcb struct */
s32i a3, a2, 0 /* store current cpuid */

View File

@ -17,6 +17,13 @@ This file get's pulled into assembly sources. Therefore, some includes need to b
#include <assert.h> //For configASSERT()
#endif /* def __ASSEMBLER__ */
#ifdef CONFIG_FREERTOS_SMP
// Pull in the SMP configuration
#include "freertos/FreeRTOSConfig_smp.h"
#else // CONFIG_FREERTOS_SMP
// The arch-specific FreeRTOSConfig_arch.h in port/<arch>/include.
#include "freertos/FreeRTOSConfig_arch.h"
@ -263,4 +270,6 @@ extern void vPortCleanUpTCB ( void *pxTCB );
// backward compatibility for 4.4
#define xTaskRemoveFromUnorderedEventList vTaskRemoveFromUnorderedEventList
#endif // CONFIG_FREERTOS_SMP
#endif /* FREERTOS_CONFIG_H */

View File

@ -1,126 +1,130 @@
[mapping:freertos]
archive: libfreertos.a
entries:
* (noflash_text)
if FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH = y:
task_snapshot (default)
if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
port: pxPortInitialiseStack (default)
port: xPortStartScheduler (default)
if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S3 = y :
port: vPortReleaseTaskMPUSettings (default)
tasks: xTaskCreateRestricted (default)
port: vPortStoreTaskMPUSettings (default)
tasks: vTaskAllocateMPURegions (default)
tasks: prvTaskCheckFreeStackSpace (default)
tasks: prvInitialiseNewTask (default)
tasks: prvInitialiseTaskLists (default)
tasks: prvDeleteTCB (default)
tasks: prvCheckTasksWaitingTermination (default)
tasks: prvIdleTask (default)
tasks: prvAddNewTaskToReadyList (default)
tasks: xTaskCreatePinnedToCore (default)
tasks: xTaskCreateStaticPinnedToCore (default)
tasks: vTaskResume (default)
tasks: vTaskStartScheduler (default)
tasks: vTaskSuspendAll (default)
tasks: uxTaskGetNumberOfTasks (default)
tasks: xTaskGetIdleTaskHandle (default)
tasks: vTaskRemoveFromUnorderedEventList (default)
tasks: uxTaskPriorityGet (default)
tasks: vTaskPrioritySet (default)
tasks: vTaskSetThreadLocalStoragePointerAndDelCallback (default)
tasks: pvTaskGetThreadLocalStoragePointer (default)
tasks: xTaskGetCurrentTaskHandleForCPU (default)
tasks: vTaskDelete (default)
tasks: vTaskDelayUntil (default)
tasks: xTaskDelayUntil (default)
tasks: vTaskDelay (default)
tasks: vTaskSuspend (default)
tasks: xTaskResumeAll (default)
tasks: uxTaskResetEventItemValue (default)
tasks: ulTaskNotifyTake (default)
tasks: ulTaskGenericNotifyTake (default)
tasks: xTaskNotifyWait (default)
tasks: xTaskGenericNotifyWait (default)
tasks: xTaskGenericNotify (default)
tasks: eTaskGetState (default)
tasks: pxTaskGetStackStart (default)
tasks: uxTaskGetStackHighWaterMark (default)
tasks: vTaskEndScheduler (default)
tasks: vTaskMissedYield (default)
tasks: vTaskSetThreadLocalStoragePointer (default)
tasks: xTaskGetAffinity (default)
tasks: xTaskGetIdleTaskHandleForCPU (default)
if FREERTOS_USE_TRACE_FACILITY = y:
tasks: uxTaskGetSystemState (default)
tasks: uxTaskGetTaskNumber (default)
tasks: vTaskSetTaskNumber (default)
if FREERTOS_USE_STATS_FORMATTING_FUNCTIONS = y:
tasks: vTaskList (default)
if FREERTOS_GENERATE_RUN_TIME_STATS = y:
tasks: vTaskGetRunTimeStats (default)
timers: prvInsertTimerInActiveList (default)
timers: prvCheckForValidListAndQueue (default)
timers: prvInitialiseNewTimer (default)
timers: prvTimerTask (default)
timers: prvSwitchTimerLists (default)
timers: prvSampleTimeNow (default)
timers: prvProcessExpiredTimer (default)
timers: prvProcessTimerOrBlockTask (default)
timers: prvProcessReceivedCommands (default)
timers: xTimerCreateTimerTask (default)
timers: xTimerCreate (default)
timers: xTimerCreateStatic (default)
timers: xTimerGenericCommand (default)
timers: xTimerGetPeriod (default)
timers: xTimerGetExpiryTime (default)
timers: xTimerIsTimerActive (default)
timers: pvTimerGetTimerID (default)
timers: vTimerSetTimerID (default)
timers: prvGetNextExpireTime (default)
if FREERTOS_USE_TRACE_FACILITY = y:
timers: uxTimerGetTimerNumber (default)
timers: vTimerSetTimerNumber (default)
event_groups: prvTestWaitCondition (default)
event_groups: xEventGroupCreate (default)
event_groups: xEventGroupCreateStatic (default)
event_groups: xEventGroupWaitBits (default)
event_groups: xEventGroupClearBits (default)
event_groups: xEventGroupSetBits (default)
event_groups: xEventGroupSync (default)
event_groups: vEventGroupDelete (default)
queue: prvIsQueueFull (default)
queue: prvInitialiseNewQueue (default)
queue: prvInitialiseMutex (default)
queue: uxQueueSpacesAvailable (default)
queue: xQueueGenericReset (default)
queue: xQueueGenericCreate (default)
queue: xQueueGetMutexHolder (default)
queue: xQueueCreateCountingSemaphore (default)
queue: xQueueGenericSend (default)
queue: xQueueCreateMutex (default)
queue: xQueueGiveMutexRecursive (default)
queue: xQueueTakeMutexRecursive (default)
queue: uxQueueMessagesWaiting (default)
queue: vQueueDelete (default)
queue: vQueueWaitForMessageRestricted (default)
queue: xQueueCreateSet (default)
queue: xQueueAddToSet (default)
queue: xQueueRemoveFromSet (default)
queue: xQueueSelectFromSet (default)
queue: xQueueGenericCreateStatic (default)
queue: xQueueCreateMutexStatic (default)
queue: xQueueCreateCountingSemaphoreStatic (default)
if FREERTOS_QUEUE_REGISTRY_SIZE > 0:
queue: pcQueueGetName (default)
queue: vQueueAddToRegistry (default)
queue: vQueueUnregisterQueue (default)
if FREERTOS_USE_TRACE_FACILITY = y:
queue: uxQueueGetQueueNumber (default)
queue: vQueueSetQueueNumber (default)
queue: ucQueueGetQueueType (default)
port_common:main_task (default)
port:esp_startup_start_app (default)
if ESP_SYSTEM_SINGLE_CORE_MODE = n:
port:esp_startup_start_app_other_cores (default)
if FREERTOS_SMP = y:
# Currently no linker conditions for FreeRTOS SMP
* (noflash_text)
else:
* (noflash_text)
if FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH = y:
task_snapshot (default)
if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
port: pxPortInitialiseStack (default)
port: xPortStartScheduler (default)
if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S3 = y :
port: vPortReleaseTaskMPUSettings (default)
tasks: xTaskCreateRestricted (default)
port: vPortStoreTaskMPUSettings (default)
tasks: vTaskAllocateMPURegions (default)
tasks: prvTaskCheckFreeStackSpace (default)
tasks: prvInitialiseNewTask (default)
tasks: prvInitialiseTaskLists (default)
tasks: prvDeleteTCB (default)
tasks: prvCheckTasksWaitingTermination (default)
tasks: prvIdleTask (default)
tasks: prvAddNewTaskToReadyList (default)
tasks: xTaskCreatePinnedToCore (default)
tasks: xTaskCreateStaticPinnedToCore (default)
tasks: vTaskResume (default)
tasks: vTaskStartScheduler (default)
tasks: vTaskSuspendAll (default)
tasks: uxTaskGetNumberOfTasks (default)
tasks: xTaskGetIdleTaskHandle (default)
tasks: vTaskRemoveFromUnorderedEventList (default)
tasks: uxTaskPriorityGet (default)
tasks: vTaskPrioritySet (default)
tasks: vTaskSetThreadLocalStoragePointerAndDelCallback (default)
tasks: pvTaskGetThreadLocalStoragePointer (default)
tasks: xTaskGetCurrentTaskHandleForCPU (default)
tasks: vTaskDelete (default)
tasks: vTaskDelayUntil (default)
tasks: xTaskDelayUntil (default)
tasks: vTaskDelay (default)
tasks: vTaskSuspend (default)
tasks: xTaskResumeAll (default)
tasks: uxTaskResetEventItemValue (default)
tasks: ulTaskNotifyTake (default)
tasks: ulTaskGenericNotifyTake (default)
tasks: xTaskNotifyWait (default)
tasks: xTaskGenericNotifyWait (default)
tasks: xTaskGenericNotify (default)
tasks: eTaskGetState (default)
tasks: pxTaskGetStackStart (default)
tasks: uxTaskGetStackHighWaterMark (default)
tasks: vTaskEndScheduler (default)
tasks: vTaskMissedYield (default)
tasks: vTaskSetThreadLocalStoragePointer (default)
tasks: xTaskGetAffinity (default)
tasks: xTaskGetIdleTaskHandleForCPU (default)
if FREERTOS_USE_TRACE_FACILITY = y:
tasks: uxTaskGetSystemState (default)
tasks: uxTaskGetTaskNumber (default)
tasks: vTaskSetTaskNumber (default)
if FREERTOS_USE_STATS_FORMATTING_FUNCTIONS = y:
tasks: vTaskList (default)
if FREERTOS_GENERATE_RUN_TIME_STATS = y:
tasks: vTaskGetRunTimeStats (default)
timers: prvInsertTimerInActiveList (default)
timers: prvCheckForValidListAndQueue (default)
timers: prvInitialiseNewTimer (default)
timers: prvTimerTask (default)
timers: prvSwitchTimerLists (default)
timers: prvSampleTimeNow (default)
timers: prvProcessExpiredTimer (default)
timers: prvProcessTimerOrBlockTask (default)
timers: prvProcessReceivedCommands (default)
timers: xTimerCreateTimerTask (default)
timers: xTimerCreate (default)
timers: xTimerCreateStatic (default)
timers: xTimerGenericCommand (default)
timers: xTimerGetPeriod (default)
timers: xTimerGetExpiryTime (default)
timers: xTimerIsTimerActive (default)
timers: pvTimerGetTimerID (default)
timers: vTimerSetTimerID (default)
timers: prvGetNextExpireTime (default)
if FREERTOS_USE_TRACE_FACILITY = y:
timers: uxTimerGetTimerNumber (default)
timers: vTimerSetTimerNumber (default)
event_groups: prvTestWaitCondition (default)
event_groups: xEventGroupCreate (default)
event_groups: xEventGroupCreateStatic (default)
event_groups: xEventGroupWaitBits (default)
event_groups: xEventGroupClearBits (default)
event_groups: xEventGroupSetBits (default)
event_groups: xEventGroupSync (default)
event_groups: vEventGroupDelete (default)
queue: prvIsQueueFull (default)
queue: prvInitialiseNewQueue (default)
queue: prvInitialiseMutex (default)
queue: uxQueueSpacesAvailable (default)
queue: xQueueGenericReset (default)
queue: xQueueGenericCreate (default)
queue: xQueueGetMutexHolder (default)
queue: xQueueCreateCountingSemaphore (default)
queue: xQueueGenericSend (default)
queue: xQueueCreateMutex (default)
queue: xQueueGiveMutexRecursive (default)
queue: xQueueTakeMutexRecursive (default)
queue: uxQueueMessagesWaiting (default)
queue: vQueueDelete (default)
queue: vQueueWaitForMessageRestricted (default)
queue: xQueueCreateSet (default)
queue: xQueueAddToSet (default)
queue: xQueueRemoveFromSet (default)
queue: xQueueSelectFromSet (default)
queue: xQueueGenericCreateStatic (default)
queue: xQueueCreateMutexStatic (default)
queue: xQueueCreateCountingSemaphoreStatic (default)
if FREERTOS_QUEUE_REGISTRY_SIZE > 0:
queue: pcQueueGetName (default)
queue: vQueueAddToRegistry (default)
queue: vQueueUnregisterQueue (default)
if FREERTOS_USE_TRACE_FACILITY = y:
queue: uxQueueGetQueueNumber (default)
queue: vQueueSetQueueNumber (default)
queue: ucQueueGetQueueType (default)
port_common:main_task (default)
port:esp_startup_start_app (default)
if ESP_SYSTEM_SINGLE_CORE_MODE = n:
port:esp_startup_start_app_other_cores (default)