feature: support multiple PHY init data

This commit is contained in:
ronghulin 2019-10-16 11:22:50 +08:00
parent 1e95cf3111
commit ffd8c26780
13 changed files with 457 additions and 21 deletions

View file

@ -58,6 +58,10 @@ endif()
if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION) if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION)
idf_component_get_property(esp_common_dir esp_common COMPONENT_DIR) idf_component_get_property(esp_common_dir esp_common COMPONENT_DIR)
partition_table_get_partition_info(phy_partition_offset "--partition-type data --partition-subtype phy" "offset") partition_table_get_partition_info(phy_partition_offset "--partition-type data --partition-subtype phy" "offset")
if(CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN)
set(phy_init_data_bin "${CMAKE_CURRENT_SOURCE_DIR}/phy_multiple_init_data.bin")
else()
set(phy_init_data_bin "${build_dir}/phy_init_data.bin") set(phy_init_data_bin "${build_dir}/phy_init_data.bin")
# To get the phy_init_data.bin file, compile phy_init_data.h as a C file and then objcopy # To get the phy_init_data.bin file, compile phy_init_data.h as a C file and then objcopy
@ -77,6 +81,7 @@ if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION)
idf_component_get_property(main_args esptool_py FLASH_ARGS) idf_component_get_property(main_args esptool_py FLASH_ARGS)
idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS) idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS)
endif()
# ToDo: remove once MP chip is supported # ToDo: remove once MP chip is supported
if(CONFIG_IDF_TARGET_ESP32) if(CONFIG_IDF_TARGET_ESP32)

View file

@ -325,7 +325,7 @@ menu "PHY"
2.Because of your board design, each time when you do calibration, the result are too unstable. 2.Because of your board design, each time when you do calibration, the result are too unstable.
If unsure, choose 'y'. If unsure, choose 'y'.
config ESP32_PHY_INIT_DATA_IN_PARTITION menuconfig ESP32_PHY_INIT_DATA_IN_PARTITION
bool "Use a partition to store PHY init data" bool "Use a partition to store PHY init data"
default n default n
help help
@ -341,6 +341,32 @@ menu "PHY"
If unsure, choose 'n'. If unsure, choose 'n'.
if ESP32_PHY_INIT_DATA_IN_PARTITION
config ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
bool "Support multiple PHY init data bin"
depends on ESP32_PHY_INIT_DATA_IN_PARTITION
default n
help
If enabled, the corresponding PHY init data type can be automatically switched
according to the country code. China's PHY init data bin is used by default.
Can be modified by country information in API esp_wifi_set_country().
The priority of switching the PHY init data type is:
1. Country configured by API esp_wifi_set_country()
and the parameter policy is WIFI_COUNTRY_POLICY_MANUAL.
2. Country notified by the connected AP.
3. Country configured by API esp_wifi_set_country()
and the parameter policy is WIFI_COUNTRY_POLICY_AUTO.
config ESP32_PHY_INIT_DATA_ERROR
bool "Terminate operation when PHY init data error"
depends on ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
default n
help
If enabled, when an error occurs while the PHY init data is updated,
the program will terminate and restart.
If not enabled, the PHY init data will not be updated when an error occurs.
endif
config ESP32_PHY_MAX_WIFI_TX_POWER config ESP32_PHY_MAX_WIFI_TX_POWER
int "Max WiFi TX power (dBm)" int "Max WiFi TX power (dBm)"
range 10 20 range 10 20

View file

@ -40,6 +40,7 @@
#include "esp_phy_init.h" #include "esp_phy_init.h"
#include "soc/dport_reg.h" #include "soc/dport_reg.h"
#include "soc/syscon_reg.h" #include "soc/syscon_reg.h"
#include "phy_init_data.h"
#include "driver/periph_ctrl.h" #include "driver/periph_ctrl.h"
#include "nvs.h" #include "nvs.h"
#include "os.h" #include "os.h"
@ -588,6 +589,7 @@ wifi_osi_funcs_t g_wifi_osi_funcs = {
._phy_load_cal_and_init = esp_phy_load_cal_and_init, ._phy_load_cal_and_init = esp_phy_load_cal_and_init,
._phy_common_clock_enable = esp_phy_common_clock_enable, ._phy_common_clock_enable = esp_phy_common_clock_enable,
._phy_common_clock_disable = esp_phy_common_clock_disable, ._phy_common_clock_disable = esp_phy_common_clock_disable,
._phy_update_country_info = esp_phy_update_country_info,
._read_mac = esp_read_mac, ._read_mac = esp_read_mac,
._timer_arm = timer_arm_wrapper, ._timer_arm = timer_arm_wrapper,
._timer_disarm = timer_disarm_wrapper, ._timer_disarm = timer_disarm_wrapper,

View file

@ -27,6 +27,12 @@
#define PHY_TX_POWER_OFFSET 44 #define PHY_TX_POWER_OFFSET 44
#define PHY_TX_POWER_NUM 5 #define PHY_TX_POWER_NUM 5
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
#define PHY_CRC_ALGORITHM 1
#define PHY_COUNTRY_CODE_LEN 2
#define PHY_INIT_DATA_TYPE_OFFSET 126
#define PHY_SUPPORT_MULTIPLE_BIN_OFFSET 125
#endif
static const char phy_init_magic_pre[] = PHY_INIT_MAGIC; static const char phy_init_magic_pre[] = PHY_INIT_MAGIC;
/** /**
@ -144,5 +150,27 @@ static const esp_phy_init_data_t phy_init_data= { {
static const char phy_init_magic_post[] = PHY_INIT_MAGIC; static const char phy_init_magic_post[] = PHY_INIT_MAGIC;
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
/**
* @brief PHY init data control infomation structure
*/
typedef struct {
uint8_t control_info_checksum[4]; /*!< 4-byte control infomation checksum */
uint8_t multiple_bin_checksum[4]; /*!< 4-byte multiple bin checksum */
uint8_t check_algorithm; /*!< check algorithm */
uint8_t version; /*!< PHY init data bin version */
uint8_t number; /*!< PHY init data bin number */
uint8_t length[2]; /*!< Length of each PHY init data bin */
uint8_t reserved[19]; /*!< 19-byte reserved */
} __attribute__ ((packed)) phy_control_info_data_t;
/**
* @brief Country corresponds to PHY init data type structure
*/
typedef struct {
char cc[PHY_COUNTRY_CODE_LEN];
uint8_t type;
} phy_country_to_bin_type_t;
#endif
#endif /* PHY_INIT_DATA_H */ #endif /* PHY_INIT_DATA_H */

View file

@ -41,6 +41,7 @@
#include "esp32s2/clk.h" #include "esp32s2/clk.h"
#include "soc/dport_reg.h" #include "soc/dport_reg.h"
#include "soc/syscon_reg.h" #include "soc/syscon_reg.h"
#include "phy_init_data.h"
#include "driver/periph_ctrl.h" #include "driver/periph_ctrl.h"
#include "nvs.h" #include "nvs.h"
#include "os.h" #include "os.h"
@ -576,6 +577,7 @@ wifi_osi_funcs_t g_wifi_osi_funcs = {
._dport_access_stall_other_cpu_end_wrap = esp_empty_wrapper, ._dport_access_stall_other_cpu_end_wrap = esp_empty_wrapper,
._phy_rf_deinit = esp_phy_rf_deinit, ._phy_rf_deinit = esp_phy_rf_deinit,
._phy_load_cal_and_init = esp_phy_load_cal_and_init, ._phy_load_cal_and_init = esp_phy_load_cal_and_init,
._phy_update_country_info = esp_phy_update_country_info,
._read_mac = esp_read_mac, ._read_mac = esp_read_mac,
._timer_arm = timer_arm_wrapper, ._timer_arm = timer_arm_wrapper,
._timer_disarm = timer_disarm_wrapper, ._timer_disarm = timer_disarm_wrapper,

View file

@ -31,6 +31,13 @@ extern "C" {
#define PHY_TX_POWER_OFFSET 44 #define PHY_TX_POWER_OFFSET 44
#define PHY_TX_POWER_NUM 5 #define PHY_TX_POWER_NUM 5
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
#define PHY_CRC_ALGORITHM 1
#define PHY_COUNTRY_CODE_LEN 2
#define PHY_INIT_DATA_TYPE_OFFSET 126
#define PHY_SUPPORT_MULTIPLE_BIN_OFFSET 125
#endif
static const char phy_init_magic_pre[] = PHY_INIT_MAGIC; static const char phy_init_magic_pre[] = PHY_INIT_MAGIC;
/** /**
@ -148,6 +155,29 @@ static const esp_phy_init_data_t phy_init_data= { {
static const char phy_init_magic_post[] = PHY_INIT_MAGIC; static const char phy_init_magic_post[] = PHY_INIT_MAGIC;
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
/**
* @brief PHY init data control infomation structure
*/
typedef struct {
uint8_t control_info_checksum[4]; /*!< 4-byte control infomation checksum */
uint8_t multiple_bin_checksum[4]; /*!< 4-byte multiple bin checksum */
uint8_t check_algorithm; /*!< check algorithm */
uint8_t version; /*!< PHY init data bin version */
uint8_t number; /*!< PHY init data bin number */
uint8_t length[2]; /*!< Length of each PHY init data bin */
uint8_t reserved[19]; /*!< 19-byte reserved */
} __attribute__ ((packed)) phy_control_info_data_t;
/**
* @brief Country corresponds to PHY init data type structure
*/
typedef struct {
char cc[PHY_COUNTRY_CODE_LEN];
uint8_t type;
} phy_country_to_bin_type_t;
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -63,6 +63,30 @@ typedef enum{
MODEM_MODULE_COUNT //!< Number of items MODEM_MODULE_COUNT //!< Number of items
}modem_sleep_module_t; }modem_sleep_module_t;
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
/**
* @brief PHY init data type
*/
typedef enum {
ESP_PHY_INIT_DATA_TYPE_DEFAULT = 0,
ESP_PHY_INIT_DATA_TYPE_SRRC,
ESP_PHY_INIT_DATA_TYPE_FCC,
ESP_PHY_INIT_DATA_TYPE_CE,
ESP_PHY_INIT_DATA_TYPE_NCC,
ESP_PHY_INIT_DATA_TYPE_KCC,
ESP_PHY_INIT_DATA_TYPE_MIC,
ESP_PHY_INIT_DATA_TYPE_IC,
ESP_PHY_INIT_DATA_TYPE_ACMA,
ESP_PHY_INIT_DATA_TYPE_ANATEL,
ESP_PHY_INIT_DATA_TYPE_ISED,
ESP_PHY_INIT_DATA_TYPE_WPC,
ESP_PHY_INIT_DATA_TYPE_OFCA,
ESP_PHY_INIT_DATA_TYPE_IFETEL,
ESP_PHY_INIT_DATA_TYPE_RCM,
ESP_PHY_INIT_DATA_TYPE_NUMBER,
} phy_init_data_type_t;
#endif
/** /**
* @brief Module WIFI mask for medem sleep * @brief Module WIFI mask for medem sleep
*/ */
@ -244,6 +268,21 @@ esp_err_t esp_modem_sleep_deregister(modem_sleep_module_t module);
* microsecond since boot when phy/rf was last switched on * microsecond since boot when phy/rf was last switched on
*/ */
int64_t esp_phy_rf_get_on_ts(void); int64_t esp_phy_rf_get_on_ts(void);
/**
* @brief Update the corresponding PHY init type according to the country code of Wi-Fi.
*/
esp_err_t esp_phy_update_country_info(const char *country);
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
/**
* @brief Apply PHY init bin to PHY
* @return ESP_OK on success.
* @return ESP_FAIL on fail.
*/
esp_err_t esp_phy_apply_phy_init_data(uint8_t *init_data);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -21,7 +21,7 @@
extern "C" { extern "C" {
#endif #endif
#define ESP_WIFI_OS_ADAPTER_VERSION 0x00000005 #define ESP_WIFI_OS_ADAPTER_VERSION 0x00000006
#define ESP_WIFI_OS_ADAPTER_MAGIC 0xDEADBEAF #define ESP_WIFI_OS_ADAPTER_MAGIC 0xDEADBEAF
#define OSI_FUNCS_TIME_BLOCKING 0xffffffff #define OSI_FUNCS_TIME_BLOCKING 0xffffffff
@ -83,6 +83,7 @@ typedef struct {
void (* _phy_common_clock_enable)(void); void (* _phy_common_clock_enable)(void);
void (* _phy_common_clock_disable)(void); void (* _phy_common_clock_disable)(void);
#endif #endif
int32_t (* _phy_update_country_info)(const char* country);
int32_t (* _read_mac)(uint8_t* mac, uint32_t type); int32_t (* _read_mac)(uint8_t* mac, uint32_t type);
void (* _timer_arm)(void *timer, uint32_t tmout, bool repeat); void (* _timer_arm)(void *timer, uint32_t tmout, bool repeat);
void (* _timer_disarm)(void *timer); void (* _timer_disarm)(void *timer);

View file

@ -592,9 +592,11 @@ esp_err_t esp_wifi_get_channel(uint8_t *primary, wifi_second_chan_t *second);
* @attention 3. When the country policy is WIFI_COUNTRY_POLICY_MANUAL, always use the configured country info. * @attention 3. When the country policy is WIFI_COUNTRY_POLICY_MANUAL, always use the configured country info.
* @attention 4. When the country info is changed because of configuration or because the station connects to a different * @attention 4. When the country info is changed because of configuration or because the station connects to a different
* external AP, the country IE in probe response/beacon of the soft-AP is changed also. * external AP, the country IE in probe response/beacon of the soft-AP is changed also.
* @attention 5. The country configuration is not stored into flash * @attention 5. The country configuration is stored into flash.
* @attention 6. This API doesn't validate the per-country rules, it's up to the user to fill in all fields according to * @attention 6. This API doesn't validate the per-country rules, it's up to the user to fill in all fields according to
* local regulations. * local regulations.
* @attention 7. When this API is called, the PHY init data will switch to the PHY init data type corresponding to the
* country info.
* *
* @param country the configured country info * @param country the configured country info
* *

@ -1 +1 @@
Subproject commit 5f483b84212a313d202580b0b20f9db09b07cbd9 Subproject commit d72ff2a27e6892b40ff6cf4a1aec67aa552c299b

Binary file not shown.

View file

@ -38,9 +38,11 @@
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h" #include "esp32/rom/ets_sys.h"
#include "esp32/rom/rtc.h" #include "esp32/rom/rtc.h"
#include "esp32/rom/crc.h"
#elif CONFIG_IDF_TARGET_ESP32S2 #elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h" #include "esp32s2/rom/ets_sys.h"
#include "esp32s2/rom/rtc.h" #include "esp32s2/rom/rtc.h"
#include "esp32s2/rom/crc.h"
#endif #endif
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
@ -85,6 +87,69 @@ static int64_t s_phy_rf_en_ts = 0;
static DRAM_ATTR portMUX_TYPE s_phy_int_mux = portMUX_INITIALIZER_UNLOCKED; static DRAM_ATTR portMUX_TYPE s_phy_int_mux = portMUX_INITIALIZER_UNLOCKED;
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
/* The following static variables are only used by Wi-Fi tasks, so they can be handled without lock */
static phy_init_data_type_t s_phy_init_data_type = 0;
static phy_init_data_type_t s_current_apply_phy_init_data = 0;
static char s_phy_current_country[PHY_COUNTRY_CODE_LEN] = {0};
/* Whether it is a new bin */
static bool s_multiple_phy_init_data_bin = false;
/* PHY init data type array */
static char* s_phy_type[ESP_PHY_INIT_DATA_TYPE_NUMBER] = {"DEFAULT", "SRRC", "FCC", "CE", "NCC", "KCC", "MIC", "IC",
"ACMA", "ANATEL", "ISED", "WPC", "OFCA", "IFETEL", "RCM"};
/* Country and PHY init data type map */
static phy_country_to_bin_type_t s_country_code_map_type_table[] = {
{"AT", ESP_PHY_INIT_DATA_TYPE_CE},
{"AU", ESP_PHY_INIT_DATA_TYPE_ACMA},
{"BE", ESP_PHY_INIT_DATA_TYPE_CE},
{"BG", ESP_PHY_INIT_DATA_TYPE_CE},
{"BR", ESP_PHY_INIT_DATA_TYPE_ANATEL},
{"CA", ESP_PHY_INIT_DATA_TYPE_ISED},
{"CH", ESP_PHY_INIT_DATA_TYPE_CE},
{"CN", ESP_PHY_INIT_DATA_TYPE_SRRC},
{"CY", ESP_PHY_INIT_DATA_TYPE_CE},
{"CZ", ESP_PHY_INIT_DATA_TYPE_CE},
{"DE", ESP_PHY_INIT_DATA_TYPE_CE},
{"DK", ESP_PHY_INIT_DATA_TYPE_CE},
{"EE", ESP_PHY_INIT_DATA_TYPE_CE},
{"ES", ESP_PHY_INIT_DATA_TYPE_CE},
{"FI", ESP_PHY_INIT_DATA_TYPE_CE},
{"FR", ESP_PHY_INIT_DATA_TYPE_CE},
{"GB", ESP_PHY_INIT_DATA_TYPE_CE},
{"GR", ESP_PHY_INIT_DATA_TYPE_CE},
{"HK", ESP_PHY_INIT_DATA_TYPE_OFCA},
{"HR", ESP_PHY_INIT_DATA_TYPE_CE},
{"HU", ESP_PHY_INIT_DATA_TYPE_CE},
{"IE", ESP_PHY_INIT_DATA_TYPE_CE},
{"IN", ESP_PHY_INIT_DATA_TYPE_WPC},
{"IS", ESP_PHY_INIT_DATA_TYPE_CE},
{"IT", ESP_PHY_INIT_DATA_TYPE_CE},
{"JP", ESP_PHY_INIT_DATA_TYPE_MIC},
{"KR", ESP_PHY_INIT_DATA_TYPE_KCC},
{"LI", ESP_PHY_INIT_DATA_TYPE_CE},
{"LT", ESP_PHY_INIT_DATA_TYPE_CE},
{"LU", ESP_PHY_INIT_DATA_TYPE_CE},
{"LV", ESP_PHY_INIT_DATA_TYPE_CE},
{"MT", ESP_PHY_INIT_DATA_TYPE_CE},
{"MX", ESP_PHY_INIT_DATA_TYPE_IFETEL},
{"NL", ESP_PHY_INIT_DATA_TYPE_CE},
{"NO", ESP_PHY_INIT_DATA_TYPE_CE},
{"NZ", ESP_PHY_INIT_DATA_TYPE_RCM},
{"PL", ESP_PHY_INIT_DATA_TYPE_CE},
{"PT", ESP_PHY_INIT_DATA_TYPE_CE},
{"RO", ESP_PHY_INIT_DATA_TYPE_CE},
{"SE", ESP_PHY_INIT_DATA_TYPE_CE},
{"SI", ESP_PHY_INIT_DATA_TYPE_CE},
{"SK", ESP_PHY_INIT_DATA_TYPE_CE},
{"TW", ESP_PHY_INIT_DATA_TYPE_NCC},
{"US", ESP_PHY_INIT_DATA_TYPE_FCC},
};
#endif
uint32_t IRAM_ATTR phy_enter_critical(void) uint32_t IRAM_ATTR phy_enter_critical(void)
{ {
if (xPortInIsrContext()) { if (xPortInIsrContext()) {
@ -502,6 +567,14 @@ const esp_phy_init_data_t* esp_phy_get_init_data(void)
ESP_LOGE(TAG, "failed to validate PHY data partition"); ESP_LOGE(TAG, "failed to validate PHY data partition");
return NULL; return NULL;
} }
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
if ((*(init_data_store + (sizeof(phy_init_magic_pre) + PHY_SUPPORT_MULTIPLE_BIN_OFFSET)))) {
s_multiple_phy_init_data_bin = true;
ESP_LOGI(TAG, "Support multiple PHY init data bins");
} else {
ESP_LOGW(TAG, "Does not support multiple PHY init data bins");
}
#endif
ESP_LOGD(TAG, "PHY data partition validated"); ESP_LOGD(TAG, "PHY data partition validated");
return (const esp_phy_init_data_t*) (init_data_store + sizeof(phy_init_magic_pre)); return (const esp_phy_init_data_t*) (init_data_store + sizeof(phy_init_magic_pre));
} }
@ -601,6 +674,7 @@ static esp_err_t load_cal_data_from_nvs_handle(nvs_handle_t handle,
{ {
esp_err_t err; esp_err_t err;
uint32_t cal_data_version; uint32_t cal_data_version;
err = nvs_get_u32(handle, PHY_CAL_VERSION_KEY, &cal_data_version); err = nvs_get_u32(handle, PHY_CAL_VERSION_KEY, &cal_data_version);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGD(TAG, "%s: failed to get cal_version (0x%x)", __func__, err); ESP_LOGD(TAG, "%s: failed to get cal_version (0x%x)", __func__, err);
@ -765,3 +839,227 @@ void esp_phy_load_cal_and_init(phy_rf_module_t module)
free(cal_data); // PHY maintains a copy of calibration data, so we can free this free(cal_data); // PHY maintains a copy of calibration data, so we can free this
} }
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
static esp_err_t phy_crc_check_init_data(uint8_t* init_data, const uint8_t* checksum, size_t init_data_length)
{
uint32_t crc_data = 0;
crc_data = crc32_le(crc_data, init_data, init_data_length);
uint32_t crc_size_conversion = htonl(crc_data);
if (crc_size_conversion != *(uint32_t*)(checksum)) {
return ESP_FAIL;
}
return ESP_OK;
}
static uint8_t phy_find_bin_type_according_country(const char* country)
{
uint32_t i = 0;
uint8_t phy_init_data_type = 0;
for (i = 0; i < sizeof(s_country_code_map_type_table)/sizeof(phy_country_to_bin_type_t); i++)
{
if (!memcmp(country, s_country_code_map_type_table[i].cc, sizeof(s_phy_current_country))) {
phy_init_data_type = s_country_code_map_type_table[i].type;
ESP_LOGD(TAG, "Current country is %c%c, PHY init data type is %s\n", s_country_code_map_type_table[i].cc[0],
s_country_code_map_type_table[i].cc[1], s_phy_type[s_country_code_map_type_table[i].type]);
break;
}
}
if (i == sizeof(s_country_code_map_type_table)/sizeof(phy_country_to_bin_type_t)) {
phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
ESP_LOGW(TAG, "Use the default certification code beacuse %c%c doesn't have a certificate", country[0], country[1]);
}
return phy_init_data_type;
}
static esp_err_t phy_find_bin_data_according_type(uint8_t* out_init_data_store,
const phy_control_info_data_t* init_data_control_info,
const uint8_t* init_data_multiple,
phy_init_data_type_t init_data_type)
{
int i = 0;
for (i = 0; i < init_data_control_info->number; i++) {
if (init_data_type == *(init_data_multiple + (i * sizeof(esp_phy_init_data_t)) + PHY_INIT_DATA_TYPE_OFFSET)) {
memcpy(out_init_data_store + sizeof(phy_init_magic_pre),
init_data_multiple + (i * sizeof(esp_phy_init_data_t)), sizeof(esp_phy_init_data_t));
break;
}
}
if (i == init_data_control_info->number) {
return ESP_FAIL;
}
return ESP_OK;
}
static esp_err_t phy_get_multiple_init_data(const esp_partition_t* partition,
uint8_t* init_data_store,
size_t init_data_store_length,
phy_init_data_type_t init_data_type)
{
phy_control_info_data_t* init_data_control_info = (phy_control_info_data_t*) malloc(sizeof(phy_control_info_data_t));
if (init_data_control_info == NULL) {
ESP_LOGE(TAG, "failed to allocate memory for PHY init data control info");
return ESP_FAIL;
}
esp_err_t err = esp_partition_read(partition, init_data_store_length, init_data_control_info, sizeof(phy_control_info_data_t));
if (err != ESP_OK) {
free(init_data_control_info);
ESP_LOGE(TAG, "failed to read PHY control info data partition (0x%x)", err);
return ESP_FAIL;
}
if ((init_data_control_info->check_algorithm) == PHY_CRC_ALGORITHM) {
err = phy_crc_check_init_data(init_data_control_info->multiple_bin_checksum, init_data_control_info->control_info_checksum,
sizeof(phy_control_info_data_t) - sizeof(init_data_control_info->control_info_checksum));
if (err != ESP_OK) {
free(init_data_control_info);
ESP_LOGE(TAG, "PHY init data control info check error");
return ESP_FAIL;
}
} else {
free(init_data_control_info);
ESP_LOGE(TAG, "Check algorithm not CRC, PHY init data update failed");
return ESP_FAIL;
}
uint8_t* init_data_multiple = (uint8_t*) malloc(sizeof(esp_phy_init_data_t) * init_data_control_info->number);
if (init_data_multiple == NULL) {
free(init_data_control_info);
ESP_LOGE(TAG, "failed to allocate memory for PHY init data multiple bin");
return ESP_FAIL;
}
err = esp_partition_read(partition, init_data_store_length + sizeof(phy_control_info_data_t),
init_data_multiple, sizeof(esp_phy_init_data_t) * init_data_control_info->number);
if (err != ESP_OK) {
free(init_data_multiple);
free(init_data_control_info);
ESP_LOGE(TAG, "failed to read PHY init data multiple bin partition (0x%x)", err);
return ESP_FAIL;
}
if ((init_data_control_info->check_algorithm) == PHY_CRC_ALGORITHM) {
err = phy_crc_check_init_data(init_data_multiple, init_data_control_info->multiple_bin_checksum,
sizeof(esp_phy_init_data_t) * init_data_control_info->number);
if (err != ESP_OK) {
free(init_data_multiple);
free(init_data_control_info);
ESP_LOGE(TAG, "PHY init data multiple bin check error");
return ESP_FAIL;
}
} else {
free(init_data_multiple);
free(init_data_control_info);
ESP_LOGE(TAG, "Check algorithm not CRC, PHY init data update failed");
return ESP_FAIL;
}
err = phy_find_bin_data_according_type(init_data_store, init_data_control_info, init_data_multiple, init_data_type);
if (err != ESP_OK) {
ESP_LOGW(TAG, "%s has not been certified, use DEFAULT PHY init data", s_phy_type[init_data_type]);
s_phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
} else {
s_phy_init_data_type = init_data_type;
}
free(init_data_multiple);
free(init_data_control_info);
return ESP_OK;
}
esp_err_t esp_phy_update_init_data(phy_init_data_type_t init_data_type)
{
const esp_partition_t* partition = esp_partition_find_first(
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL);
if (partition == NULL) {
ESP_LOGE(TAG, "Updated country code PHY data partition not found");
return ESP_FAIL;
}
size_t init_data_store_length = sizeof(phy_init_magic_pre) +
sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
uint8_t* init_data_store = (uint8_t*) malloc(init_data_store_length);
if (init_data_store == NULL) {
ESP_LOGE(TAG, "failed to allocate memory for updated country code PHY init data");
return ESP_ERR_NO_MEM;
}
esp_err_t err = esp_partition_read(partition, 0, init_data_store, init_data_store_length);
if (err != ESP_OK) {
free(init_data_store);
ESP_LOGE(TAG, "failed to read updated country code PHY data partition (0x%x)", err);
return ESP_FAIL;
}
if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) != 0 ||
memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post),
PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) {
free(init_data_store);
ESP_LOGE(TAG, "failed to validate updated country code PHY data partition");
return ESP_FAIL;
}
//find init data bin according init data type
if (init_data_type != ESP_PHY_INIT_DATA_TYPE_DEFAULT) {
err = phy_get_multiple_init_data(partition, init_data_store, init_data_store_length, init_data_type);
if (err != ESP_OK) {
free(init_data_store);
#if CONFIG_ESP32_PHY_INIT_DATA_ERROR
abort();
#else
return ESP_FAIL;
#endif
}
} else {
s_phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
}
if (s_current_apply_phy_init_data != s_phy_init_data_type) {
err = esp_phy_apply_phy_init_data(init_data_store + sizeof(phy_init_magic_pre));
if (err != ESP_OK) {
ESP_LOGE(TAG, "PHY init data failed to load");
free(init_data_store);
return ESP_FAIL;
}
ESP_LOGI(TAG, "PHY init data type updated from %s to %s",
s_phy_type[s_current_apply_phy_init_data], s_phy_type[s_phy_init_data_type]);
s_current_apply_phy_init_data = s_phy_init_data_type;
}
free(init_data_store);
return ESP_OK;
}
#endif
esp_err_t esp_phy_update_country_info(const char *country)
{
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
uint8_t phy_init_data_type_map = 0;
//if country equal s_phy_current_country, return;
if (!memcmp(country, s_phy_current_country, sizeof(s_phy_current_country))) {
return ESP_OK;
}
memcpy(s_phy_current_country, country, sizeof(s_phy_current_country));
if (!s_multiple_phy_init_data_bin) {
ESP_LOGD(TAG, "Does not support multiple PHY init data bins");
return ESP_FAIL;
}
phy_init_data_type_map = phy_find_bin_type_according_country(country);
if (phy_init_data_type_map == s_phy_init_data_type) {
return ESP_OK;
}
esp_err_t err = esp_phy_update_init_data(phy_init_data_type_map);
if (err != ESP_OK) {
return err;
}
#endif
return ESP_OK;
}

View file

@ -0,0 +1,3 @@
CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION=y
CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN=y
CONFIG_IDF_TARGET="esp32"