Explorar el Código

Merge branch 'refactor/freertos_port_malloc_macros' into 'master'

FreeRTOS(IDF): Refactor pvPortMalloc()/vPortFree(), Implement IDF heap wrapper for FreeRTOS.

Closes IDF-3997

See merge request espressif/esp-idf!22565
Darian hace 2 años
padre
commit
daf4150846

+ 1 - 0
components/freertos/CMakeLists.txt

@@ -21,6 +21,7 @@ set(arch "linux")
 endif()
 
 set(srcs
+    "heap_idf.c"
     "${kernel_dir}/list.c"
     "${kernel_dir}/queue.c"
     "${kernel_dir}/tasks.c"

+ 26 - 9
components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -286,15 +286,32 @@ static inline bool IRAM_ATTR xPortCanYield(void)
 
 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
+// -------------------- Heap Related -----------------------
+
+/**
+ * @brief Checks if a given piece of memory can be used to store a task's TCB
+ *
+ * - Defined in heap_idf.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 heap_idf.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 portTcbMemoryCaps               (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
-#define portStackMemoryCaps             (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
+#define portVALID_TCB_MEM(ptr)      xPortCheckValidTCBMem(ptr)
+#define portVALID_STACK_MEM(ptr)    xPortcheckValidStackMem(ptr)
 
 /* ------------------------------------------------------ Misc ---------------------------------------------------------
  * - Miscellaneous porting macros

+ 0 - 36
components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c

@@ -349,42 +349,6 @@ void vPortEndScheduler(void)
     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
-
 // ------------------------ Stack --------------------------
 
 /**

+ 26 - 9
components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -352,15 +352,32 @@ static inline bool IRAM_ATTR xPortCanYield(void)
 
 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
+// -------------------- Heap Related -----------------------
+
+/**
+ * @brief Checks if a given piece of memory can be used to store a task's TCB
+ *
+ * - Defined in heap_idf.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 heap_idf.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 portTcbMemoryCaps               (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
-#define portStackMemoryCaps             (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
+#define portVALID_TCB_MEM(ptr)      xPortCheckValidTCBMem(ptr)
+#define portVALID_STACK_MEM(ptr)    xPortcheckValidStackMem(ptr)
 
 // --------------- Compatibility Includes ------------------
 /*

+ 0 - 36
components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c

@@ -386,42 +386,6 @@ void vPortEndScheduler( void )
     ;
 }
 
-// ----------------------- 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
-
 // ------------------------ Stack --------------------------
 
 // User exception dispatcher when exiting

+ 0 - 25
components/freertos/FreeRTOS-Kernel/include/freertos/portable.h

@@ -139,8 +139,6 @@
     #endif
 #endif /* if ( portUSING_MPU_WRAPPERS == 1 ) */
 
-#ifdef configUSE_FREERTOS_PROVIDED_HEAP
-
 /* Used by heap_5.c to define the start address and size of each memory region
  * that together comprise the total FreeRTOS heap space. */
 typedef struct HeapRegion
@@ -189,29 +187,6 @@ void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
 size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
 size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
 
-#if( configSTACK_ALLOCATION_FROM_SEPARATE_HEAP == 1 )
-    void *pvPortMallocStack( size_t xSize ) PRIVILEGED_FUNCTION;
-    void vPortFreeStack( void *pv ) PRIVILEGED_FUNCTION;
-#else
-    #define pvPortMallocStack pvPortMalloc
-    #define vPortFreeStack vPortFree
-#endif
-#else  // configUSE_FREERTOS_PROVIDED_HEAP
-
-/*
- * Map to the memory management routines required for the port.
- *
- * Note that libc standard malloc/free are also available for
- * non-FreeRTOS-specific code, and behave the same as
- * pvPortMalloc()/vPortFree().
- */
-#define pvPortMalloc malloc
-#define vPortFree free
-#define xPortGetFreeHeapSize esp_get_free_heap_size
-#define xPortGetMinimumEverFreeHeapSize esp_get_minimum_free_heap_size
-
-#endif
-
 /*
  * Setup the hardware ready for the scheduler to take control.  This generally
  * sets up a tick interrupt and sets timers for the correct tick frequency.

+ 22 - 10
components/freertos/FreeRTOS-Kernel/portable/linux/include/freertos/portmacro_idf.h

@@ -51,18 +51,30 @@ static inline BaseType_t IRAM_ATTR xPortGetCoreID(void)
     return (BaseType_t) 0;
 }
 
-static inline bool portVALID_TCB_MEM(const void *ptr)
-{
-    return true;
-}
+/**
+ * @brief Checks if a given piece of memory can be used to store a task's TCB
+ *
+ * - Defined in heap_idf.c
+ *
+ * @param ptr Pointer to memory
+ * @return true Memory can be used to store a TCB
+ * @return false Otherwise
+ */
+bool xPortCheckValidTCBMem(const void *ptr);
 
-static inline bool portVALID_STACK_MEM(const void *ptr)
-{
-    return true;
-}
+/**
+ * @brief Checks if a given piece of memory can be used to store a task's stack
+ *
+ * - Defined in heap_idf.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 pvPortMallocTcbMem(size)        pvPortMalloc(size)
-#define pvPortMallocStackMem(size)      pvPortMalloc(size)
+#define portVALID_TCB_MEM(ptr)      xPortCheckValidTCBMem(ptr)
+#define portVALID_STACK_MEM(ptr)    xPortcheckValidStackMem(ptr)
 
 BaseType_t xPortCheckIfInISR(void);
 

+ 4 - 18
components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h

@@ -303,20 +303,6 @@ FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void)
  * - Maps to forward 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)        pvPortMalloc(size)
-#define pvPortMallocStackMem(size)      pvPortMalloc(size)
-
 // --------------------- Interrupts ------------------------
 
 #define portDISABLE_INTERRUPTS()            portSET_INTERRUPT_MASK_FROM_ISR()
@@ -446,7 +432,7 @@ FORCE_INLINE_ATTR bool xPortCanYield(void)
 /**
  * @brief Checks if a given piece of memory can be used to store a task's TCB
  *
- * - Defined in port_common.c
+ * - Defined in heap_idf.c
  *
  * @param ptr Pointer to memory
  * @return true Memory can be used to store a TCB
@@ -457,7 +443,7 @@ 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
+ * - Defined in heap_idf.c
  *
  * @param ptr Pointer to memory
  * @return true Memory can be used to store a task stack
@@ -465,8 +451,8 @@ bool xPortCheckValidTCBMem(const void *ptr);
  */
 bool xPortcheckValidStackMem(const void *ptr);
 
-#define portVALID_TCB_MEM(ptr) xPortCheckValidTCBMem(ptr)
-#define portVALID_STACK_MEM(ptr) xPortcheckValidStackMem(ptr)
+#define portVALID_TCB_MEM(ptr)      xPortCheckValidTCBMem(ptr)
+#define portVALID_STACK_MEM(ptr)    xPortcheckValidStackMem(ptr)
 
 // --------------------- App-Trace -------------------------
 

+ 4 - 18
components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h

@@ -414,20 +414,6 @@ FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void);
  * - Maps to forward 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 ------------------------
 
 /**
@@ -656,7 +642,7 @@ void vPortCleanUpCoprocArea(void *pvTCB);
 /**
  * @brief Checks if a given piece of memory can be used to store a task's TCB
  *
- * - Defined in port_common.c
+ * - Defined in heap_idf.c
  *
  * @param ptr Pointer to memory
  * @return true Memory can be used to store a TCB
@@ -667,7 +653,7 @@ 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
+ * - Defined in heap_idf.c
  *
  * @param ptr Pointer to memory
  * @return true Memory can be used to store a task stack
@@ -675,8 +661,8 @@ bool xPortCheckValidTCBMem(const void *ptr);
  */
 bool xPortcheckValidStackMem(const void *ptr);
 
-#define portVALID_TCB_MEM(ptr) xPortCheckValidTCBMem(ptr)
-#define portVALID_STACK_MEM(ptr) xPortcheckValidStackMem(ptr)
+#define portVALID_TCB_MEM(ptr)      xPortCheckValidTCBMem(ptr)
+#define portVALID_STACK_MEM(ptr)    xPortcheckValidStackMem(ptr)
 
 // --------------------- App-Trace -------------------------
 

+ 5 - 5
components/freertos/FreeRTOS-Kernel/tasks.c

@@ -820,7 +820,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
             /* Allocate space for the TCB.  Where the memory comes from depends
              * on the implementation of the port malloc function and whether or
              * not static allocation is being used. */
-            pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) );
+            pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
 
             if( pxNewTCB != NULL )
             {
@@ -877,14 +877,14 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
                 /* Allocate space for the TCB.  Where the memory comes from depends on
                  * the implementation of the port malloc function and whether or not static
                  * allocation is being used. */
-                pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) );
+                pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
 
                 if( pxNewTCB != NULL )
                 {
                     /* Allocate space for the stack used by the task being created.
                      * The base of the stack memory stored in the TCB so the task can
                      * be deleted later if required. */
-                    pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStackMem( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+                    pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
 
                     if( pxNewTCB->pxStack == NULL )
                     {
@@ -899,12 +899,12 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
                 StackType_t * pxStack;
 
                 /* Allocate space for the stack used by the task being created. */
-                pxStack = pvPortMallocStackMem( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
+                pxStack = pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
 
                 if( pxStack != NULL )
                 {
                     /* Allocate space for the TCB. */
-                    pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
+                    pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
 
                     if( pxNewTCB != NULL )
                     {

+ 127 - 0
components/freertos/heap_idf.c

@@ -0,0 +1,127 @@
+/*
+ * SPDX-FileCopyrightText: 2020 Amazon.com, Inc. or its affiliates
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD
+ */
+
+/*
+ * FreeRTOS Kernel V10.4.3
+ * Copyright (C) 2020 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.
+ *
+ * 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
+ *
+ */
+
+#include "sdkconfig.h"
+
+/* This file implements the heap related functions that are called by FreeRTOS.
+ * ESP-IDF provides its own heap containing memory with different capabilities
+ * (see esp_heap_caps.h). Thus, this file maps a subset of the ESP-IDF heap to
+ * act as the FreeRTOS heap.
+ *
+ * All dynamic allocation done by FreeRTOS should be placed in internal 8-bit
+ * accessible RAM (i.e., using the MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT flags).
+ * This is due to the fact that FreeRTOS objects (e.g., task stacks, TCBs,
+ * queues etc) must be accessible even if the cache is disabled. Therefore, the
+ * heap that is made available to FreeRTOS for dynamic allocation is a subset of
+ * the ESP-IDF heap (where all MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT memory is
+ * made available to FreeRTOS for dynamic allocation).
+ */
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+ * all the API functions to use the MPU wrappers.  That should only be done when
+ * task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
+    #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
+#endif
+
+#include "esp_heap_caps.h"
+
+#if !CONFIG_IDF_TARGET_LINUX
+    /* Memory util functions are not implemented in the Linux simulator */
+    #include "esp_memory_utils.h"
+#endif /* CONFIG_IDF_TARGET_LINUX */
+
+#define portFREERTOS_HEAP_CAPS    ( MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT )
+
+/*-----------------------------------------------------------*/
+
+void * pvPortMalloc( size_t xWantedSize )
+{
+    void * pvReturn = NULL;
+
+    /* All dynamic allocation done by FreeRTOS goes through this function. If
+     * users need to allocate FreeRTOS objects into external RAM, they should
+     * use the "static" equivalents of FreeRTOS API to create FreeRTOS objects
+     * (e.g., queues). */
+    pvReturn = heap_caps_malloc( xWantedSize, portFREERTOS_HEAP_CAPS );
+
+    return pvReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vPortFree( void * pv )
+{
+    heap_caps_free( pv );
+}
+/*-----------------------------------------------------------*/
+
+size_t xPortGetFreeHeapSize( void )
+{
+    return heap_caps_get_free_size( portFREERTOS_HEAP_CAPS );
+}
+/*-----------------------------------------------------------*/
+
+size_t xPortGetMinimumEverFreeHeapSize( void )
+{
+    return heap_caps_get_minimum_free_size( portFREERTOS_HEAP_CAPS );
+}
+/*-----------------------------------------------------------*/
+
+bool xPortCheckValidTCBMem(const void *ptr)
+{
+    #if CONFIG_IDF_TARGET_LINUX
+        return true;
+    #else /* CONFIG_IDF_TARGET_LINUX */
+        return esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr);
+    #endif /* CONFIG_IDF_TARGET_LINUX */
+}
+
+bool xPortcheckValidStackMem(const void *ptr)
+{
+    #if CONFIG_IDF_TARGET_LINUX
+        return true;
+    #else /* CONFIG_IDF_TARGET_LINUX */
+        #ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
+            return esp_ptr_byte_accessible(ptr);
+        #else
+            return esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr);
+        #endif
+    #endif /* CONFIG_IDF_TARGET_LINUX */
+}

+ 17 - 3
components/freertos/linker_common.lf

@@ -46,6 +46,23 @@ entries:
     # ------------------------------------------------------------------------------------------------------------------
     FreeRTOS-openocd (noflash)
 
+    # ------------------------------------------------------------------------------------------------------------------
+    # heap_idf.c
+    # Placement Rules:
+    #   - Default: Place all functions in internal RAM.
+    #   - CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH: Place functions in flash if they are never called from an ISR
+    #     context (directly or indirectly).
+    # ------------------------------------------------------------------------------------------------------------------
+    heap_idf (noflash_text)         # Default all functions to internal RAM
+    if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
+        heap_idf:pvPortMalloc (default)
+        heap_idf:vPortFree (default)
+        heap_idf:xPortGetFreeHeapSize (default)
+        heap_idf:xPortGetMinimumEverFreeHeapSize (default)
+        if FREERTOS_SMP = n:
+            heap_idf:xPortCheckValidTCBMem (default)
+            heap_idf:xPortcheckValidStackMem (default)
+
     # ------------------------------------------------------------------------------------------------------------------
     # port_common.c
     # Placement Rules:
@@ -55,8 +72,5 @@ entries:
     # ------------------------------------------------------------------------------------------------------------------
     port_common (noflash_text)      # Default all functions to internal RAM
     if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
-        if FREERTOS_SMP = n:
-            port_common:xPortCheckValidTCBMem (default)
-            port_common:xPortcheckValidStackMem (default)
         port_common:vApplicationGetIdleTaskMemory (default)
         port_common:vApplicationGetTimerTaskMemory (default)

+ 15 - 54
components/freertos/port_common.c

@@ -16,32 +16,13 @@
  * - These functions are common to all FreeRTOS ports (i.e., on all architectures and all FreeRTOS implementations).
  * ------------------------------------------------------------------------------------------------------------------ */
 
-// -------------------- Heap Related -----------------------
-
-#if !CONFIG_FREERTOS_SMP    // IDF-3997
-bool xPortCheckValidTCBMem(const void *ptr)
-{
-    return esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr);
-}
-
-bool xPortcheckValidStackMem(const void *ptr)
-{
-#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
-    return esp_ptr_byte_accessible(ptr);
-#else
-    return esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr);
-#endif
-}
-#endif
-
 // ------------- FreeRTOS Static Allocation ----------------
 
 /*
 These function are required by FreeRTOS when configSUPPORT_STATIC_ALLOCATION is
 enabled and is used by FreeRTOS to obtain memory for its IDLE/Timer tasks.
 
-Like the pvPortMallocTcbMem() and pvPortMallocStackMem() macros, TCB and stack
-memory MUST be placed in internal RAM.
+We simply allocate the IDLE/Timer tasks memory from the FreeRTOS heap.
 */
 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
 void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
@@ -51,30 +32,20 @@ void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
     StaticTask_t *pxTCBBufferTemp;
     StackType_t *pxStackBufferTemp;
 
-    /* If the stack grows down then allocate the stack then the TCB so the stack
+    /* Allocate TCB and stack buffer from the FreeRTOS heap
+     *
+     * If the stack grows down then allocate the stack then the TCB so the stack
      * does not grow into the TCB.  Likewise if the stack grows up then allocate
      * the TCB then the stack. */
     #if (portSTACK_GROWTH > 0)
     {
-        //Allocate TCB and stack buffer in internal memory
-        #if CONFIG_FREERTOS_SMP     // IDF-3997
-            pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
-            pxStackBufferTemp = pvPortMalloc(configMINIMAL_STACK_SIZE);
-        #else
-            pxTCBBufferTemp = pvPortMallocTcbMem(sizeof(StaticTask_t));
-            pxStackBufferTemp = pvPortMallocStackMem(configMINIMAL_STACK_SIZE);
-        #endif /* CONFIG_FREERTOS_SMP */
+        pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
+        pxStackBufferTemp = pvPortMalloc(configMINIMAL_STACK_SIZE);
     }
     #else /* portSTACK_GROWTH */
     {
-        //Allocate TCB and stack buffer in internal memory
-        #if CONFIG_FREERTOS_SMP     // IDF-3997
-            pxStackBufferTemp = pvPortMalloc(configMINIMAL_STACK_SIZE);
-            pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
-        #else
-            pxStackBufferTemp = pvPortMallocStackMem(configMINIMAL_STACK_SIZE);
-            pxTCBBufferTemp = pvPortMallocTcbMem(sizeof(StaticTask_t));
-        #endif /* CONFIG_FREERTOS_SMP */
+        pxStackBufferTemp = pvPortMalloc(configMINIMAL_STACK_SIZE);
+        pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
     }
     #endif /* portSTACK_GROWTH */
 
@@ -93,30 +64,20 @@ void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
     StaticTask_t *pxTCBBufferTemp;
     StackType_t *pxStackBufferTemp;
 
-    /* If the stack grows down then allocate the stack then the TCB so the stack
+    /* Allocate TCB and stack buffer from the FreeRTOS heap
+     *
+     * If the stack grows down then allocate the stack then the TCB so the stack
      * does not grow into the TCB.  Likewise if the stack grows up then allocate
      * the TCB then the stack. */
     #if (portSTACK_GROWTH > 0)
     {
-        //Allocate TCB and stack buffer in internal memory
-        #if CONFIG_FREERTOS_SMP     // IDF-3997
-            pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
-            pxStackBufferTemp = pvPortMalloc(configTIMER_TASK_STACK_DEPTH);
-        #else
-            pxTCBBufferTemp = pvPortMallocTcbMem(sizeof(StaticTask_t));
-            pxStackBufferTemp = pvPortMallocStackMem(configTIMER_TASK_STACK_DEPTH);
-        #endif /* CONFIG_FREERTOS_SMP */
+        pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
+        pxStackBufferTemp = pvPortMalloc(configTIMER_TASK_STACK_DEPTH);
     }
     #else /* portSTACK_GROWTH */
     {
-        //Allocate TCB and stack buffer in internal memory
-        #if CONFIG_FREERTOS_SMP     // IDF-3997
-            pxStackBufferTemp = pvPortMalloc(configTIMER_TASK_STACK_DEPTH);
-            pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
-        #else
-            pxStackBufferTemp = pvPortMallocStackMem(configTIMER_TASK_STACK_DEPTH);
-            pxTCBBufferTemp = pvPortMallocTcbMem(sizeof(StaticTask_t));
-        #endif /* CONFIG_FREERTOS_SMP */
+        pxStackBufferTemp = pvPortMalloc(configTIMER_TASK_STACK_DEPTH);
+        pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
     }
     #endif /* portSTACK_GROWTH */
 

+ 2 - 2
components/freertos/test_apps/freertos/kernel/tasks/test_freertos_task_delete.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -31,7 +31,7 @@
 #define NO_OF_TSKS  3
 #define DELAY_TICKS 2
 /* Caps of all memory which is allocated from when a task is created */
-#define HEAP_CAPS   (portTcbMemoryCaps | portStackMemoryCaps)
+#define HEAP_CAPS   (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
 
 #define DELAY_US_ITERATIONS	1000
 

+ 2 - 1
components/heap/test_apps/main/test_malloc.c

@@ -16,6 +16,7 @@
 #include "freertos/queue.h"
 #include "unity.h"
 #include "esp_heap_caps.h"
+#include "esp_system.h"
 
 #include "sdkconfig.h"
 
@@ -127,7 +128,7 @@ TEST_CASE("unreasonable allocs should all fail", "[heap]")
     TEST_ASSERT_NULL(test_malloc_wrapper(16*1024*1024));
     TEST_ASSERT_NULL(test_malloc_wrapper(SIZE_MAX / 2));
     TEST_ASSERT_NULL(test_malloc_wrapper(SIZE_MAX - 256));
-    TEST_ASSERT_NULL(test_malloc_wrapper(xPortGetFreeHeapSize() - 1));
+    TEST_ASSERT_NULL(test_malloc_wrapper(esp_get_free_heap_size() - 1));
 }
 
 TEST_CASE("malloc(0) should return a NULL pointer", "[heap]")

+ 7 - 6
components/wear_levelling/test_apps/main/test_wl.c

@@ -13,6 +13,7 @@
 #include "esp_private/esp_clk.h"
 #include "sdkconfig.h"
 #include "esp_cpu.h"
+#include "esp_system.h"
 #include "spi_flash_mmap.h"
 
 
@@ -43,10 +44,10 @@ TEST(wear_levelling, wl_unmount_doesnt_leak_memory)
     wl_unmount(handle);
 
     // test that we didn't leak any memory on the next init/deinit
-    size_t size_before = xPortGetFreeHeapSize();
+    size_t size_before = esp_get_free_heap_size();
     TEST_ESP_OK(wl_mount(partition, &handle));
     wl_unmount(handle);
-    size_t size_after = xPortGetFreeHeapSize();
+    size_t size_after = esp_get_free_heap_size();
 
     TEST_ASSERT_EQUAL(size_before, size_after);
 }
@@ -64,21 +65,21 @@ TEST(wear_levelling, wl_mount_checks_partition_params)
     // test small partition: result should be error
     for (int i = 0; i < 5; i++) {
         fake_partition.size = SPI_FLASH_SEC_SIZE * (i);
-        size_before = xPortGetFreeHeapSize();
+        size_before = esp_get_free_heap_size();
         TEST_ESP_ERR(ESP_ERR_INVALID_ARG, wl_mount(&fake_partition, &handle));
         // test that we didn't leak any memory
-        size_after = xPortGetFreeHeapSize();
+        size_after = esp_get_free_heap_size();
         TEST_ASSERT_EQUAL_HEX32(size_before, size_after);
     }
 
     // test minimum size partition: result should be OK
     fake_partition.size = SPI_FLASH_SEC_SIZE * 5;
-    size_before = xPortGetFreeHeapSize();
+    size_before = esp_get_free_heap_size();
     TEST_ESP_OK(wl_mount(&fake_partition, &handle));
     wl_unmount(handle);
 
     // test that we didn't leak any memory
-    size_after = xPortGetFreeHeapSize();
+    size_after = esp_get_free_heap_size();
     TEST_ASSERT_EQUAL_HEX32(size_before, size_after);
 }
 

+ 8 - 0
docs/en/api-reference/system/freertos.rst

@@ -117,3 +117,11 @@ FreeRTOS Additions
 ------------------
 
 ESP-IDF provides some supplemental features to FreeRTOS such as Ring Buffers, ESP-IDF style Tick and Idle Hooks, and TLSP deletion callbacks. See :doc:`freertos_additions` for more details.
+
+FreeRTOS Heap
+-------------
+
+Vanilla FreeRTOS provides its own `selection of heap implementations <https://www.freertos.org/a00111.html>`_. However, ESP-IDF already implements its own heap (see :doc:`/api-reference/system/mem_alloc`), thus ESP-IDF does not make use of the heap implementations provided by Vanilla FreeRTOS. All FreeRTOS ports in ESP-IDF map FreeRTOS memory allocation/free calls (e.g., ``pvPortMalloc()`` and ``pvPortFree()``) to ESP-IDF heap API (i.e., :cpp:func:`heap_caps_malloc` and :cpp:func:`heap_caps_free`). However, the FreeRTOS ports ensure that all dynamic memory allocated by FreeRTOS is placed in internal memory.
+
+.. note::
+    If users wish to place FreeRTOS objects in external memory, users should allocate those objects manually using :cpp:func:`heap_caps_malloc`, then create the object using the object's ``...CreateStatic()`` function.