• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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