mirror of
https://github.com/espressif/esp-idf.git
synced 2025-12-16 04:22:22 +00:00
freertos: Refactor OS startup functions
This commit refactors the OS startup functions as follows:
- Moved the OS/app startup functions listed below to "app_startup.c". Their
implementations are now common to all ports (RISC-V and Xtensa) of all
FreeRTOS implementations (IDF and Amazon SMP).
- esp_startup_start_app()
- esp_startup_start_app_other_cores()
- Removed esp_startup_start_app_common() as app startup functions are now
already common to all ports.
- Added extra logs to "main_task" to help with user debugging
Note: Increased startup delay on "unity_task". The "unity_run_menu()" is non
blocking, thus if the main task or other startup tasks have not been freed
by the time "unity_run_menu()" is run, those tasks will be freed the next time
"unity_task" blocks. This could cause some tests to have a memory leak, thus
the "unity_task" startup delay has increased.
This commit is contained in:
@@ -7,130 +7,9 @@
|
||||
#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 -----------------------
|
||||
|
||||
|
||||
@@ -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];
|
||||
@@ -473,16 +471,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();
|
||||
}
|
||||
|
||||
@@ -69,15 +69,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");
|
||||
|
||||
@@ -88,8 +84,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};
|
||||
@@ -618,53 +613,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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user