feature: support multiple PHY init data
This commit is contained in:
parent
1e95cf3111
commit
ffd8c26780
13 changed files with 457 additions and 21 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
BIN
components/esp_wifi/phy_multiple_init_data.bin
Normal file
BIN
components/esp_wifi/phy_multiple_init_data.bin
Normal file
Binary file not shown.
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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"
|
Loading…
Reference in a new issue