startup.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  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. #include <stdint.h>
  15. #include <string.h>
  16. #include "esp_attr.h"
  17. #include "esp_err.h"
  18. #include "esp_system.h"
  19. #include "esp_log.h"
  20. #include "esp_ota_ops.h"
  21. #include "sdkconfig.h"
  22. #include "soc/soc_caps.h"
  23. #include "hal/wdt_hal.h"
  24. #include "hal/uart_types.h"
  25. #include "hal/uart_ll.h"
  26. #include "esp_system.h"
  27. #include "esp_log.h"
  28. #include "esp_heap_caps_init.h"
  29. #include "esp_spi_flash.h"
  30. #include "esp_flash_internal.h"
  31. #include "esp_newlib.h"
  32. #include "esp_vfs_dev.h"
  33. #include "esp_timer.h"
  34. #include "esp_efuse.h"
  35. #include "esp_flash_encrypt.h"
  36. #include "esp_secure_boot.h"
  37. /***********************************************/
  38. // Headers for other components init functions
  39. #include "nvs_flash.h"
  40. #include "esp_phy_init.h"
  41. #include "esp_coexist_internal.h"
  42. #if CONFIG_ESP_COREDUMP_ENABLE
  43. #include "esp_core_dump.h"
  44. #endif
  45. #include "esp_app_trace.h"
  46. #include "esp_private/dbg_stubs.h"
  47. #include "esp_pm.h"
  48. #include "esp_private/pm_impl.h"
  49. #include "esp_pthread.h"
  50. #include "esp_private/usb_console.h"
  51. #include "esp_vfs_cdcacm.h"
  52. #include "esp_rom_sys.h"
  53. // [refactor-todo] make this file completely target-independent
  54. #if CONFIG_IDF_TARGET_ESP32
  55. #include "esp32/clk.h"
  56. #include "esp32/spiram.h"
  57. #include "esp32/brownout.h"
  58. #elif CONFIG_IDF_TARGET_ESP32S2
  59. #include "esp32s2/clk.h"
  60. #include "esp32s2/spiram.h"
  61. #include "esp32s2/brownout.h"
  62. #elif CONFIG_IDF_TARGET_ESP32S3
  63. #include "esp32s3/clk.h"
  64. #include "esp32s3/spiram.h"
  65. #include "esp32s3/brownout.h"
  66. #elif CONFIG_IDF_TARGET_ESP32C3
  67. #include "esp32c3/clk.h"
  68. #include "esp32c3/brownout.h"
  69. #endif
  70. /***********************************************/
  71. #include "esp_private/startup_internal.h"
  72. // Ensure that system configuration matches the underlying number of cores.
  73. // This should enable us to avoid checking for both everytime.
  74. #if !(SOC_CPU_CORES_NUM > 1) && !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
  75. #error "System has been configured to run on multiple cores, but target SoC only has a single core."
  76. #endif
  77. #define STRINGIFY(s) STRINGIFY2(s)
  78. #define STRINGIFY2(s) #s
  79. uint64_t g_startup_time = 0;
  80. #if SOC_APB_BACKUP_DMA
  81. // APB DMA lock initialising API
  82. extern void esp_apb_backup_dma_lock_init(void);
  83. #endif
  84. // App entry point for core 0
  85. extern void esp_startup_start_app(void);
  86. // Entry point for core 0 from hardware init (port layer)
  87. void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default"))) __attribute__((noreturn));
  88. #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
  89. // Entry point for core [1..X] from hardware init (port layer)
  90. void start_cpu_other_cores(void) __attribute__((weak, alias("start_cpu_other_cores_default"))) __attribute__((noreturn));
  91. // App entry point for core [1..X]
  92. void esp_startup_start_app_other_cores(void) __attribute__((weak, alias("esp_startup_start_app_other_cores_default"))) __attribute__((noreturn));
  93. static volatile bool s_system_inited[SOC_CPU_CORES_NUM] = { false };
  94. sys_startup_fn_t g_startup_fn[SOC_CPU_CORES_NUM] = { [0] = start_cpu0,
  95. #if SOC_CPU_CORES_NUM > 1
  96. [1 ... SOC_CPU_CORES_NUM - 1] = start_cpu_other_cores
  97. #endif
  98. };
  99. static volatile bool s_system_full_inited = false;
  100. #else
  101. sys_startup_fn_t g_startup_fn[1] = { start_cpu0 };
  102. #endif
  103. #ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
  104. // workaround for C++ exception crashes
  105. void _Unwind_SetNoFunctionContextInstall(unsigned char enable) __attribute__((weak, alias("_Unwind_SetNoFunctionContextInstall_Default")));
  106. // workaround for C++ exception large memory allocation
  107. void _Unwind_SetEnableExceptionFdeSorting(unsigned char enable);
  108. static IRAM_ATTR void _Unwind_SetNoFunctionContextInstall_Default(unsigned char enable __attribute__((unused)))
  109. {
  110. (void)0;
  111. }
  112. #endif // CONFIG_COMPILER_CXX_EXCEPTIONS
  113. static const char* TAG = "cpu_start";
  114. /**
  115. * Xtensa gcc is configured to emit a .ctors section, RISC-V gcc is configured with --enable-initfini-array
  116. * so it emits an .init_array section instead.
  117. * But the init_priority sections will be sorted for iteration in ascending order during startup.
  118. * The rest of the init_array sections is sorted for iteration in descending order during startup, however.
  119. * Hence a different section is generated for the init_priority functions which is looped
  120. * over in ascending direction instead of descending direction.
  121. * The RISC-V-specific behavior is dependent on the linker script esp32c3.project.ld.in.
  122. */
  123. static void do_global_ctors(void)
  124. {
  125. #if __riscv
  126. extern void (*__init_priority_array_start)(void);
  127. extern void (*__init_priority_array_end)(void);
  128. #endif
  129. extern void (*__init_array_start)(void);
  130. extern void (*__init_array_end)(void);
  131. #ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
  132. struct object { long placeholder[ 10 ]; };
  133. void __register_frame_info (const void *begin, struct object *ob);
  134. extern char __eh_frame[];
  135. static struct object ob;
  136. __register_frame_info( __eh_frame, &ob );
  137. #endif // CONFIG_COMPILER_CXX_EXCEPTIONS
  138. void (**p)(void);
  139. #if __riscv
  140. for (p = &__init_priority_array_start; p < &__init_priority_array_end; ++p) {
  141. ESP_EARLY_LOGD(TAG, "calling init function: %p", *p);
  142. (*p)();
  143. }
  144. #endif
  145. for (p = &__init_array_end - 1; p >= &__init_array_start; --p) {
  146. ESP_EARLY_LOGD(TAG, "calling init function: %p", *p);
  147. (*p)();
  148. }
  149. }
  150. static void do_system_init_fn(void)
  151. {
  152. extern esp_system_init_fn_t _esp_system_init_fn_array_start;
  153. extern esp_system_init_fn_t _esp_system_init_fn_array_end;
  154. esp_system_init_fn_t *p;
  155. for (p = &_esp_system_init_fn_array_end - 1; p >= &_esp_system_init_fn_array_start; --p) {
  156. if (p->cores & BIT(cpu_hal_get_core_id())) {
  157. (*(p->fn))();
  158. }
  159. }
  160. #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
  161. s_system_inited[cpu_hal_get_core_id()] = true;
  162. #endif
  163. }
  164. #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
  165. static void esp_startup_start_app_other_cores_default(void)
  166. {
  167. while (1) {
  168. esp_rom_delay_us(UINT32_MAX);
  169. }
  170. }
  171. static void IRAM_ATTR start_cpu_other_cores_default(void)
  172. {
  173. do_system_init_fn();
  174. while (!s_system_full_inited) {
  175. esp_rom_delay_us(100);
  176. }
  177. esp_startup_start_app_other_cores();
  178. }
  179. #endif
  180. static void do_core_init(void)
  181. {
  182. /* Initialize heap allocator. WARNING: This *needs* to happen *after* the app cpu has booted.
  183. If the heap allocator is initialized first, it will put free memory linked list items into
  184. memory also used by the ROM. Starting the app cpu will let its ROM initialize that memory,
  185. corrupting those linked lists. Initializing the allocator *after* the app cpu has booted
  186. works around this problem.
  187. With SPI RAM enabled, there's a second reason: half of the SPI RAM will be managed by the
  188. app CPU, and when that is not up yet, the memory will be inaccessible and heap_caps_init may
  189. fail initializing it properly. */
  190. heap_caps_init();
  191. esp_newlib_init();
  192. esp_newlib_time_init();
  193. if (g_spiram_ok) {
  194. #if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
  195. esp_err_t r=esp_spiram_add_to_heapalloc();
  196. if (r != ESP_OK) {
  197. ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!");
  198. abort();
  199. }
  200. #if CONFIG_SPIRAM_USE_MALLOC
  201. heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
  202. #endif
  203. #endif
  204. }
  205. #if CONFIG_ESP32_BROWNOUT_DET || \
  206. CONFIG_ESP32S2_BROWNOUT_DET || \
  207. CONFIG_ESP32S3_BROWNOUT_DET || \
  208. CONFIG_ESP32C3_BROWNOUT_DET
  209. // [refactor-todo] leads to call chain rtc_is_register (driver) -> esp_intr_alloc (esp32/esp32s2) ->
  210. // malloc (newlib) -> heap_caps_malloc (heap), so heap must be at least initialized
  211. esp_brownout_init();
  212. #endif
  213. #ifdef CONFIG_VFS_SUPPORT_IO
  214. #ifdef CONFIG_ESP_CONSOLE_UART
  215. esp_vfs_dev_uart_register();
  216. const char *default_stdio_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
  217. #endif // CONFIG_ESP_CONSOLE_UART
  218. #ifdef CONFIG_ESP_CONSOLE_USB_CDC
  219. ESP_ERROR_CHECK(esp_usb_console_init());
  220. ESP_ERROR_CHECK(esp_vfs_dev_cdcacm_register());
  221. const char *default_stdio_dev = "/dev/cdcacm";
  222. #endif // CONFIG_ESP_CONSOLE_USB_CDC
  223. #endif // CONFIG_VFS_SUPPORT_IO
  224. #if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE)
  225. esp_reent_init(_GLOBAL_REENT);
  226. _GLOBAL_REENT->_stdin = fopen(default_stdio_dev, "r");
  227. _GLOBAL_REENT->_stdout = fopen(default_stdio_dev, "w");
  228. _GLOBAL_REENT->_stderr = fopen(default_stdio_dev, "w");
  229. #else // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE)
  230. _REENT_SMALL_CHECK_INIT(_GLOBAL_REENT);
  231. #endif // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE)
  232. #ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
  233. esp_flash_encryption_init_checks();
  234. #endif
  235. #ifdef CONFIG_SECURE_BOOT
  236. esp_secure_boot_init_checks();
  237. #endif
  238. esp_err_t err;
  239. #if CONFIG_SECURE_DISABLE_ROM_DL_MODE
  240. err = esp_efuse_disable_rom_download_mode();
  241. assert(err == ESP_OK && "Failed to disable ROM download mode");
  242. #endif
  243. #if CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
  244. err = esp_efuse_enable_rom_secure_download_mode();
  245. assert(err == ESP_OK && "Failed to enable Secure Download mode");
  246. #endif
  247. #if CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE
  248. esp_efuse_disable_basic_rom_console();
  249. #endif
  250. // [refactor-todo] move this to secondary init
  251. #if CONFIG_APPTRACE_ENABLE
  252. err = esp_apptrace_init();
  253. assert(err == ESP_OK && "Failed to init apptrace module on PRO CPU!");
  254. #endif
  255. #if CONFIG_SYSVIEW_ENABLE
  256. SEGGER_SYSVIEW_Conf();
  257. #endif
  258. #if CONFIG_ESP_DEBUG_STUBS_ENABLE
  259. esp_dbg_stubs_init();
  260. #endif
  261. err = esp_pthread_init();
  262. assert(err == ESP_OK && "Failed to init pthread module!");
  263. spi_flash_init();
  264. /* init default OS-aware flash access critical section */
  265. spi_flash_guard_set(&g_flash_guard_default_ops);
  266. esp_flash_app_init();
  267. esp_err_t flash_ret = esp_flash_init_default_chip();
  268. assert(flash_ret == ESP_OK);
  269. }
  270. static void do_secondary_init(void)
  271. {
  272. #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
  273. // The port layer transferred control to this function with other cores 'paused',
  274. // resume execution so that cores might execute component initialization functions.
  275. startup_resume_other_cores();
  276. #endif
  277. // Execute initialization functions esp_system_init_fn_t assigned to the main core. While
  278. // this is happening, all other cores are executing the initialization functions
  279. // assigned to them since they have been resumed already.
  280. do_system_init_fn();
  281. #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
  282. // Wait for all cores to finish secondary init.
  283. volatile bool system_inited = false;
  284. while (!system_inited) {
  285. system_inited = true;
  286. for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
  287. system_inited &= s_system_inited[i];
  288. }
  289. esp_rom_delay_us(100);
  290. }
  291. #endif
  292. }
  293. static void start_cpu0_default(void)
  294. {
  295. ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
  296. int cpu_freq = esp_clk_cpu_freq();
  297. ESP_EARLY_LOGI(TAG, "cpu freq: %d", cpu_freq);
  298. // Display information about the current running image.
  299. if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) {
  300. const esp_app_desc_t *app_desc = esp_ota_get_app_description();
  301. ESP_EARLY_LOGI(TAG, "Application information:");
  302. #ifndef CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR
  303. ESP_EARLY_LOGI(TAG, "Project name: %s", app_desc->project_name);
  304. #endif
  305. #ifndef CONFIG_APP_EXCLUDE_PROJECT_VER_VAR
  306. ESP_EARLY_LOGI(TAG, "App version: %s", app_desc->version);
  307. #endif
  308. #ifdef CONFIG_BOOTLOADER_APP_SECURE_VERSION
  309. ESP_EARLY_LOGI(TAG, "Secure version: %d", app_desc->secure_version);
  310. #endif
  311. #ifdef CONFIG_APP_COMPILE_TIME_DATE
  312. ESP_EARLY_LOGI(TAG, "Compile time: %s %s", app_desc->date, app_desc->time);
  313. #endif
  314. char buf[17];
  315. esp_ota_get_app_elf_sha256(buf, sizeof(buf));
  316. ESP_EARLY_LOGI(TAG, "ELF file SHA256: %s...", buf);
  317. ESP_EARLY_LOGI(TAG, "ESP-IDF: %s", app_desc->idf_ver);
  318. }
  319. // Initialize core components and services.
  320. do_core_init();
  321. // Execute constructors.
  322. do_global_ctors();
  323. // Execute init functions of other components; blocks
  324. // until all cores finish (when !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE).
  325. do_secondary_init();
  326. // Now that the application is about to start, disable boot watchdog
  327. #ifndef CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE
  328. wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
  329. wdt_hal_write_protect_disable(&rtc_wdt_ctx);
  330. wdt_hal_disable(&rtc_wdt_ctx);
  331. wdt_hal_write_protect_enable(&rtc_wdt_ctx);
  332. #endif
  333. #if SOC_CPU_CORES_NUM > 1 && !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
  334. s_system_full_inited = true;
  335. #endif
  336. esp_startup_start_app();
  337. while (1);
  338. }
  339. IRAM_ATTR ESP_SYSTEM_INIT_FN(init_components0, BIT(0))
  340. {
  341. esp_timer_init();
  342. #if defined(CONFIG_PM_ENABLE)
  343. esp_pm_impl_init();
  344. #endif
  345. #if CONFIG_ESP_COREDUMP_ENABLE
  346. esp_core_dump_init();
  347. #endif
  348. #if SOC_APB_BACKUP_DMA
  349. esp_apb_backup_dma_lock_init();
  350. #endif
  351. #if CONFIG_SW_COEXIST_ENABLE
  352. esp_coex_adapter_register(&g_coex_adapter_funcs);
  353. coex_pre_init();
  354. #endif
  355. #ifdef CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
  356. const esp_partition_t *efuse_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_EFUSE_EM, NULL);
  357. if (efuse_partition) {
  358. esp_efuse_init(efuse_partition->address, efuse_partition->size);
  359. }
  360. #endif
  361. #ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
  362. ESP_EARLY_LOGD(TAG, "Setting C++ exception workarounds.");
  363. _Unwind_SetNoFunctionContextInstall(1);
  364. _Unwind_SetEnableExceptionFdeSorting(0);
  365. #endif // CONFIG_COMPILER_CXX_EXCEPTIONS
  366. }