feature: support multiple PHY init data

This commit is contained in:
ronghulin 2019-10-16 11:22:50 +08:00 committed by chenwen@espressif.com
parent 4235ee44e6
commit e01b690e5b
13 changed files with 1104 additions and 19 deletions

View File

@ -38,6 +38,9 @@
#include "esp_private/wifi_os_adapter.h" #include "esp_private/wifi_os_adapter.h"
#include "esp_private/wifi.h" #include "esp_private/wifi.h"
#include "esp_phy_init.h" #include "esp_phy_init.h"
#include "soc/dport_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"
@ -568,6 +571,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

@ -38,22 +38,38 @@ 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")
set(phy_init_data_bin "${build_dir}/phy_init_data.bin")
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")
# 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
# the object file to a raw binary # the object file to a raw binary
idf_build_get_property(config_dir CONFIG_DIR) idf_build_get_property(config_dir CONFIG_DIR)
add_custom_command( add_custom_command(
OUTPUT ${phy_init_data_bin} OUTPUT ${phy_init_data_bin}
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/${idf_target}/include/phy_init_data.h DEPENDS ${CMAKE_CURRENT_LIST_DIR}/${idf_target}/include/phy_init_data.h
COMMAND ${CMAKE_C_COMPILER} -x c -c COMMAND ${CMAKE_C_COMPILER} -x c -c
-I ${esp_common_dir}/include -I ${CMAKE_CURRENT_LIST_DIR}/include -I ${config_dir} -I ${esp_common_dir}/include -I ${CMAKE_CURRENT_LIST_DIR}/include -I ${config_dir}
-o phy_init_data.obj -o phy_init_data.obj
${CMAKE_CURRENT_LIST_DIR}/${idf_target}/include/phy_init_data.h ${CMAKE_CURRENT_LIST_DIR}/${idf_target}/include/phy_init_data.h
COMMAND ${CMAKE_OBJCOPY} -O binary phy_init_data.obj ${phy_init_data_bin} COMMAND ${CMAKE_OBJCOPY} -O binary phy_init_data.obj ${phy_init_data_bin}
) )
add_custom_target(phy_init_data ALL DEPENDS ${phy_init_data_bin}) add_custom_target(phy_init_data ALL DEPENDS ${phy_init_data_bin})
add_dependencies(flash phy_init_data) add_dependencies(flash phy_init_data)
idf_component_get_property(main_args esptool_py FLASH_ARGS)
idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS)
endif()
# ToDo: remove once MP chip is supported
if(CONFIG_IDF_TARGET_ESP32)
set(phy_name "phy")
endif()
esptool_py_flash_project_args(phy ${phy_partition_offset} ${phy_init_data_bin} FLASH_IN_PROJECT) esptool_py_flash_project_args(phy ${phy_partition_offset} ${phy_init_data_bin} FLASH_IN_PROJECT)
# esptool_py_flash_target(${phy_name}-flash "${main_args}" "${sub_args}")
# esptool_py_flash_target_image(${phy_name}-flash ${phy_name} "${phy_partition_offset}" "${phy_init_data_bin}")
# esptool_py_flash_target_image(flash ${phy_name} "${phy_partition_offset}" "${phy_init_data_bin}")
endif() endif()

View File

@ -334,7 +334,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
@ -350,6 +350,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

@ -0,0 +1,663 @@
// Copyright 2015-2018 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 <stdio.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#include "freertos/xtensa_api.h"
#include "freertos/portmacro.h"
#include "freertos/xtensa_api.h"
#include "esp_types.h"
#include "esp_system.h"
#include "esp_task.h"
#include "esp_intr_alloc.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_event.h"
#include "esp_heap_caps.h"
#include "esp_private/wifi_os_adapter.h"
#include "esp_private/wifi.h"
#include "esp_phy_init.h"
#include "soc/dport_reg.h"
#include "soc/syscon_reg.h"
#include "phy_init_data.h"
#include "driver/periph_ctrl.h"
#include "nvs.h"
#include "os.h"
#include "esp_smartconfig.h"
#include "esp_coexist_internal.h"
#include "esp_coexist_adapter.h"
#include "esp32/dport_access.h"
#define TAG "esp_adapter"
static void IRAM_ATTR s_esp_dport_access_stall_other_cpu_start(void)
{
DPORT_STALL_OTHER_CPU_START();
}
static void IRAM_ATTR s_esp_dport_access_stall_other_cpu_end(void)
{
DPORT_STALL_OTHER_CPU_END();
}
/*
If CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly.
If failed, try to allocate it in internal memory then.
*/
IRAM_ATTR void *wifi_malloc( size_t size )
{
#if CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP
return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
#else
return malloc(size);
#endif
}
/*
If CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly.
If failed, try to allocate it in internal memory then.
*/
IRAM_ATTR void *wifi_realloc( void *ptr, size_t size )
{
#if CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP
return heap_caps_realloc_prefer(ptr, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
#else
return realloc(ptr, size);
#endif
}
/*
If CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly.
If failed, try to allocate it in internal memory then.
*/
IRAM_ATTR void *wifi_calloc( size_t n, size_t size )
{
#if CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP
return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
#else
return calloc(n, size);
#endif
}
static void * IRAM_ATTR wifi_zalloc_wrapper(size_t size)
{
void *ptr = wifi_calloc(1, size);
if (ptr) {
memset(ptr, 0, size);
}
return ptr;
}
wifi_static_queue_t* wifi_create_queue( int queue_len, int item_size)
{
wifi_static_queue_t *queue = NULL;
queue = (wifi_static_queue_t*)heap_caps_malloc(sizeof(wifi_static_queue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
if (!queue) {
return NULL;
}
#if CONFIG_SPIRAM_USE_MALLOC
queue->storage = heap_caps_calloc(1, sizeof(StaticQueue_t) + (queue_len*item_size), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
if (!queue->storage) {
goto _error;
}
queue->handle = xQueueCreateStatic( queue_len, item_size, ((uint8_t*)(queue->storage)) + sizeof(StaticQueue_t), (StaticQueue_t*)(queue->storage));
if (!queue->handle) {
goto _error;
}
return queue;
_error:
if (queue) {
if (queue->storage) {
free(queue->storage);
}
free(queue);
}
return NULL;
#else
queue->handle = xQueueCreate( queue_len, item_size);
return queue;
#endif
}
void wifi_delete_queue(wifi_static_queue_t *queue)
{
if (queue) {
vQueueDelete(queue->handle);
#if CONFIG_SPIRAM_USE_MALLOC
if (queue->storage) {
free(queue->storage);
}
#endif
free(queue);
}
}
static void * wifi_create_queue_wrapper(int queue_len, int item_size)
{
return wifi_create_queue(queue_len, item_size);
}
static void wifi_delete_queue_wrapper(void *queue)
{
wifi_delete_queue(queue);
}
static void set_isr_wrapper(int32_t n, void *f, void *arg)
{
xt_set_interrupt_handler(n, (xt_handler)f, arg);
}
static void * spin_lock_create_wrapper(void)
{
portMUX_TYPE tmp = portMUX_INITIALIZER_UNLOCKED;
void *mux = malloc(sizeof(portMUX_TYPE));
if (mux) {
memcpy(mux,&tmp,sizeof(portMUX_TYPE));
return mux;
}
return NULL;
}
static uint32_t IRAM_ATTR wifi_int_disable_wrapper(void *wifi_int_mux)
{
if (xPortInIsrContext()) {
portENTER_CRITICAL_ISR(wifi_int_mux);
} else {
portENTER_CRITICAL(wifi_int_mux);
}
return 0;
}
static void IRAM_ATTR wifi_int_restore_wrapper(void *wifi_int_mux, uint32_t tmp)
{
if (xPortInIsrContext()) {
portEXIT_CRITICAL_ISR(wifi_int_mux);
} else {
portEXIT_CRITICAL(wifi_int_mux);
}
}
static void IRAM_ATTR task_yield_from_isr_wrapper(void)
{
portYIELD_FROM_ISR();
}
static void * semphr_create_wrapper(uint32_t max, uint32_t init)
{
return (void *)xSemaphoreCreateCounting(max, init);
}
static void semphr_delete_wrapper(void *semphr)
{
vSemaphoreDelete(semphr);
}
static void wifi_thread_semphr_free(void* data)
{
xSemaphoreHandle *sem = (xSemaphoreHandle*)(data);
if (sem) {
vSemaphoreDelete(sem);
}
}
static void * wifi_thread_semphr_get_wrapper(void)
{
static bool s_wifi_thread_sem_key_init = false;
static pthread_key_t s_wifi_thread_sem_key;
xSemaphoreHandle sem = NULL;
if (s_wifi_thread_sem_key_init == false) {
if (0 != pthread_key_create(&s_wifi_thread_sem_key, wifi_thread_semphr_free)) {
return NULL;
}
s_wifi_thread_sem_key_init = true;
}
sem = pthread_getspecific(s_wifi_thread_sem_key);
if (!sem) {
sem = xSemaphoreCreateCounting(1, 0);
if (sem) {
pthread_setspecific(s_wifi_thread_sem_key, sem);
ESP_LOGV(TAG, "thread sem create: sem=%p", sem);
}
}
ESP_LOGV(TAG, "thread sem get: sem=%p", sem);
return (void*)sem;
}
static int32_t IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
{
return (int32_t)xSemaphoreTakeFromISR(semphr, hptw);
}
static int32_t IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw)
{
return (int32_t)xSemaphoreGiveFromISR(semphr, hptw);
}
static int32_t semphr_take_wrapper(void *semphr, uint32_t block_time_tick)
{
if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) {
return (int32_t)xSemaphoreTake(semphr, portMAX_DELAY);
} else {
return (int32_t)xSemaphoreTake(semphr, block_time_tick);
}
}
static int32_t semphr_give_wrapper(void *semphr)
{
return (int32_t)xSemaphoreGive(semphr);
}
static void * recursive_mutex_create_wrapper(void)
{
return (void *)xSemaphoreCreateRecursiveMutex();
}
static void * mutex_create_wrapper(void)
{
return (void *)xSemaphoreCreateMutex();
}
static void mutex_delete_wrapper(void *mutex)
{
vSemaphoreDelete(mutex);
}
static int32_t IRAM_ATTR mutex_lock_wrapper(void *mutex)
{
return (int32_t)xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
}
static int32_t IRAM_ATTR mutex_unlock_wrapper(void *mutex)
{
return (int32_t)xSemaphoreGiveRecursive(mutex);
}
static void * queue_create_wrapper(uint32_t queue_len, uint32_t item_size)
{
return (void *)xQueueCreate(queue_len, item_size);
}
static int32_t queue_send_wrapper(void *queue, void *item, uint32_t block_time_tick)
{
if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) {
return (int32_t)xQueueSend(queue, item, portMAX_DELAY);
} else {
return (int32_t)xQueueSend(queue, item, block_time_tick);
}
}
static int32_t IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item, void *hptw)
{
return (int32_t)xQueueSendFromISR(queue, item, hptw);
}
static int32_t queue_send_to_back_wrapper(void *queue, void *item, uint32_t block_time_tick)
{
return (int32_t)xQueueGenericSend(queue, item, block_time_tick, queueSEND_TO_BACK);
}
static int32_t queue_send_to_front_wrapper(void *queue, void *item, uint32_t block_time_tick)
{
return (int32_t)xQueueGenericSend(queue, item, block_time_tick, queueSEND_TO_FRONT);
}
static int32_t queue_recv_wrapper(void *queue, void *item, uint32_t block_time_tick)
{
if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) {
return (int32_t)xQueueReceive(queue, item, portMAX_DELAY);
} else {
return (int32_t)xQueueReceive(queue, item, block_time_tick);
}
}
static uint32_t event_group_wait_bits_wrapper(void *event, uint32_t bits_to_wait_for, int clear_on_exit, int wait_for_all_bits, uint32_t block_time_tick)
{
if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) {
return (uint32_t)xEventGroupWaitBits(event, bits_to_wait_for, clear_on_exit, wait_for_all_bits, portMAX_DELAY);
} else {
return (uint32_t)xEventGroupWaitBits(event, bits_to_wait_for, clear_on_exit, wait_for_all_bits, block_time_tick);
}
}
static int32_t task_create_pinned_to_core_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id)
{
return (uint32_t)xTaskCreatePinnedToCore(task_func, name, stack_depth, param, prio, task_handle, (core_id < portNUM_PROCESSORS ? core_id : tskNO_AFFINITY));
}
static int32_t task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle)
{
return (uint32_t)xTaskCreate(task_func, name, stack_depth, param, prio, task_handle);
}
static int32_t IRAM_ATTR task_ms_to_tick_wrapper(uint32_t ms)
{
return (int32_t)(ms / portTICK_PERIOD_MS);
}
static int32_t task_get_max_priority_wrapper(void)
{
return (int32_t)(configMAX_PRIORITIES);
}
static int32_t esp_event_post_wrapper(const char* event_base, int32_t event_id, void* event_data, size_t event_data_size, uint32_t ticks_to_wait)
{
if (ticks_to_wait == OSI_FUNCS_TIME_BLOCKING) {
return (int32_t)esp_event_post(event_base, event_id, event_data, event_data_size, portMAX_DELAY);
} else {
return (int32_t)esp_event_post(event_base, event_id, event_data, event_data_size, ticks_to_wait);
}
}
static void IRAM_ATTR timer_arm_wrapper(void *timer, uint32_t tmout, bool repeat)
{
ets_timer_arm(timer, tmout, repeat);
}
static void IRAM_ATTR timer_disarm_wrapper(void *timer)
{
ets_timer_disarm(timer);
}
static void timer_done_wrapper(void *ptimer)
{
ets_timer_done(ptimer);
}
static void timer_setfn_wrapper(void *ptimer, void *pfunction, void *parg)
{
ets_timer_setfn(ptimer, pfunction, parg);
}
static void IRAM_ATTR timer_arm_us_wrapper(void *ptimer, uint32_t us, bool repeat)
{
ets_timer_arm_us(ptimer, us, repeat);
}
static void wifi_reset_mac_wrapper(void)
{
DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, DPORT_MAC_RST);
DPORT_CLEAR_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, DPORT_MAC_RST);
}
static void wifi_clock_enable_wrapper(void)
{
periph_module_enable(PERIPH_WIFI_MODULE);
}
static void wifi_clock_disable_wrapper(void)
{
periph_module_disable(PERIPH_WIFI_MODULE);
}
static int get_time_wrapper(void *t)
{
return os_get_time(t);
}
static void * IRAM_ATTR malloc_internal_wrapper(size_t size)
{
return heap_caps_malloc(size, MALLOC_CAP_8BIT|MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
}
static void * IRAM_ATTR realloc_internal_wrapper(void *ptr, size_t size)
{
return heap_caps_realloc(ptr, size, MALLOC_CAP_8BIT|MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
}
static void * IRAM_ATTR calloc_internal_wrapper(size_t n, size_t size)
{
return heap_caps_calloc(n, size, MALLOC_CAP_8BIT|MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
}
static void * IRAM_ATTR zalloc_internal_wrapper(size_t size)
{
void *ptr = heap_caps_calloc(1, size, MALLOC_CAP_8BIT|MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
if (ptr) {
memset(ptr, 0, size);
}
return ptr;
}
static uint32_t coex_status_get_wrapper(void)
{
#if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE
return coex_status_get();
#else
return 0;
#endif
}
static void coex_condition_set_wrapper(uint32_t type, bool dissatisfy)
{
#if CONFIG_SW_COEXIST_ENABLE
coex_condition_set(type, dissatisfy);
#endif
}
static int coex_wifi_request_wrapper(uint32_t event, uint32_t latency, uint32_t duration)
{
#if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE
return coex_wifi_request(event, latency, duration);
#else
return 0;
#endif
}
static int coex_wifi_release_wrapper(uint32_t event)
{
#if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE
return coex_wifi_release(event);
#else
return 0;
#endif
}
int IRAM_ATTR coex_bt_request_wrapper(uint32_t event, uint32_t latency, uint32_t duration)
{
#if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE
return coex_bt_request(event, latency, duration);
#else
return 0;
#endif
}
int IRAM_ATTR coex_bt_release_wrapper(uint32_t event)
{
#if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE
return coex_bt_release(event);
#else
return 0;
#endif
}
int coex_register_bt_cb_wrapper(coex_func_cb_t cb)
{
#if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE
return coex_register_bt_cb(cb);
#else
return 0;
#endif
}
uint32_t IRAM_ATTR coex_bb_reset_lock_wrapper(void)
{
#if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE
return coex_bb_reset_lock();
#else
return 0;
#endif
}
void IRAM_ATTR coex_bb_reset_unlock_wrapper(uint32_t restore)
{
#if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE
coex_bb_reset_unlock(restore);
#endif
}
int32_t IRAM_ATTR coex_is_in_isr_wrapper(void)
{
return !xPortCanYield();
}
wifi_osi_funcs_t g_wifi_osi_funcs = {
._version = ESP_WIFI_OS_ADAPTER_VERSION,
._set_isr = set_isr_wrapper,
._ints_on = xt_ints_on,
._ints_off = xt_ints_off,
._spin_lock_create = spin_lock_create_wrapper,
._spin_lock_delete = free,
._wifi_int_disable = wifi_int_disable_wrapper,
._wifi_int_restore = wifi_int_restore_wrapper,
._task_yield_from_isr = task_yield_from_isr_wrapper,
._semphr_create = semphr_create_wrapper,
._semphr_delete = semphr_delete_wrapper,
._semphr_take = semphr_take_wrapper,
._semphr_give = semphr_give_wrapper,
._wifi_thread_semphr_get = wifi_thread_semphr_get_wrapper,
._mutex_create = mutex_create_wrapper,
._recursive_mutex_create = recursive_mutex_create_wrapper,
._mutex_delete = mutex_delete_wrapper,
._mutex_lock = mutex_lock_wrapper,
._mutex_unlock = mutex_unlock_wrapper,
._queue_create = queue_create_wrapper,
._queue_delete = (void(*)(void *))vQueueDelete,
._queue_send = queue_send_wrapper,
._queue_send_from_isr = queue_send_from_isr_wrapper,
._queue_send_to_back = queue_send_to_back_wrapper,
._queue_send_to_front = queue_send_to_front_wrapper,
._queue_recv = queue_recv_wrapper,
._queue_msg_waiting = (uint32_t(*)(void *))uxQueueMessagesWaiting,
._event_group_create = (void *(*)(void))xEventGroupCreate,
._event_group_delete = (void(*)(void *))vEventGroupDelete,
._event_group_set_bits = (uint32_t(*)(void *,uint32_t))xEventGroupSetBits,
._event_group_clear_bits = (uint32_t(*)(void *,uint32_t))xEventGroupClearBits,
._event_group_wait_bits = event_group_wait_bits_wrapper,
._task_create_pinned_to_core = task_create_pinned_to_core_wrapper,
._task_create = task_create_wrapper,
._task_delete = (void(*)(void *))vTaskDelete,
._task_delay = vTaskDelay,
._task_ms_to_tick = task_ms_to_tick_wrapper,
._task_get_current_task = (void *(*)(void))xTaskGetCurrentTaskHandle,
._task_get_max_priority = task_get_max_priority_wrapper,
._malloc = malloc,
._free = free,
._event_post = esp_event_post_wrapper,
._get_free_heap_size = esp_get_free_heap_size,
._rand = esp_random,
._dport_access_stall_other_cpu_start_wrap = s_esp_dport_access_stall_other_cpu_start,
._dport_access_stall_other_cpu_end_wrap = s_esp_dport_access_stall_other_cpu_end,
._phy_rf_deinit = esp_phy_rf_deinit,
._phy_load_cal_and_init = esp_phy_load_cal_and_init,
._phy_common_clock_enable = esp_phy_common_clock_enable,
._phy_common_clock_disable = esp_phy_common_clock_disable,
._phy_update_country_info = esp_phy_update_country_info,
._read_mac = esp_read_mac,
._timer_arm = timer_arm_wrapper,
._timer_disarm = timer_disarm_wrapper,
._timer_done = timer_done_wrapper,
._timer_setfn = timer_setfn_wrapper,
._timer_arm_us = timer_arm_us_wrapper,
._wifi_reset_mac = wifi_reset_mac_wrapper,
._wifi_clock_enable = wifi_clock_enable_wrapper,
._wifi_clock_disable = wifi_clock_disable_wrapper,
._esp_timer_get_time = esp_timer_get_time,
._nvs_set_i8 = nvs_set_i8,
._nvs_get_i8 = nvs_get_i8,
._nvs_set_u8 = nvs_set_u8,
._nvs_get_u8 = nvs_get_u8,
._nvs_set_u16 = nvs_set_u16,
._nvs_get_u16 = nvs_get_u16,
._nvs_open = nvs_open,
._nvs_close = nvs_close,
._nvs_commit = nvs_commit,
._nvs_set_blob = nvs_set_blob,
._nvs_get_blob = nvs_get_blob,
._nvs_erase_key = nvs_erase_key,
._get_random = os_get_random,
._get_time = get_time_wrapper,
._random = os_random,
._log_write = esp_log_write,
._log_timestamp = esp_log_timestamp,
._malloc_internal = malloc_internal_wrapper,
._realloc_internal = realloc_internal_wrapper,
._calloc_internal = calloc_internal_wrapper,
._zalloc_internal = zalloc_internal_wrapper,
._wifi_malloc = wifi_malloc,
._wifi_realloc = wifi_realloc,
._wifi_calloc = wifi_calloc,
._wifi_zalloc = wifi_zalloc_wrapper,
._wifi_create_queue = wifi_create_queue_wrapper,
._wifi_delete_queue = wifi_delete_queue_wrapper,
._modem_sleep_enter = esp_modem_sleep_enter,
._modem_sleep_exit = esp_modem_sleep_exit,
._modem_sleep_register = esp_modem_sleep_register,
._modem_sleep_deregister = esp_modem_sleep_deregister,
._coex_status_get = coex_status_get_wrapper,
._coex_condition_set = coex_condition_set_wrapper,
._coex_wifi_request = coex_wifi_request_wrapper,
._coex_wifi_release = coex_wifi_release_wrapper,
._magic = ESP_WIFI_OS_ADAPTER_MAGIC,
};
coex_adapter_funcs_t g_coex_adapter_funcs = {
._version = COEX_ADAPTER_VERSION,
._spin_lock_create = spin_lock_create_wrapper,
._spin_lock_delete = free,
._int_disable = wifi_int_disable_wrapper,
._int_enable = wifi_int_restore_wrapper,
._task_yield_from_isr = task_yield_from_isr_wrapper,
._semphr_create = semphr_create_wrapper,
._semphr_delete = semphr_delete_wrapper,
._semphr_take_from_isr = semphr_take_from_isr_wrapper,
._semphr_give_from_isr = semphr_give_from_isr_wrapper,
._semphr_take = semphr_take_wrapper,
._semphr_give = semphr_give_wrapper,
._is_in_isr = coex_is_in_isr_wrapper,
._malloc_internal = malloc_internal_wrapper,
._free = free,
._timer_disarm = timer_disarm_wrapper,
._timer_done = timer_done_wrapper,
._timer_setfn = timer_setfn_wrapper,
._timer_arm_us = timer_arm_us_wrapper,
._esp_timer_get_time = esp_timer_get_time,
._magic = COEX_ADAPTER_MAGIC,
};

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

@ -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
*/ */
@ -251,6 +275,20 @@ int64_t esp_phy_rf_get_on_ts(void);
*/ */
char * get_phy_version_str(void); char * get_phy_version_str(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
@ -81,6 +81,7 @@ typedef struct {
void (* _phy_load_cal_and_init)(uint32_t module); void (* _phy_load_cal_and_init)(uint32_t module);
void (* _phy_common_clock_enable)(void); void (* _phy_common_clock_enable)(void);
void (* _phy_common_clock_disable)(void); void (* _phy_common_clock_disable)(void);
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

@ -596,9 +596,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
* *

@ -0,0 +1 @@
Subproject commit 51e2668fd4e6416f8ad6292e846e177e7d3859bd

@ -1 +1 @@
Subproject commit 63df20cc99da2226bd94c20853d5dee467304a93 Subproject commit 4c46338b90a4f7aa2dc6a14736be1fe63f8a2e10

Binary file not shown.

View File

@ -39,6 +39,13 @@
#include "driver/periph_ctrl.h" #include "driver/periph_ctrl.h"
#include "esp_private/wifi.h" #include "esp_private/wifi.h"
#include "esp32/rom/ets_sys.h"
#include "esp32/rom/rtc.h"
#include "esp32/rom/crc.h"
//#if CONFIG_IDF_TARGET_ESP32
extern wifi_mac_time_update_cb_t s_wifi_mac_time_update_cb; extern wifi_mac_time_update_cb_t s_wifi_mac_time_update_cb;
static const char* TAG = "phy_init"; static const char* TAG = "phy_init";
@ -69,6 +76,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()) {
@ -425,6 +495,14 @@ const esp_phy_init_data_t* esp_phy_get_init_data()
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));
} }
@ -524,6 +602,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);
@ -687,3 +766,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"