Wrap structure around phy_info PHY initialisation settings
Add notes based on testing some of the values found there.
This commit is contained in:
parent
b2c032a867
commit
b61d06e940
4 changed files with 661 additions and 36 deletions
|
@ -24,6 +24,7 @@
|
|||
#include "os_version.h"
|
||||
|
||||
#include "espressif/esp_common.h"
|
||||
#include "espressif/phy_info.h"
|
||||
#include "sdk_internal.h"
|
||||
|
||||
/* This is not declared in any header file (but arguably should be) */
|
||||
|
@ -31,8 +32,6 @@
|
|||
void user_init(void);
|
||||
|
||||
#define BOOT_INFO_SIZE 28
|
||||
//TODO: phy_info should probably be a struct (no idea about its organization, though)
|
||||
#define PHY_INFO_SIZE 128
|
||||
|
||||
// These are the offsets of these values within the RTCMEM regions. It appears
|
||||
// that the ROM saves them to RTCMEM before calling us, and we pull them out of
|
||||
|
@ -45,26 +44,6 @@ void user_init(void);
|
|||
extern uint32_t _bss_start;
|
||||
extern uint32_t _bss_end;
|
||||
|
||||
// .Ldata003 -- .irom.text+0x0
|
||||
static const uint8_t IROM default_phy_info[PHY_INFO_SIZE] = {
|
||||
0x05, 0x00, 0x04, 0x02, 0x05, 0x05, 0x05, 0x02,
|
||||
0x05, 0x00, 0x04, 0x05, 0x05, 0x04, 0x05, 0x05,
|
||||
0x04, 0xfe, 0xfd, 0xff, 0xf0, 0xf0, 0xf0, 0xe0,
|
||||
0xe0, 0xe0, 0xe1, 0x0a, 0xff, 0xff, 0xf8, 0x00,
|
||||
0xf8, 0xf8, 0x52, 0x4e, 0x4a, 0x44, 0x40, 0x38,
|
||||
0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xe1, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x93, 0x43, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
// user_init_flag -- .bss+0x0
|
||||
uint8_t sdk_user_init_flag;
|
||||
|
||||
|
@ -82,7 +61,7 @@ xTaskHandle sdk_xWatchDogTaskHandle;
|
|||
static void IRAM get_otp_mac_address(uint8_t *buf);
|
||||
static void IRAM set_spi0_divisor(uint32_t divisor);
|
||||
static void zero_bss(void);
|
||||
static void init_networking(uint8_t *phy_info, uint8_t *mac_addr);
|
||||
static void init_networking(sdk_phy_info_t *phy_info, uint8_t *mac_addr);
|
||||
static void init_g_ic(void);
|
||||
static void dump_excinfo(void);
|
||||
static void user_start_phase2(void);
|
||||
|
@ -273,7 +252,7 @@ static void zero_bss(void) {
|
|||
}
|
||||
|
||||
// .Lfunc006 -- .irom0.text+0x70
|
||||
static void init_networking(uint8_t *phy_info, uint8_t *mac_addr) {
|
||||
static void init_networking(sdk_phy_info_t *phy_info, uint8_t *mac_addr) {
|
||||
if (sdk_register_chipv6_phy(phy_info)) {
|
||||
printf("FATAL: sdk_register_chipv6_phy failed");
|
||||
halt();
|
||||
|
@ -413,7 +392,7 @@ extern void (*__init_array_end)(void);
|
|||
// .Lfunc009 -- .irom0.text+0x5b4
|
||||
static __attribute__((noinline)) void user_start_phase2(void) {
|
||||
uint8_t *buf;
|
||||
uint8_t *phy_info;
|
||||
sdk_phy_info_t phy_info, default_phy_info;
|
||||
|
||||
sdk_system_rtc_mem_read(0, &sdk_rst_if, sizeof(sdk_rst_if));
|
||||
if (sdk_rst_if.version > 3) {
|
||||
|
@ -431,8 +410,16 @@ static __attribute__((noinline)) void user_start_phase2(void) {
|
|||
sdk_info._unknown1 = 0x00ffffff;
|
||||
sdk_info._unknown2 = 0x0104a8c0;
|
||||
init_g_ic();
|
||||
phy_info = malloc(PHY_INFO_SIZE);
|
||||
sdk_spi_flash_read(sdk_flashchip.chip_size - sdk_flashchip.sector_size * 4, (uint32_t *)phy_info, PHY_INFO_SIZE);
|
||||
|
||||
read_saved_phy_info(&phy_info);
|
||||
get_default_phy_info(&default_phy_info);
|
||||
|
||||
if (phy_info.version != default_phy_info.version) {
|
||||
/* Versions don't match, use default for PHY info
|
||||
(may be a blank config sector, or a new default version.)
|
||||
*/
|
||||
memcpy(&phy_info, &default_phy_info, sizeof(sdk_phy_info_t));
|
||||
}
|
||||
|
||||
// Disable default buffering on stdout
|
||||
setbuf(stdout, NULL);
|
||||
|
@ -440,13 +427,7 @@ static __attribute__((noinline)) void user_start_phase2(void) {
|
|||
uart_flush_txfifo(0);
|
||||
uart_flush_txfifo(1);
|
||||
|
||||
if (phy_info[0] != 5) {
|
||||
// Bad version byte. Discard what we read and use default values
|
||||
// instead.
|
||||
memcpy(phy_info, default_phy_info, PHY_INFO_SIZE);
|
||||
}
|
||||
init_networking(phy_info, sdk_info.sta_mac_addr);
|
||||
free(phy_info);
|
||||
init_networking(&phy_info, sdk_info.sta_mac_addr);
|
||||
|
||||
// Call gcc constructor functions
|
||||
void (**ctor)(void);
|
||||
|
@ -487,7 +468,7 @@ static __attribute__((noinline)) void dump_flash_config_sectors(uint32_t start_s
|
|||
printf("system param error\n");
|
||||
// Note: original SDK code didn't dump PHY info
|
||||
printf("phy_info:\n");
|
||||
dump_flash_sector(start_sector, PHY_INFO_SIZE);
|
||||
dump_flash_sector(start_sector, sizeof(sdk_phy_info_t));
|
||||
printf("\ng_ic saved 0:\n");
|
||||
dump_flash_sector(start_sector + 1, sizeof(struct sdk_g_ic_saved_st));
|
||||
printf("\ng_ic saved 1:\n");
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "espressif/esp_wifi.h"
|
||||
#include "espressif/spi_flash.h"
|
||||
#include "espressif/phy_info.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -217,7 +218,7 @@ void sdk_phy_enable_agc(void);
|
|||
void sdk_pm_attach(void);
|
||||
void sdk_pp_attach(void);
|
||||
void sdk_pp_soft_wdt_init(void);
|
||||
int sdk_register_chipv6_phy(uint8_t *);
|
||||
int sdk_register_chipv6_phy(sdk_phy_info_t *);
|
||||
void sdk_sleep_reset_analog_rtcreg_8266(void);
|
||||
uint32_t sdk_system_get_checksum(uint8_t *, uint32_t);
|
||||
void sdk_system_restart_in_nmi(void);
|
||||
|
|
161
core/phy_info.c
Normal file
161
core/phy_info.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* Routines to allow custom access to the Internal Espressif
|
||||
SDK PHY datastructures.
|
||||
|
||||
Matches espressif/phy_internal.h
|
||||
|
||||
Part of esp-open-rtos. Copyright (C) 2016 Angus Gratton,
|
||||
BSD Licensed as described in the file LICENSE.
|
||||
*/
|
||||
#include <espressif/phy_info.h>
|
||||
#include <espressif/esp_common.h>
|
||||
#include <common_macros.h>
|
||||
#include <string.h>
|
||||
|
||||
static const sdk_phy_info_t IROM default_phy_info = {
|
||||
._reserved00 = { 0x05, 0x00, 0x04, 0x02, 0x05 },
|
||||
.version = 5,
|
||||
._reserved06 = { 0x05, 0x02, 0x05, 0x00, 0x04, 0x05, 0x05, 0x04,
|
||||
0x05, 0x05, 0x04,-0x02,-0x03,-0x01,-0x10,-0x10,
|
||||
-0x10,-0x20,-0x20, -0x20},
|
||||
.spur_freq_primary = 225,
|
||||
.spur_freq_divisor = 10,
|
||||
.spur_freq_en_h = 0xFF,
|
||||
.spur_freq_en_l = 0xFF,
|
||||
|
||||
._reserved1e = { 0xf8, 0, 0xf8, 0xf8 },
|
||||
|
||||
.target_power = { 82, 78, 74, 68, 64, 56 },
|
||||
.target_power_index_mcs = { 0, 0, 1, 1, 2, 3, 4, 5 },
|
||||
|
||||
.crystal_freq = CRYSTAL_FREQ_26M,
|
||||
|
||||
.sdio_config = SDIO_CONFIG_AUTO,
|
||||
|
||||
.bt_coexist_config = BT_COEXIST_CONFIG_NONE,
|
||||
.bt_coexist_protocol = BT_COEXIST_PROTOCOL_WIFI_ONLY,
|
||||
|
||||
.dual_ant_config = DUAL_ANT_CONFIG_NONE,
|
||||
|
||||
._reserved34 = 0x02,
|
||||
|
||||
.crystal_sleep = CRYSTAL_SLEEP_OFF,
|
||||
|
||||
.spur_freq_2_primary = 225,
|
||||
.spur_freq_2_divisor = 10,
|
||||
.spur_freq_2_en_h = 0x00,
|
||||
.spur_freq_2_en_l = 0x00,
|
||||
.spur_freq_cfg_msb = 0x00,
|
||||
.spur_freq_2_cfg_msb = 0x00,
|
||||
.spur_freq_3_cfg = 0x0000,
|
||||
.spur_freq_4_cfg = 0x0000,
|
||||
|
||||
._reserved4a = { 0x01, 0x93, 0x43, 0x00 },
|
||||
|
||||
.low_power_en = false,
|
||||
.lp_atten_stage01 = LP_ATTEN_STAGE01_23DB,
|
||||
.lp_atten_bb = 0,
|
||||
|
||||
.pwr_ind_11b_en = false,
|
||||
.pwr_ind_11b_0 = 0,
|
||||
.pwr_ind_11b_1 = 0,
|
||||
|
||||
/* Nominal 3.3V VCC. NOTE: This value is 0 in the
|
||||
esp-open-rtos SDK default config sector, and may be unused
|
||||
by that version of the SDK?
|
||||
*/
|
||||
.pa_vdd = 33,
|
||||
|
||||
/* Note: untested with the esp-open-rtos SDK default config sector, may be unused? */
|
||||
.freq_correct_mode = FREQ_CORRECT_DISABLE,
|
||||
.force_freq_offset = 0,
|
||||
|
||||
/* Note: is zero with the esp-open-rtos SDK default config sector, may be unused? */
|
||||
.rf_cal_mode = RF_CAL_MODE_SAVED,
|
||||
};
|
||||
|
||||
void get_default_phy_info(sdk_phy_info_t *info) __attribute__((weak, alias("get_sdk_default_phy_info")));
|
||||
|
||||
void get_sdk_default_phy_info(sdk_phy_info_t *info)
|
||||
{
|
||||
memcpy(info, &default_phy_info, sizeof(sdk_phy_info_t));
|
||||
}
|
||||
|
||||
void read_saved_phy_info(sdk_phy_info_t *info)
|
||||
{
|
||||
sdk_spi_flash_read(sdk_flashchip.chip_size - sdk_flashchip.sector_size * 4, (uint32_t *)info, sizeof(sdk_phy_info_t));
|
||||
}
|
||||
|
||||
void write_saved_phy_info(const sdk_phy_info_t *info)
|
||||
{
|
||||
sdk_spi_flash_write(sdk_flashchip.chip_size - sdk_flashchip.sector_size * 4, (uint32_t *)info, sizeof(sdk_phy_info_t));
|
||||
}
|
||||
|
||||
void dump_phy_info(const sdk_phy_info_t *info, bool raw)
|
||||
{
|
||||
printf("version=%d\n", info->version);
|
||||
printf("spur_freq = %.3f (%d/%d)\n",
|
||||
(float)info->spur_freq_primary / info->spur_freq_divisor,
|
||||
info->spur_freq_primary,
|
||||
info->spur_freq_divisor);
|
||||
printf("spur_freq_en = 0x%02x 0x%02x\n", info->spur_freq_en_h,
|
||||
info->spur_freq_en_l);
|
||||
printf("target_power\n");
|
||||
for(int i = 0; i < 6; i++) {
|
||||
printf(" %d: %.2fdB (raw 0x%02x)\n", i,
|
||||
info->target_power[i]/4.0,
|
||||
info->target_power[i]);
|
||||
}
|
||||
printf("target_power_index_mcs:");
|
||||
for(int i = 0; i < 8; i++) {
|
||||
printf(" %d%c", info->target_power_index_mcs[i],
|
||||
i == 7 ? '\n' : ',');
|
||||
}
|
||||
|
||||
printf("crystal_freq: %s (raw %d)\n",
|
||||
(info->crystal_freq == CRYSTAL_FREQ_40M ? "40MHz" :
|
||||
(info->crystal_freq == CRYSTAL_FREQ_26M ? "26MHz" :
|
||||
(info->crystal_freq == CRYSTAL_FREQ_24M ? "24MHz" : "???"))),
|
||||
info->crystal_freq);
|
||||
|
||||
printf("sdio_config: %d\n", info->sdio_config);
|
||||
printf("bt_coexist config: %d protocol: 0x%02x\n",
|
||||
info->bt_coexist_config, info->bt_coexist_protocol);
|
||||
printf("dual_ant_config: %d\n", info->dual_ant_config);
|
||||
|
||||
printf("crystal_sleep: %d\n", info->crystal_sleep);
|
||||
|
||||
printf("spur_freq_2 = %.3f (%d/%d)\n",
|
||||
(float)info->spur_freq_2_primary / info->spur_freq_2_divisor,
|
||||
info->spur_freq_2_primary,
|
||||
info->spur_freq_2_divisor);
|
||||
printf("spur_freq_2_en = 0x%02x 0x%02x\n", info->spur_freq_2_en_h,
|
||||
info->spur_freq_2_en_l);
|
||||
|
||||
printf("spur_freq_cfg_msb = 0x%02x\n", info->spur_freq_cfg_msb);
|
||||
printf("spur_freq_2_)cfg_msb = 0x%02x\n", info->spur_freq_2_cfg_msb);
|
||||
printf("spur_freq_3_cfg = 0x%04x\n", info->spur_freq_3_cfg);
|
||||
printf("spur_freq_4_cfg = 0x%04x\n", info->spur_freq_4_cfg);
|
||||
|
||||
printf("low_power_en = %d\n", info->low_power_en);
|
||||
printf("lp_atten_stage01 = 0x%02x\n", info->lp_atten_stage01);
|
||||
printf("lp_atten_bb = %.2f (raw 0x%02x)\n", info->lp_atten_bb / 4.0,
|
||||
info->lp_atten_bb);
|
||||
|
||||
printf("pa_vdd = %d\n", info->pa_vdd);
|
||||
|
||||
printf("freq_correct_mode = 0x%02x\n", info->freq_correct_mode);
|
||||
printf("force_freq_offset = %d\n", info->force_freq_offset);
|
||||
printf("rf_cal_mode = 0x%02x\n", info->rf_cal_mode);
|
||||
|
||||
if(raw) {
|
||||
printf("Raw values:");
|
||||
uint8_t *p = (uint8_t *)info;
|
||||
for(int i = 0; i < sizeof(sdk_phy_info_t); i ++) {
|
||||
if(i % 8 == 0) {
|
||||
printf("\n0x%02x:", i);
|
||||
}
|
||||
printf(" %02x", p[i]);
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
}
|
482
include/espressif/phy_info.h
Normal file
482
include/espressif/phy_info.h
Normal file
|
@ -0,0 +1,482 @@
|
|||
/** Internal Espressif SDK "PHY info" data structure
|
||||
|
||||
The data structure (sdk_phy_info_t) is used to configure the
|
||||
ESP8266 PHY layer via the SDK. The fields here are not written
|
||||
directly to hardware, the SDK code (mostly in libphy) parses this
|
||||
structure and configures the hardware.
|
||||
|
||||
The structure loaded at reset time from a flash configuration
|
||||
sector (see read_saved_phy_info()) (Espressif's SDK sources this
|
||||
from a file "esp_init_data_default.bin"). If no valid structure is
|
||||
found in the flash config sector then the SDK loads default values
|
||||
(see get_default_phy_info()). It is possible to implement a custom
|
||||
get_default_phy_info() to change the PHY default settings (see the
|
||||
'version' field below).
|
||||
|
||||
@note It is possible that the SDK will quietly write a new
|
||||
configuration sector to flash itself following internal
|
||||
calibration, etc. However this does not seem to happen, you need to
|
||||
flash it explicitly if you want it stored there.
|
||||
|
||||
@note Most of what is below is unconfirmed, except where a @note
|
||||
says that it has been confirmed to work as expected. Please
|
||||
consider submitting notes if you find behaviour here that works or
|
||||
doesn't work as expected.
|
||||
|
||||
Information on the meaning/offset of fields comes from Espressif's
|
||||
flash download tool, which uses an Excel spreadsheet (in the
|
||||
init_data directory of the ZIP file) to configure and a Python
|
||||
script to convert an esp_init_data_custom.bin file to flash:
|
||||
http://bbs.espressif.com/viewtopic.php?f=5&t=433
|
||||
|
||||
Many fields remain undocumented (& disassembly of libphy suggests
|
||||
that some documented fields supported undocumented values.)
|
||||
|
||||
A few additional notes about the phy_info fields can be found
|
||||
in the ESP Arduino ESP8266 phy_init_data structure (however most of
|
||||
that content is verbatim from Espressif's spreadsheet):
|
||||
https://github.com/esp8266/Arduino/blob/master/cores/esp8266/core_esp8266_phy.c#L29
|
||||
|
||||
Part of esp-open-rtos. Copyright (C) 2016 Angus Gratton,
|
||||
BSD Licensed as described in the file LICENSE.
|
||||
*/
|
||||
#ifndef _ESPRESSIF_PHY_INFO_H
|
||||
#define _ESPRESSIF_PHY_INFO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* CRYSTAL_FREQ_xx values as used by sdk_phy_info_t.crystal_freq */
|
||||
#define CRYSTAL_FREQ_40M 0
|
||||
#define CRYSTAL_FREQ_26M 1
|
||||
#define CRYSTAL_FREQ_24M 2
|
||||
|
||||
/* SDIO_CONFIG_xx values as used by sdk_phy_info_t.sdio_config */
|
||||
#define SDIO_CONFIG_AUTO 0 /* Uses pin strapping to determine */
|
||||
#define SDIO_CONFIG_SDIOV1_1 /* Data output on negative edge */
|
||||
#define SDIO_CONFIG_SDIOV2_0 /* data output on positive edge */
|
||||
|
||||
/* BT_COEXIST_CONFIG_xx values as used by sdk_phy_info_t.bt_coexist */
|
||||
/* No bluetooth */
|
||||
#define BT_COEXIST_CONFIG_NONE 0
|
||||
/* Coexistence configuration A:
|
||||
GPIO 0 - WLAN_ACTIVE
|
||||
GPIO 14 - BT_ACTIVE
|
||||
GPIO 13 - BT_PRIORITY
|
||||
GPIO 3 - ANT_SEL_BT
|
||||
*/
|
||||
#define BT_COEXIST_CONFIG_A 1
|
||||
/* No coexistence, but Bluetooth enabled?
|
||||
Unsure how this works?
|
||||
*/
|
||||
#define BT_COEXIST_CONFIG_PRESENT 2
|
||||
/* Coexistence configuration B:
|
||||
GPIO 0 - WLAN_ACTIVE
|
||||
GPIO 14 - BT_PRIORITY
|
||||
GPIO 13 - BT_ACTIVE
|
||||
GPIO 3 - ANT_SEL_BT
|
||||
*/
|
||||
#define BT_COEXIST_CONFIG_B 3
|
||||
|
||||
/* BT_COEXIST_PROTOCOL_xx values for coexistence protocol,
|
||||
field sdk_phy_info_t.bt_coexist_protocol
|
||||
*/
|
||||
#define BT_COEXIST_PROTOCOL_WIFI_ONLY 0
|
||||
#define BT_COEXIST_PROTOCOL_BT_ONLY 1
|
||||
|
||||
/* Coexistence is enabled, Bluetooth has its own antenna */
|
||||
#define BT_COEXIST_PROTOCOL_FLAG_SEPARATE_ANT 2
|
||||
/* Coexistence is enabled, Bluetooth shares WiFi antenna */
|
||||
#define BT_COEXIST_PROTOCOL_FLAG_SHARE_ANT 4
|
||||
|
||||
/* Coexistence is enabled, use only BT_ACTIVE signal */
|
||||
#define BT_COEXIST_PROTOCOL_FLAG_BT_ACTIVE_ONLY 0
|
||||
/* Coexistence is enabled, use both BT_ACTIVE and BT_PRIORITY signals */
|
||||
#define BT_COEXIST_PROTOCOL_FLAG_BT_ACTIVE_PRIORITY 1
|
||||
|
||||
/* DUAL_ANT_CONFIG_xx values for dual antenna config,
|
||||
field sdk_phy_info_t.dual_ant_config
|
||||
|
||||
(Not really clear how this feature works, if at all.)
|
||||
*/
|
||||
#define DUAL_ANT_CONFIG_NONE 0
|
||||
/* antenna diversity for WiFi, use GPIO0 + U0RXD (?) */
|
||||
#define DUAL_ANT_CONFIG_DUAL 1
|
||||
/* TX/RX switch for external PA & LNA: GPIO 0 high, GPIO 3 low during TX */
|
||||
#define DUAL_ANT_CONFIG_TX_GPIO0_HIGH_GPIO3_LOW
|
||||
/* TX/RX switch for external PA & LNA: GPIO 0 low, GPIO 3 high during TX */
|
||||
#define DUAL_ANT_CONFIG_TX_GPIO0_LOW_GPIO3_HIGH
|
||||
|
||||
|
||||
/* CRYSTAL_SLEEP_xx values used for sdk_phy_info_t.crystal_sleep
|
||||
*/
|
||||
#define CRYSTAL_SLEEP_OFF 0
|
||||
#define CRYSTAL_SLEEP_ON 1
|
||||
#define CRYSTAL_SLEEP_GPIO16 2
|
||||
#define CRYSTAL_SLEEP_GPIO2 3
|
||||
|
||||
/* RF Stage 0 & 1 attenuation constants. Use for sdk_phy_info_t.lp_atten_stage01
|
||||
|
||||
@note These values have been tested and are confirmed to work as
|
||||
expected by measuring RSSI w/ rt73 USB adapter in monitor mode
|
||||
(some values also checked on spectrum analyzer) - provided
|
||||
low_power_en is set then the signal is attenuated as per this
|
||||
setting.
|
||||
|
||||
(It may look like LP_ATTEN_STAGE01_11_5DB is out of order, but
|
||||
according to monitor mode captures this is the correct ordering of
|
||||
these constants.)
|
||||
|
||||
Setting the numeric values in between these constants appears to
|
||||
also attenuate the signal, but not necessarily by the amount you'd
|
||||
expect.
|
||||
*/
|
||||
#define LP_ATTEN_STAGE01_0DB 0x0f /* 0dB */
|
||||
#define LP_ATTEN_STAGE01_2_5DB 0x0e /* -2.5dB */
|
||||
#define LP_ATTEN_STAGE01_6DB 0x0d /* -6dB */
|
||||
#define LP_ATTEN_STAGE01_8_5DB 0x09 /* -8.5dB */
|
||||
#define LP_ATTEN_STAGE01_11_5DB 0x0c /* -11.5dB */
|
||||
#define LP_ATTEN_STAGE01_14DB 0x08 /* -14dB */
|
||||
#define LP_ATTEN_STAGE01_17_5DB 0x04 /* -17.5dB */
|
||||
#define LP_ATTEN_STAGE01_23DB 0x00 /* -23dB */
|
||||
|
||||
/* Constant for sdk_phy_info_t.pa_vdd */
|
||||
#define PA_VDD_MEASURE_VCC 0xFF
|
||||
|
||||
/* Bitmask flags for sdk_phy_info_t.freq_correct_mode */
|
||||
|
||||
/* Set this flag to disable frequency offset correction */
|
||||
#define FREQ_CORRECT_DISABLE 0
|
||||
|
||||
/* Set this flag to enable frequency offset correction */
|
||||
#define FREQ_CORRECT_ENABLE BIT(0)
|
||||
|
||||
/* Set = Baseband PLL frequency is 160MHz (can only apply +ve offset)
|
||||
* Unset = Baseband PLL frequency is 168MHz (can apply +ve/-ve offset */
|
||||
#define FREQ_CORRECT_BB_160M BIT(1)
|
||||
|
||||
/* Set = use force_freq_offset field to correct, Unset = automatically
|
||||
measure & correct offset
|
||||
*/
|
||||
#define FREQ_CORRECT_FORCE BIT(2)
|
||||
|
||||
|
||||
/* RF_CAL_MODE_xx fields used for sdk_phy_info_t.rf_cal_mode
|
||||
*/
|
||||
/* Use saved RF CAL data from flash, only. RF init takes 2ms. */
|
||||
#define RF_CAL_MODE_SAVED 0
|
||||
/* Calibrate TX power control only, use saved RF CAL data for others.
|
||||
RF init takes 20ms. */
|
||||
#define RF_CAL_MODE_TXPOWER_ONLY 1
|
||||
/* Unclear if/how this mode is different to 2? */
|
||||
#define RF_CAL_MODE_SAVED_2 2
|
||||
/* Run full RF CAL routine. RF init takes approx 200ms. */
|
||||
#define RF_CAL_MODE_FULL 3
|
||||
|
||||
/* Data structure that maps to the phy_info configuration block */
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t _reserved00[0x05]; /* 0x00 - 0x04 */
|
||||
|
||||
/* This "version" field was set to 5 in the SDK phy_info,
|
||||
and the original SDK startup code checks it is 5 and then loads
|
||||
default PHY configuration otherwise.
|
||||
|
||||
esp-open-rtos will load phy_info from get_default_phy_info() if
|
||||
the value stored in flash has a different value to the value
|
||||
returned in get_default_phy_info(). This means you can
|
||||
increment the version return by get_default_phy_info() (to any
|
||||
value but 0xFF), and know that the new defaults will replace
|
||||
any older stored values.
|
||||
|
||||
@notes It's not clear whether this is actually a version field
|
||||
(the other 24 bytes here have equally arbitrary numbers in
|
||||
them.) Changing the "version" to other values does not seem to
|
||||
effect WiFi performance at all, neither does zeroing out the
|
||||
first 5 reserved bytes in _reserved00. However zeroing bytes in
|
||||
the _reserved06 region will break WiFi entirely.
|
||||
*/
|
||||
uint8_t version; /* 0x05 */
|
||||
int8_t _reserved06[0x14]; /* 0x06 - 0x19 */
|
||||
|
||||
/* spur_freq = spur_freq_primary / spur_freq_divisor */
|
||||
uint8_t spur_freq_primary; /* 0x1a */
|
||||
uint8_t spur_freq_divisor; /* 0x1b */
|
||||
|
||||
/* Bitmask to enable spur_freq for each channel
|
||||
Appears to be a big endian short word?
|
||||
*/
|
||||
uint8_t spur_freq_en_h; /* 0x1c */
|
||||
uint8_t spur_freq_en_l; /* 0x1d */
|
||||
|
||||
uint8_t _reserved1e[4]; /* 0x1e - 0x21 */
|
||||
|
||||
/* Each value is a target power level.
|
||||
Units are 1/4 dBm ie value 64 = 16dBm.
|
||||
|
||||
SDK defaults to using these transmit powers:
|
||||
20.5dBm, 19.5dBm, 18.5dBm, 17dBm, 16dBm, 14dBm
|
||||
|
||||
@note Adjusting these values is confirmed to reduce
|
||||
transmit power accordingly.
|
||||
*/
|
||||
uint8_t target_power[6]; /* 0x22 - 0x27 */
|
||||
|
||||
/* Maps 8 MCS (modulation & coding schemes) types for 802.11b, g &
|
||||
* n to a target_power level index (0-5), set above.
|
||||
|
||||
This mapping of MCS slot to MCS type is derived from the
|
||||
spreadsheet and also a table sent by Espressif, but is untested
|
||||
and may be SDK version dependendent (especially any 802.11n
|
||||
rates). However the general relationship is confirmed to hold
|
||||
(higher MCS index = higher bit rate).
|
||||
|
||||
MCS 0: 1Mbps/2Mbps/5.5Mbps/11Mbps (802.11b) / 6Mbps/9Mbps (802.11g)
|
||||
default target_power 0 (default 20.5dBm)
|
||||
(see also pwr_ind_11b_en)
|
||||
|
||||
MCS 1: 12Mbps (802.11g)
|
||||
default target_power 0 (default 20.5dBm)
|
||||
|
||||
MCS 2: 18Mbps (802.11g)
|
||||
default target_power 1 (19.5dBm)
|
||||
|
||||
MCS 3: 24Mbps (802.11g)
|
||||
default target_power 1 (19.5dBm)
|
||||
|
||||
MCS 4: 36Mbps (802.11g)
|
||||
default target_power 2 (18.5dBm)
|
||||
|
||||
MCS 5: 48Mbps (802.11g)
|
||||
default target_power 3 (17dBm)
|
||||
|
||||
MCS 6: 54Mbps (802.11g)
|
||||
default target_power 4 (16dBm)
|
||||
|
||||
MCS 7: 65Mbps (802.11n) - unclear if ever used?
|
||||
default target_power 5 (14dBm)
|
||||
*/
|
||||
uint8_t target_power_index_mcs[8]; /* 0x28 - 0x2f */
|
||||
|
||||
/* One of CRYSTAL_FREQ_40M / CRYSTAL_FREQ_26M / CRYSTAL_FREQ_24M
|
||||
|
||||
The crystal configured here is the input to the PLL setting
|
||||
calculations which are used to derive the CPU & APB peripheral
|
||||
clock frequency, and probably the WiFi PLLs (unconfirmed.)
|
||||
*/
|
||||
uint8_t crystal_freq; /* 0x30 */
|
||||
|
||||
uint8_t _unused31; /* 0x31: Possibly high byte of crystal freq? */
|
||||
|
||||
/* One of SDIO_CONFIG_AUTO, SDIO_CONFIG_SDIOV1_1, SDIO_CONFIG_SDIOV2_0 */
|
||||
uint8_t sdio_config; /* 0x32 */
|
||||
|
||||
/* BT coexistence pin configuration.
|
||||
|
||||
One of BT_COEXIST_CONFIG_NONE, BT_COEXIST_CONFIG_A,
|
||||
BT_COEXIST_CONFIG_PRESENT, BT_COEXIST_CONFIG_B
|
||||
*/
|
||||
uint8_t bt_coexist_config; /* 0x33 */
|
||||
|
||||
/* BT coexistence pin protocol.
|
||||
|
||||
If no coexistence:
|
||||
Either BT_COEXIST_PROTOCOL_WIFI_ONLY, or
|
||||
BT_COEXIST_PROTOCOL_BT_ONLY.
|
||||
|
||||
If coexistence:
|
||||
Combine one of
|
||||
BT_COEXIST_PROTOCOL_FLAG_SEPARATE_ANT or
|
||||
BT_COEXIST_PROTOCOL_FLAG_SHARE_ANT
|
||||
with one of
|
||||
BT_COEXIST_PROTOCOL_FLAG_BT_ACTIVE_ONLY or
|
||||
BT_COEXIST_PROTOCOL_FLAG_BT_ACTIVE_BT_PRIORITY
|
||||
*/
|
||||
uint8_t bt_coexist_protocol; /* 0x34 */
|
||||
|
||||
/* Dual antenna configuration
|
||||
|
||||
One of DUAL_ANT_CONFIG_NONE, DUAL_ANT_CONFIG_DUAL,
|
||||
DUAL_ANT_CONFIG_TX_GPIO0_HIGH_GPIO3_LOW,
|
||||
DUAL_ANT_CONFIG_TX_GPIO0_LOW_GPIO3_HIGH
|
||||
*/
|
||||
uint8_t dual_ant_config; /* 0x35 */
|
||||
|
||||
uint8_t _reserved34; /* 0x36 */
|
||||
|
||||
/* For sharing crystal clock with other devices:
|
||||
one of CRYSTAL_SLEEP_OFF, CRYSTAL_SLEEP_ON,
|
||||
CRYSTAL_SLEEP_GPIO16, CRYSTAL_SLEEP_GPIO2
|
||||
*/
|
||||
uint8_t crystal_sleep; /* 0x37 */
|
||||
|
||||
uint8_t _unused38[8];
|
||||
|
||||
/* spur_freq_2 = spur_freq_2_primary / spur_freq_2_divisor */
|
||||
uint8_t spur_freq_2_primary; /* 0x40 */
|
||||
uint8_t spur_freq_2_divisor; /* 0x41 */
|
||||
|
||||
/* Bitmask to enable spur_freq_2 for each channel?
|
||||
Appears to be a big endian short word?
|
||||
*/
|
||||
uint8_t spur_freq_2_en_h; /* 0x42 */
|
||||
uint8_t spur_freq_2_en_l; /* 0x43 */
|
||||
|
||||
/* Not really clear what these do */
|
||||
uint8_t spur_freq_cfg_msb; /* 0x44 */
|
||||
uint8_t spur_freq_2_cfg_msb; /* 0x45 */
|
||||
uint16_t spur_freq_3_cfg; /* 0x46 - 0x47 */
|
||||
uint16_t spur_freq_4_cfg; /* 0x48 - 0x49 */
|
||||
|
||||
uint8_t _reserved4a[4]; /* 0x4a - 0x4d */
|
||||
|
||||
uint8_t _unused78[15]; /* 0x4e - 0x5c */
|
||||
|
||||
/* Flag to enable low power mode */
|
||||
uint8_t low_power_en; /* 0x5d */
|
||||
|
||||
/* Low Power attenuation of RF gain stages 0 & 1
|
||||
|
||||
Attenuates transmit power if/when low_power_en is set.
|
||||
|
||||
Use one of the constants LP_ATTEN_STAGE01_0DB,
|
||||
LP_ATTEN_STAGE01_2_5DB, LP_ATTEN_STAGE01_6DB,
|
||||
LP_ATTEN_STAGE01_8_5DB, LP_ATTEN_STAGE01_11_5DB,
|
||||
LP_ATTEN_STAGE01_14DB, LP_ATTEN_STAGE01_17_5DB,
|
||||
LP_ATTEN_STAGE01_23DB.
|
||||
*/
|
||||
uint8_t lp_atten_stage01; /* 0x5e */
|
||||
|
||||
/* Low Power(?) attenuation of baseband gain
|
||||
|
||||
Units are minus 1/4 dB, ie value 4 == -1dB.
|
||||
|
||||
Maximum value is 24 (0x18) == -6dB
|
||||
*/
|
||||
uint8_t lp_atten_bb; /* 0x5f */
|
||||
|
||||
/* I believe this means, when pwr_ind_11b_en == 0 then the 802.11g
|
||||
MCS 0 level from target_power_index_mcs are used to
|
||||
determine 802.11b transmit power level.
|
||||
|
||||
However, when pwr_ind_11b_en == 1 then the index values in
|
||||
pwr_ind_11b_0 & pwr_ind_11b_1 are used for 802.11b instead.
|
||||
|
||||
This is all unconfirmed, if you can confirm then please update
|
||||
this comment.
|
||||
*/
|
||||
uint8_t pwr_ind_11b_en; /* 0x60 */
|
||||
|
||||
/* 802.11b low data rate power index (0~5).
|
||||
Sets the power level index for operation at 1 & 2Mbps
|
||||
*/
|
||||
uint8_t pwr_ind_11b_0; /* 0x61 */
|
||||
|
||||
/* 802.11b high data rate power index (0~5)
|
||||
Sets the power level index for operation at 5.5 & 11Mbps
|
||||
*/
|
||||
uint8_t pwr_ind_11b_1; /* 0x62 */
|
||||
|
||||
uint8_t _unused63[8]; /* 0x63 - 0x6a */
|
||||
|
||||
/* Set the voltage of PA_VDD, which appears to be an internal analog
|
||||
reference voltage(?)
|
||||
|
||||
This field is called vdd33_const in the Arduino phy fields,
|
||||
and relates to usage of the TOUT pin (ADC pin).
|
||||
|
||||
Set to PA_VDD_MEASURE_VCC (0xFF) and leave TOUT (ADC) pin
|
||||
floating in order to use the ADC to measure the 3.3V input
|
||||
voltage.
|
||||
|
||||
Set to value in the range 18-36 (1.8V to 3.6V) to set a
|
||||
reference voltage(?) when using TOUT pin as an ADC input. I
|
||||
think this is the reference voltage used to scale the 0-1V
|
||||
which is allowed on the pin, in order to get an accurate
|
||||
reading. So it should be set to a value that matches system
|
||||
VCC... I think!
|
||||
*/
|
||||
uint8_t pa_vdd; /* 0x6b */
|
||||
|
||||
/* Disable RF calibration cycle for this many times */
|
||||
uint8_t disable_rfcal_count; /* 0x6c */
|
||||
|
||||
uint8_t _unused6d[3];
|
||||
|
||||
/* Flags for frequency correction
|
||||
|
||||
A bitmask combination of any of: FREQ_CORRECT_DISABLE,
|
||||
FREQ_CORRECT_ENABLE, FREQ_CORRECT_BB_160M, FREQ_CORRECT_FORCE
|
||||
*/
|
||||
uint8_t freq_correct_mode; /* 0x70 */
|
||||
|
||||
/* Force frequency offset adjustment (instead of auto measuring)
|
||||
units are 1 = 8kHz, full range +/- 1016kHz.
|
||||
|
||||
Only used if FREQ_CORRECT_ENABLE and FREQ_CORRECT_FORCE are
|
||||
set in freq_correct_mode.
|
||||
|
||||
Unclear whether setting FREQ_CORRECT_BB_160M (which allows only positive offsets) changes the usable range.
|
||||
*/
|
||||
int8_t force_freq_offset; /* 0x71 */
|
||||
|
||||
/* Use stored data in flash for RF calibration.
|
||||
|
||||
This field was previously called rf_cal_use_flash.
|
||||
|
||||
Acceptable values one of RF_CAL_MODE_SAVED, RF_CAL_MODE_TXPOWER_ONLY, RF_CAL_MODE_SAVED_2, RF_CAL_MODE_FULL.
|
||||
*/
|
||||
uint8_t rf_cal_mode; /* 0x72 */
|
||||
|
||||
uint8_t _unused73[13];
|
||||
} sdk_phy_info_t;
|
||||
|
||||
/* Some sanity check static assertions. These can probably be
|
||||
removed after this structure has been better tested.
|
||||
*/
|
||||
_Static_assert(sizeof(sdk_phy_info_t) == 128, "sdk_phy_info_t is wrong size!");
|
||||
_Static_assert(offsetof(sdk_phy_info_t, version) == 5, "version at wrong offset");
|
||||
_Static_assert(offsetof(sdk_phy_info_t, target_power) == 34, "target_power_qdb at wrong offset");
|
||||
_Static_assert(offsetof(sdk_phy_info_t, bt_coexist_protocol) == 52, "bt_coexist_protocol at wrong offset");
|
||||
_Static_assert(offsetof(sdk_phy_info_t, spur_freq_2_primary) == 64, "spur_freq_2_primary at wrong offset");
|
||||
_Static_assert(offsetof(sdk_phy_info_t, lp_atten_stage01) == 94, "lp_atten_stage01 at wrong offset");
|
||||
_Static_assert(offsetof(sdk_phy_info_t, pa_vdd) == 107, "pa_vdd aka vdd33_const at wrong offset");
|
||||
_Static_assert(offsetof(sdk_phy_info_t, rf_cal_mode) == 114, "rf_cal_use_flash at wrong offset!");
|
||||
|
||||
/* Read the default PHY info into the supplied structure.
|
||||
|
||||
This function is weak-aliased to get_sdk_default_phy_info() so you
|
||||
can replace it with your own if you want to vary the default values
|
||||
- suggested way to do this is to call get_sdk_default_phy_info()
|
||||
and then only update the fields you care about.
|
||||
|
||||
The default PHY info is used at startup whenever the version field
|
||||
in the default sdk_phy_info_t does not match the version field
|
||||
stored in flash. So you can increment the version field to force a
|
||||
reset to defaults, regardless of what values are in flash.
|
||||
*/
|
||||
void get_default_phy_info(sdk_phy_info_t *info);
|
||||
|
||||
/* Read the "SDK default" PHY info as used by the Espressif SDK */
|
||||
void get_sdk_default_phy_info(sdk_phy_info_t *info);
|
||||
|
||||
/* Read the PHY info currently stored in the SPI flash SDK configuration sector.
|
||||
|
||||
This PHY info is updated by the SDK following RF calibration, etc.
|
||||
|
||||
Note that the saved data may be corrupt - read the 'version' field to verify.
|
||||
*/
|
||||
void read_saved_phy_info(sdk_phy_info_t *info);
|
||||
|
||||
/* Update the saved PHY info in the SPI flash. A reset is necessary to use these values.
|
||||
|
||||
Note that the SDK may clobber these values, so it's recommended you reset ASAP after updating them.
|
||||
*/
|
||||
void write_saved_phy_info(const sdk_phy_info_t *info);
|
||||
|
||||
/* Dump known fields in the phy info structure to stdout,
|
||||
if 'raw' flag is set then the raw hex values are also dumped.
|
||||
*/
|
||||
void dump_phy_info(const sdk_phy_info_t *info, bool raw);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue