Merge branch 'feature/freertos_iram_optimization_5.0' into 'release/v5.0'

freertos: Update linker fragment files to optimise IRAM utilisation (v5.0)

See merge request espressif/esp-idf!24222
This commit is contained in:
Jiang Jiang Jian
2023-08-21 10:33:23 +08:00
18 changed files with 896 additions and 913 deletions

View File

@@ -7,7 +7,7 @@ endif()
idf_build_get_property(target IDF_TARGET)
if(CONFIG_FREERTOS_SMP)
set(ldfragments linker_smp.lf)
set(ldfragments linker_smp.lf linker_common.lf)
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
set(srcs
"FreeRTOS-Kernel-SMP/portable/xtensa/port.c"
@@ -50,6 +50,7 @@ if(CONFIG_FREERTOS_SMP)
endif()
list(APPEND srcs
"port_common.c"
"FreeRTOS-Kernel-SMP/croutine.c"
"FreeRTOS-Kernel-SMP/event_groups.c"
"FreeRTOS-Kernel-SMP/list.c"
@@ -57,6 +58,7 @@ if(CONFIG_FREERTOS_SMP)
"FreeRTOS-Kernel-SMP/tasks.c"
"FreeRTOS-Kernel-SMP/timers.c"
"FreeRTOS-Kernel-SMP/stream_buffer.c"
"app_startup.c"
"FreeRTOS-openocd.c"
)
@@ -69,7 +71,7 @@ if(CONFIG_FREERTOS_SMP)
endif()
else()
set(ldfragments linker.lf)
set(ldfragments linker.lf linker_common.lf)
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
set(srcs
"FreeRTOS-Kernel/portable/xtensa/port.c"
@@ -112,7 +114,7 @@ else()
endif()
list(APPEND srcs
"FreeRTOS-Kernel/portable/port_common.c"
"port_common.c"
"FreeRTOS-Kernel/portable/port_systick.c"
"FreeRTOS-Kernel/croutine.c"
"FreeRTOS-Kernel/event_groups.c"
@@ -121,6 +123,7 @@ else()
"FreeRTOS-Kernel/tasks.c"
"FreeRTOS-Kernel/timers.c"
"FreeRTOS-Kernel/stream_buffer.c"
"app_startup.c"
"FreeRTOS-openocd.c"
"esp_additions/freertos_v8_compat.c")

View File

@@ -35,24 +35,17 @@
#include "hal/systimer_hal.h"
#include "hal/systimer_ll.h"
#endif
#ifdef CONFIG_PM_TRACE
#include "esp_private/pm_trace.h"
#endif //CONFIG_PM_TRACE
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
#include "esp_gdbstub.h"
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
_Static_assert(portBYTE_ALIGNMENT == 16, "portBYTE_ALIGNMENT must be set to 16");
/* ---------------------------------------------------- Variables ------------------------------------------------------
*
* ------------------------------------------------------------------------------------------------------------------ */
static const char *TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but
BaseType_t uxSchedulerRunning = 0;
BaseType_t uxSchedulerRunning = 0; // Duplicate of xSchedulerRunning, accessible to port files
volatile UBaseType_t uxInterruptNesting = 0;
portMUX_TYPE port_xTaskLock = portMUX_INITIALIZER_UNLOCKED;
portMUX_TYPE port_xISRLock = portMUX_INITIALIZER_UNLOCKED;
@@ -229,83 +222,7 @@ IRAM_ATTR void SysTickIsrHandler(void *arg)
#endif // CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
// --------------------- App Start-up ----------------------
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 (uxSchedulerRunning == 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
#if CONFIG_ESP_TASK_WDT_INIT
esp_task_wdt_config_t twdt_config = {
.timeout_ms = CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000,
.idle_core_mask = 0,
#if CONFIG_ESP_TASK_WDT_PANIC
.trigger_panic = true,
#endif
};
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
twdt_config.idle_core_mask |= (1 << 0);
#endif
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
twdt_config.idle_core_mask |= (1 << 1);
#endif
ESP_ERROR_CHECK(esp_task_wdt_init(&twdt_config));
#endif // CONFIG_ESP_TASK_WDT_INIT
app_main();
vTaskDelete(NULL);
}
void esp_startup_start_app_common(void)
{
#if CONFIG_ESP_INT_WDT_INIT
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
portBASE_TYPE res = xTaskCreatePinnedToCore(main_task, "main",
ESP_TASK_MAIN_STACK, NULL,
ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE);
assert(res == pdTRUE);
(void)res;
}
void esp_startup_start_app(void)
{
esp_startup_start_app_common();
ESP_LOGI(TAG, "Starting scheduler.");
vTaskStartScheduler();
}
/* ---------------------------------------------- Port Implementations -------------------------------------------------
* Implementations of Porting Interface functions
@@ -471,52 +388,6 @@ void vPortFreeStack( void *pv )
}
#endif
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize )
{
StackType_t *pxStackBufferTemp;
StaticTask_t *pxTCBBufferTemp;
/* Stack always grows downwards (from high address to low address) on all
* ESP RISC-V targets. Given that the heap allocator likely allocates memory
* from low to high address, we allocate the stack first and then the TCB so
* that the stack does not grow downwards into the TCB.
*
* Allocate TCB and stack buffer in internal memory. */
pxStackBufferTemp = pvPortMalloc(CONFIG_FREERTOS_IDLE_TASK_STACKSIZE);
pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
assert(pxStackBufferTemp != NULL);
assert(pxTCBBufferTemp != NULL);
// Write back pointers
*ppxIdleTaskStackBuffer = pxStackBufferTemp;
*ppxIdleTaskTCBBuffer = pxTCBBufferTemp;
*pulIdleTaskStackSize = CONFIG_FREERTOS_IDLE_TASK_STACKSIZE;
}
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize )
{
StackType_t *pxStackBufferTemp;
StaticTask_t *pxTCBBufferTemp;
/* Stack always grows downwards (from high address to low address) on all
* ESP RISC-V targets. Given that the heap allocator likely allocates memory
* from low to high address, we allocate the stack first and then the TCB so
* that the stack does not grow downwards into the TCB.
*
* Allocate TCB and stack buffer in internal memory. */
pxStackBufferTemp = pvPortMalloc(configTIMER_TASK_STACK_DEPTH);
pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
assert(pxStackBufferTemp != NULL);
assert(pxTCBBufferTemp != NULL);
// Write back pointers
*ppxTimerTaskStackBuffer = pxStackBufferTemp;
*ppxTimerTaskTCBBuffer = pxTCBBufferTemp;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
#endif //( configSUPPORT_STATIC_ALLOCATION == 1 )
// ------------------------ Stack --------------------------
#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
/**

View File

@@ -31,18 +31,6 @@
#include "esp_freertos_hooks.h"
#include "esp_intr_alloc.h"
#include "esp_memory_utils.h"
#include "esp_chip_info.h"
#if CONFIG_SPIRAM
/* Required by esp_psram_extram_reserve_dma_pool() */
#include "esp_psram.h"
#include "esp_private/esp_psram_extram.h"
#endif
#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
#ifdef CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
#include "soc/periph_defs.h"
#include "soc/system_reg.h"
@@ -55,7 +43,7 @@ _Static_assert(portBYTE_ALIGNMENT == 16, "portBYTE_ALIGNMENT must be set to 16")
/*
OS state variables
*/
volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0};
volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Indicates whether scheduler is running on a per-core basis
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;
@@ -307,121 +295,6 @@ IRAM_ATTR void SysTickIsrHandler(void *arg)
#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
// --------------------- 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 (esp_psram_is_initialized()) {
esp_err_t r = esp_psram_extram_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 TWDT if configured to do so
#if CONFIG_ESP_TASK_WDT_INIT
esp_task_wdt_config_t twdt_config = {
.timeout_ms = CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000,
.idle_core_mask = 0,
#if CONFIG_ESP_TASK_WDT_PANIC
.trigger_panic = true,
#endif
};
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
twdt_config.idle_core_mask |= (1 << 0);
#endif
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
twdt_config.idle_core_mask |= (1 << 1);
#endif
ESP_ERROR_CHECK(esp_task_wdt_init(&twdt_config));
#endif // CONFIG_ESP_TASK_WDT
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
portBASE_TYPE res = xTaskCreatePinnedToCore(main_task, "main",
ESP_TASK_MAIN_STACK, NULL,
ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE);
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 -------------------------------------------------
@@ -535,52 +408,6 @@ void vPortFreeStack( void *pv )
}
#endif
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize )
{
StackType_t *pxStackBufferTemp;
StaticTask_t *pxTCBBufferTemp;
/* Stack always grows downwards (from high address to low address) on all
* ESP Xtensa targets. Given that the heap allocator likely allocates memory
* from low to high address, we allocate the stack first and then the TCB so
* that the stack does not grow downwards into the TCB.
*
* Allocate TCB and stack buffer in internal memory. */
pxStackBufferTemp = pvPortMalloc(CONFIG_FREERTOS_IDLE_TASK_STACKSIZE);
pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
assert(pxStackBufferTemp != NULL);
assert(pxTCBBufferTemp != NULL);
// Write back pointers
*ppxIdleTaskStackBuffer = pxStackBufferTemp;
*ppxIdleTaskTCBBuffer = pxTCBBufferTemp;
*pulIdleTaskStackSize = CONFIG_FREERTOS_IDLE_TASK_STACKSIZE;
}
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize )
{
StaticTask_t *pxTCBBufferTemp;
StackType_t *pxStackBufferTemp;
/* Stack always grows downwards (from high address to low address) on all
* ESP Xtensa targets. Given that the heap allocator likely allocates memory
* from low to high address, we allocate the stack first and then the TCB so
* that the stack does not grow downwards into the TCB.
*
* Allocate TCB and stack buffer in internal memory. */
pxStackBufferTemp = pvPortMalloc(configTIMER_TASK_STACK_DEPTH);
pxTCBBufferTemp = pvPortMalloc(sizeof(StaticTask_t));
assert(pxStackBufferTemp != NULL);
assert(pxTCBBufferTemp != NULL);
// Write back pointers
*ppxTimerTaskStackBuffer = pxStackBufferTemp;
*ppxTimerTaskTCBBuffer = pxTCBBufferTemp;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
#endif //( configSUPPORT_STATIC_ALLOCATION == 1 )
// ------------------------ Stack --------------------------
// User exception dispatcher when exiting

View File

@@ -1,230 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "FreeRTOS.h"
#include "task.h"
#include "portmacro.h"
#include "esp_private/esp_int_wdt.h"
#include "esp_system.h"
#include "esp_heap_caps_init.h"
#include "esp_task_wdt.h"
#include "esp_task.h"
#include "esp_private/crosscore_int.h"
#include "esp_log.h"
#include "esp_memory_utils.h"
#include "esp_freertos_hooks.h"
#include "sdkconfig.h"
#include "esp_freertos_hooks.h"
#if CONFIG_SPIRAM
#include "esp_psram.h"
#include "esp_private/esp_psram_extram.h"
#endif
#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
static const char* TAG = "cpu_start";
#endif
/* Architecture-agnostic parts of the FreeRTOS ESP-IDF port layer can go here.
*
* The actual call flow will be to call esp_startup_start_app() in <ARCH>/port.c,
* which will then call esp_startup_start_app_common()
*/
// Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0};
// For now, running FreeRTOS on one core and a bare metal on the other (or other OSes)
// is not supported. For now CONFIG_FREERTOS_UNICORE and CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
// should mirror each other's values.
//
// And since this should be true, we can just check for CONFIG_FREERTOS_UNICORE.
#if CONFIG_FREERTOS_UNICORE != CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
#error "FreeRTOS and system configuration mismatch regarding the use of multiple cores."
#endif
static void main_task(void* args);
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
void esp_gdbstub_init(void);
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
extern void app_main(void);
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();
#if CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME && !CONFIG_IDF_TARGET_ESP32C2
esp_gdbstub_init();
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
ESP_TASK_MAIN_STACK, NULL,
ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE);
assert(res == pdTRUE);
(void)res;
}
#if !CONFIG_FREERTOS_UNICORE
static volatile bool s_other_cpu_startup_done = false;
static bool other_cpu_startup_idle_hook_cb(void)
{
s_other_cpu_startup_done = true;
return true;
}
#endif
static void main_task(void* args)
{
#if !CONFIG_FREERTOS_UNICORE
// Wait for FreeRTOS initialization to finish on other core, before replacing its startup stack
esp_register_freertos_idle_hook_for_cpu(other_cpu_startup_idle_hook_cb, !xPortGetCoreID());
while (!s_other_cpu_startup_done) {
;
}
esp_deregister_freertos_idle_hook_for_cpu(other_cpu_startup_idle_hook_cb, !xPortGetCoreID());
#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 (esp_psram_is_initialized()) {
esp_err_t r = esp_psram_extram_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 TWDT if configured to do so
#if CONFIG_ESP_TASK_WDT_INIT
esp_task_wdt_config_t twdt_config = {
.timeout_ms = CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000,
.idle_core_mask = 0,
#if CONFIG_ESP_TASK_WDT_PANIC
.trigger_panic = true,
#endif
};
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
twdt_config.idle_core_mask |= (1 << 0);
#endif
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
twdt_config.idle_core_mask |= (1 << 1);
#endif
ESP_ERROR_CHECK(esp_task_wdt_init(&twdt_config));
#endif // CONFIG_ESP_TASK_WDT
app_main();
vTaskDelete(NULL);
}
// -------------------- Heap Related -----------------------
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
}
// ------------- FreeRTOS Static Allocation ----------------
/*
This function is required by FreeRTOS when configSUPPORT_STATIC_ALLOCATION is
enabled and is used by FreeRTOS to obtain memory for its IDLE tasks.
Like the pvPortMallocTcbMem() and pvPortMallocStackMem() macros, TCB and stack
memory MUST be placed in internal RAM.
*/
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize )
{
StaticTask_t *pxTCBBufferTemp;
StackType_t *pxStackBufferTemp;
/* 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
pxTCBBufferTemp = pvPortMallocTcbMem(sizeof(StaticTask_t));
pxStackBufferTemp = pvPortMallocStackMem(configIDLE_TASK_STACK_SIZE);
}
#else /* portSTACK_GROWTH */
{
//Allocate TCB and stack buffer in internal memory
pxStackBufferTemp = pvPortMallocStackMem(configIDLE_TASK_STACK_SIZE);
pxTCBBufferTemp = pvPortMallocTcbMem(sizeof(StaticTask_t));
}
#endif /* portSTACK_GROWTH */
assert(pxTCBBufferTemp != NULL);
assert(pxStackBufferTemp != NULL);
//Write back pointers
*ppxIdleTaskTCBBuffer = pxTCBBufferTemp;
*ppxIdleTaskStackBuffer = pxStackBufferTemp;
*pulIdleTaskStackSize = configIDLE_TASK_STACK_SIZE;
}
/*
This function is required by FreeRTOS when configSUPPORT_STATIC_ALLOCATION is
enabled and is used by the FreeRTOS Timer to obtain memory for its daemone task.
Like the pvPortMallocTcbMem() and pvPortMallocStackMem() macros, TCB and stack
memory MUST be placed in internal RAM.
*/
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize )
{
StaticTask_t *pxTCBBufferTemp;
StackType_t *pxStackBufferTemp;
/* 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
pxTCBBufferTemp = pvPortMallocTcbMem(sizeof(StaticTask_t));
pxStackBufferTemp = pvPortMallocStackMem(configTIMER_TASK_STACK_DEPTH);
}
#else /* portSTACK_GROWTH */
{
//Allocate TCB and stack buffer in internal memory
pxStackBufferTemp = pvPortMallocStackMem(configTIMER_TASK_STACK_DEPTH);
pxTCBBufferTemp = pvPortMallocTcbMem(sizeof(StaticTask_t));
}
#endif /* portSTACK_GROWTH */
assert(pxTCBBufferTemp != NULL);
assert(pxStackBufferTemp != NULL);
//Write back pointers
*ppxTimerTaskTCBBuffer = pxTCBBufferTemp;
*ppxTimerTaskStackBuffer = pxStackBufferTemp;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}

View File

@@ -63,8 +63,6 @@ _Static_assert(portBYTE_ALIGNMENT == 16, "portBYTE_ALIGNMENT must be set to 16")
*
* ------------------------------------------------------------------------------------------------------------------ */
static const char *TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but
/**
* @brief A variable is used to keep track of the critical section nesting.
* @note This variable has to be stored as part of the task context and must be initialized to a non zero value
@@ -73,7 +71,7 @@ static const char *TAG = "cpu_start"; // [refactor-todo]: might be appropriate t
*/
static UBaseType_t uxCriticalNesting = 0;
static UBaseType_t uxSavedInterruptState = 0;
BaseType_t uxSchedulerRunning = 0;
BaseType_t uxSchedulerRunning = 0; // Duplicate of xSchedulerRunning, accessible to port files
UBaseType_t uxInterruptNesting = 0;
BaseType_t xPortSwitchFlag = 0;
__attribute__((aligned(16))) static StackType_t xIsrStack[configISR_STACK_SIZE];
@@ -381,16 +379,3 @@ void vPortSetStackWatchpoint(void *pxStackStart)
/* ---------------------------------------------- Misc Implementations -------------------------------------------------
*
* ------------------------------------------------------------------------------------------------------------------ */
// --------------------- App Start-up ----------------------
/* [refactor-todo]: See if we can include this through a header */
extern void esp_startup_start_app_common(void);
void esp_startup_start_app(void)
{
esp_startup_start_app_common();
ESP_LOGI(TAG, "Starting scheduler.");
vTaskStartScheduler();
}

View File

@@ -68,15 +68,11 @@
#include "esp_private/esp_int_wdt.h"
#include "esp_system.h"
#include "esp_log.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_memory_utils.h"
#include "esp_chip_info.h"
_Static_assert(portBYTE_ALIGNMENT == 16, "portBYTE_ALIGNMENT must be set to 16");
@@ -87,8 +83,7 @@ _Static_assert(tskNO_AFFINITY == CONFIG_FREERTOS_NO_AFFINITY, "incorrect tskNO_A
*
* ------------------------------------------------------------------------------------------------------------------ */
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];
volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Indicates whether scheduler is running on a per-core basis
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};
@@ -445,53 +440,3 @@ void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings )
_xt_coproc_release( xMPUSettings->coproc_area );
}
#endif /* portUSING_MPU_WRAPPERS */
// --------------------- App Start-up ----------------------
#if !CONFIG_FREERTOS_UNICORE
void esp_startup_start_app_other_cores(void)
{
// For now, we only support up to two core: 0 and 1.
if (xPortGetCoreID() >= 2) {
abort();
}
// Wait for FreeRTOS initialization to finish on PRO CPU
while (port_xSchedulerRunning[0] == 0) {
;
}
#if CONFIG_APPTRACE_ENABLE
// [refactor-todo] move to esp_system initialization
esp_err_t err = esp_apptrace_init();
assert(err == ESP_OK && "Failed to init apptrace module on APP CPU!");
#endif
#if CONFIG_ESP_INT_WDT
//Initialize the interrupt watch dog for CPU1.
esp_int_wdt_cpu_init();
#endif
esp_crosscore_int_init();
ESP_EARLY_LOGI(TAG, "Starting scheduler on APP CPU.");
xPortStartScheduler();
abort(); /* Only get to here if FreeRTOS somehow very broken */
}
#endif // !CONFIG_FREERTOS_UNICORE
extern void esp_startup_start_app_common(void);
void esp_startup_start_app(void)
{
#if !CONFIG_ESP_INT_WDT
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
assert(!soc_has_cache_lock_bug() && "ESP32 Rev 3 + Dual Core + PSRAM requires INT WDT enabled in project config!");
#endif
#endif
esp_startup_start_app_common();
ESP_LOGI(TAG, "Starting scheduler on PRO CPU.");
vTaskStartScheduler();
}

View File

@@ -1,9 +1,10 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*
*/
/*
* Since at least FreeRTOS V7.5.3 uxTopUsedPriority is no longer
* present in the kernel, so it has to be supplied by other means for
* OpenOCD's threads awareness.
@@ -15,7 +16,6 @@
*/
#include "FreeRTOS.h"
#include "esp_attr.h"
#include "sdkconfig.h"
#ifdef __GNUC__
@@ -25,5 +25,5 @@
#endif
#ifdef CONFIG_FREERTOS_DEBUG_OCDAWARE
const int USED DRAM_ATTR uxTopUsedPriority = configMAX_PRIORITIES - 1; //will be removed
const int USED uxTopUsedPriority = configMAX_PRIORITIES - 1; //will be removed
#endif

View File

@@ -0,0 +1,211 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include <stddef.h>
#include <assert.h>
#include "esp_task.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/portmacro.h"
#include "esp_private/esp_int_wdt.h"
#include "esp_private/crosscore_int.h"
#include "esp_task_wdt.h"
#include "esp_freertos_hooks.h"
#include "esp_heap_caps_init.h"
#include "esp_chip_info.h"
#if CONFIG_SPIRAM
/* Required by esp_psram_extram_reserve_dma_pool() */
#include "esp_psram.h"
#include "esp_private/esp_psram_extram.h"
#endif
#ifdef CONFIG_APPTRACE_ENABLE
#include "esp_app_trace.h" /* Required for esp_apptrace_init. [refactor-todo] */
#endif
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
#include "esp_gdbstub.h" /* Required by esp_gdbstub_init() */
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
/* ------------------------------------------------- App/OS Startup ----------------------------------------------------
* - Functions related to application and FreeRTOS startup
* - This startup is common to all architectures (e.g. RISC-V and Xtensa) and all FreeRTOS implementations (i.e., IDF
* FreeRTOS and Amazon SMP FreeRTOS).
* - Application startup flow as follows:
* - For CPU 0
* - CPU0 completes CPU startup (in startup.c), then calls esp_startup_start_app()
* - esp_startup_start_app() registers some daemon services for CPU0 then starts FreeRTOS
* - For CPUx (1 to N-1)
* - CPUx completes CPU startup in startup.c, then calls esp_startup_start_app_other_cores()
* - esp_startup_start_app_other_cores(), registers some daemon services for CPUx, waits for CPU0 to start
* FreeRTOS, then yields (via xPortStartScheduler()) to schedule a task.
* ------------------------------------------------------------------------------------------------------------------ */
// ----------------------- Checks --------------------------
/*
For now, AMP is not supported (i.e., running FreeRTOS on one core and a bare metal/other OS on the other). Therefore,
CONFIG_FREERTOS_UNICORE and CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE should be identical. We add a check for this here.
*/
#if CONFIG_FREERTOS_UNICORE != CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
#error "AMP not supported. FreeRTOS number of cores and system number of cores must be identical"
#endif
// -------------------- Declarations -----------------------
static void main_task(void* args);
static const char* APP_START_TAG = "app_start";
// ------------------ CPU0 App Startup ---------------------
void esp_startup_start_app(void)
{
#if CONFIG_ESP_INT_WDT
esp_int_wdt_init();
// Initialize the interrupt watch dog for CPU0.
esp_int_wdt_cpu_init();
#elif CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
// If the INT WDT isn't enabled on ESP32 ECO3, issue an error regarding the cache lock bug
assert(!soc_has_cache_lock_bug() && "ESP32 Rev 3 + Dual Core + PSRAM requires INT WDT enabled in project config!");
#endif
// Initialize the cross-core interrupt on CPU0
esp_crosscore_int_init();
#if CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME && !CONFIG_IDF_TARGET_ESP32C2
void esp_gdbstub_init(void);
esp_gdbstub_init();
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
BaseType_t res = xTaskCreatePinnedToCore(main_task, "main",
ESP_TASK_MAIN_STACK, NULL,
ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE);
assert(res == pdTRUE);
(void)res;
/*
If a particular FreeRTOS port has port/arch specific OS startup behavior, they can implement a function of type
"void port_start_app_hook(void)" in their `port.c` files. This function will be called below, thus allowing each
FreeRTOS port to implement port specific app startup behavior.
*/
void __attribute__((weak)) port_start_app_hook(void);
if (port_start_app_hook != NULL) {
port_start_app_hook();
}
ESP_EARLY_LOGI(APP_START_TAG, "Starting scheduler on CPU0");
vTaskStartScheduler();
}
// --------------- CPU[1:N-1] App Startup ------------------
#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 CPU0 to start FreeRTOS before progressing
extern volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS];
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
// Initialize the cross-core interrupt on CPU1
esp_crosscore_int_init();
ESP_EARLY_LOGI(APP_START_TAG, "Starting scheduler on CPU%d", xPortGetCoreID());
xPortStartScheduler();
abort(); // Only get to here if FreeRTOS somehow very broken
}
#endif // !CONFIG_FREERTOS_UNICORE
/* ---------------------------------------------------- Main Task ------------------------------------------------------
* - main_task is a daemon task created by CPU0 before it starts FreeRTOS
* - Pinned to CPU(ESP_TASK_MAIN_CORE)
* - Priority of ESP_TASK_MAIN_PRIO
* - Used to dispatch "void app_main(void)" provided by the application
* - main_task will self delete if app_main returns
* ------------------------------------------------------------------------------------------------------------------ */
static const char* MAIN_TAG = "main_task";
#if !CONFIG_FREERTOS_UNICORE
static volatile bool s_other_cpu_startup_done = false;
static bool other_cpu_startup_idle_hook_cb(void)
{
s_other_cpu_startup_done = true;
return true;
}
#endif
static void main_task(void* args)
{
ESP_LOGI(MAIN_TAG, "Started on CPU%d", xPortGetCoreID());
#if !CONFIG_FREERTOS_UNICORE
// Wait for FreeRTOS initialization to finish on other core, before replacing its startup stack
esp_register_freertos_idle_hook_for_cpu(other_cpu_startup_idle_hook_cb, !xPortGetCoreID());
while (!s_other_cpu_startup_done) {
;
}
esp_deregister_freertos_idle_hook_for_cpu(other_cpu_startup_idle_hook_cb, !xPortGetCoreID());
#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 (esp_psram_is_initialized()) {
esp_err_t r = esp_psram_extram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
if (r != ESP_OK) {
ESP_LOGE(MAIN_TAG, "Could not reserve internal/DMA pool (error 0x%x)", r);
abort();
}
}
#endif
// Initialize TWDT if configured to do so
#if CONFIG_ESP_TASK_WDT_INIT
esp_task_wdt_config_t twdt_config = {
.timeout_ms = CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000,
.idle_core_mask = 0,
#if CONFIG_ESP_TASK_WDT_PANIC
.trigger_panic = true,
#endif
};
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
twdt_config.idle_core_mask |= (1 << 0);
#endif
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
twdt_config.idle_core_mask |= (1 << 1);
#endif
ESP_ERROR_CHECK(esp_task_wdt_init(&twdt_config));
#endif // CONFIG_ESP_TASK_WDT
/*
Note: Be careful when changing the "Calling app_main()" log below as multiple pytest scripts expect this log as a
start-of-application marker.
*/
ESP_LOGI(MAIN_TAG, "Calling app_main()");
extern void app_main(void);
app_main();
ESP_LOGI(MAIN_TAG, "Returned from app_main()");
vTaskDelete(NULL);
}

View File

@@ -201,7 +201,7 @@ This file get's pulled into assembly sources. Therefore, some includes need to b
#define INCLUDE_xSemaphoreGetMutexHolder 1
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_uxTaskGetStackHighWaterMark2 0
#define INCLUDE_uxTaskGetStackHighWaterMark2 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTaskResumeFromISR 1
#define INCLUDE_xTimerPendFunctionCall 1

View File

@@ -1,133 +1,243 @@
# ----------------------------------------------------------------------------------------------------------------------
# Linker fragment file for IDF FreeRTOS (i.e., CONFIG_FREERTOS_SMP=n)
[mapping:freertos]
# Flash function placements are listed per source file, in the order that they appear in the source file.
#
# 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).
# - Some functions that are called often (such as critical sections) are placed in internal RAM for speed.
# ----------------------------------------------------------------------------------------------------------------------
[mapping:freertos_idf]
archive: libfreertos.a
entries:
* (noflash_text)
if FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH = y:
# vTaskGetSnapshot is omitted on purpose: as it is used to by the Task Watchdog (TWDT) interrupt
# handler, we want to always keep it in IRAM
tasks: pxTaskGetNext (default)
tasks: uxTaskGetSnapshotAll (default)
tasks: pxGetNextTaskList (default)
* (noflash_text) # Default all FreeRTOS functions to IRAM
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: prvTaskPriorityRaise (default)
tasks: prvTaskPriorityRestore (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)
# --------------------------------------------------------------------------------------------------------------
# event_groups.c
# - Exclude all ...FromISR() functions and their dependents
# --------------------------------------------------------------------------------------------------------------
event_groups:xEventGroupCreateStatic (default)
event_groups:xEventGroupCreate (default)
event_groups:xEventGroupSync (default)
event_groups:xEventGroupWaitBits (default)
event_groups:xEventGroupClearBits (default)
event_groups:xEventGroupSetBits (default)
event_groups:vEventGroupDelete (default)
event_groups:vEventGroupSetBitsCallback (default)
event_groups:vEventGroupClearBitsCallback (default)
event_groups:prvTestWaitCondition (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)
event_groups: uxEventGroupGetNumber (default)
event_groups: vEventGroupSetNumber (default)
# --------------------------------------------------------------------------------------------------------------
# list.c
# - List/List Item initialization functions are never called from ISR
# --------------------------------------------------------------------------------------------------------------
list:vListInitialise (default)
list:vListInitialiseItem (default)
# --------------------------------------------------------------------------------------------------------------
# queue.c
# - Keep all ...FromISR() functions (and their prv... calls) in internal RAM
# - All other functions can be moved to flash
# --------------------------------------------------------------------------------------------------------------
queue:xQueueGenericReset (default)
queue:xQueueGenericCreateStatic (default)
queue:xQueueGenericCreate (default)
queue:prvInitialiseNewQueue (default)
queue:prvInitialiseMutex (default)
queue:xQueueCreateMutex (default)
queue:xQueueCreateMutexStatic (default)
queue:xQueueGetMutexHolder (default)
queue:xQueueGiveMutexRecursive (default)
queue:xQueueTakeMutexRecursive (default)
queue:xQueueCreateCountingSemaphoreStatic (default)
queue:xQueueCreateCountingSemaphore (default)
queue:xQueueGenericSend (default)
queue:xQueueReceive (default)
queue:xQueueSemaphoreTake (default)
queue:xQueuePeek (default)
queue:uxQueueMessagesWaiting (default)
queue:uxQueueSpacesAvailable (default)
queue:vQueueDelete (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)
queue:uxQueueGetQueueNumber (default)
queue:vQueueSetQueueNumber (default)
queue:ucQueueGetQueueType (default)
queue:prvGetDisinheritPriorityAfterTimeout (default)
queue:prvUnlockQueue (default)
queue:prvIsQueueEmpty (default)
queue:prvIsQueueFull (default)
if FREERTOS_QUEUE_REGISTRY_SIZE > 0:
queue: pcQueueGetName (default)
queue: vQueueAddToRegistry (default)
queue: vQueueUnregisterQueue (default)
queue:vQueueAddToRegistry (default)
queue:pcQueueGetName (default)
queue:vQueueUnregisterQueue (default)
queue:vQueueWaitForMessageRestricted (default)
queue:xQueueCreateSet (default)
queue:xQueueAddToSet (default)
queue:xQueueRemoveFromSet (default)
queue:xQueueSelectFromSet (default)
# --------------------------------------------------------------------------------------------------------------
# stream_buffer.c
# --------------------------------------------------------------------------------------------------------------
stream_buffer:xStreamBufferGenericCreate (default)
stream_buffer:xStreamBufferGenericCreateStatic (default)
stream_buffer:vStreamBufferDelete (default)
stream_buffer:xStreamBufferReset (default)
stream_buffer:xStreamBufferSetTriggerLevel (default)
stream_buffer:xStreamBufferBytesAvailable (default)
stream_buffer:xStreamBufferSend (default)
stream_buffer:xStreamBufferReceive (default)
stream_buffer:xStreamBufferNextMessageLengthBytes (default)
stream_buffer:xStreamBufferIsEmpty (default)
stream_buffer:xStreamBufferIsFull (default)
stream_buffer:prvWriteBytesToBuffer (default)
stream_buffer:prvReadBytesFromBuffer (default)
stream_buffer:prvInitialiseNewStreamBuffer (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)
stream_buffer:uxStreamBufferGetStreamBufferNumber (default)
stream_buffer:vStreamBufferSetStreamBufferNumber (default)
stream_buffer:ucStreamBufferGetStreamBufferType (default)
# --------------------------------------------------------------------------------------------------------------
# tasks.c
# - Tickless idle functions (i.e., step tick) are left in internal RAM for speed
# - The following functions are called when the cache is disabled, thus they are excluded from the list below
# (i.e., called after "spi_flash_disable_interrupts_caches_and_other_cpu()" is called).
# - "xTaskGetSchedulerState"
# - "xTaskGetTickCount"
# --------------------------------------------------------------------------------------------------------------
tasks:xTaskCreateStaticPinnedToCore (default)
tasks:xTaskCreatePinnedToCore (default)
tasks:prvInitialiseNewTask (default)
tasks:prvAddNewTaskToReadyList (default)
tasks:vTaskDelete (default)
tasks:vTaskDelayUntil (default)
tasks:xTaskDelayUntil (default)
tasks:vTaskDelay (default)
tasks:eTaskGetState (default)
tasks:uxTaskPriorityGet (default)
tasks:vTaskPrioritySet (default)
tasks:vTaskSuspend (default)
tasks:vTaskResume (default)
tasks:vTaskStartScheduler (default)
tasks:vTaskEndScheduler (default)
tasks:vTaskSuspendAll (default)
if CONFIG_FREERTOS_USE_TICKLESS_IDLE = y:
tasks:prvGetExpectedIdleTime (default)
tasks:xTaskResumeAll (default)
tasks:uxTaskGetNumberOfTasks (default)
tasks:pcTaskGetName (default)
tasks:prvSearchForNameWithinSingleList (default)
tasks:xTaskGetHandle (default)
tasks:xTaskGetIdleTaskHandle (default)
tasks:xTaskGetIdleTaskHandleForCPU (default)
tasks:xTaskAbortDelay (default)
# IDF-6410 Application tags not supported yet
#tasks:vTaskSetApplicationTaskTag (default)
#tasks:xTaskGetApplicationTaskTag (default)
#tasks:xTaskCallApplicationTaskHook (default)
tasks:vTaskPlaceOnEventList (default)
tasks:vTaskPlaceOnUnorderedEventList (default)
tasks:vTaskPlaceOnEventListRestricted (default)
tasks:vTaskRemoveFromUnorderedEventList (default)
tasks:vTaskSetTimeOutState (default)
tasks:vTaskInternalSetTimeOutState (default)
tasks:xTaskCheckForTimeOut (default)
tasks:vTaskMissedYield (default)
tasks:prvIdleTask (default)
if FREERTOS_TLSP_DELETION_CALLBACKS = y:
tasks:vTaskSetThreadLocalStoragePointerAndDelCallback (default)
tasks:prvDeleteTLS (default)
if FREERTOS_THREAD_LOCAL_STORAGE_POINTERS != 0:
tasks:vTaskSetThreadLocalStoragePointer (default)
tasks:pvTaskGetThreadLocalStoragePointer (default)
tasks:prvInitialiseTaskLists (default)
tasks:prvCheckTasksWaitingTermination (default)
tasks:xTaskGetAffinity (default)
tasks:prvTaskCheckFreeStackSpace (default)
tasks:uxTaskGetStackHighWaterMark (default)
tasks:pxTaskGetStackStart (default)
tasks:prvDeleteTCB (default)
tasks:xTaskGetCurrentTaskHandle (default)
tasks:xTaskGetCurrentTaskHandleForCPU (default)
tasks:xTaskPriorityInherit (default)
tasks:xTaskPriorityDisinherit (default)
tasks:vTaskPriorityDisinheritAfterTimeout (default)
if FREERTOS_USE_TRACE_FACILITY = y && FREERTOS_USE_STATS_FORMATTING_FUNCTIONS = y:
tasks:prvWriteNameToBuffer (default)
tasks:vTaskList (default)
if FREERTOS_GENERATE_RUN_TIME_STATS = y && FREERTOS_USE_STATS_FORMATTING_FUNCTIONS = y:
tasks:vTaskGetRunTimeStats (default)
tasks:uxTaskResetEventItemValue (default)
tasks:pvTaskIncrementMutexHeldCount (default)
tasks:ulTaskNotifyTake (default)
tasks:ulTaskGenericNotifyTake (default)
tasks:xTaskNotifyWait (default)
tasks:xTaskGenericNotifyWait (default)
tasks:xTaskGenericNotify (default)
tasks:xTaskGenericNotifyStateClear (default)
tasks:ulTaskGenericNotifyValueClear (default)
if FREERTOS_GENERATE_RUN_TIME_STATS = y:
tasks:ulTaskGetIdleRunTimeCounter (default)
tasks:prvAddCurrentTaskToDelayedList (default)
if FREERTOS_USE_TRACE_FACILITY = y:
tasks:uxTaskGetSystemState (default)
tasks:uxTaskGetTaskNumber (default)
tasks:vTaskSetTaskNumber (default)
tasks:vTaskGetInfo (default)
tasks:prvListTasksWithinSingleList (default)
# --------------------------------------------------------------------------------------------------------------
# timers.c
# - xTimerGenericCommand() is used for ISR calls as well. Thus leave it (and its dependents) in internal RAM
# --------------------------------------------------------------------------------------------------------------
timers:xTimerCreateTimerTask (default)
timers:xTimerCreate (default)
timers:xTimerCreateStatic (default)
timers:prvInitialiseNewTimer (default)
timers:xTimerGenericCommand (default)
timers:xTimerGetTimerDaemonTaskHandle (default)
timers:xTimerGetPeriod (default)
timers:vTimerSetReloadMode (default)
timers:uxTimerGetReloadMode (default)
timers:xTimerGetExpiryTime (default)
timers:pcTimerGetName (default)
timers:prvProcessExpiredTimer (default)
timers:prvTimerTask (default)
timers:prvProcessTimerOrBlockTask (default)
timers:prvGetNextExpireTime (default)
timers:prvSampleTimeNow (default)
timers:prvInsertTimerInActiveList (default)
timers:prvProcessReceivedCommands (default)
timers:prvSwitchTimerLists (default)
timers:prvCheckForValidListAndQueue (default)
timers:xTimerIsTimerActive (default)
timers:pvTimerGetTimerID (default)
timers:vTimerSetTimerID (default)
timers:xTimerPendFunctionCall (default)
if FREERTOS_USE_TRACE_FACILITY = y:
timers:uxTimerGetTimerNumber (default)
timers:vTimerSetTimerNumber (default)
# --------------------------------------------------------------------------------------------------------------
# portable/xtensa/port.c
# - Most functions are called from an ISR context, except for scheduler/task init/deinit functions
# - MPU/Coproc currently only exists on ESP32/S3
# --------------------------------------------------------------------------------------------------------------
if IDF_TARGET_ARCH_XTENSA = y:
port:xPortStartScheduler (default)
port:vPortEndScheduler (default)
if FREERTOS_TASK_FUNCTION_WRAPPER = y:
port:vPortTaskWrapper (default)
port:pxPortInitialiseStack (default)
port:xPortGetTickRateHz (default)
# --------------------------------------------------------------------------------------------------------------
# portable/riscv/port.c
# - Most functions are called from an ISR context, except for scheduler/task init/deinit functions
# --------------------------------------------------------------------------------------------------------------
if IDF_TARGET_ARCH_RISCV = y:
port:xPortStartScheduler (default)
port:vPortEndScheduler (default)
if FREERTOS_TASK_FUNCTION_WRAPPER = y:
port:vPortTaskWrapper (default)
port:pxPortInitialiseStack (default)
port:xPortGetTickRateHz (default)

View File

@@ -0,0 +1,62 @@
# Linker fragment file for common FreeRTOS files (i.e., both "port_common.c" and "esp_additions/..."
# Flash function placements are listed per source file, in the order that they appear in the source file.
[mapping:freertos_common]
archive: libfreertos.a
entries:
# ------------------------------------------------------------------------------------------------------------------
# esp_additions/private_include/freertos_tasks_c_additions.h
# Placement Rules (Task Snapshot):
# - Default: Place all functions in internal RAM.
# - CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH: Place functions in flash
# - vTaskGetSnapshot is omitted on purpose as it is used to by the Task Watchdog (TWDT) interrupt handler, we want
# to always keep it in IRAM
# Placement Rules (FreeRTOS API Additions):
# - 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).
# ------------------------------------------------------------------------------------------------------------------
# Task Snapshot
if FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH = y:
tasks:pxGetNextTaskList (default)
tasks:pxTaskGetNext (default)
tasks:uxTaskGetSnapshotAll (default)
# FreeRTOS API Additions
if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
if FREERTOS_SMP = y:
tasks:xTaskCreatePinnedToCore (default)
tasks:xTaskCreateStaticPinnedToCore (default)
tasks:xTaskGetCurrentTaskHandleForCPU (default)
tasks:xTaskGetIdleTaskHandleForCPU (default)
tasks:xTaskGetAffinity (default)
if FREERTOS_TLSP_DELETION_CALLBACKS = y:
tasks:vTaskSetThreadLocalStoragePointerAndDelCallback (default)
tasks:prvTaskPriorityRaise (default)
tasks:prvTaskPriorityRestore (default)
# ------------------------------------------------------------------------------------------------------------------
# app_startup.c
# Placement Rules: Functions always in flash as they are never called from an ISR
# ------------------------------------------------------------------------------------------------------------------
app_startup (default) # Place functions (but not Data and BSS) to flash
# ------------------------------------------------------------------------------------------------------------------
# FreeRTOS-openocd.c
# Placement Rules: All functions/data in internal RAM as they are called/used by OpenOCD
# ------------------------------------------------------------------------------------------------------------------
FreeRTOS-openocd (noflash)
# ------------------------------------------------------------------------------------------------------------------
# port_common.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).
# ------------------------------------------------------------------------------------------------------------------
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)

View File

@@ -1,178 +1,242 @@
# ----------------------------------------------------------------------------------------------------------------------
# Linker fragment file for SMP FreeRTOS (i.e., CONFIG_FREERTOS_SMP=y)
[mapping:freertos]
# Flash function placements are listed per source file, in the order that they appear in the source file.
#
# 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).
# - Some functions that are called often (such as critical sections) are placed in internal RAM for speed.
# ----------------------------------------------------------------------------------------------------------------------
[mapping:freertos_smp]
archive: libfreertos.a
entries:
# Default all FreeRTOS functions to IRAM
* (noflash_text)
# Todo: Check if flash placements are missing or can be further optimized IDF-5259
* (noflash_text) # Default all FreeRTOS functions to IRAM
if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
# --------------------------------------------------------------------------------------------------------------
# event_groups.c
event_groups: xEventGroupCreateStatic (default)
event_groups: xEventGroupCreate (default)
event_groups: xEventGroupSync (default)
event_groups: xEventGroupWaitBits (default)
event_groups: xEventGroupClearBits (default)
event_groups: xEventGroupSetBits (default)
event_groups: vEventGroupDelete (default)
event_groups: vEventGroupSetBitsCallback (default)
event_groups: vEventGroupClearBitsCallback (default)
event_groups: prvTestWaitCondition (default)
# - Exclude all ...FromISR() functions and their dependents
# --------------------------------------------------------------------------------------------------------------
event_groups:xEventGroupCreateStatic (default)
event_groups:xEventGroupCreate (default)
event_groups:xEventGroupSync (default)
event_groups:xEventGroupWaitBits (default)
event_groups:xEventGroupClearBits (default)
event_groups:xEventGroupSetBits (default)
event_groups:vEventGroupDelete (default)
event_groups:vEventGroupSetBitsCallback (default)
event_groups:vEventGroupClearBitsCallback (default)
event_groups:prvTestWaitCondition (default)
if FREERTOS_USE_TRACE_FACILITY = y:
event_groups: uxEventGroupGetNumber (default)
event_groups: vEventGroupSetNumber (default)
# --------------------------------------------------------------------------------------------------------------
# list.c
# - List/List Item initialization functions are never called from ISR
# --------------------------------------------------------------------------------------------------------------
list:vListInitialise (default)
list:vListInitialiseItem (default)
# --------------------------------------------------------------------------------------------------------------
# queue.c
queue: xQueueGenericReset (default)
queue: xQueueGenericCreateStatic (default)
queue: xQueueGenericCreate (default)
queue: prvInitialiseNewQueue (default)
queue: prvInitialiseMutex (default)
queue: xQueueCreateMutex (default)
queue: xQueueCreateMutexStatic (default)
queue: xQueueGetMutexHolder (default)
queue: xQueueGiveMutexRecursive (default)
queue: xQueueTakeMutexRecursive (default)
queue: xQueueCreateCountingSemaphoreStatic (default)
queue: xQueueCreateCountingSemaphore (default)
queue: xQueueGenericSend (default)
queue: xQueueReceive (default)
queue: xQueueSemaphoreTake (default)
queue: xQueuePeek (default)
queue: uxQueueMessagesWaiting (default)
queue: uxQueueSpacesAvailable (default)
queue: vQueueDelete (default)
# - Keep all ...FromISR() functions (and their prv... calls) in internal RAM
# - All other functions can be moved to flash
# --------------------------------------------------------------------------------------------------------------
queue:xQueueGenericReset (default)
queue:xQueueGenericCreateStatic (default)
queue:xQueueGenericCreate (default)
queue:prvInitialiseNewQueue (default)
queue:prvInitialiseMutex (default)
queue:xQueueCreateMutex (default)
queue:xQueueCreateMutexStatic (default)
queue:xQueueGetMutexHolder (default)
queue:xQueueGiveMutexRecursive (default)
queue:xQueueTakeMutexRecursive (default)
queue:xQueueCreateCountingSemaphoreStatic (default)
queue:xQueueCreateCountingSemaphore (default)
queue:xQueueGenericSend (default)
queue:xQueueReceive (default)
queue:xQueueSemaphoreTake (default)
queue:xQueuePeek (default)
queue:uxQueueMessagesWaiting (default)
queue:uxQueueSpacesAvailable (default)
queue:vQueueDelete (default)
if FREERTOS_USE_TRACE_FACILITY = y:
queue: uxQueueGetQueueNumber (default)
queue: vQueueSetQueueNumber (default)
queue: ucQueueGetQueueType (default)
queue: prvGetDisinheritPriorityAfterTimeout (default)
queue: prvUnlockQueue (default)
queue: prvIsQueueEmpty (default)
queue: prvIsQueueFull (default)
queue:uxQueueGetQueueNumber (default)
queue:vQueueSetQueueNumber (default)
queue:ucQueueGetQueueType (default)
queue:prvGetDisinheritPriorityAfterTimeout (default)
queue:prvUnlockQueue (default)
queue:prvIsQueueEmpty (default)
queue:prvIsQueueFull (default)
if FREERTOS_QUEUE_REGISTRY_SIZE > 0:
queue: vQueueAddToRegistry (default)
queue: pcQueueGetName (default)
queue: vQueueUnregisterQueue (default)
queue: vQueueWaitForMessageRestricted (default)
queue: xQueueCreateSet (default)
queue: xQueueAddToSet (default)
queue: xQueueRemoveFromSet (default)
queue: xQueueSelectFromSet (default)
queue:vQueueAddToRegistry (default)
queue:pcQueueGetName (default)
queue:vQueueUnregisterQueue (default)
queue:vQueueWaitForMessageRestricted (default)
queue:xQueueCreateSet (default)
queue:xQueueAddToSet (default)
queue:xQueueRemoveFromSet (default)
queue:xQueueSelectFromSet (default)
# --------------------------------------------------------------------------------------------------------------
# stream_buffer.c
# tasks.c: Vanilla
tasks: xTaskCreateStatic (default)
tasks: xTaskCreate (default)
# --------------------------------------------------------------------------------------------------------------
stream_buffer:xStreamBufferGenericCreate (default)
stream_buffer:xStreamBufferGenericCreateStatic (default)
stream_buffer:vStreamBufferDelete (default)
stream_buffer:xStreamBufferReset (default)
stream_buffer:xStreamBufferSetTriggerLevel (default)
stream_buffer:xStreamBufferBytesAvailable (default)
stream_buffer:xStreamBufferSend (default)
stream_buffer:xStreamBufferReceive (default)
stream_buffer:xStreamBufferNextMessageLengthBytes (default)
stream_buffer:xStreamBufferIsEmpty (default)
stream_buffer:xStreamBufferIsFull (default)
stream_buffer:prvWriteBytesToBuffer (default)
stream_buffer:prvReadBytesFromBuffer (default)
stream_buffer:prvInitialiseNewStreamBuffer (default)
if FREERTOS_USE_TRACE_FACILITY = y:
stream_buffer:uxStreamBufferGetStreamBufferNumber (default)
stream_buffer:vStreamBufferSetStreamBufferNumber (default)
stream_buffer:ucStreamBufferGetStreamBufferType (default)
# --------------------------------------------------------------------------------------------------------------
# tasks.c
# - The following functions are called when the cache is disabled, thus they are excluded from the list below
# (i.e., called after "spi_flash_disable_interrupts_caches_and_other_cpu()" is called).
# - "xTaskGetSchedulerState"
# - "xTaskGetTickCount"
# --------------------------------------------------------------------------------------------------------------
tasks:xTaskCreateStatic (default)
tasks:xTaskCreate (default)
if FREERTOS_UNICORE = n:
tasks: xTaskCreateStaticAffinitySet (default)
tasks: xTaskCreateAffinitySet (default)
tasks: vTaskCoreAffinitySet (default)
tasks: vTaskCoreAffinityGet (default)
tasks: prvMinimalIdleTask (default)
tasks: prvInitialiseNewTask (default)
tasks: prvAddNewTaskToReadyList (default)
tasks: vTaskDelete (default)
tasks: xTaskDelayUntil (default)
tasks: vTaskDelay (default)
tasks: eTaskGetState (default)
tasks: uxTaskPriorityGet (default)
tasks: vTaskPrioritySet (default)
tasks: prvTaskPriorityRaise (default)
tasks: prvTaskPriorityRestore (default)
tasks: vTaskSuspend (default)
tasks: vTaskResume (default)
tasks: prvCreateIdleTasks (default)
tasks: vTaskStartScheduler (default)
tasks: vTaskEndScheduler (default)
tasks: vTaskSuspendAll (default)
#Todo: prvGetExpectedIdleTime
tasks: xTaskResumeAll (default)
tasks: uxTaskGetNumberOfTasks (default)
tasks: pcTaskGetName (default)
tasks: prvSearchForNameWithinSingleList (default)
tasks: xTaskGetHandle (default)
tasks:xTaskCreateStaticAffinitySet (default)
tasks:xTaskCreateAffinitySet (default)
tasks:vTaskCoreAffinitySet (default)
tasks:vTaskCoreAffinityGet (default)
tasks:prvMinimalIdleTask (default)
tasks:prvInitialiseNewTask (default)
tasks:prvAddNewTaskToReadyList (default)
tasks:vTaskDelete (default)
tasks:xTaskDelayUntil (default)
tasks:vTaskDelay (default)
tasks:eTaskGetState (default)
tasks:uxTaskPriorityGet (default)
tasks:vTaskPrioritySet (default)
tasks:vTaskSuspend (default)
tasks:vTaskResume (default)
tasks:prvCreateIdleTasks (default)
tasks:vTaskStartScheduler (default)
tasks:vTaskEndScheduler (default)
tasks:vTaskSuspendAll (default)
#Todo:prvGetExpectedIdleTime
tasks:xTaskResumeAll (default)
tasks:uxTaskGetNumberOfTasks (default)
tasks:pcTaskGetName (default)
tasks:prvSearchForNameWithinSingleList (default)
tasks:xTaskGetHandle (default)
if FREERTOS_USE_TRACE_FACILITY = y:
tasks: uxTaskGetSystemState (default)
tasks: uxTaskGetTaskNumber (default)
tasks: vTaskSetTaskNumber (default)
tasks: vTaskGetInfo (default)
tasks: prvListTasksWithinSingleList (default)
tasks: prvTaskCheckFreeStackSpace (default)
tasks: xTaskGetIdleTaskHandle (default)
tasks: xTaskAbortDelay (default)
tasks: vTaskPlaceOnEventList (default)
tasks: vTaskRemoveFromUnorderedEventList (default)
tasks: vTaskPlaceOnEventListRestricted (default)
tasks: vTaskSetTimeOutState (default)
tasks: vTaskInternalSetTimeOutState (default)
tasks: xTaskCheckForTimeOut (default)
tasks: vTaskMissedYield (default)
tasks: prvIdleTask (default)
tasks:uxTaskGetSystemState (default)
tasks:uxTaskGetTaskNumber (default)
tasks:vTaskSetTaskNumber (default)
tasks:vTaskGetInfo (default)
tasks:prvListTasksWithinSingleList (default)
tasks:prvTaskCheckFreeStackSpace (default)
tasks:xTaskGetIdleTaskHandle (default)
tasks:xTaskAbortDelay (default)
tasks:vTaskPlaceOnEventList (default)
tasks:vTaskRemoveFromUnorderedEventList (default)
tasks:vTaskPlaceOnEventListRestricted (default)
tasks:vTaskSetTimeOutState (default)
tasks:vTaskInternalSetTimeOutState (default)
tasks:xTaskCheckForTimeOut (default)
tasks:vTaskMissedYield (default)
tasks:prvIdleTask (default)
if FREERTOS_THREAD_LOCAL_STORAGE_POINTERS > 0:
tasks: vTaskSetThreadLocalStoragePointer (default)
tasks: pvTaskGetThreadLocalStoragePointer (default)
tasks: prvInitialiseTaskLists (default)
tasks: prvCheckTasksWaitingTermination (default)
tasks: uxTaskGetStackHighWaterMark (default)
tasks: prvDeleteTCB (default)
tasks:vTaskSetThreadLocalStoragePointer (default)
tasks:pvTaskGetThreadLocalStoragePointer (default)
tasks:prvInitialiseTaskLists (default)
tasks:prvCheckTasksWaitingTermination (default)
tasks:uxTaskGetStackHighWaterMark (default)
tasks:prvDeleteTCB (default)
if FREERTOS_USE_STATS_FORMATTING_FUNCTIONS = y:
tasks: prvWriteNameToBuffer (default)
tasks: vTaskList (default)
tasks:prvWriteNameToBuffer (default)
tasks:vTaskList (default)
if FREERTOS_GENERATE_RUN_TIME_STATS = y:
tasks: vTaskGetRunTimeStats (default)
tasks: ulTaskGetIdleRunTimeCounter (default)
tasks: uxTaskResetEventItemValue (default)
tasks: pvTaskIncrementMutexHeldCount (default)
tasks: ulTaskGenericNotifyTake (default)
tasks: xTaskGenericNotifyWait (default)
tasks: xTaskGenericNotify (default)
tasks: xTaskGenericNotifyStateClear (default)
tasks: ulTaskGenericNotifyValueClear (default)
# tasks.c: Additions
if FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH = y:
tasks: non_ready_task_lists (default)
tasks: pxGetNextTaskList (default)
tasks: pxTaskGetNext (default)
tasks: vTaskGetSnapshot (default)
tasks: uxTaskGetSnapshotAll (default)
tasks: xTaskCreatePinnedToCore (default)
tasks: xTaskCreateStaticPinnedToCore (default)
tasks: xTaskGetCurrentTaskHandleForCPU (default)
tasks: xTaskGetIdleTaskHandleForCPU (default)
tasks: xTaskGetAffinity (default)
if FREERTOS_TLSP_DELETION_CALLBACKS = y:
tasks: vTaskSetThreadLocalStoragePointerAndDelCallback (default)
# port
port: pxPortInitialiseStack (default)
port: xPortStartScheduler (default)
port: main_task (default)
port: esp_startup_start_app (default)
if ESP_SYSTEM_SINGLE_CORE_MODE = n:
port:esp_startup_start_app_other_cores (default)
tasks:vTaskGetRunTimeStats (default)
tasks:ulTaskGetIdleRunTimeCounter (default)
tasks:uxTaskResetEventItemValue (default)
tasks:pvTaskIncrementMutexHeldCount (default)
tasks:ulTaskGenericNotifyTake (default)
tasks:xTaskGenericNotifyWait (default)
tasks:xTaskGenericNotify (default)
tasks:xTaskGenericNotifyStateClear (default)
tasks:ulTaskGenericNotifyValueClear (default)
# --------------------------------------------------------------------------------------------------------------
# timers.c
timers: xTimerCreateTimerTask (default)
timers: xTimerCreate (default)
timers: xTimerCreateStatic (default)
timers: prvInitialiseNewTimer (default)
timers: xTimerGenericCommandFromTask (default)
timers: xTimerGetTimerDaemonTaskHandle (default)
timers: xTimerGetPeriod (default)
timers: vTimerSetReloadMode (default)
timers: uxTimerGetReloadMode (default)
timers: xTimerGetExpiryTime (default)
timers: pcTimerGetName (default)
timers: prvProcessExpiredTimer (default)
timers: prvTimerTask (default)
timers: prvProcessTimerOrBlockTask (default)
timers: prvGetNextExpireTime (default)
timers: prvSampleTimeNow (default)
timers: prvInsertTimerInActiveList (default)
timers: prvProcessReceivedCommands (default)
timers: prvSwitchTimerLists (default)
timers: prvCheckForValidListAndQueue (default)
timers: xTimerIsTimerActive (default)
timers: pvTimerGetTimerID (default)
timers: vTimerSetTimerID (default)
timers: xTimerPendFunctionCall (default)
# - Only timer function called from ISR is xTimerGenericCommandFromISR() and its dependents
# --------------------------------------------------------------------------------------------------------------
timers:xTimerCreateTimerTask (default)
timers:xTimerCreate (default)
timers:xTimerCreateStatic (default)
timers:prvInitialiseNewTimer (default)
timers:xTimerGenericCommandFromTask (default)
timers:xTimerGetTimerDaemonTaskHandle (default)
timers:xTimerGetPeriod (default)
timers:vTimerSetReloadMode (default)
timers:uxTimerGetReloadMode (default)
timers:xTimerGetExpiryTime (default)
timers:pcTimerGetName (default)
timers:prvProcessExpiredTimer (default)
timers:prvTimerTask (default)
timers:prvProcessTimerOrBlockTask (default)
timers:prvGetNextExpireTime (default)
timers:prvSampleTimeNow (default)
timers:prvInsertTimerInActiveList (default)
timers:prvProcessReceivedCommands (default)
timers:prvSwitchTimerLists (default)
timers:prvCheckForValidListAndQueue (default)
timers:xTimerIsTimerActive (default)
timers:pvTimerGetTimerID (default)
timers:vTimerSetTimerID (default)
timers:xTimerPendFunctionCall (default)
if FREERTOS_USE_TRACE_FACILITY = y:
timers: uxTimerGetTimerNumber (default)
timers: vTimerSetTimerNumber (default)
timers:uxTimerGetTimerNumber (default)
timers:vTimerSetTimerNumber (default)
# --------------------------------------------------------------------------------------------------------------
# portable/xtensa/port.c
# - Most functions are called from an ISR context, except for scheduler/task init/deinit functions
# --------------------------------------------------------------------------------------------------------------
if IDF_TARGET_ARCH_XTENSA = y:
port:vPortSetupTimer (default)
port:xPortStartScheduler (default)
port:vPortEndScheduler (default)
port:pvPortMalloc (default)
port:vPortFree (default)
port:vPortInitialiseBlocks (default)
port:xPortGetFreeHeapSize (default)
if FREERTOS_TASK_FUNCTION_WRAPPER = y:
port:vPortTaskWrapper (default)
port:pxPortInitialiseStack (default)
if FREERTOS_UNICORE = n:
port:vPortCleanUpCoprocArea (default)
if FREERTOS_TLSP_DELETION_CALLBACKS = y:
port:vPortTLSPointersDelCb (default)
port:vPortCleanUpTCB (default)
# --------------------------------------------------------------------------------------------------------------
# portable/riscv/port.c
# - Most functions are called from an ISR context, except for scheduler/task init/deinit functions
# --------------------------------------------------------------------------------------------------------------
if IDF_TARGET_ARCH_RISCV = y:
port:vPortSetupTimer (default)
port:xPortStartScheduler (default)
port:vPortEndScheduler (default)
port:pvPortMalloc (default)
port:vPortFree (default)
port:vPortInitialiseBlocks (default)
port:xPortGetFreeHeapSize (default)
if FREERTOS_TASK_FUNCTION_WRAPPER = y:
port:vPortTaskWrapper (default)
port:pxPortInitialiseStack (default)
if FREERTOS_TLSP_DELETION_CALLBACKS = y:
port:vPortTLSPointersDelCb (default)
port:vPortCleanUpTCB (default)

View File

@@ -0,0 +1,134 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "FreeRTOS.h"
#include "task.h"
#include "esp_system.h"
#include "esp_memory_utils.h"
#include "sdkconfig.h"
/* ----------------------------------------- Port Implementations (Common) --------------------------------------------
* - Common FreeRTOS port function implementations
* - 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.
*/
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize )
{
StaticTask_t *pxTCBBufferTemp;
StackType_t *pxStackBufferTemp;
/* 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(configIDLE_TASK_STACK_SIZE);
#endif /* CONFIG_FREERTOS_SMP */
}
#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(configIDLE_TASK_STACK_SIZE);
pxTCBBufferTemp = pvPortMallocTcbMem(sizeof(StaticTask_t));
#endif /* CONFIG_FREERTOS_SMP */
}
#endif /* portSTACK_GROWTH */
assert(pxTCBBufferTemp != NULL);
assert(pxStackBufferTemp != NULL);
//Write back pointers
*ppxIdleTaskTCBBuffer = pxTCBBufferTemp;
*ppxIdleTaskStackBuffer = pxStackBufferTemp;
#if CONFIG_FREERTOS_SMP
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
#else
*pulIdleTaskStackSize = configIDLE_TASK_STACK_SIZE;
#endif /* CONFIG_FREERTOS_SMP */
}
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize )
{
StaticTask_t *pxTCBBufferTemp;
StackType_t *pxStackBufferTemp;
/* 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 */
}
#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 */
}
#endif /* portSTACK_GROWTH */
assert(pxTCBBufferTemp != NULL);
assert(pxStackBufferTemp != NULL);
//Write back pointers
*ppxTimerTaskTCBBuffer = pxTCBBufferTemp;
*ppxTimerTaskStackBuffer = pxStackBufferTemp;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
#endif // configSUPPORT_STATIC_ALLOCATION == 1

View File

@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import textwrap
@@ -16,7 +16,7 @@ def test_plugins(dut: Dut) -> None:
Successfully registered plugin 'Nihao'
Hello plugin performing self-registration...
Successfully registered plugin 'Hello'
cpu_start: Starting scheduler
main_task: Calling app_main()
List of plugins:
- Plugin 'Hello'
- Plugin 'Nihao'

View File

@@ -286,8 +286,8 @@ def test_examples_efuse_with_virt_secure_boot_v1(env, _): # type: (ttfw_idf.Tin
dut.expect('Disable ROM BASIC interpreter fallback...')
dut.expect('secure_boot_v1: secure boot is now enabled for bootloader image')
dut.expect('cpu_start: Pro cpu up')
dut.expect('Loading virtual efuse blocks from flash')
dut.expect('main_task: Calling app_main()')
dut.expect('Start eFuse example')
dut.expect('example: Done')
@@ -312,8 +312,8 @@ def test_examples_efuse_with_virt_secure_boot_v1_pre_loaded(env, _): # type: (t
dut.bootloader_flash()
dut.start_app()
dut.expect('Loading virtual efuse blocks from real efuses')
dut.expect('cpu_start: Pro cpu up')
dut.expect('Loading virtual efuse blocks from flash')
dut.expect('main_task: Calling app_main()')
dut.expect('Start eFuse example')
dut.expect('example: Done')
@@ -339,8 +339,8 @@ def test_examples_efuse_with_virt_secure_boot_v1_pre_loaded(env, _): # type: (t
dut.expect('Disable ROM BASIC interpreter fallback...')
dut.expect('secure_boot_v1: secure boot is now enabled for bootloader image')
dut.expect('cpu_start: Pro cpu up')
dut.expect('Loading virtual efuse blocks from flash')
dut.expect('main_task: Calling app_main()')
dut.expect('Start eFuse example')
dut.expect('example: Done')
@@ -527,8 +527,8 @@ def test_examples_efuse_with_virt_secure_boot_v2_esp32xx(env, _): # type: (ttfw
dut.expect('Disable hardware & software JTAG...')
dut.expect('secure_boot_v2: Secure boot permanently enabled')
dut.expect('cpu_start: Pro cpu up')
dut.expect('Loading virtual efuse blocks from flash')
dut.expect('main_task: Calling app_main()')
dut.expect('Start eFuse example')
dut.expect('example: Done')
@@ -554,8 +554,8 @@ def test_examples_efuse_with_virt_secure_boot_v2_esp32xx_pre_loaded(env, _): #
dut.bootloader_flash()
dut.start_app()
dut.expect('Loading virtual efuse blocks from real efuses')
dut.expect('cpu_start: Pro cpu up')
dut.expect('Loading virtual efuse blocks from flash')
dut.expect('main_task: Calling app_main()')
dut.expect('Start eFuse example')
dut.expect('example: Done')
@@ -595,8 +595,8 @@ def test_examples_efuse_with_virt_secure_boot_v2_esp32xx_pre_loaded(env, _): #
dut.expect('Disable hardware & software JTAG...')
dut.expect('secure_boot_v2: Secure boot permanently enabled')
dut.expect('cpu_start: Pro cpu up')
dut.expect('Loading virtual efuse blocks from flash')
dut.expect('main_task: Calling app_main()')
dut.expect('Start eFuse example')
dut.expect('example: Done')
@@ -665,7 +665,6 @@ def test_examples_efuse_with_virt_sb_v1_and_fe(env, _): # type: (ttfw_idf.TinyF
dut.expect('Checking secure boot...')
dut.expect('secure_boot_v1: bootloader secure boot is already enabled, continuing..')
dut.expect('cpu_start: Pro cpu up')
dut.expect('Loading virtual efuse blocks from flash')
dut.expect('flash_encrypt: Flash encryption mode is DEVELOPMENT (not secure)')
dut.expect('Start eFuse example')

View File

@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
@@ -16,7 +16,7 @@ from pytest_embedded import Dut
@pytest.mark.generic
def test_eventfd(dut: Dut) -> None:
dut.expect_exact('cpu_start: Starting scheduler')
dut.expect_exact('main_task: Calling app_main()')
exp_list_5seconds = [
'eventfd_example: Select timeouted for 1 times',

View File

@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
import os
@@ -25,7 +25,7 @@ def get_uart_msgs(i: int) -> List[str]:
@pytest.mark.generic
def test_examples_select(dut: Dut) -> None:
dut.expect_exact('cpu_start: Starting scheduler', timeout=30)
dut.expect_exact('main_task: Calling app_main()', timeout=30)
exp_list = []
for i in range(1, 10):

View File

@@ -21,8 +21,10 @@
static void unity_task(void *pvParameters)
{
vTaskDelay(2); /* Delay a bit to let the main task be deleted */
unity_run_menu(); /* Doesn't return */
// Delay a bit to let the main task and any other startup tasks be deleted
vTaskDelay(pdMS_TO_TICKS(50));
// Start running unity (prints test menu and doesn't return)
unity_run_menu();
}
void test_main(void)