diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/FreeRTOSConfig_smp.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/FreeRTOSConfig_smp.h new file mode 100644 index 0000000000..6626101312 --- /dev/null +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/FreeRTOSConfig_smp.h @@ -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 //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 */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h index b016f8c9df..be1edd2a2f 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h @@ -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 -#include -#include -#include -#include -#include /* required for xthal_get_ccount. [refactor-todo] use cpu_hal instead */ -#include /* 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 -#include -#include +/* +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 +#include +#include +#include +#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 +#include +#include #ifdef __cplusplus } #endif - -#endif // __ASSEMBLER__ - -#endif /* PORTMACRO_H */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro_deprecated.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro_deprecated.h index 378617c73a..4b3379a6fc 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro_deprecated.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro_deprecated.h @@ -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); } diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_api.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_api.h index bd2bfeb208..42a8aeec82 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_api.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_api.h @@ -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 in future */ #include diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_context.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_context.h index 45c4272869..9e3c4d9074 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_context.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/xtensa_context.h @@ -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 in future */ #include diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c index 15729559ff..029275b4da 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c @@ -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 -#include #include -#include -#include -#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 + +#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(); -} diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/portasm.S b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/portasm.S index 27b76d97b4..6719e6b07e 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/portasm.S +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/portasm.S @@ -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 diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_vectors.S b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_vectors.S index e70de48ba0..1d29edf48a 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_vectors.S +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/xtensa_vectors.S @@ -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 */ diff --git a/components/freertos/esp_additions/include/freertos/FreeRTOSConfig.h b/components/freertos/esp_additions/include/freertos/FreeRTOSConfig.h index d4bd304db6..8bdb5f4c18 100644 --- a/components/freertos/esp_additions/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/esp_additions/include/freertos/FreeRTOSConfig.h @@ -17,6 +17,13 @@ This file get's pulled into assembly sources. Therefore, some includes need to b #include //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//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 */ diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index de2027dd92..f10057ef34 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -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)