1 // Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <stdint.h>
16 #include <string.h>
17
18 #include "esp_attr.h"
19 #include "esp_err.h"
20
21 #include "esp_system.h"
22 #include "esp_log.h"
23 #include "esp_ota_ops.h"
24
25 #include "sdkconfig.h"
26
27 #include "soc/soc_caps.h"
28 #include "hal/wdt_hal.h"
29 #include "hal/uart_types.h"
30 #include "hal/uart_ll.h"
31
32 #include "esp_system.h"
33 #include "esp_log.h"
34 #include "esp_heap_caps_init.h"
35 #include "esp_spi_flash.h"
36 #include "esp_flash_internal.h"
37 #include "esp_newlib.h"
38 #include "esp_timer.h"
39 #include "esp_efuse.h"
40 #include "esp_flash_encrypt.h"
41 #include "esp_secure_boot.h"
42 #include "esp_sleep.h"
43
44 /***********************************************/
45 // Headers for other components init functions
46 #include "nvs_flash.h"
47 #include "esp_phy_init.h"
48 #include "esp_coexist_internal.h"
49 //#include "esp_core_dump.h"
50 // #include "esp_app_trace.h"
51 #include "esp_private/dbg_stubs.h"
52 #include "esp_pthread.h"
53 #include "esp_private/usb_console.h"
54
55 #include "esp_rom_sys.h"
56
57 // [refactor-todo] make this file completely target-independent
58 #if CONFIG_IDF_TARGET_ESP32
59 #include "esp32/clk.h"
60 #include "esp32/spiram.h"
61 #include "esp32/brownout.h"
62 #elif CONFIG_IDF_TARGET_ESP32S2
63 #include "esp32s2/clk.h"
64 #include "esp32s2/spiram.h"
65 #include "esp32s2/brownout.h"
66 #elif CONFIG_IDF_TARGET_ESP32S3
67 #include "esp32s3/clk.h"
68 #include "esp32s3/spiram.h"
69 #include "esp32s3/brownout.h"
70 #elif CONFIG_IDF_TARGET_ESP32C3
71 #include "esp32c3/clk.h"
72 #include "esp32c3/brownout.h"
73 #endif
74 /***********************************************/
75
76 #include "esp_private/startup_internal.h"
77
78 // Ensure that system configuration matches the underlying number of cores.
79 // This should enable us to avoid checking for both everytime.
80 #if !(SOC_CPU_CORES_NUM > 1) && !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
81 #error "System has been configured to run on multiple cores, but target SoC only has a single core."
82 #endif
83
84 #define STRINGIFY(s) STRINGIFY2(s)
85 #define STRINGIFY2(s) #s
86
87 uint64_t g_startup_time = 0;
88
89 #if SOC_APB_BACKUP_DMA
90 // APB DMA lock initialising API
91 extern void esp_apb_backup_dma_lock_init(void);
92 #endif
93
94 // App entry point for core 0
95 extern void esp_startup_start_app(void);
96
97 // Entry point for core 0 from hardware init (port layer)
98 void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default"))) __attribute__((noreturn));
99
100 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
101 // Entry point for core [1..X] from hardware init (port layer)
102 void start_cpu_other_cores(void) __attribute__((weak, alias("start_cpu_other_cores_default"))) __attribute__((noreturn));
103
104 // App entry point for core [1..X]
105 void esp_startup_start_app_other_cores(void) __attribute__((weak, alias("esp_startup_start_app_other_cores_default"))) __attribute__((noreturn));
106
107 static volatile bool s_system_inited[SOC_CPU_CORES_NUM] = { false };
108
109 const sys_startup_fn_t g_startup_fn[SOC_CPU_CORES_NUM] = { [0] = start_cpu0,
110 #if SOC_CPU_CORES_NUM > 1
111 [1 ... SOC_CPU_CORES_NUM - 1] = start_cpu_other_cores
112 #endif
113 };
114
115 static volatile bool s_system_full_inited = false;
116 #else
117 const sys_startup_fn_t g_startup_fn[1] = { start_cpu0 };
118 #endif
119
120 #ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
121 // workaround for C++ exception crashes
122 void _Unwind_SetNoFunctionContextInstall(unsigned char enable) __attribute__((weak, alias("_Unwind_SetNoFunctionContextInstall_Default")));
123 // workaround for C++ exception large memory allocation
124 void _Unwind_SetEnableExceptionFdeSorting(unsigned char enable);
125
_Unwind_SetNoFunctionContextInstall_Default(unsigned char enable)126 static IRAM_ATTR void _Unwind_SetNoFunctionContextInstall_Default(unsigned char enable __attribute__((unused)))
127 {
128 (void)0;
129 }
130 #endif // CONFIG_COMPILER_CXX_EXCEPTIONS
131
132 static const char* TAG = "cpu_start";
133
134 /**
135 * This function overwrites a the same function of libsupc++ (part of libstdc++).
136 * Consequently, libsupc++ will then follow our configured exception emergency pool size.
137 *
138 * It will be called even with -fno-exception for user code since the stdlib still uses exceptions.
139 */
__cxx_eh_arena_size_get(void)140 size_t __cxx_eh_arena_size_get(void)
141 {
142 #ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
143 return CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE;
144 #else
145 return 0;
146 #endif
147 }
148
149 /**
150 * Xtensa gcc is configured to emit a .ctors section, RISC-V gcc is configured with --enable-initfini-array
151 * so it emits an .init_array section instead.
152 * But the init_priority sections will be sorted for iteration in ascending order during startup.
153 * The rest of the init_array sections is sorted for iteration in descending order during startup, however.
154 * Hence a different section is generated for the init_priority functions which is looped
155 * over in ascending direction instead of descending direction.
156 * The RISC-V-specific behavior is dependent on the linker script esp32c3.project.ld.in.
157 */
do_global_ctors(void)158 static void do_global_ctors(void)
159 {
160 #if __riscv
161 extern void (*__init_priority_array_start)(void);
162 extern void (*__init_priority_array_end)(void);
163 #endif
164
165 extern void (*__init_array_start)(void);
166 extern void (*__init_array_end)(void);
167
168 #ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
169 struct object { long placeholder[ 10 ]; };
170 void __register_frame_info (const void *begin, struct object *ob);
171 extern char __eh_frame[];
172
173 static struct object ob;
174 __register_frame_info( __eh_frame, &ob );
175 #endif // CONFIG_COMPILER_CXX_EXCEPTIONS
176
177 void (**p)(void);
178
179 #if __riscv
180 for (p = &__init_priority_array_start; p < &__init_priority_array_end; ++p) {
181 ESP_EARLY_LOGD(TAG, "calling init function: %p", *p);
182 (*p)();
183 }
184 #endif
185
186 for (p = &__init_array_end - 1; p >= &__init_array_start; --p) {
187 ESP_EARLY_LOGD(TAG, "calling init function: %p", *p);
188 (*p)();
189 }
190 }
191
do_system_init_fn(void)192 static void do_system_init_fn(void)
193 {
194 extern esp_system_init_fn_t _esp_system_init_fn_array_start;
195 extern esp_system_init_fn_t _esp_system_init_fn_array_end;
196
197 esp_system_init_fn_t *p;
198
199 for (p = &_esp_system_init_fn_array_end - 1; p >= &_esp_system_init_fn_array_start; --p) {
200 if (p->cores & BIT(cpu_hal_get_core_id())) {
201 (*(p->fn))();
202 }
203 }
204
205 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
206 s_system_inited[cpu_hal_get_core_id()] = true;
207 #endif
208 }
209
210 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
esp_startup_start_app_other_cores_default(void)211 static void esp_startup_start_app_other_cores_default(void)
212 {
213 while (1) {
214 esp_rom_delay_us(UINT32_MAX);
215 }
216 }
217
start_cpu_other_cores_default(void)218 static void IRAM_ATTR start_cpu_other_cores_default(void)
219 {
220 do_system_init_fn();
221
222 while (!s_system_full_inited) {
223 esp_rom_delay_us(100);
224 }
225
226 esp_startup_start_app_other_cores();
227 }
228 #endif
229
do_core_init(void)230 static void do_core_init(void)
231 {
232 /* Initialize heap allocator. WARNING: This *needs* to happen *after* the app cpu has booted.
233 If the heap allocator is initialized first, it will put free memory linked list items into
234 memory also used by the ROM. Starting the app cpu will let its ROM initialize that memory,
235 corrupting those linked lists. Initializing the allocator *after* the app cpu has booted
236 works around this problem.
237 With SPI RAM enabled, there's a second reason: half of the SPI RAM will be managed by the
238 app CPU, and when that is not up yet, the memory will be inaccessible and heap_caps_init may
239 fail initializing it properly. */
240 heap_caps_init();
241 {
242 extern uint32_t LOS_KernelInit(void);
243 LOS_KernelInit();
244 }
245 esp_newlib_init();
246 esp_newlib_time_init();
247
248 if (g_spiram_ok) {
249 #if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
250 esp_err_t r=esp_spiram_add_to_heapalloc();
251 if (r != ESP_OK) {
252 ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!");
253 abort();
254 }
255 #if CONFIG_SPIRAM_USE_MALLOC
256 heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
257 #endif
258 #endif
259 }
260
261 #if CONFIG_ESP32_BROWNOUT_DET || \
262 CONFIG_ESP32S2_BROWNOUT_DET || \
263 CONFIG_ESP32S3_BROWNOUT_DET || \
264 CONFIG_ESP32C3_BROWNOUT_DET
265 // [refactor-todo] leads to call chain rtc_is_register (driver) -> esp_intr_alloc (esp32/esp32s2) ->
266 // malloc (newlib) -> heap_caps_malloc (heap), so heap must be at least initialized
267 esp_brownout_init();
268 #endif
269
270 #ifdef CONFIG_VFS_SUPPORT_IO
271 #ifdef CONFIG_ESP_CONSOLE_UART
272 esp_vfs_dev_uart_register();
273 const char *default_stdio_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
274 #endif // CONFIG_ESP_CONSOLE_UART
275 #ifdef CONFIG_ESP_CONSOLE_USB_CDC
276 ESP_ERROR_CHECK(esp_usb_console_init());
277 ESP_ERROR_CHECK(esp_vfs_dev_cdcacm_register());
278 const char *default_stdio_dev = "/dev/cdcacm";
279 #endif // CONFIG_ESP_CONSOLE_USB_CDC
280 #endif // CONFIG_VFS_SUPPORT_IO
281
282 #if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE)
283 esp_reent_init(_GLOBAL_REENT);
284 _GLOBAL_REENT->_stdin = fopen(default_stdio_dev, "r");
285 _GLOBAL_REENT->_stdout = fopen(default_stdio_dev, "w");
286 _GLOBAL_REENT->_stderr = fopen(default_stdio_dev, "w");
287 #else // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE)
288 _REENT_SMALL_CHECK_INIT(_GLOBAL_REENT);
289 #endif // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE)
290
291 esp_err_t err __attribute__((unused));
292
293 #if CONFIG_SECURE_DISABLE_ROM_DL_MODE
294 err = esp_efuse_disable_rom_download_mode();
295 assert(err == ESP_OK && "Failed to disable ROM download mode");
296 #endif
297
298 #if CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
299 err = esp_efuse_enable_rom_secure_download_mode();
300 assert(err == ESP_OK && "Failed to enable Secure Download mode");
301 #endif
302
303 #if CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE
304 esp_efuse_disable_basic_rom_console();
305 #endif
306
307 // [refactor-todo] move this to secondary init
308 #if CONFIG_APPTRACE_ENABLE
309 err = esp_apptrace_init();
310 assert(err == ESP_OK && "Failed to init apptrace module on PRO CPU!");
311 #endif
312 #if CONFIG_SYSVIEW_ENABLE
313 SEGGER_SYSVIEW_Conf();
314 #endif
315
316 #if CONFIG_ESP_DEBUG_STUBS_ENABLE
317 esp_dbg_stubs_init();
318 #endif
319
320 // err = esp_pthread_init();
321 // assert(err == ESP_OK && "Failed to init pthread module!");
322
323 spi_flash_init();
324 /* init default OS-aware flash access critical section */
325 spi_flash_guard_set(&g_flash_guard_default_ops);
326
327 esp_flash_app_init();
328 esp_err_t flash_ret = esp_flash_init_default_chip();
329 assert(flash_ret == ESP_OK);
330
331 #ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
332 esp_flash_encryption_init_checks();
333 #endif
334
335 #if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT)
336 // Note: in some configs this may read flash, so placed after flash init
337 esp_secure_boot_init_checks();
338 #endif
339 }
340
do_secondary_init(void)341 static void do_secondary_init(void)
342 {
343 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
344 // The port layer transferred control to this function with other cores 'paused',
345 // resume execution so that cores might execute component initialization functions.
346 startup_resume_other_cores();
347 #endif
348
349 // Execute initialization functions esp_system_init_fn_t assigned to the main core. While
350 // this is happening, all other cores are executing the initialization functions
351 // assigned to them since they have been resumed already.
352 do_system_init_fn();
353
354 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
355 // Wait for all cores to finish secondary init.
356 volatile bool system_inited = false;
357
358 while (!system_inited) {
359 system_inited = true;
360 for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
361 system_inited &= s_system_inited[i];
362 }
363 esp_rom_delay_us(100);
364 }
365 #endif
366 }
367
start_cpu0_default(void)368 static void start_cpu0_default(void)
369 {
370
371 ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
372 int cpu_freq = esp_clk_cpu_freq();
373 ESP_EARLY_LOGI(TAG, "cpu freq: %d", cpu_freq);
374
375 // Display information about the current running image.
376 if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) {
377 const esp_app_desc_t *app_desc = esp_ota_get_app_description();
378 ESP_EARLY_LOGI(TAG, "Application information:");
379 #ifndef CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR
380 ESP_EARLY_LOGI(TAG, "Project name: %s", app_desc->project_name);
381 #endif
382 #ifndef CONFIG_APP_EXCLUDE_PROJECT_VER_VAR
383 ESP_EARLY_LOGI(TAG, "App version: %s", app_desc->version);
384 #endif
385 #ifdef CONFIG_BOOTLOADER_APP_SECURE_VERSION
386 ESP_EARLY_LOGI(TAG, "Secure version: %d", app_desc->secure_version);
387 #endif
388 #ifdef CONFIG_APP_COMPILE_TIME_DATE
389 ESP_EARLY_LOGI(TAG, "Compile time: %s %s", app_desc->date, app_desc->time);
390 #endif
391 char buf[17];
392 esp_ota_get_app_elf_sha256(buf, sizeof(buf));
393 ESP_EARLY_LOGI(TAG, "ELF file SHA256: %s...", buf);
394 ESP_EARLY_LOGI(TAG, "ESP-IDF: %s", app_desc->idf_ver);
395 }
396
397 // Initialize core components and services.
398 do_core_init();
399
400 // Execute constructors.
401 do_global_ctors();
402
403 // Execute init functions of other components; blocks
404 // until all cores finish (when !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE).
405 do_secondary_init();
406
407 // Now that the application is about to start, disable boot watchdog
408 #ifndef CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE
409 wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
410 wdt_hal_write_protect_disable(&rtc_wdt_ctx);
411 wdt_hal_disable(&rtc_wdt_ctx);
412 wdt_hal_write_protect_enable(&rtc_wdt_ctx);
413 #endif
414
415 #if SOC_CPU_CORES_NUM > 1 && !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
416 s_system_full_inited = true;
417 #endif
418
419 esp_startup_start_app();
420 while (1);
421 }
422
423 IRAM_ATTR ESP_SYSTEM_INIT_FN(init_components0, BIT(0))
424 {
425 esp_timer_init();
426
427 #if CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND && !CONFIG_PM_SLP_DISABLE_GPIO
428 /* Configure to isolate (disable the Input/Output/Pullup/Pulldown
429 * function of the pin) all GPIO pins in sleep state
430 */
431 esp_sleep_config_gpio_isolate();
432 /* Enable automatic switching of GPIO configuration */
433 esp_sleep_enable_gpio_switch(true);
434 #endif
435
436 #if defined(CONFIG_PM_ENABLE)
437 esp_pm_impl_init();
438 #endif
439
440 #if CONFIG_ESP_COREDUMP_ENABLE
441 esp_core_dump_init();
442 #endif
443
444 #if SOC_APB_BACKUP_DMA
445 esp_apb_backup_dma_lock_init();
446 #endif
447
448 #if CONFIG_SW_COEXIST_ENABLE
449 esp_coex_adapter_register(&g_coex_adapter_funcs);
450 coex_pre_init();
451 #endif
452
453 #ifdef CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
454 const esp_partition_t *efuse_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_EFUSE_EM, NULL);
455 if (efuse_partition) {
456 esp_efuse_init(efuse_partition->address, efuse_partition->size);
457 }
458 #endif
459
460 #ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
461 ESP_EARLY_LOGD(TAG, "Setting C++ exception workarounds.");
462 _Unwind_SetNoFunctionContextInstall(1);
463 _Unwind_SetEnableExceptionFdeSorting(0);
464 #endif // CONFIG_COMPILER_CXX_EXCEPTIONS
465 }
466