mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feature: support multiple PHY init data
This commit is contained in:
parent
4235ee44e6
commit
e01b690e5b
@ -38,6 +38,9 @@
|
||||
#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"
|
||||
@ -568,6 +571,7 @@ wifi_osi_funcs_t g_wifi_osi_funcs = {
|
||||
._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,
|
||||
|
@ -38,22 +38,38 @@ endif()
|
||||
if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION)
|
||||
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")
|
||||
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
|
||||
# the object file to a raw binary
|
||||
idf_build_get_property(config_dir CONFIG_DIR)
|
||||
add_custom_command(
|
||||
OUTPUT ${phy_init_data_bin}
|
||||
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/${idf_target}/include/phy_init_data.h
|
||||
COMMAND ${CMAKE_C_COMPILER} -x c -c
|
||||
-I ${esp_common_dir}/include -I ${CMAKE_CURRENT_LIST_DIR}/include -I ${config_dir}
|
||||
-o phy_init_data.obj
|
||||
${CMAKE_CURRENT_LIST_DIR}/${idf_target}/include/phy_init_data.h
|
||||
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_dependencies(flash phy_init_data)
|
||||
# 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
|
||||
idf_build_get_property(config_dir CONFIG_DIR)
|
||||
add_custom_command(
|
||||
OUTPUT ${phy_init_data_bin}
|
||||
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/${idf_target}/include/phy_init_data.h
|
||||
COMMAND ${CMAKE_C_COMPILER} -x c -c
|
||||
-I ${esp_common_dir}/include -I ${CMAKE_CURRENT_LIST_DIR}/include -I ${config_dir}
|
||||
-o phy_init_data.obj
|
||||
${CMAKE_CURRENT_LIST_DIR}/${idf_target}/include/phy_init_data.h
|
||||
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_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_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()
|
||||
|
@ -334,7 +334,7 @@ menu "PHY"
|
||||
2.Because of your board design, each time when you do calibration, the result are too unstable.
|
||||
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"
|
||||
default n
|
||||
help
|
||||
@ -350,6 +350,32 @@ menu "PHY"
|
||||
|
||||
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
|
||||
int "Max WiFi TX power (dBm)"
|
||||
range 10 20
|
||||
|
663
components/esp_wifi/esp32/esp_adapter.c
Normal file
663
components/esp_wifi/esp32/esp_adapter.c
Normal 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,
|
||||
};
|
@ -27,6 +27,12 @@
|
||||
#define PHY_TX_POWER_OFFSET 44
|
||||
#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;
|
||||
|
||||
/**
|
||||
@ -144,5 +150,27 @@ static const esp_phy_init_data_t phy_init_data= { {
|
||||
|
||||
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 */
|
||||
|
||||
|
@ -63,6 +63,30 @@ typedef enum{
|
||||
MODEM_MODULE_COUNT //!< Number of items
|
||||
}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
|
||||
*/
|
||||
@ -251,6 +275,20 @@ int64_t esp_phy_rf_get_on_ts(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
|
||||
}
|
||||
#endif
|
||||
|
@ -21,7 +21,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_WIFI_OS_ADAPTER_VERSION 0x00000005
|
||||
#define ESP_WIFI_OS_ADAPTER_VERSION 0x00000006
|
||||
#define ESP_WIFI_OS_ADAPTER_MAGIC 0xDEADBEAF
|
||||
|
||||
#define OSI_FUNCS_TIME_BLOCKING 0xffffffff
|
||||
@ -81,6 +81,7 @@ typedef struct {
|
||||
void (* _phy_load_cal_and_init)(uint32_t module);
|
||||
void (* _phy_common_clock_enable)(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);
|
||||
void (* _timer_arm)(void *timer, uint32_t tmout, bool repeat);
|
||||
void (* _timer_disarm)(void *timer);
|
||||
|
@ -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 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.
|
||||
* @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
|
||||
* 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
|
||||
*
|
||||
|
1
components/esp_wifi/lib
Submodule
1
components/esp_wifi/lib
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 51e2668fd4e6416f8ad6292e846e177e7d3859bd
|
@ -1 +1 @@
|
||||
Subproject commit 63df20cc99da2226bd94c20853d5dee467304a93
|
||||
Subproject commit 4c46338b90a4f7aa2dc6a14736be1fe63f8a2e10
|
BIN
components/esp_wifi/phy_multiple_init_data.bin
Normal file
BIN
components/esp_wifi/phy_multiple_init_data.bin
Normal file
Binary file not shown.
@ -39,6 +39,13 @@
|
||||
#include "driver/periph_ctrl.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;
|
||||
|
||||
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;
|
||||
|
||||
#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)
|
||||
{
|
||||
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");
|
||||
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");
|
||||
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;
|
||||
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 (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
|
||||
}
|
||||
|
||||
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
|
||||
static esp_err_t phy_crc_check_init_data(uint8_t* init_data, const uint8_t* checksum, size_t init_data_length)
|
||||
{
|
||||
uint32_t crc_data = 0;
|
||||
crc_data = crc32_le(crc_data, init_data, init_data_length);
|
||||
uint32_t crc_size_conversion = htonl(crc_data);
|
||||
|
||||
if (crc_size_conversion != *(uint32_t*)(checksum)) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static uint8_t phy_find_bin_type_according_country(const char* country)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint8_t phy_init_data_type = 0;
|
||||
|
||||
for (i = 0; i < sizeof(s_country_code_map_type_table)/sizeof(phy_country_to_bin_type_t); i++)
|
||||
{
|
||||
if (!memcmp(country, s_country_code_map_type_table[i].cc, sizeof(s_phy_current_country))) {
|
||||
phy_init_data_type = s_country_code_map_type_table[i].type;
|
||||
ESP_LOGD(TAG, "Current country is %c%c, PHY init data type is %s\n", s_country_code_map_type_table[i].cc[0],
|
||||
s_country_code_map_type_table[i].cc[1], s_phy_type[s_country_code_map_type_table[i].type]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == sizeof(s_country_code_map_type_table)/sizeof(phy_country_to_bin_type_t)) {
|
||||
phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
|
||||
ESP_LOGW(TAG, "Use the default certification code beacuse %c%c doesn't have a certificate", country[0], country[1]);
|
||||
}
|
||||
|
||||
return phy_init_data_type;
|
||||
}
|
||||
|
||||
static esp_err_t phy_find_bin_data_according_type(uint8_t* out_init_data_store,
|
||||
const phy_control_info_data_t* init_data_control_info,
|
||||
const uint8_t* init_data_multiple,
|
||||
phy_init_data_type_t init_data_type)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < init_data_control_info->number; i++) {
|
||||
if (init_data_type == *(init_data_multiple + (i * sizeof(esp_phy_init_data_t)) + PHY_INIT_DATA_TYPE_OFFSET)) {
|
||||
memcpy(out_init_data_store + sizeof(phy_init_magic_pre),
|
||||
init_data_multiple + (i * sizeof(esp_phy_init_data_t)), sizeof(esp_phy_init_data_t));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == init_data_control_info->number) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t phy_get_multiple_init_data(const esp_partition_t* partition,
|
||||
uint8_t* init_data_store,
|
||||
size_t init_data_store_length,
|
||||
phy_init_data_type_t init_data_type)
|
||||
{
|
||||
phy_control_info_data_t* init_data_control_info = (phy_control_info_data_t*) malloc(sizeof(phy_control_info_data_t));
|
||||
if (init_data_control_info == NULL) {
|
||||
ESP_LOGE(TAG, "failed to allocate memory for PHY init data control info");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_partition_read(partition, init_data_store_length, init_data_control_info, sizeof(phy_control_info_data_t));
|
||||
if (err != ESP_OK) {
|
||||
free(init_data_control_info);
|
||||
ESP_LOGE(TAG, "failed to read PHY control info data partition (0x%x)", err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if ((init_data_control_info->check_algorithm) == PHY_CRC_ALGORITHM) {
|
||||
err = phy_crc_check_init_data(init_data_control_info->multiple_bin_checksum, init_data_control_info->control_info_checksum,
|
||||
sizeof(phy_control_info_data_t) - sizeof(init_data_control_info->control_info_checksum));
|
||||
if (err != ESP_OK) {
|
||||
free(init_data_control_info);
|
||||
ESP_LOGE(TAG, "PHY init data control info check error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
} else {
|
||||
free(init_data_control_info);
|
||||
ESP_LOGE(TAG, "Check algorithm not CRC, PHY init data update failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
uint8_t* init_data_multiple = (uint8_t*) malloc(sizeof(esp_phy_init_data_t) * init_data_control_info->number);
|
||||
if (init_data_multiple == NULL) {
|
||||
free(init_data_control_info);
|
||||
ESP_LOGE(TAG, "failed to allocate memory for PHY init data multiple bin");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = esp_partition_read(partition, init_data_store_length + sizeof(phy_control_info_data_t),
|
||||
init_data_multiple, sizeof(esp_phy_init_data_t) * init_data_control_info->number);
|
||||
if (err != ESP_OK) {
|
||||
free(init_data_multiple);
|
||||
free(init_data_control_info);
|
||||
ESP_LOGE(TAG, "failed to read PHY init data multiple bin partition (0x%x)", err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if ((init_data_control_info->check_algorithm) == PHY_CRC_ALGORITHM) {
|
||||
err = phy_crc_check_init_data(init_data_multiple, init_data_control_info->multiple_bin_checksum,
|
||||
sizeof(esp_phy_init_data_t) * init_data_control_info->number);
|
||||
if (err != ESP_OK) {
|
||||
free(init_data_multiple);
|
||||
free(init_data_control_info);
|
||||
ESP_LOGE(TAG, "PHY init data multiple bin check error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
} else {
|
||||
free(init_data_multiple);
|
||||
free(init_data_control_info);
|
||||
ESP_LOGE(TAG, "Check algorithm not CRC, PHY init data update failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = phy_find_bin_data_according_type(init_data_store, init_data_control_info, init_data_multiple, init_data_type);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "%s has not been certified, use DEFAULT PHY init data", s_phy_type[init_data_type]);
|
||||
s_phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
|
||||
} else {
|
||||
s_phy_init_data_type = init_data_type;
|
||||
}
|
||||
|
||||
free(init_data_multiple);
|
||||
free(init_data_control_info);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_phy_update_init_data(phy_init_data_type_t init_data_type)
|
||||
{
|
||||
const esp_partition_t* partition = esp_partition_find_first(
|
||||
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL);
|
||||
if (partition == NULL) {
|
||||
ESP_LOGE(TAG, "Updated country code PHY data partition not found");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
size_t init_data_store_length = sizeof(phy_init_magic_pre) +
|
||||
sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
|
||||
uint8_t* init_data_store = (uint8_t*) malloc(init_data_store_length);
|
||||
if (init_data_store == NULL) {
|
||||
ESP_LOGE(TAG, "failed to allocate memory for updated country code PHY init data");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_partition_read(partition, 0, init_data_store, init_data_store_length);
|
||||
if (err != ESP_OK) {
|
||||
free(init_data_store);
|
||||
ESP_LOGE(TAG, "failed to read updated country code PHY data partition (0x%x)", err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) != 0 ||
|
||||
memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post),
|
||||
PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) {
|
||||
free(init_data_store);
|
||||
ESP_LOGE(TAG, "failed to validate updated country code PHY data partition");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
//find init data bin according init data type
|
||||
if (init_data_type != ESP_PHY_INIT_DATA_TYPE_DEFAULT) {
|
||||
err = phy_get_multiple_init_data(partition, init_data_store, init_data_store_length, init_data_type);
|
||||
if (err != ESP_OK) {
|
||||
free(init_data_store);
|
||||
#if CONFIG_ESP32_PHY_INIT_DATA_ERROR
|
||||
abort();
|
||||
#else
|
||||
return ESP_FAIL;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
s_phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
if (s_current_apply_phy_init_data != s_phy_init_data_type) {
|
||||
err = esp_phy_apply_phy_init_data(init_data_store + sizeof(phy_init_magic_pre));
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "PHY init data failed to load");
|
||||
free(init_data_store);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "PHY init data type updated from %s to %s",
|
||||
s_phy_type[s_current_apply_phy_init_data], s_phy_type[s_phy_init_data_type]);
|
||||
s_current_apply_phy_init_data = s_phy_init_data_type;
|
||||
}
|
||||
|
||||
free(init_data_store);
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t esp_phy_update_country_info(const char *country)
|
||||
{
|
||||
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
|
||||
uint8_t phy_init_data_type_map = 0;
|
||||
//if country equal s_phy_current_country, return;
|
||||
if (!memcmp(country, s_phy_current_country, sizeof(s_phy_current_country))) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
memcpy(s_phy_current_country, country, sizeof(s_phy_current_country));
|
||||
|
||||
if (!s_multiple_phy_init_data_bin) {
|
||||
ESP_LOGD(TAG, "Does not support multiple PHY init data bins");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
phy_init_data_type_map = phy_find_bin_type_according_country(country);
|
||||
if (phy_init_data_type_map == s_phy_init_data_type) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_phy_update_init_data(phy_init_data_type_map);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -0,0 +1,3 @@
|
||||
CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION=y
|
||||
CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN=y
|
||||
CONFIG_IDF_TARGET="esp32"
|
Loading…
Reference in New Issue
Block a user