1 // Copyright 2013-2016 Espressif Systems (Shanghai) PTE LTD
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "esp_system.h"
20 #include "esp_wifi_internal.h"
22 #include "sdkconfig.h"
23 #include "rom/efuse.h"
24 #include "rom/cache.h"
26 #include "soc/dport_reg.h"
27 #include "soc/efuse_reg.h"
28 #include "soc/rtc_cntl_reg.h"
29 #include "soc/timer_group_reg.h"
30 #include "soc/timer_group_struct.h"
33 #include "freertos/FreeRTOS.h"
34 #include "freertos/task.h"
35 #include "freertos/xtensa_api.h"
36 #include "esp_heap_caps.h"
38 static const char* TAG = "system_api";
40 static uint8_t base_mac_addr[6] = { 0 };
46 esp_err_t esp_base_mac_addr_set(uint8_t *mac)
49 ESP_LOGE(TAG, "Base MAC address is NULL");
53 memcpy(base_mac_addr, mac, 6);
58 esp_err_t esp_base_mac_addr_get(uint8_t *mac)
60 uint8_t null_mac[6] = {0};
62 if (memcmp(base_mac_addr, null_mac, 6) == 0) {
63 ESP_LOGI(TAG, "Base MAC address is not set, read default base MAC address from BLK0 of EFUSE");
64 return ESP_ERR_INVALID_MAC;
67 memcpy(mac, base_mac_addr, 6);
72 esp_err_t esp_efuse_mac_get_custom(uint8_t *mac)
79 uint8_t version = REG_READ(EFUSE_BLK3_RDATA5_REG) >> 24;
82 ESP_LOGE(TAG, "Base MAC address from BLK3 of EFUSE version error, version = %d", version);
83 return ESP_ERR_INVALID_VERSION;
86 mac_low = REG_READ(EFUSE_BLK3_RDATA1_REG);
87 mac_high = REG_READ(EFUSE_BLK3_RDATA0_REG);
89 mac[0] = mac_high >> 8;
90 mac[1] = mac_high >> 16;
91 mac[2] = mac_high >> 24;
93 mac[4] = mac_low >> 8;
94 mac[5] = mac_low >> 16;
98 calc_crc = esp_crc8(mac, 6);
100 if (efuse_crc != calc_crc) {
101 ESP_LOGE(TAG, "Base MAC address from BLK3 of EFUSE CRC error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc);
102 return ESP_ERR_INVALID_CRC;
107 esp_err_t esp_efuse_mac_get_default(uint8_t* mac)
114 mac_low = REG_READ(EFUSE_BLK0_RDATA1_REG);
115 mac_high = REG_READ(EFUSE_BLK0_RDATA2_REG);
117 mac[0] = mac_high >> 8;
119 mac[2] = mac_low >> 24;
120 mac[3] = mac_low >> 16;
121 mac[4] = mac_low >> 8;
124 efuse_crc = mac_high >> 16;
126 calc_crc = esp_crc8(mac, 6);
128 if (efuse_crc != calc_crc) {
129 // Small range of MAC addresses are accepted even if CRC is invalid.
130 // These addresses are reserved for Espressif internal use.
131 if ((mac_high & 0xFFFF) == 0x18fe) {
132 if ((mac_low >= 0x346a85c7) && (mac_low <= 0x346a85f8)) {
136 ESP_LOGE(TAG, "Base MAC address from BLK0 of EFUSE CRC error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc);
143 esp_err_t system_efuse_read_mac(uint8_t *mac) __attribute__((alias("esp_efuse_mac_get_default")));
144 esp_err_t esp_efuse_read_mac(uint8_t *mac) __attribute__((alias("esp_efuse_mac_get_default")));
146 esp_err_t esp_derive_mac(uint8_t* local_mac, const uint8_t* universal_mac)
150 if (local_mac == NULL || universal_mac == NULL) {
151 ESP_LOGE(TAG, "mac address param is NULL");
152 return ESP_ERR_INVALID_ARG;
155 memcpy(local_mac, universal_mac, 6);
156 for (idx = 0; idx < 64; idx++) {
157 local_mac[0] = universal_mac[0] | 0x02;
158 local_mac[0] ^= idx << 2;
160 if (memcmp(local_mac, universal_mac, 6)) {
168 esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type)
170 uint8_t efuse_mac[6];
173 ESP_LOGE(TAG, "mac address param is NULL");
174 return ESP_ERR_INVALID_ARG;
177 if (type < ESP_MAC_WIFI_STA || type > ESP_MAC_ETH) {
178 ESP_LOGE(TAG, "mac type is incorrect");
179 return ESP_ERR_INVALID_ARG;
182 _Static_assert(UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR \
183 || UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR, \
184 "incorrect NUM_MAC_ADDRESS_FROM_EFUSE value");
186 if (esp_base_mac_addr_get(efuse_mac) != ESP_OK) {
187 esp_efuse_mac_get_default(efuse_mac);
191 case ESP_MAC_WIFI_STA:
192 memcpy(mac, efuse_mac, 6);
194 case ESP_MAC_WIFI_SOFTAP:
195 if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
196 memcpy(mac, efuse_mac, 6);
199 else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
200 esp_derive_mac(mac, efuse_mac);
204 memcpy(mac, efuse_mac, 6);
205 if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
208 else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
213 if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
214 memcpy(mac, efuse_mac, 6);
217 else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
219 esp_derive_mac(mac, efuse_mac);
223 ESP_LOGW(TAG, "incorrect mac type");
230 void esp_restart_noos() __attribute__ ((noreturn));
232 /* Dummy function to be used instead of esp_wifi_stop if WiFi stack is not
233 * linked in (even though CONFIG_WIFI_ENABLED is set).
235 esp_err_t wifi_stop_noop()
240 esp_err_t esp_wifi_stop(void) __attribute((weak, alias("wifi_stop_noop")));
242 void IRAM_ATTR esp_restart(void)
244 #ifdef CONFIG_WIFI_ENABLED
248 // Disable scheduler on this core.
254 /* "inner" restart function for after RTOS, interrupts & anything else on this
255 * core are already stopped. Stalls other core, resets hardware,
258 void IRAM_ATTR esp_restart_noos()
260 const uint32_t core_id = xPortGetCoreID();
261 const uint32_t other_core_id = core_id == 0 ? 1 : 0;
262 esp_cpu_stall(other_core_id);
264 // other core is now stalled, can access DPORT registers directly
265 esp_dport_access_int_deinit();
267 // We need to disable TG0/TG1 watchdogs
268 // First enable RTC watchdog for 1 second
269 REG_WRITE(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
270 REG_WRITE(RTC_CNTL_WDTCONFIG0_REG,
271 RTC_CNTL_WDT_FLASHBOOT_MOD_EN_M |
272 (RTC_WDT_STG_SEL_RESET_SYSTEM << RTC_CNTL_WDT_STG0_S) |
273 (RTC_WDT_STG_SEL_RESET_RTC << RTC_CNTL_WDT_STG1_S) |
274 (1 << RTC_CNTL_WDT_SYS_RESET_LENGTH_S) |
275 (1 << RTC_CNTL_WDT_CPU_RESET_LENGTH_S) );
276 REG_WRITE(RTC_CNTL_WDTCONFIG1_REG, rtc_clk_slow_freq_get_hz() * 1);
278 // Disable TG0/TG1 watchdogs
279 TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
280 TIMERG0.wdt_config0.en = 0;
281 TIMERG0.wdt_wprotect=0;
282 TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
283 TIMERG1.wdt_config0.en = 0;
284 TIMERG1.wdt_wprotect=0;
286 // Disable all interrupts
287 xt_ints_off(0xFFFFFFFF);
290 Cache_Read_Disable(0);
291 Cache_Read_Disable(1);
293 // Flush any data left in UART FIFOs
294 uart_tx_wait_idle(0);
295 uart_tx_wait_idle(1);
296 uart_tx_wait_idle(2);
298 // Reset wifi/bluetooth/ethernet/sdio (bb/mac)
299 DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG,
300 DPORT_BB_RST | DPORT_FE_RST | DPORT_MAC_RST |
301 DPORT_BT_RST | DPORT_BTMAC_RST | DPORT_SDIO_RST |
302 DPORT_SDIO_HOST_RST | DPORT_EMAC_RST | DPORT_MACPWR_RST |
303 DPORT_RW_BTMAC_RST | DPORT_RW_BTLP_RST);
304 DPORT_REG_WRITE(DPORT_CORE_RST_EN_REG, 0);
306 // Reset timer/spi/uart
307 DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,
308 DPORT_TIMERS_RST | DPORT_SPI_RST_1 | DPORT_UART_RST);
309 DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0);
311 // Set CPU back to XTAL source, no PLL, same as hard reset
312 rtc_clk_cpu_freq_set(RTC_CPU_FREQ_XTAL);
314 // Clear entry point for APP CPU
315 DPORT_REG_WRITE(DPORT_APPCPU_CTRL_D_REG, 0);
319 // Running on PRO CPU: APP CPU is stalled. Can reset both CPUs.
320 SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG,
321 RTC_CNTL_SW_PROCPU_RST_M | RTC_CNTL_SW_APPCPU_RST_M);
323 // Running on APP CPU: need to reset PRO CPU and unstall it,
324 // then reset APP CPU
325 SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST_M);
327 SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_APPCPU_RST_M);
334 void system_restart(void) __attribute__((alias("esp_restart")));
336 void system_restore(void)
341 uint32_t esp_get_free_heap_size( void )
343 return heap_caps_get_free_size( MALLOC_CAP_8BIT );
346 uint32_t esp_get_minimum_free_heap_size( void )
348 return heap_caps_get_minimum_free_size( MALLOC_CAP_8BIT );
351 uint32_t system_get_free_heap_size(void) __attribute__((alias("esp_get_free_heap_size")));
353 const char* system_get_sdk_version(void)
358 const char* esp_get_idf_version(void)
363 static void get_chip_info_esp32(esp_chip_info_t* out_info)
365 out_info->model = CHIP_ESP32;
366 uint32_t reg = REG_READ(EFUSE_BLK0_RDATA3_REG);
367 memset(out_info, 0, sizeof(*out_info));
368 if ((reg & EFUSE_RD_CHIP_VER_REV1_M) != 0) {
369 out_info->revision = 1;
371 if ((reg & EFUSE_RD_CHIP_VER_DIS_APP_CPU_M) == 0) {
376 out_info->features = CHIP_FEATURE_WIFI_BGN;
377 if ((reg & EFUSE_RD_CHIP_VER_DIS_BT_M) == 0) {
378 out_info->features |= CHIP_FEATURE_BT | CHIP_FEATURE_BLE;
380 if (((reg & EFUSE_RD_CHIP_VER_PKG_M) >> EFUSE_RD_CHIP_VER_PKG_S) ==
381 EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
382 out_info->features |= CHIP_FEATURE_EMB_FLASH;
386 void esp_chip_info(esp_chip_info_t* out_info)
388 // Only ESP32 is supported now, in the future call one of the
389 // chip-specific functions based on sdkconfig choice
390 return get_chip_info_esp32(out_info);