Merge branch 'feature/speed_up_system_startup' into 'master'

feat(startup): add fast boot and fast restart function

See merge request sdk/ESP8266_RTOS_SDK!1302
This commit is contained in:
Dong Heng
2020-08-05 11:21:00 +08:00
19 changed files with 428 additions and 43 deletions

View File

@ -19,6 +19,13 @@ config BOOTLOADER_DISABLE_JTAG_IO
If users use JTAG to help develop, please disable this option.
config BOOTLOADER_FAST_BOOT
bool "Bootloader fast boot"
default n
help
Enable this option, after initializing hardware, bootloader will try to load boot image
information from RTC memory directly and then run image without verifying it.
choice LOG_BOOTLOADER_LEVEL
bool "Bootloader log verbosity"
default LOG_BOOTLOADER_LEVEL_INFO

View File

@ -30,11 +30,19 @@ static int selected_boot_partition(const bootloader_state_t *bs);
void call_start_cpu(void)
{
#ifdef CONFIG_BOOTLOADER_FAST_BOOT
REG_SET_BIT(DPORT_CTL_REG, DPORT_CTL_DOUBLE_CLK);
#endif
// 1. Hardware initialization
if(bootloader_init() != ESP_OK){
return;
}
#ifdef CONFIG_BOOTLOADER_FAST_BOOT
bootloader_utility_fast_boot_image();
#endif
// 2. Select image to boot
esp_image_metadata_t image_data;
if(select_image(&image_data) != ESP_OK){

View File

@ -62,3 +62,8 @@ bool bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
* @param[in] data Structure to hold on-flash image metadata.
*/
void bootloader_utility_load_image(const esp_image_metadata_t* image_data);
/**
* @brief Loading boot image information from RTC memory and then running image without verifying.
*/
void bootloader_utility_fast_boot_image(void);

View File

@ -493,6 +493,7 @@ static void set_cache_and_start_app(
#include "esp_log.h"
#include "esp_flash_partitions.h"
#include "esp_fast_boot.h"
#include "internal/esp_system_internal.h"
static const char* TAG = "boot";
@ -743,6 +744,16 @@ static bool try_load_partition(const esp_partition_pos_t *partition, esp_image_m
#define TRY_LOG_FORMAT "Trying partition index %d offs 0x%x size 0x%x"
static void bootloader_utility_start_image(uint32_t image_start, uint32_t image_size, uint32_t entry_addr)
{
void (*user_start)(size_t start_addr);
bootloader_mmap(image_start, image_size);
user_start = (void *)entry_addr;
user_start(image_start);
}
bool bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index, esp_image_metadata_t *result)
{
int index = start_index;
@ -793,8 +804,6 @@ bool bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
void bootloader_utility_load_image(const esp_image_metadata_t* image_data)
{
void (*user_start)(size_t start_addr);
#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED)
esp_err_t err;
#endif
@ -838,11 +847,18 @@ void bootloader_utility_load_image(const esp_image_metadata_t* image_data)
copy loaded segments to RAM, set up caches for mapped segments, and start application
unpack_load_app(image_data);
#else
bootloader_mmap(image_data->start_addr, image_data->image_len);
user_start = (void *)image_data->image.entry_addr;
user_start(image_data->start_addr);
bootloader_utility_start_image(image_data->start_addr, image_data->image_len, image_data->image.entry_addr);
#endif /* BOOTLOADER_UNPACK_APP */
}
void bootloader_utility_fast_boot_image(void)
{
uint32_t image_start, image_size, image_entry;
if (!esp_fast_boot_get_info(&image_start, &image_size, &image_entry)) {
bootloader_utility_start_image(image_start, image_size, image_entry);
}
ESP_LOGD(TAG, "fast boot image fail");
}
#endif

View File

@ -2,7 +2,7 @@ if(BOOTLOADER_BUILD)
# For bootloader, all we need from esp8266 is headers
set(COMPONENT_ADD_INCLUDEDIRS include)
# set(COMPONENT_REQUIRES ${COMPONENTS})
set(COMPONENT_SRCS source/ets_printf.c source/crc.c)
set(COMPONENT_SRCS source/ets_printf.c source/crc.c source/esp_fast_boot.c)
register_component(esp8266)
# as cmake won't attach linker args to a header-only library, attach
@ -37,6 +37,7 @@ else()
"source/task_wdt.c"
"source/rom.c"
"source/hw_random.c"
"source/esp_fast_boot.c"
"driver/adc.c"
"driver/gpio.c"
"driver/hw_timer.c"
@ -53,7 +54,7 @@ else()
set(include_dirs "include" "include/driver")
set(requires "esp_common" "esp_event")
set(priv_requires "wpa_supplicant" "log" "spi_flash" "tcpip_adapter" "esp_ringbuf" "bootloader_support" "nvs_flash")
set(priv_requires "wpa_supplicant" "log" "spi_flash" "tcpip_adapter" "esp_ringbuf" "bootloader_support" "nvs_flash" "app_update")
set(fragments linker.lf ld/esp8266_fragments.lf ld/esp8266_bss_fragments.lf)
idf_component_register(SRCS "${srcs}"

View File

@ -2,7 +2,7 @@
# Component Makefile
#
ifdef IS_BOOTLOADER_BUILD
COMPONENT_OBJS := source/ets_printf.o source/crc.o
COMPONENT_OBJS := source/ets_printf.o source/crc.o source/esp_fast_boot.o
COMPONENT_SRCDIRS := source
else
COMPONENT_ADD_INCLUDEDIRS += include

View File

@ -205,6 +205,9 @@
#define CACHE_READ_EN_BIT BIT8
//}}
#define ESP_CACHE1_ADDR_MAX (0x100000)
#define ESP_CACHE2_ADDR_MAX (0x200000)
#define DRAM_BASE (0x3FFE8000)
#define DRAM_SIZE (96 * 1024)

View File

@ -1,9 +1,16 @@
#ifndef _ROM_FUNCTIONS_H
#define _ROM_FUNCTIONS_H
#include "sdkconfig.h"
#include <stdint.h>
#include <stdarg.h>
#ifdef CONFIG_SOC_FULL_ICACHE
#define SOC_CACHE_SIZE 1 // 32KB
#else
#define SOC_CACHE_SIZE 0 // 16KB
#endif
#define ROM_FLASH_BUF_DECLARE(__name, __size) uint8_t __name[__size] __attribute__((aligned(4)))
typedef struct {

View File

@ -0,0 +1,87 @@
// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifndef BOOTLOADER_BUILD
#include "esp_partition.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef BOOTLOADER_BUILD
/**
* @brief Setting target partition as fast boot partition and enable fast boot function.
*
* @param partition partition which has image to be booted
*
* @return
* - 0 on success
* - -EINVAL parameter error
* - -EIO read flash error
*/
int esp_fast_boot_enable_partition(const esp_partition_t *partition);
/**
* @brief Setting current running partition as fast boot partition and enable fast boot function.
*
* @return
* - 0 on success
* - -EINVAL current running partition information error
* - -EIO read flash error
*/
int esp_fast_boot_enable(void);
/**
* @brief Directly running the image which is to be booted after restart.
*
* @note It is just like jumping directly from one APP to another one without running ROM bootloader and level 2 bootloader.
* Using this API, system starting up is fastest.
*
* @return
* - 0 on success
* - -EINVAL booted partition information error
* - -EIO read flash error
*/
int esp_fast_boot_restart(void);
#endif
/**
* @brief Disabling fast boot function and bootloader will not boot fast.
*/
void esp_fast_boot_disable(void);
/**
* @brief Getting fast boot information.
*
* @param image_start image startting address in the SPI Flash
* @param image_size image max size in the SPI Flash
* @param image_entry image entry address in the SPI Flash
*
* @return
* - 0 on success
* - -EINVAL fast boot information error
*/
int esp_fast_boot_get_info(uint32_t *image_start, uint32_t *image_size, uint32_t *image_entry);
/**
* @brief Printing fast boot information.
*/
void esp_fast_boot_print_info(void);
#ifdef __cplusplus
}
#endif

View File

@ -50,6 +50,7 @@ typedef enum {
ESP_RST_DEEPSLEEP, //!< Reset after exiting deep sleep mode
ESP_RST_BROWNOUT, //!< Brownout reset (software or hardware)
ESP_RST_SDIO, //!< Reset over SDIO
ESP_RST_FAST_SW, //!< Fast reboot
} esp_reset_reason_t;
/**
@ -187,6 +188,13 @@ uint32_t esp_random(void);
*/
void esp_fill_random(void *buf, size_t len);
/**
* @brief Initialize MAC address
*
* @return 0 if sucess or others failed
*/
esp_err_t esp_mac_init(void);
typedef enum {
FLASH_SIZE_4M_MAP_256_256 = 0, /**< Flash size : 4Mbits. Map : 256KBytes + 256KBytes */
FLASH_SIZE_2M, /**< Flash size : 2Mbits. Map : 256KBytes */

View File

@ -22,6 +22,7 @@ extern "C" {
#endif
#define RTC_SYS_RAM_SIZE 256
#define ESP_SYSTEM_FAST_BOOT_IMAGE 0x5aa5a55a
/**
* @brief Station's AP base information of old SDK
@ -50,6 +51,13 @@ struct _rtc_sys_info {
uint32_t hint; // software reset reason
uint32_t old_sysconf_addr; /*<! old SDK system configuration parameters base address,
if your bootloader is older than v3.2, please don't use this */
struct {
uint32_t magic;
uint32_t image_start;
uint32_t image_size;
uint32_t image_entry;
uint32_t crc32;
} fast_boot;
};
/**

View File

@ -101,6 +101,11 @@ static inline STATUS UartRxString(uint8_t *pString, uint8_t MaxStrlen)
return OK;
}
/**
* @brief Disable UART0 I/O swap and don't care about if TX FIFO is empty
*/
void uart_disable_swap_io(void);
/**
* @}
*/

View File

@ -0,0 +1,205 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// #define LOG_LOCAL_LEVEL ESP_LOG_ERROR
#include <stdio.h>
#include <string.h>
#include <sys/errno.h>
#include "esp_log.h"
#include "rom/crc.h"
#include "internal/esp_system_internal.h"
#include "esp_fast_boot.h"
#ifndef BOOTLOADER_BUILD
#include "esp_ota_ops.h"
#include "esp_image_format.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp8266/rom_functions.h"
#include "esp8266/eagle_soc.h"
#include "rom/uart.h"
#include "esp_spi_flash.h"
#include "FreeRTOS.h"
#include "task.h"
#endif
static char *TAG = "fast_boot";
#ifndef BOOTLOADER_BUILD
int esp_fast_boot_enable_partition(const esp_partition_t *partition)
{
int ret;
esp_image_header_t image;
if (!partition || partition->type != ESP_PARTITION_TYPE_APP)
return -EINVAL;
ret = spi_flash_read(partition->address, &image, sizeof(esp_image_header_t));
if (ret != ESP_OK) {
ESP_LOGE(TAG, "read image head from spi flash error");
return -EIO;
}
rtc_sys_info.fast_boot.image_start = partition->address;
rtc_sys_info.fast_boot.image_size = partition->size - 4;
rtc_sys_info.fast_boot.image_entry = image.entry_addr;
rtc_sys_info.fast_boot.magic = ESP_SYSTEM_FAST_BOOT_IMAGE;
rtc_sys_info.fast_boot.crc32 = crc32_le(UINT32_MAX, (uint8_t *)&rtc_sys_info.fast_boot, sizeof(rtc_sys_info.fast_boot) - 4);
return 0;
}
int esp_fast_boot_enable(void)
{
const esp_partition_t *running = esp_ota_get_running_partition();
return esp_fast_boot_enable_partition(running);
}
void IRAM_ATTR esp_fast_boot_restart_app(uint32_t image_start, uint32_t entry_addr, uint8_t region, uint8_t sub_region)
{
const uint32_t sp = DRAM_BASE + DRAM_SIZE - 16;
void (*user_start)(size_t start_addr);
Cache_Read_Disable();
Cache_Read_Enable(sub_region, region, SOC_CACHE_SIZE);
__asm__ __volatile__(
"mov a1, %0\n"
: : "a"(sp) : "memory"
);
user_start = (void *)entry_addr;
user_start(image_start);
}
int esp_fast_boot_restart(void)
{
extern void pm_goto_rf_on(void);
extern void clockgate_watchdog(int on);
int ret;
uint8_t region, sub_region;
uint32_t image_start, image_size, image_entry, image_mask;
const esp_partition_t *to_boot;
esp_image_header_t image;
to_boot = esp_ota_get_boot_partition();
if (!to_boot) {
ESP_LOGI(TAG, "no OTA boot partition");
to_boot = esp_ota_get_running_partition();
if (!to_boot) {
ESP_LOGE(TAG, "ERROR: Fail to get running partition");
return -EINVAL;
}
}
image_start = to_boot->address;
image_size = to_boot->size - 4;
ret = spi_flash_read(image_start, &image, sizeof(esp_image_header_t));
if (ret != ESP_OK) {
ESP_LOGE(TAG, "ERROR: Fail to read image head from spi flash error=%d", ret);
return -EIO;
}
image_entry = image.entry_addr;
if (image_start < 0x200000) {
region = 0;
} else if (image_start < 0x400000) {
region = 1;
} else if (image_start < 0x600000) {
region = 2;
} else if (image_start < 0x800000) {
region = 3;
} else {
ESP_LOGE(TAG, "ERROR: App bin error, start_addr 0x%08x image_len %d\n", image_start, image_size);
return -EINVAL;
}
image_mask = image_start & 0x1fffff;
if (image_mask < 0x100000) {
sub_region = 0;
} else {
sub_region = 1;
}
if (esp_wifi_stop() != ESP_OK) {
ESP_LOGD(TAG, "ERROR: Fail to stop Wi-Fi");
}
uart_tx_wait_idle(1);
uart_tx_wait_idle(0);
vTaskDelay(40 / portTICK_RATE_MS);
pm_goto_rf_on();
clockgate_watchdog(0);
REG_WRITE(0x3ff00018, 0xffff00ff);
SET_PERI_REG_MASK(0x60000D48, BIT1);
CLEAR_PERI_REG_MASK(0x60000D48, BIT1);
/* Get startup time */
//ets_printf("\nets\n");
uart_disable_swap_io();
vPortEnterCritical();
REG_WRITE(INT_ENA_WDEV, 0);
_xt_isr_mask(UINT32_MAX);
esp_reset_reason_set_hint(ESP_RST_FAST_SW);
esp_fast_boot_restart_app(image_start, image_entry, region, sub_region);
return 0;
}
#endif
void esp_fast_boot_disable(void)
{
memset(&rtc_sys_info.fast_boot, 0, sizeof(rtc_sys_info.fast_boot));
}
int esp_fast_boot_get_info(uint32_t *image_start, uint32_t *image_size, uint32_t *image_entry)
{
if (rtc_sys_info.fast_boot.magic != ESP_SYSTEM_FAST_BOOT_IMAGE) {
ESP_LOGE(TAG, "magic error");
return -EINVAL;
}
if (rtc_sys_info.fast_boot.crc32 != crc32_le(UINT32_MAX, (uint8_t *)&rtc_sys_info.fast_boot, sizeof(rtc_sys_info.fast_boot) - 4)) {
ESP_LOGE(TAG, "CRC32 error");
esp_fast_boot_disable();
return -EINVAL;
}
*image_start = rtc_sys_info.fast_boot.image_start;
*image_size = rtc_sys_info.fast_boot.image_size;
*image_entry = rtc_sys_info.fast_boot.image_entry;
esp_fast_boot_disable();
return 0;
}
void esp_fast_boot_print_info(void)
{
ets_printf("\nmagic is %x\n", rtc_sys_info.fast_boot.magic);
ets_printf("image start is %x\n", rtc_sys_info.fast_boot.image_start);
ets_printf("image size is %x\n", rtc_sys_info.fast_boot.image_size);
ets_printf("image entry is %x\n", rtc_sys_info.fast_boot.image_entry);
ets_printf("CRC32 is %x\n", rtc_sys_info.fast_boot.crc32);
}

View File

@ -30,6 +30,7 @@ const bool _g_esp_wifi_connect_open_router_when_pwd_is_set = true;
const bool _g_esp_wifi_connect_open_router_when_pwd_is_set = false;
#endif
esp_err_t mac_init(void);
esp_err_t esp_wifi_init_internal(const wifi_init_config_t *config);
ESP_EVENT_DEFINE_BASE(WIFI_EVENT);
@ -129,6 +130,10 @@ static void esp_wifi_set_debug_log()
*/
esp_err_t esp_wifi_init(const wifi_init_config_t *config)
{
mac_init();
esp_wifi_set_rx_pbuf_mem_type(WIFI_RX_PBUF_DRAM);
esp_err_t result = esp_wifi_init_internal(config);
if (result == ESP_OK) {
esp_wifi_set_debug_log();

View File

@ -72,11 +72,6 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibrat
esp_err_t status = ESP_OK;
uint8_t sta_mac[6];
uint8_t *local_init_data = calloc(1, 256);
#ifdef CONFIG_ESP_CONSOLE_UART_BAUDRATE
const uint32_t uart_baudrate = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
#else
const uint32_t uart_baudrate = 74880; // ROM default baudrate
#endif
memcpy(local_init_data, init_data->params, 128);
memcpy(local_init_data + 128, calibration_data->rf_cal_data, 128);
@ -102,12 +97,7 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibrat
* so UARTs must be flush here, then reconfigurate the UART frequency dividor
*/
uart_tx_wait_idle(0);
uart_div_modify(0, UART_CLK_FREQ / uart_baudrate);
uart_tx_wait_idle(1);
uart_div_modify(1, UART_CLK_FREQ / uart_baudrate);
rtc_init_clk(local_init_data);
int ret = register_chipv6_phy(local_init_data);
if (ret) {

View File

@ -41,7 +41,7 @@ static inline void esp_reset_reason_clear_hint()
static inline uint32_t esp_reset_reason_get_hint(uint32_t hw_reset)
{
if (hw_reset == POWERON_RESET && rtc_sys_info.hint != ESP_RST_SW)
if (hw_reset == POWERON_RESET && ((rtc_sys_info.hint != ESP_RST_SW) && (rtc_sys_info.hint != ESP_RST_FAST_SW)))
rtc_sys_info.hint = 0;
return rtc_sys_info.hint;
@ -63,7 +63,8 @@ static inline uint32_t get_reset_reason(uint32_t rtc_reset_reason, uint32_t rese
{
switch (rtc_reset_reason) {
case POWERON_RESET:
if (reset_reason_hint == ESP_RST_SW)
if (reset_reason_hint == ESP_RST_SW ||
reset_reason_hint == ESP_RST_FAST_SW)
return reset_reason_hint;
return ESP_RST_POWERON;
case EXT_RESET:
@ -108,7 +109,7 @@ static void __esp_reset_reason_init(int init)
}
if (init)
ESP_LOGI(TAG, "RTC reset %u wakeup %u store %u, reason is %u", hw_reset, hw_wakeup, hint, s_reset_reason);
ESP_LOGD(TAG, "RTC reset %u wakeup %u store %u, reason is %u", hw_reset, hw_wakeup, hint, s_reset_reason);
}
/**

View File

@ -31,3 +31,8 @@ void uart_tx_wait_idle(uint8_t uart_no)
ets_delay_us(byte_delay_us);
}
void uart_disable_swap_io(void)
{
CLEAR_PERI_REG_MASK(UART_SWAP_REG, 0x4);
}

View File

@ -39,18 +39,10 @@
#include "esp_newlib.h"
#endif
extern void chip_boot(void);
extern int rtc_init(void);
extern int mac_init(void);
extern int base_gpio_init(void);
extern int watchdog_init(void);
extern int wifi_timer_init(void);
extern int wifi_nvs_init(void);
extern esp_err_t esp_pthread_init(void);
extern void phy_get_bb_evm(void);
extern void uart_div_modify(uint8_t uart_no, uint16_t DivLatchValue);
/*Only for calling esp_wifi_set_ps can compile successfully */
uint32_t LwipTimOutLim = 0;
extern void chip_boot(void);
extern int base_gpio_init(void);
extern int rtc_init(void);
static inline int should_load(uint32_t load_addr)
{
@ -73,23 +65,19 @@ static void user_init_entry(void *param)
extern void (*__init_array_end)(void);
extern void app_main(void);
extern uint32_t esp_get_time(void);
/* initialize C++ construture function */
for (func = &__init_array_start; func < &__init_array_end; func++)
func[0]();
/*enable tsf0 interrupt for pwm*/
REG_WRITE(PERIPHS_DPORT_BASEADDR, (REG_READ(PERIPHS_DPORT_BASEADDR) & ~0x1F) | 0x1);
REG_WRITE(INT_ENA_WDEV, REG_READ(INT_ENA_WDEV) | WDEV_TSF0_REACH_INT);
assert(nvs_flash_init() == 0);
assert(rtc_init() == 0);
assert(mac_init() == 0);
rtc_init();
esp_phy_init_clk();
assert(base_gpio_init() == 0);
esp_wifi_set_rx_pbuf_mem_type(WIFI_RX_PBUF_DRAM);
esp_phy_init_clk();
if (esp_reset_reason_early() != ESP_RST_FAST_SW) {
assert(esp_mac_init() == ESP_OK);
}
#if CONFIG_RESET_REASON
esp_reset_reason_init();
@ -103,6 +91,10 @@ static void user_init_entry(void *param)
assert(esp_pthread_init() == 0);
#endif
#ifdef CONFIG_BOOTLOADER_FAST_BOOT
REG_CLR_BIT(DPORT_CTL_REG, DPORT_CTL_DOUBLE_CLK);
#endif
#ifdef CONFIG_ESP8266_DEFAULT_CPU_FREQ_160
esp_set_cpu_freq(ESP_CPU_FREQ_160M);
#endif
@ -120,6 +112,10 @@ void call_start_cpu(size_t start_addr)
extern int _bss_start, _bss_end;
extern int _iram_bss_start, _iram_bss_end;
#ifdef CONFIG_BOOTLOADER_FAST_BOOT
REG_SET_BIT(DPORT_CTL_REG, DPORT_CTL_DOUBLE_CLK);
#endif
esp_image_header_t *head = (esp_image_header_t *)(FLASH_BASE + (start_addr & (FLASH_SIZE - 1)));
esp_image_segment_header_t *segment = (esp_image_segment_header_t *)((uintptr_t)head + sizeof(esp_image_header_t));

View File

@ -313,6 +313,34 @@ esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type)
return ESP_OK;
}
esp_err_t esp_mac_init(void)
{
esp_err_t ret;
uint8_t efuse_mac[6];
if ((ret = nvs_flash_init()) != ESP_OK) {
ESP_LOGE(TAG, "Init NVS error=%d", ret);
return ESP_ERR_INVALID_MAC;
}
if (load_backup_mac_data(efuse_mac) == ESP_OK) {
ESP_LOGD(TAG, "Load MAC from NVS error=%d", ret);
return ESP_OK;
}
if ((ret = esp_efuse_mac_get_default(efuse_mac)) != ESP_OK) {
ESP_LOGE(TAG, "Get mac address error=%d", ret);
return ESP_ERR_INVALID_MAC;
}
if ((ret = store_backup_mac_data()) != ESP_OK) {
ESP_LOGE(TAG, "Store mac address error=%d", ret);
return ESP_ERR_INVALID_MAC;
}
return ESP_OK;
}
/**
* Get IDF version
*/