startup.c 13 KB

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