]> granicus.if.org Git - esp-idf/blob - components/esp32/cpu_start.c
Merge branch 'master' into feature/btdm_bluedroid
[esp-idf] / components / esp32 / cpu_start.c
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
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
17 #include "esp_attr.h"
18 #include "esp_err.h"
19
20 #include "rom/ets_sys.h"
21 #include "rom/uart.h"
22 #include "rom/rtc.h"
23 #include "rom/cache.h"
24
25 #include "soc/cpu.h"
26 #include "soc/dport_reg.h"
27 #include "soc/io_mux_reg.h"
28 #include "soc/rtc_cntl_reg.h"
29
30 #include "freertos/FreeRTOS.h"
31 #include "freertos/task.h"
32 #include "freertos/semphr.h"
33 #include "freertos/queue.h"
34 #include "freertos/portmacro.h"
35
36 #include "tcpip_adapter.h"
37
38 #include "heap_alloc_caps.h"
39 #include "sdkconfig.h"
40 #include "esp_system.h"
41 #include "esp_spi_flash.h"
42 #include "nvs_flash.h"
43 #include "esp_event.h"
44 #include "esp_spi_flash.h"
45 #include "esp_ipc.h"
46 #include "esp_crosscore_int.h"
47 #include "esp_log.h"
48 #include "esp_vfs_dev.h"
49 #include "esp_newlib.h"
50 #include "esp_brownout.h"
51 #include "esp_int_wdt.h"
52 #include "esp_task_wdt.h"
53 #include "esp_phy_init.h"
54 #include "esp_coexist.h"
55 #include "trax.h"
56
57 void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default")));
58 void start_cpu0_default(void) IRAM_ATTR;
59 #if !CONFIG_FREERTOS_UNICORE
60 static void IRAM_ATTR call_start_cpu1();
61 void start_cpu1(void) __attribute__((weak, alias("start_cpu1_default")));
62 void start_cpu1_default(void) IRAM_ATTR;
63 static bool app_cpu_started = false;
64 #endif //!CONFIG_FREERTOS_UNICORE
65
66 static void do_global_ctors(void);
67 static void do_phy_init();
68 static void main_task(void* args);
69 extern void app_main(void);
70
71 extern int _bss_start;
72 extern int _bss_end;
73 extern int _rtc_bss_start;
74 extern int _rtc_bss_end;
75 extern int _init_start;
76 extern void (*__init_array_start)(void);
77 extern void (*__init_array_end)(void);
78 extern volatile int port_xSchedulerRunning[2];
79
80 static const char* TAG = "cpu_start";
81
82 /*
83  * We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized,
84  * and the app CPU is in reset. We do have a stack, so we can do the initialization in C.
85  */
86
87 void IRAM_ATTR call_start_cpu0()
88 {
89     //Kill wdt
90     REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN);
91     REG_CLR_BIT(0x6001f048, BIT(14)); //DR_REG_BB_BASE+48
92
93     cpu_configure_region_protection();
94
95     //Move exception vectors to IRAM
96     asm volatile (\
97                   "wsr    %0, vecbase\n" \
98                   ::"r"(&_init_start));
99
100     uartAttach();
101     ets_install_uart_printf();
102
103     memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
104
105     /* Unless waking from deep sleep (implying RTC memory is intact), clear RTC bss */
106     if (rtc_get_reset_reason(0) != DEEPSLEEP_RESET) {
107         memset(&_rtc_bss_start, 0, (&_rtc_bss_end - &_rtc_bss_start) * sizeof(_rtc_bss_start));
108     }
109
110     // Initialize heap allocator
111     heap_alloc_caps_init();
112
113     ESP_EARLY_LOGI(TAG, "Pro cpu up.");
114
115 #if !CONFIG_FREERTOS_UNICORE
116     ESP_EARLY_LOGI(TAG, "Starting app cpu, entry point is %p", call_start_cpu1);
117     //Flush and enable icache for APP CPU
118     Cache_Flush(1);
119     Cache_Read_Enable(1);
120     esp_cpu_unstall(1);
121     //Enable clock gating and reset the app cpu.
122     SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
123     CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_C_REG, DPORT_APPCPU_RUNSTALL);
124     SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
125     CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
126     ets_set_appcpu_boot_addr((uint32_t)call_start_cpu1);
127
128     while (!app_cpu_started) {
129         ets_delay_us(100);
130     }
131 #else
132     ESP_EARLY_LOGI(TAG, "Single core mode");
133     CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
134 #endif
135     ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
136     start_cpu0();
137 }
138
139 #if !CONFIG_FREERTOS_UNICORE
140 void IRAM_ATTR call_start_cpu1()
141 {
142     asm volatile (\
143                   "wsr    %0, vecbase\n" \
144                   ::"r"(&_init_start));
145
146     cpu_configure_region_protection();
147
148     ESP_EARLY_LOGI(TAG, "App cpu up.");
149     app_cpu_started = 1;
150     start_cpu1();
151 }
152 #endif //!CONFIG_FREERTOS_UNICORE
153
154 void start_cpu0_default(void)
155 {
156     esp_setup_syscall_table();
157 //Enable trace memory and immediately start trace.
158 #if CONFIG_MEMMAP_TRACEMEM
159 #if CONFIG_MEMMAP_TRACEMEM_TWOBANKS
160     trax_enable(TRAX_ENA_PRO_APP);
161 #else
162     trax_enable(TRAX_ENA_PRO);
163 #endif
164     trax_start_trace(TRAX_DOWNCOUNT_WORDS);
165 #endif
166     esp_set_cpu_freq();     // set CPU frequency configured in menuconfig
167     uart_div_modify(0, (APB_CLK_FREQ << 4) / 115200);
168 #if CONFIG_BROWNOUT_DET
169     esp_brownout_init();
170 #endif
171 #if CONFIG_INT_WDT
172     esp_int_wdt_init();
173 #endif
174 #if CONFIG_TASK_WDT
175     esp_task_wdt_init();
176 #endif
177     esp_setup_time_syscalls();
178     esp_vfs_dev_uart_register();
179     esp_reent_init(_GLOBAL_REENT);
180     const char* default_uart_dev = "/dev/uart/0";
181     _GLOBAL_REENT->_stdin  = fopen(default_uart_dev, "r");
182     _GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
183     _GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
184     do_global_ctors();
185 #if !CONFIG_FREERTOS_UNICORE
186     esp_crosscore_int_init();
187 #endif
188     esp_ipc_init();
189     spi_flash_init();
190
191 #if CONFIG_ESP32_PHY_AUTO_INIT
192     nvs_flash_init();
193     do_phy_init();
194 #endif
195
196 #if CONFIG_SW_COEXIST_ENABLE
197         if (coex_init() == ESP_OK) {
198         coexist_set_enable(true);
199         }
200 #endif
201
202     xTaskCreatePinnedToCore(&main_task, "main",
203             ESP_TASK_MAIN_STACK, NULL,
204             ESP_TASK_MAIN_PRIO, NULL, 0);
205     ESP_LOGI(TAG, "Starting scheduler on PRO CPU.");
206     vTaskStartScheduler();
207 }
208
209 #if !CONFIG_FREERTOS_UNICORE
210 void start_cpu1_default(void)
211 {
212 #if CONFIG_MEMMAP_TRACEMEM_TWOBANKS
213     trax_start_trace(TRAX_DOWNCOUNT_WORDS);
214 #endif
215     // Wait for FreeRTOS initialization to finish on PRO CPU
216     while (port_xSchedulerRunning[0] == 0) {
217         ;
218     }
219     esp_crosscore_int_init();
220     ESP_LOGI(TAG, "Starting scheduler on APP CPU.");
221     xPortStartScheduler();
222 }
223 #endif //!CONFIG_FREERTOS_UNICORE
224
225 static void do_global_ctors(void)
226 {
227     void (**p)(void);
228     for (p = &__init_array_end - 1; p >= &__init_array_start; --p) {
229         (*p)();
230     }
231 }
232
233 static void main_task(void* args)
234 {
235     app_main();
236     vTaskDelete(NULL);
237 }
238
239 static void do_phy_init()
240 {
241     esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL;
242     if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) {
243         calibration_mode = PHY_RF_CAL_NONE;
244     }
245     const esp_phy_init_data_t* init_data = esp_phy_get_init_data();
246     if (init_data == NULL) {
247         ESP_LOGE(TAG, "failed to obtain PHY init data");
248         abort();
249     }
250     esp_phy_calibration_data_t* cal_data =
251             (esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1);
252     if (cal_data == NULL) {
253         ESP_LOGE(TAG, "failed to allocate memory for RF calibration data");
254         abort();
255     }
256     esp_err_t err = esp_phy_load_cal_data_from_nvs(cal_data);
257     if (err != ESP_OK) {
258         ESP_LOGW(TAG, "failed to load RF calibration data, falling back to full calibration");
259         calibration_mode = PHY_RF_CAL_FULL;
260     }
261
262     esp_phy_init(init_data, calibration_mode, cal_data);
263
264     if (calibration_mode != PHY_RF_CAL_NONE) {
265         err = esp_phy_store_cal_data_to_nvs(cal_data);
266     } else {
267         err = ESP_OK;
268     }
269     esp_phy_release_init_data(init_data);
270     free(cal_data); // PHY maintains a copy of calibration data, so we can free this
271 }