add PHY init support

pull/124/head
Ivan Grokhotkov 2016-11-15 18:36:18 +08:00
rodzic a0feea8daa
commit 4db29f74a0
8 zmienionych plików z 736 dodań i 1 usunięć

Wyświetl plik

@ -364,4 +364,58 @@ config ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
depends on DOCUMENTATION_FOR_RTC_CNTL
endchoice
config ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS
bool "Store PHY calibration data in NVS"
default y
help
Choose whether to use non-volatile storage library (NVS)
to store PHY calibration data obtained at run time.
If enabled, this will use approximately 2kB of NVS storage
for PHY calibration data.
If this option is not enabled, calibration data will not be stored,
unless application provides its own implementations of
esp_phy_store_cal_data and esp_phy_load_cal_data functions.
See esp_phy_init.h for details.
If unsure, choose 'y'.
config ESP32_PHY_AUTO_INIT
bool "Initialize PHY in startup code"
default y
help
If enabled, PHY will be initialized in startup code, before
app_main function runs.
If this is undesired, disable this option and call esp_phy_init
from the application before enabling WiFi or BT.
If this option is enabled along with ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS,
startup code will also initialize NVS prior to initializing PHY.
If unsure, choose 'y'.
config ESP32_PHY_INIT_DATA_IN_PARTITION
bool "Use a partition to store PHY init data"
default n
help
If enabled, PHY init data will be loaded from a partition.
When using a custom partition table, make sure that PHY data
partition is included (type: 'data', subtype: 'phy').
With default partition tables, this is done automatically.
If PHY init data is stored in a partition, it has to be flashed there,
otherwise runtime error will occur.
If this option is not enabled, PHY init data will be embedded
into the application binary.
If unsure, choose 'n'.
config ESP32_PHY_MAX_TX_POWER
int "Max TX power (dBm)"
range 0 20
default 20
help
Set maximum transmit power. Actual transmit power for high
data rates may be lower than this setting.
endmenu

Wyświetl plik

@ -0,0 +1,42 @@
ifdef CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
PHY_INIT_DATA_OBJ = $(BUILD_DIR_BASE)/phy_init_data.o
PHY_INIT_DATA_BIN = $(BUILD_DIR_BASE)/phy_init_data.bin
PARTITION_TABLE_COMPONENT_PATH := $(COMPONENT_PATH)/../partition_table
ESP32_COMPONENT_PATH := $(COMPONENT_PATH)
GEN_ESP32PART := $(PYTHON) $(PARTITION_TABLE_COMPONENT_PATH)/gen_esp32part.py -q
# Path to partition CSV file is relative to project path for custom
# partition CSV files, but relative to component dir otherwise.
PARTITION_TABLE_ROOT := $(call dequote,$(if $(CONFIG_PARTITION_TABLE_CUSTOM),$(PROJECT_PATH),$(PARTITION_TABLE_COMPONENT_PATH)))
PARTITION_TABLE_CSV_PATH := $(call dequote,$(abspath $(PARTITION_TABLE_ROOT)/$(subst $(quote),,$(CONFIG_PARTITION_TABLE_FILENAME))))
PARTITION_TABLE_BIN := $(BUILD_DIR_BASE)/$(notdir $(PARTITION_TABLE_CSV_PATH:.csv=.bin))
# Parse partition table and get offset of PHY init data partition
PHY_INIT_GET_ADDR_CMD := $(GEN_ESP32PART) $(PARTITION_TABLE_CSV_PATH) | $(GEN_ESP32PART) - | sed -n -e "s/[^,]*,data,phy,\\([^,]*\\),.*/\\1/p"
PHY_INIT_DATA_ADDR = $(shell $(PHY_INIT_GET_ADDR_CMD))
# Command to flash PHY init data partition
PHY_INIT_DATA_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(PHY_INIT_DATA_ADDR) $(PHY_INIT_DATA_BIN)
ESPTOOL_ALL_FLASH_ARGS += $(PHY_INIT_DATA_ADDR) $(PHY_INIT_DATA_BIN)
$(PHY_INIT_DATA_OBJ): $(ESP32_COMPONENT_PATH)/phy_init_data.h $(BUILD_DIR_BASE)/include/sdkconfig.h
$(summary) CC $(notdir $@)
printf "#include \"phy_init_data.h\"\n" | $(CC) -I $(BUILD_DIR_BASE)/include -I $(ESP32_COMPONENT_PATH) -I $(ESP32_COMPONENT_PATH)/include -c -o $@ -xc -
$(PHY_INIT_DATA_BIN): $(PHY_INIT_DATA_OBJ)
$(summary) BIN $(notdir $@)
$(OBJCOPY) -O binary $< $@
phy_init_data: $(PHY_INIT_DATA_BIN)
phy_init_data-flash: $(BUILD_DIR_BASE)/phy_init_data.bin
@echo "Flashing PHY init data..."
$(PHY_INIT_DATA_FLASH_CMD)
phy_init_data-clean:
rm -f $(PHY_INIT_DATA_BIN) $(PHY_INIT_DATA_OBJ)
endif # CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION

Wyświetl plik

@ -50,6 +50,7 @@
#include "esp_brownout.h"
#include "esp_int_wdt.h"
#include "esp_task_wdt.h"
#include "esp_phy_init.h"
#include "trax.h"
void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default")));
@ -187,6 +188,20 @@ void start_cpu0_default(void)
esp_ipc_init();
spi_flash_init();
#if CONFIG_ESP32_PHY_AUTO_INIT
#if CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS
nvs_flash_init();
#endif
esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL;
if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) {
calibration_mode = PHY_RF_CAL_NONE;
}
if (esp_phy_init(calibration_mode) != ESP_OK) {
ESP_LOGD(TAG, "phy init has failed");
abort();
}
#endif
xTaskCreatePinnedToCore(&main_task, "main",
ESP_TASK_MAIN_STACK, NULL,
ESP_TASK_MAIN_PRIO, NULL, 0);

Wyświetl plik

@ -0,0 +1,170 @@
// Copyright 2015-2016 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
#include <stdint.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint8_t param_ver_id; /*!< init_data structure version */
uint8_t crystal_select; /*!< 0: 40MHz, 1: 26 MHz, 2: 24 MHz, 3: auto */
uint8_t wifi_rx_gain_swp_step_1; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_2; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_3; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_4; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_5; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_6; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_7; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_8; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_9; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_10; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_11; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_12; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_13; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_14; /*!< do not change */
uint8_t wifi_rx_gain_swp_step_15; /*!< do not change */
uint8_t bt_rx_gain_swp_step_1; /*!< do not change */
uint8_t bt_rx_gain_swp_step_2; /*!< do not change */
uint8_t bt_rx_gain_swp_step_3; /*!< do not change */
uint8_t bt_rx_gain_swp_step_4; /*!< do not change */
uint8_t bt_rx_gain_swp_step_5; /*!< do not change */
uint8_t bt_rx_gain_swp_step_6; /*!< do not change */
uint8_t bt_rx_gain_swp_step_7; /*!< do not change */
uint8_t bt_rx_gain_swp_step_8; /*!< do not change */
uint8_t bt_rx_gain_swp_step_9; /*!< do not change */
uint8_t bt_rx_gain_swp_step_10; /*!< do not change */
uint8_t bt_rx_gain_swp_step_11; /*!< do not change */
uint8_t bt_rx_gain_swp_step_12; /*!< do not change */
uint8_t bt_rx_gain_swp_step_13; /*!< do not change */
uint8_t bt_rx_gain_swp_step_14; /*!< do not change */
uint8_t bt_rx_gain_swp_step_15; /*!< do not change */
uint8_t gain_cmp_1; /*!< do not change */
uint8_t gain_cmp_6; /*!< do not change */
uint8_t gain_cmp_11; /*!< do not change */
uint8_t gain_cmp_ext2_1; /*!< do not change */
uint8_t gain_cmp_ext2_6; /*!< do not change */
uint8_t gain_cmp_ext2_11; /*!< do not change */
uint8_t gain_cmp_ext3_1; /*!< do not change */
uint8_t gain_cmp_ext3_6; /*!< do not change */
uint8_t gain_cmp_ext3_11; /*!< do not change */
uint8_t gain_cmp_bt_ofs_1; /*!< do not change */
uint8_t gain_cmp_bt_ofs_6; /*!< do not change */
uint8_t gain_cmp_bt_ofs_11; /*!< do not change */
uint8_t target_power_qdb_0; /*!< 78 means target power is 78/4=19.5dbm */
uint8_t target_power_qdb_1; /*!< 76 means target power is 76/4=19dbm */
uint8_t target_power_qdb_2; /*!< 74 means target power is 74/4=18.5dbm */
uint8_t target_power_qdb_3; /*!< 68 means target power is 68/4=17dbm */
uint8_t target_power_qdb_4; /*!< 64 means target power is 64/4=16dbm */
uint8_t target_power_qdb_5; /*!< 52 means target power is 52/4=13dbm */
uint8_t target_power_index_mcs0; /*!< target power index is 0, means target power is target_power_qdb_0 19.5dbm; (1m,2m,5.5m,11m,6m,9m) */
uint8_t target_power_index_mcs1; /*!< target power index is 0, means target power is target_power_qdb_0 19.5dbm; (12m) */
uint8_t target_power_index_mcs2; /*!< target power index is 1, means target power is target_power_qdb_1 19dbm; (18m) */
uint8_t target_power_index_mcs3; /*!< target power index is 1, means target power is target_power_qdb_1 19dbm; (24m) */
uint8_t target_power_index_mcs4; /*!< target power index is 2, means target power is target_power_qdb_2 18.5dbm; (36m) */
uint8_t target_power_index_mcs5; /*!< target power index is 3, means target power is target_power_qdb_3 17dbm; (48m) */
uint8_t target_power_index_mcs6; /*!< target power index is 4, means target power is target_power_qdb_4 16dbm; (54m) */
uint8_t target_power_index_mcs7; /*!< target power index is 5, means target power is target_power_qdb_5 13dbm */
uint8_t pwr_ind_11b_en; /*!< 0: 11b power is same as mcs0 and 6m, 1: 11b power different with OFDM */
uint8_t pwr_ind_11b_0; /*!< 1m, 2m power index [0~5] */
uint8_t pwr_ind_11b_1; /*!< 5.5m, 11m power index [0~5] */
uint8_t chan_backoff_en; /*!< 0: channel backoff disable, 1:channel backoff enable */
uint8_t chan1_power_backoff_qdb; /*!< 4 means backoff is 1db */
uint8_t chan2_power_backoff_qdb; /*!< see chan1_power_backoff_qdb */
uint8_t chan3_power_backoff_qdb; /*!< chan1_power_backoff_qdb */
uint8_t chan4_power_backoff_qdb; /*!< chan1_power_backoff_qdb */
uint8_t chan5_power_backoff_qdb; /*!< chan1_power_backoff_qdb */
uint8_t chan6_power_backoff_qdb; /*!< chan1_power_backoff_qdb */
uint8_t chan7_power_backoff_qdb; /*!< chan1_power_backoff_qdb */
uint8_t chan8_power_backoff_qdb; /*!< chan1_power_backoff_qdb */
uint8_t chan9_power_backoff_qdb; /*!< chan1_power_backoff_qdb */
uint8_t chan10_power_backoff_qdb; /*!< chan1_power_backoff_qdb */
uint8_t chan11_power_backoff_qdb; /*!< chan1_power_backoff_qdb */
uint8_t chan12_power_backoff_qdb; /*!< chan1_power_backoff_qdb */
uint8_t chan13_power_backoff_qdb; /*!< chan1_power_backoff_qdb */
uint8_t chan14_power_backoff_qdb; /*!< chan1_power_backoff_qdb */
uint8_t chan1_rate_backoff_index; /*!< if bit i is set, backoff data rate is target_power_qdb_i */
uint8_t chan2_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t chan3_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t chan4_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t chan5_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t chan6_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t chan7_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t chan8_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t chan9_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t chan10_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t chan11_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t chan12_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t chan13_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t chan14_rate_backoff_index; /*!< see chan1_rate_backoff_index */
uint8_t spur_freq_cfg_msb_1; /*!< first spur: */
uint8_t spur_freq_cfg_1; /*!< spur_freq_cfg = (spur_freq_cfg_msb_1 <<8) | spur_freq_cfg_1 */
uint8_t spur_freq_cfg_div_1; /*!< spur_freq=spur_freq_cfg/spur_freq_cfg_div_1 */
uint8_t spur_freq_en_h_1; /*!< the seventh bit for total enable */
uint8_t spur_freq_en_l_1; /*!< each bit for 1 channel, and use [spur_freq_en_h, spur_freq_en_l] to select the spur's channel priority */
uint8_t spur_freq_cfg_msb_2; /*!< second spur: */
uint8_t spur_freq_cfg_2; /*!< spur_freq_cfg = (spur_freq_cfg_msb_2 <<8) | spur_freq_cfg_2 */
uint8_t spur_freq_cfg_div_2; /*!< spur_freq=spur_freq_cfg/spur_freq_cfg_div_2 */
uint8_t spur_freq_en_h_2; /*!< the seventh bit for total enable */
uint8_t spur_freq_en_l_2; /*!< each bit for 1 channel, and use [spur_freq_en_h, spur_freq_en_l] to select the spur's channel priority */
uint8_t spur_freq_cfg_msb_3; /*!< third spur: */
uint8_t spur_freq_cfg_3; /*!< spur_freq_cfg = (spur_freq_cfg_msb_3 <<8) | spur_freq_cfg_3 */
uint8_t spur_freq_cfg_div_3; /*!< spur_freq=spur_freq_cfg/spur_freq_cfg_div_3 */
uint8_t spur_freq_en_h_3; /*!< the seventh bit for total enable */
uint8_t spur_freq_en_l_3; /*!< each bit for 1 channel, and use [spur_freq_en_h, spur_freq_en_l] to select the spur's channel priority, */
uint8_t reserved[23]; /*!< reserved for future expansion */
} esp_phy_init_data_t;
typedef struct {
uint8_t opaque[1904]; /*!< opaque calibration data */
} esp_phy_calibration_data_t;
typedef enum {
PHY_RF_CAL_PARTIAL = 0x00000000, /*!< Do part of RF calibration. This should be used after power-on reset. */
PHY_RF_CAL_NONE = 0x00000001, /*!< Don't do any RF calibration. This mode is only suggested to be used after deep sleep reset. */
PHY_RF_CAL_FULL = 0x00000002 /*!< Do full RF calibration. Produces best results, but also consumes a lot of time and current. Suggested to be used once. */
} esp_phy_calibration_mode_t;
/**
*
* @param mode
* @return
*/
esp_err_t esp_phy_init(esp_phy_calibration_mode_t mode);
#ifndef CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS
/**
*
* @param cal_data
* @return
*/
esp_err_t esp_phy_store_cal_data(const esp_phy_calibration_data_t* cal_data);
/**
*
* @param out_cal_data
* @return
*/
esp_err_t esp_phy_load_cal_data(esp_phy_calibration_data_t* out_cal_data);
#endif // CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS
#ifdef __cplusplus
}
#endif

@ -1 +1 @@
Subproject commit e188536a6315cc3ce4f1006ac3a4450faea6abc6
Subproject commit db867fe9128cc1fc273d76af5a412f6743519149

Wyświetl plik

@ -0,0 +1,51 @@
// Copyright 2015-2016 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
#include "esp_phy_init.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file phy.h
* @brief Declarations for functions provided by libphy.a
*/
/**
* @brief Initialize function pointer table in PHY library.
* @note This function should be called before register_chipv7_phy.
*/
void phy_get_romfunc_addr(void);
/**
* @brief Initialize PHY module and do RF calibration
* @param[in] init_data Initialization parameters to be used by the PHY
* @param[inout] cal_data As input, calibration data previously obtained. As output, will contain new calibration data.
* @param[in] cal_mode RF calibration mode
* @return reserved for future use
*/
int register_chipv7_phy(const esp_phy_init_data_t* init_data, esp_phy_calibration_data_t *cal_data, esp_phy_calibration_mode_t cal_mode);
/**
* @brief Get the format version of calibration data used by PHY library.
* @return Format version number
*/
uint32_t phy_get_rf_cal_version();
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -0,0 +1,264 @@
// Copyright 2015-2016 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.
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "rom/ets_sys.h"
#include "soc/dport_reg.h"
#include "esp_err.h"
#include "esp_phy_init.h"
#include "esp_system.h"
#include "phy.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "phy_init_data.h"
static const char* TAG = "phy_init";
static const esp_phy_init_data_t* phy_get_init_data();
static void phy_release_init_data(const esp_phy_init_data_t*);
esp_err_t esp_phy_init(esp_phy_calibration_mode_t mode)
{
ESP_LOGD(TAG, "esp_phy_init, mode=%d", mode);
esp_err_t err;
const esp_phy_init_data_t* init_data = phy_get_init_data();
if (init_data == NULL) {
ESP_LOGE(TAG, "failed to obtain PHY init data");
return ESP_FAIL;
}
esp_phy_calibration_data_t* cal_data =
(esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1);
if (cal_data == NULL) {
ESP_LOGE(TAG, "failed to allocate memory for RF calibration data");
return ESP_ERR_NO_MEM;
}
// Initialize PHY function pointer table
phy_get_romfunc_addr();
// Enable WiFi peripheral clock
SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, 0x87cf);
// If full calibration is requested, don't need to load previous calibration data
if (mode != PHY_RF_CAL_FULL) {
err = esp_phy_load_cal_data(cal_data);
if (err != ESP_OK) {
ESP_LOGW(TAG, "failed to load RF calibration data, falling back to full calibration");
mode = PHY_RF_CAL_FULL;
}
}
ESP_LOGV(TAG, "calling register_chipv7_phy, init_data=%p, cal_data=%p, mode=%d", init_data, cal_data, mode);
register_chipv7_phy(init_data, cal_data, mode);
if (mode != PHY_RF_CAL_NONE) {
err = esp_phy_store_cal_data(cal_data);
} else {
err = ESP_OK;
}
phy_release_init_data(init_data);
free(cal_data); // PHY maintains a copy of calibration data, so we can free this
return err;
}
// PHY init data handling functions
#if CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
#define NO_DEFAULT_INIT_DATA
#include "esp_partition.h"
static const esp_phy_init_data_t* phy_get_init_data()
{
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, "PHY data partition not found");
return NULL;
}
ESP_LOGD(TAG, "loading PHY init data from partition at offset 0x%x", partition->address);
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 PHY init data");
return NULL;
}
esp_err_t err = esp_partition_read(partition, 0, init_data_store, init_data_store_length);
if (err != ESP_OK) {
ESP_LOGE(TAG, "failed to read PHY data partition (%d)", err);
return NULL;
}
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) {
ESP_LOGE(TAG, "failed to validate PHY data partition");
return NULL;
}
ESP_LOGE(TAG, "PHY data partition validated");
return (const esp_phy_init_data_t*) (init_data_store + sizeof(phy_init_magic_pre));
}
static void phy_release_init_data(const esp_phy_init_data_t* init_data)
{
free((uint8_t*) init_data - sizeof(phy_init_magic_pre));
}
#else // CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
// phy_init_data.h will declare static 'phy_init_data' variable initialized with default init data
static const esp_phy_init_data_t* phy_get_init_data()
{
ESP_LOGD(TAG, "loading PHY init data from application binary");
return &phy_init_data;
}
static void phy_release_init_data(const esp_phy_init_data_t* init_data)
{
// no-op
}
#endif // CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
// PHY calibration data handling functions
#if CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS
#include "nvs.h"
static const char* PHY_NAMESPACE = "phy";
static const char* PHY_CAL_VERSION_KEY = "cal_version";
static const char* PHY_CAL_MAC_KEY = "cal_mac";
static const char* PHY_CAL_DATA_KEY = "cal_data";
static esp_err_t load_cal_data_from_nvs(nvs_handle handle,
esp_phy_calibration_data_t* out_cal_data);
static esp_err_t store_cal_data_to_nvs(nvs_handle handle,
const esp_phy_calibration_data_t* cal_data);
esp_err_t esp_phy_load_cal_data(esp_phy_calibration_data_t* out_cal_data)
{
nvs_handle handle;
esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READONLY, &handle);
if (err != ESP_OK) {
ESP_LOGD(TAG, "%s: failed to open NVS namespace (%d)", __func__, err);
return err;
}
else {
err = load_cal_data_from_nvs(handle, out_cal_data);
nvs_close(handle);
return err;
}
}
esp_err_t esp_phy_store_cal_data(const esp_phy_calibration_data_t* cal_data)
{
nvs_handle handle;
esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READWRITE, &handle);
if (err != ESP_OK) {
ESP_LOGD(TAG, "%s: failed to open NVS namespace (%d)", __func__, err);
return err;
}
else {
err = store_cal_data_to_nvs(handle, cal_data);
nvs_close(handle);
return err;
}
}
static esp_err_t load_cal_data_from_nvs(nvs_handle handle, esp_phy_calibration_data_t* out_cal_data)
{
esp_err_t err;
uint32_t cal_data_version;
err = nvs_get_u32(handle, PHY_CAL_VERSION_KEY, &cal_data_version);
if (err != ESP_OK) {
ESP_LOGD(TAG, "%s: failed to get cal_version (%d)", __func__, err);
return err;
}
uint32_t cal_format_version = phy_get_rf_cal_version();
if (cal_data_version != cal_format_version) {
ESP_LOGD(TAG, "%s: expected calibration data format %d, found %d",
__func__, cal_format_version, cal_data_version);
return ESP_FAIL;
}
uint8_t cal_data_mac[6];
size_t length = sizeof(cal_data_mac);
err = nvs_get_blob(handle, PHY_CAL_MAC_KEY, cal_data_mac, &length);
if (err != ESP_OK) {
ESP_LOGD(TAG, "%s: failed to get cal_mac (%d)", __func__, err);
return err;
}
if (length != sizeof(cal_data_mac)) {
ESP_LOGD(TAG, "%s: invalid length of cal_mac (%d)", __func__, length);
return ESP_ERR_INVALID_SIZE;
}
uint8_t sta_mac[6];
system_efuse_read_mac(sta_mac);
if (memcmp(sta_mac, cal_data_mac, sizeof(sta_mac)) != 0) {
ESP_LOGE(TAG, "%s: calibration data MAC check failed: expected " \
MACSTR ", found " MACSTR,
__func__, MAC2STR(sta_mac), MAC2STR(cal_data_mac));
return ESP_FAIL;
}
length = sizeof(*out_cal_data);
err = nvs_get_blob(handle, PHY_CAL_DATA_KEY, out_cal_data, &length);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: failed to get cal_data(%d)", __func__, err);
return err;
}
if (length != sizeof(*out_cal_data)) {
ESP_LOGD(TAG, "%s: invalid length of cal_data (%d)", __func__, length);
return ESP_ERR_INVALID_SIZE;
}
return ESP_OK;
}
static esp_err_t store_cal_data_to_nvs(nvs_handle handle,
const esp_phy_calibration_data_t* cal_data)
{
esp_err_t err;
uint32_t cal_format_version = phy_get_rf_cal_version();
err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version);
if (err != ESP_OK) {
return err;
}
uint8_t sta_mac[6];
system_efuse_read_mac(sta_mac);
err = nvs_set_blob(handle, PHY_CAL_MAC_KEY, sta_mac, sizeof(sta_mac));
if (err != ESP_OK) {
return err;
}
err = nvs_set_blob(handle, PHY_CAL_DATA_KEY, cal_data, sizeof(*cal_data));
return err;
}
#else // CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS
// Default implementation: don't store or load calibration data.
// These functions are defined as weak and can be overridden in the application.
esp_err_t esp_phy_store_cal_data(const esp_phy_calibration_data_t* cal_data) __attribute__((weak))
{
// pretend that calibration data is stored
return ESP_OK;
}
esp_err_t esp_phy_load_cal_data(const esp_phy_calibration_data_t* cal_data) __attribute__((weak))
{
// nowhere to load data from
return ESP_ERR_NOT_SUPPORTED;
}
#endif // CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS

Wyświetl plik

@ -0,0 +1,139 @@
// Copyright 2016 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
#include "esp_phy_init.h"
#include "sdkconfig.h"
// constrain a value between 'low' and 'high', inclusive
#define LIMIT(val, low, high) ((val < low) ? low : (val > high) ? high : val)
#define PHY_INIT_MAGIC "PHYINIT"
static const char phy_init_magic_pre[] = PHY_INIT_MAGIC;
/**
* @brief Structure containing default recommended PHY initialization parameters.
*/
static const esp_phy_init_data_t phy_init_data= {
.param_ver_id = 0,
.crystal_select = 3,
.wifi_rx_gain_swp_step_1 = 0x05,
.wifi_rx_gain_swp_step_2 = 0x04,
.wifi_rx_gain_swp_step_3 = 0x06,
.wifi_rx_gain_swp_step_4 = 0x05,
.wifi_rx_gain_swp_step_5 = 0x01,
.wifi_rx_gain_swp_step_6 = 0x06,
.wifi_rx_gain_swp_step_7 = 0x05,
.wifi_rx_gain_swp_step_8 = 0x04,
.wifi_rx_gain_swp_step_9 = 0x06,
.wifi_rx_gain_swp_step_10 = 0x04,
.wifi_rx_gain_swp_step_11 = 0x05,
.wifi_rx_gain_swp_step_12 = 0x00,
.wifi_rx_gain_swp_step_13 = 0x00,
.wifi_rx_gain_swp_step_14 = 0x00,
.wifi_rx_gain_swp_step_15 = 0x00,
.bt_rx_gain_swp_step_1 = 0x05,
.bt_rx_gain_swp_step_2 = 0x04,
.bt_rx_gain_swp_step_3 = 0x06,
.bt_rx_gain_swp_step_4 = 0x05,
.bt_rx_gain_swp_step_5 = 0x01,
.bt_rx_gain_swp_step_6 = 0x06,
.bt_rx_gain_swp_step_7 = 0x05,
.bt_rx_gain_swp_step_8 = 0x00,
.bt_rx_gain_swp_step_9 = 0x00,
.bt_rx_gain_swp_step_10 = 0x00,
.bt_rx_gain_swp_step_11 = 0x00,
.bt_rx_gain_swp_step_12 = 0x00,
.bt_rx_gain_swp_step_13 = 0x00,
.bt_rx_gain_swp_step_14 = 0x00,
.bt_rx_gain_swp_step_15 = 0x00,
.gain_cmp_1 = 0x0a,
.gain_cmp_6 = 0x0a,
.gain_cmp_11 = 0x0c,
.gain_cmp_ext2_1 = 0xf0,
.gain_cmp_ext2_6 = 0xf0,
.gain_cmp_ext2_11 = 0xf0,
.gain_cmp_ext3_1 = 0xe0,
.gain_cmp_ext3_6 = 0xe0,
.gain_cmp_ext3_11 = 0xe0,
.gain_cmp_bt_ofs_1 = 0x18,
.gain_cmp_bt_ofs_6 = 0x18,
.gain_cmp_bt_ofs_11 = 0x18,
.target_power_qdb_0 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 78),
.target_power_qdb_1 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 76),
.target_power_qdb_2 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 74),
.target_power_qdb_3 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 68),
.target_power_qdb_4 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 64),
.target_power_qdb_5 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 52),
.target_power_index_mcs0 = 0,
.target_power_index_mcs1 = 0,
.target_power_index_mcs2 = 1,
.target_power_index_mcs3 = 1,
.target_power_index_mcs4 = 2,
.target_power_index_mcs5 = 3,
.target_power_index_mcs6 = 4,
.target_power_index_mcs7 = 5,
.pwr_ind_11b_en = 0,
.pwr_ind_11b_0 = 0,
.pwr_ind_11b_1 = 0,
.chan_backoff_en = 0,
.chan1_power_backoff_qdb = 0,
.chan2_power_backoff_qdb = 0,
.chan3_power_backoff_qdb = 0,
.chan4_power_backoff_qdb = 0,
.chan5_power_backoff_qdb = 0,
.chan6_power_backoff_qdb = 0,
.chan7_power_backoff_qdb = 0,
.chan8_power_backoff_qdb = 0,
.chan9_power_backoff_qdb = 0,
.chan10_power_backoff_qdb = 0,
.chan11_power_backoff_qdb = 0,
.chan12_power_backoff_qdb = 0,
.chan13_power_backoff_qdb = 0,
.chan14_power_backoff_qdb = 0,
.chan1_rate_backoff_index = 0,
.chan2_rate_backoff_index = 0,
.chan3_rate_backoff_index = 0,
.chan4_rate_backoff_index = 0,
.chan5_rate_backoff_index = 0,
.chan6_rate_backoff_index = 0,
.chan7_rate_backoff_index = 0,
.chan8_rate_backoff_index = 0,
.chan9_rate_backoff_index = 0,
.chan10_rate_backoff_index = 0,
.chan11_rate_backoff_index = 0,
.chan12_rate_backoff_index = 0,
.chan13_rate_backoff_index = 0,
.chan14_rate_backoff_index = 0,
.spur_freq_cfg_msb_1 = 0,
.spur_freq_cfg_1 = 0,
.spur_freq_cfg_div_1 = 0,
.spur_freq_en_h_1 = 0,
.spur_freq_en_l_1 = 0,
.spur_freq_cfg_msb_2 = 0,
.spur_freq_cfg_2 = 0,
.spur_freq_cfg_div_2 = 0,
.spur_freq_en_h_2 = 0,
.spur_freq_en_l_2 = 0,
.spur_freq_cfg_msb_3 = 0,
.spur_freq_cfg_3 = 0,
.spur_freq_cfg_div_3 = 0,
.spur_freq_en_h_3 = 0,
.spur_freq_en_l_3 = 0,
.reserved = {0}
};
static const char phy_init_magic_post[] = PHY_INIT_MAGIC;