cpu_start.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Copyright 2015-2016 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. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include <stdint.h>
  14. #include <string.h>
  15. #include "esp_attr.h"
  16. #include "esp_err.h"
  17. #include "rom/ets_sys.h"
  18. #include "rom/uart.h"
  19. #include "soc/dport_reg.h"
  20. #include "soc/io_mux_reg.h"
  21. #include "freertos/FreeRTOS.h"
  22. #include "freertos/task.h"
  23. #include "freertos/semphr.h"
  24. #include "freertos/queue.h"
  25. #include "freertos/portmacro.h"
  26. #include "tcpip_adapter.h"
  27. #include "heap_alloc_caps.h"
  28. #include "sdkconfig.h"
  29. #include "esp_system.h"
  30. #include "esp_spi_flash.h"
  31. #include "nvs_flash.h"
  32. #include "esp_event.h"
  33. #include "esp_spi_flash.h"
  34. #include "esp_ipc.h"
  35. static void IRAM_ATTR user_start_cpu0(void);
  36. static void IRAM_ATTR call_user_start_cpu1();
  37. static void IRAM_ATTR user_start_cpu1(void);
  38. void Cache_Read_Enable();
  39. extern void ets_setup_syscalls(void);
  40. extern int __cpu1_entry_point;
  41. extern int _bss_start;
  42. extern int _bss_end;
  43. extern int _init_start;
  44. extern int _init_end;
  45. extern int _iram_romjumptable_start;
  46. extern int _iram_romjumptable_end;
  47. extern int _iram_text_start;
  48. extern int _iram_text_end;
  49. /*
  50. We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized,
  51. flash cache is down and the app CPU is in reset. We do have a stack, so we can do the initialization in C.
  52. */
  53. static bool app_cpu_started = false;
  54. void IRAM_ATTR call_user_start_cpu0() {
  55. //Kill wdt
  56. REG_CLR_BIT(0x3ff4808c, BIT(10)); //RTCCNTL+8C RTC_WDTCONFIG0 RTC_
  57. REG_CLR_BIT(0x6001f048, BIT(14)); //DR_REG_BB_BASE+48
  58. //Move exception vectors to IRAM
  59. asm volatile (\
  60. "wsr %0, vecbase\n" \
  61. ::"r"(&_init_start));
  62. uartAttach();
  63. ets_install_uart_printf();
  64. //Make page 0 access raise an exception
  65. //Also some other unused pages so we can catch weirdness
  66. //ToDo: this but nicer.
  67. asm volatile (\
  68. "movi a4,0x00000000\n" \
  69. "movi a5,0xf\n" \
  70. "wdtlb a5,a4\n" \
  71. "witlb a5,a4\n" \
  72. "movi a4,0x80000000\n" \
  73. "wdtlb a5,a4\n" \
  74. "witlb a5,a4\n" \
  75. "movi a4,0xa0000000\n" \
  76. "wdtlb a5,a4\n" \
  77. "witlb a5,a4\n" \
  78. "movi a4,0xc0000000\n" \
  79. "wdtlb a5,a4\n" \
  80. "witlb a5,a4\n" \
  81. "movi a4,0xe0000000\n" \
  82. "wdtlb a5,a4\n" \
  83. "witlb a5,a4\n" \
  84. "movi a4,0x20000000\n" \
  85. "movi a5,0x0\n" \
  86. "wdtlb a5,a4\n" \
  87. "witlb a5,a4\n" \
  88. "movi a4,0x40000000\n" \
  89. "movi a5,0x2\n" \
  90. "wdtlb a5,a4\n" \
  91. "witlb a5,a4\n" \
  92. "isync\n" \
  93. :::"a4","a5");
  94. memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
  95. //Initialize heap allocator
  96. heap_alloc_caps_init();
  97. ets_printf("Pro cpu up.\n");
  98. #ifndef CONFIG_FREERTOS_UNICORE
  99. ets_printf("Starting app cpu, entry point is %p\n", call_user_start_cpu1);
  100. SET_PERI_REG_MASK(APPCPU_CTRL_REG_B, DPORT_APPCPU_CLKGATE_EN);
  101. CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_C, DPORT_APPCPU_RUNSTALL);
  102. SET_PERI_REG_MASK(APPCPU_CTRL_REG_A, DPORT_APPCPU_RESETTING);
  103. CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_A, DPORT_APPCPU_RESETTING);
  104. ets_set_appcpu_boot_addr((uint32_t)call_user_start_cpu1);
  105. while (!app_cpu_started) {
  106. ets_delay_us(100);
  107. }
  108. #else
  109. CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_B, DPORT_APPCPU_CLKGATE_EN);
  110. #endif
  111. ets_printf("Pro cpu start user code\n");
  112. user_start_cpu0();
  113. }
  114. extern int _init_start;
  115. void IRAM_ATTR call_user_start_cpu1() {
  116. asm volatile (\
  117. "wsr %0, vecbase\n" \
  118. ::"r"(&_init_start));
  119. //Make page 0 access raise an exception
  120. //Also some other unused pages so we can catch weirdness
  121. //ToDo: this but nicer.
  122. asm volatile (\
  123. "movi a4,0x00000000\n" \
  124. "movi a5,0xf\n" \
  125. "wdtlb a5,a4\n" \
  126. "witlb a5,a4\n" \
  127. "movi a4,0x80000000\n" \
  128. "wdtlb a5,a4\n" \
  129. "witlb a5,a4\n" \
  130. "movi a4,0xa0000000\n" \
  131. "wdtlb a5,a4\n" \
  132. "witlb a5,a4\n" \
  133. "movi a4,0xc0000000\n" \
  134. "wdtlb a5,a4\n" \
  135. "witlb a5,a4\n" \
  136. "movi a4,0xe0000000\n" \
  137. "wdtlb a5,a4\n" \
  138. "witlb a5,a4\n" \
  139. "movi a4,0x20000000\n" \
  140. "movi a5,0x0\n" \
  141. "wdtlb a5,a4\n" \
  142. "witlb a5,a4\n" \
  143. "movi a4,0x40000000\n" \
  144. "movi a5,0x2\n" \
  145. "wdtlb a5,a4\n" \
  146. "witlb a5,a4\n" \
  147. "isync\n" \
  148. :::"a4","a5");
  149. ets_printf("App cpu up.\n");
  150. app_cpu_started = 1;
  151. user_start_cpu1();
  152. }
  153. extern volatile int port_xSchedulerRunning[2];
  154. void IRAM_ATTR user_start_cpu1(void) {
  155. // Wait for FreeRTOS initialization to finish on PRO CPU
  156. while (port_xSchedulerRunning[0] == 0) {
  157. ;
  158. }
  159. ets_printf("Starting scheduler on APP CPU.\n");
  160. xPortStartScheduler();
  161. }
  162. extern void (*__init_array_start)(void);
  163. extern void (*__init_array_end)(void);
  164. static void do_global_ctors(void) {
  165. void (**p)(void);
  166. for(p = &__init_array_start; p != &__init_array_end; ++p)
  167. (*p)();
  168. }
  169. extern esp_err_t app_main();
  170. void user_start_cpu0(void) {
  171. ets_setup_syscalls();
  172. do_global_ctors();
  173. esp_ipc_init();
  174. spi_flash_init();
  175. #if CONFIG_WIFI_ENABLED
  176. esp_err_t ret = nvs_flash_init(5, 3);
  177. if (ret != ESP_OK) {
  178. printf("nvs_flash_init failed, ret=%d\n", ret);
  179. }
  180. system_init();
  181. esp_event_init(NULL);
  182. tcpip_adapter_init();
  183. #endif
  184. #if CONFIG_WIFI_ENABLED && CONFIG_WIFI_AUTO_STARTUP
  185. #include "esp_wifi.h"
  186. esp_wifi_startup(app_main);
  187. #else
  188. app_main();
  189. #endif
  190. ets_printf("Starting scheduler on PRO CPU.\n");
  191. vTaskStartScheduler();
  192. }