forked from espressif/esp-idf
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:
@@ -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")
|
||||
|
||||
|
@@ -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
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
@@ -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();
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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
|
||||
|
211
components/freertos/app_startup.c
Normal file
211
components/freertos/app_startup.c
Normal 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);
|
||||
}
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
62
components/freertos/linker_common.lf
Normal file
62
components/freertos/linker_common.lf
Normal 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)
|
@@ -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)
|
||||
|
134
components/freertos/port_common.c
Normal file
134
components/freertos/port_common.c
Normal 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
|
@@ -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'
|
||||
|
@@ -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')
|
||||
|
@@ -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',
|
||||
|
@@ -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):
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user