Select one of the symbols to view example projects that use it.
 
Outline
#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"
#include "esp_psram.h"
#include "esp_private/esp_psram_extram.h"
#include "esp_app_trace.h"
#include "esp_gdbstub.h"
Checks
Declarations
APP_START_TAG
CPU0 App Startup
esp_startup_start_app()
esp_startup_start_app_other_cores()
MAIN_TAG
s_other_cpu_startup_done
other_cpu_startup_idle_hook_cb()
main_task(void *)
Files
loading...
SourceVuESP-IDF Framework and ExamplesFreeRTOSapp_startup.c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * SPDX-FileCopyrightText: 2022-2024 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"14 includes #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 Checks // -------------------- Declarations ----------------------- static void main_task(void* args); static const char* APP_START_TAG = "app_start"; Declarations // ------------------ 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 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_LOGD(APP_START_TAG, "Starting scheduler on CPU0"); vTaskStartScheduler(); }{ ... } CPU0 App Startup// --------------- 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_LOGD(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", (int)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); }{ ... }
Details