diff --git a/components/esp_phy/CMakeLists.txt b/components/esp_phy/CMakeLists.txt index a8b3bff068..9a83ed4252 100644 --- a/components/esp_phy/CMakeLists.txt +++ b/components/esp_phy/CMakeLists.txt @@ -20,6 +20,10 @@ if(CONFIG_SOC_BT_SUPPORTED OR CONFIG_SOC_IEEE802154_SUPPORTED OR CONFIG_SOC_IEEE list(APPEND srcs "src/btbb_init.c") endif() +if(CONFIG_ESP_PHY_ENABLE_CERT_TEST) + list(APPEND srcs "src/phy_callback.c") +endif() + idf_build_get_property(build_dir BUILD_DIR) if(CONFIG_SOC_WIFI_SUPPORTED) @@ -74,6 +78,11 @@ if(link_binary_libs) target_link_libraries(${COMPONENT_LIB} INTERFACE $ libphy.a libbtbb.a $) endif() + + if(CONFIG_ESP_PHY_ENABLE_CERT_TEST) + target_link_libraries(${COMPONENT_LIB} INTERFACE $ libbttestmode.a + librfate.a librftest.a $) + endif() endif() if(CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION) diff --git a/components/esp_phy/Kconfig b/components/esp_phy/Kconfig index f31edc8a75..9febe98d26 100644 --- a/components/esp_phy/Kconfig +++ b/components/esp_phy/Kconfig @@ -114,4 +114,11 @@ menu "PHY" When using USB Serial/JTAG/OTG/CDC, PHY should enable USB, otherwise USB module can not work properly. Notice: Enabling this configuration option will slightly impact wifi performance. + config ESP_PHY_ENABLE_CERT_TEST + bool "Enable RF certification test functions" + default n + depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 + help + If enabled, you can use RF certification test APIs. + endmenu # PHY diff --git a/components/esp_phy/include/esp_phy_cert_test.h b/components/esp_phy/include/esp_phy_cert_test.h new file mode 100644 index 0000000000..461295683c --- /dev/null +++ b/components/esp_phy/include/esp_phy_cert_test.h @@ -0,0 +1,193 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +typedef enum { + //11b + PHY_RATE_1M = 0x0, + PHY_RATE_2M = 0x1, + PHY_RATE_5M5 = 0x2, + PHY_RATE_11M = 0x3, + //11g + PHY_RATE_6M = 0xb, + PHY_RATE_9M = 0xf, + PHY_RATE_12M = 0xa, + PHY_RATE_18M = 0xe, + PHY_RATE_24M = 0x9, + PHY_RATE_36M = 0xd, + PHY_RATE_48M = 0x8, + PHY_RATE_54M = 0xc, + //11n + PHY_RATE_MCS0 = 0x10, + PHY_RATE_MCS1 = 0x11, + PHY_RATE_MCS2 = 0x12, + PHY_RATE_MCS3 = 0x13, + PHY_RATE_MCS4 = 0x14, + PHY_RATE_MCS5 = 0x15, + PHY_RATE_MCS6 = 0x16, + PHY_RATE_MCS7 = 0x17, + PHY_WIFI_RATE_MAX +} esp_phy_wifi_rate_t; + +typedef enum { + PHY_BLE_RATE_1M = 0, + PHY_BLE_RATE_2M, + PHY_BLE_RATE_125K, + PHY_BLE_RATE_500k, + PHY_BLE_RATE_MAX +} esp_phy_ble_rate_t; + +typedef enum { + PHY_BLE_TYPE_1010 = 0, + PHY_BLE_TYPE_00001111 = 1, + PHY_BLE_TYPE_prbs9 = 2, + PHY_BLE_TYPE_00111100 = 4, + PHY_BLE_TYPE_MAX +} esp_phy_ble_type_t; + +/** + * @brief Structure holding PHY RX result + */ +typedef struct { + uint32_t phy_rx_correct_count; /*!< The number of desired packets received */ + int phy_rx_rssi; /*!< Average RSSI of desired packets */ + uint32_t phy_rx_total_count; /*!< The number of total packets received */ + uint32_t phy_rx_result_flag; /*!< 0 means no RX info; 1 means the lastest Wi-Fi RX info; 2 means the lastest BLE RX info. */ +} esp_phy_rx_result_t; + +/** + * @brief Wifi power domain power on + */ +void esp_wifi_power_domain_on(void); + +/** + * @brief Wifi power domain power off + */ +void esp_wifi_power_domain_off(void); + +/** + * @brief Environment variable configuration + * + * @param conf: + * Set to 1 to enter RF test mode. + */ +void esp_phy_rftest_config(uint8_t conf); + +/** + * @brief RF initialization configuration + */ +void esp_phy_rftest_init(void); + +/** + * @brief TX Continuous mode + * + * @param contin_en: + * Set to true for continuous packet sending, which can be used for certification testing; + * Set to false to cancel continuous mode, which is the default mode and can be used for WLAN tester. +*/ +void esp_phy_tx_contin_en(bool contin_en); + +/** + * @brief HT40/HT20 mode selection + * + * @param en: + * Set to false to enter 11n HT20 mode; + * Set to true to enter 11n HT40 mode; + **/ +void esp_phy_cbw40m_en(bool en); + +/** + * @brief Wi-Fi TX command + * + * @param chan: channel setting, 1~14; + * @param rate: rate setting; + * @param backoff: Transmit power attenuation, unit is 0.25dB. For example, 4 means that the power is attenuated by 1dB; + * @param length_byte: TX packet length configuration, indicating PSDU Length, unit is byte; + * @param packet_delay: TX packet interval configuration, unit is us; + * @param packet_num: The number of packets sent, 0 means sending packets continuously, other values represent the number of packets to send. + */ +void esp_phy_wifi_tx(uint32_t chan, esp_phy_wifi_rate_t rate, int8_t backoff, uint32_t length_byte, uint32_t packet_delay, uint32_t packet_num); + +/** + * @brief Test start/stop command, used to stop transmitting or reciving state. + * + * @param value: + * Value should be set to 3 before TX/RX. + * Set value to 0 to end TX/RX state. + */ +void esp_phy_test_start_stop(uint8_t value); + +/** + * @brief Wi-Fi RX command + * + * @param chan: channel setting, 1~14; + * @param rate: rate setting; + * + */ +void esp_phy_wifi_rx(uint32_t chan, esp_phy_wifi_rate_t rate); + +/** + * @brief Wi-Fi Carrier Wave(CW) TX command + * + * @param start: enable CW, 1 means transmit, 0 means stop transmitting; + * @param chan: CW channel setting, 1~14; + * @param backoff: CW power attenuation parameter, unit is 0.25dB. 4 indicates the power is attenuated by 1dB. + * + */ +void esp_phy_wifi_tx_tone(uint32_t start, uint32_t chan, uint32_t backoff); + +/** + * @brief BLE TX command + * + * @param txpwr: Transmit power level. Tx power is about (level-8)*3 dBm, step is 3dB. Level 8 is around 0 dBm; + * @param chan: channel setting, range is 0~39, corresponding frequency = 2402+chan*2; + * @param len: Payload length setting, range is 0-255, unit is byte, 37 bytes is employed generally; + * @param data_type: Data type setting; + * @param syncw: Packet identification (need to be provided by the packet generator or instrument manufacturer), 0x71764129 is employed generally; + * @param rate: rate setting; + * @param tx_num_in: The number of packets sent, 0 means sending packets continuously, other values represent the number of packets to send. + */ +void esp_phy_ble_tx(uint32_t txpwr, uint32_t chan, uint32_t len, esp_phy_ble_type_t data_type, uint32_t syncw, esp_phy_ble_rate_t rate, uint32_t tx_num_in); + +/** + * @brief BLE RX command + * + * @param chan: channel selection, range is 0-39; + * Channels 0, 1, 2~10 correspond to 2404MHz, 2406MHz, 2408MHz~2424MHz respectively; + * Channels 11, 12, 13~36 correspond to 2428MHz, 2430MHz, 2432MHz~2478MHz respectively; + * Channel 37: 2402MHz, Channel 38: 2426MHz, Channel 39: 2480MHz; + * @param syncw: Packet identification (need to be provided by the packet generator or instrument manufacturer), 0x71764129 is employed generally; + * @param rate: rate setting; + */ +void esp_phy_ble_rx(uint32_t chan, uint32_t syncw, esp_phy_ble_rate_t rate); + +/** + * @brief BLE Carrier Wave(CW) TX command + * + * @param start: enable CW, 1 means transmit, 0 means stop transmitting; + * @param chan: Single carrier transmission channel selection, range is 0~39, corresponding frequency freq = 2402+chan*2; + * @param power: CW power attenuation parameter, unit is 0.25dB. 4 indicates the power is attenuated by 1dB. + */ +void esp_phy_bt_tx_tone(uint32_t start, uint32_t chan, uint32_t power); + +/** + * @brief Get some RX information + * + * @param rx_result: This struct for storing RX information; + */ +void esp_phy_get_rx_result(esp_phy_rx_result_t *rx_result); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_phy/lib b/components/esp_phy/lib index 1b8e12d3e0..c38381964b 160000 --- a/components/esp_phy/lib +++ b/components/esp_phy/lib @@ -1 +1 @@ -Subproject commit 1b8e12d3e0e8b7bcd87c115f09ec0f385700579a +Subproject commit c38381964b48fe53dac584b74eefec62fc86511b diff --git a/components/esp_phy/src/phy_callback.c b/components/esp_phy/src/phy_callback.c new file mode 100644 index 0000000000..e05676b39c --- /dev/null +++ b/components/esp_phy/src/phy_callback.c @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +typedef enum { + OK = 0, + FAIL, + PENDING, + BUSY, + CANCEL, +} STATUS; + +extern int phy_printf(const char* format, ...); + +static uint8_t g_rf_cmdstop = 3; + +void esp_phy_test_start_stop(uint8_t value) +{ + g_rf_cmdstop = value; +} + +int esp_phy_cmdstop_callback(void) +{ + return g_rf_cmdstop; +} + +STATUS esp_phy_getstopcmd(void) +{ + uint8_t value = esp_phy_cmdstop_callback(); + if (value == 0) { + return OK; + } else if (value == 1) { + return BUSY; + } else if (value == 2) { + phy_printf("Please run cmdstop to exit current cmd!\n"); + return FAIL; + } else { + return FAIL; + } +} diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index e16546bc1f..63be6bbe0f 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -161,6 +161,7 @@ INPUT = \ $(PROJECT_PATH)/components/esp_netif/include/esp_netif_sntp.h \ $(PROJECT_PATH)/components/esp_partition/include/esp_partition.h \ $(PROJECT_PATH)/components/esp_phy/include/esp_phy_init.h \ + $(PROJECT_PATH)/components/esp_phy/include/esp_phy_cert_test.h \ $(PROJECT_PATH)/components/esp_pm/include/esp_pm.h \ $(PROJECT_PATH)/components/esp_ringbuf/include/freertos/ringbuf.h \ $(PROJECT_PATH)/components/esp_rom/include/esp_rom_sys.h \ diff --git a/docs/en/api-guides/RF_calibration.rst b/docs/en/api-guides/RF_calibration.rst index 4979d3fc23..ce99a34ee5 100644 --- a/docs/en/api-guides/RF_calibration.rst +++ b/docs/en/api-guides/RF_calibration.rst @@ -63,3 +63,4 @@ API Reference ------------- .. include-build-file:: inc/esp_phy_init.inc +.. include-build-file:: inc/esp_phy_cert_test.inc diff --git a/examples/phy/.build-test-rules.yml b/examples/phy/.build-test-rules.yml new file mode 100644 index 0000000000..78b3f1475e --- /dev/null +++ b/examples/phy/.build-test-rules.yml @@ -0,0 +1,7 @@ +# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps + +examples/phy/cert_test: + enable: + - if: IDF_TARGET in ["esp32c3", "esp32s3"] + temporary: true + reason: the other targets are not tested yet diff --git a/examples/phy/cert_test/CMakeLists.txt b/examples/phy/cert_test/CMakeLists.txt new file mode 100644 index 0000000000..607964536c --- /dev/null +++ b/examples/phy/cert_test/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/system/console/advanced/components) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(cert_test) diff --git a/examples/phy/cert_test/README.md b/examples/phy/cert_test/README.md new file mode 100644 index 0000000000..b5ff530578 --- /dev/null +++ b/examples/phy/cert_test/README.md @@ -0,0 +1,112 @@ +| Supported Targets | ESP32-C3 | ESP32-S3 | +| ----------------- | -------- | -------- | + +# Certification Test Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example shows how to use the Certification test APIS. + +## How to use example + +Before project configuration and build, be sure to set the correct chip target using `idf.py set-target `. + +### Hardware Required + +* A development board with ESP32-C3/ESP32-S3/ SoC. +* A USB cable for Power supply and programming + +### Configure the project + +Open the project configuration menu (`idf.py menuconfig`). + +In the `Example Configuration` menu: + +* Enable RF certification test functions. +* Disable Interrupt Watchdog. +* Disable Task Watchdog Timer. + +### Build and Flash + +Build the project and flash it to the board, then run the monitor tool to view the serial output: + +Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for all the steps to configure and use the ESP-IDF to build projects. + +* [ESP-IDF Getting Started Guide on ESP32-C3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html) +* [ESP-IDF Getting Started Guide on ESP32-S3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/get-started/index.html) + +## Example Output + +The command and output logs for each test are as follows: + +``` + ================================================== + | RF certification test | + | | + | 1. Print 'help' to gain overview of commands | + | 2. Wi-Fi certification test | + | 3. Bluetooth certification test | + | | + ================================================= + + +Type 'help' to get the list of commands. +Use UP/DOWN arrows to navigate through command history. +Press TAB when typing command name to auto-complete. +I (598) main_task: Returned from app_main() +phy> +phy> tx_contin_en 1 +I (4788) phy: Tx continuous test! +phy> +phy> tx_contin_en 0 +I (7518) phy: Tx packet test! +phy> +phy> cbw40m_en 1 +I (10668) phy: cbw40m_en: 1 +phy> +phy> cbw40m_en 0 +I (13238) phy: cbw40m_en: 0 +phy> +phy> cmdstop +I (8828) phy: Tx Over 0x0 +phy> +phy> esp_rx -n 1 -r 0 +I (19348) phy: wifi rx start: channel is 1, rate is 0x0 +phy> +phy> cmdstop +I (142881) phy: Total: 535 Correct: 474 RSSI: -650 noise: -960 gain: 531 para1: 5759 para2: 3 +phy> +phy> get_rx_result +I (145991) cmd_phy: Total: 535, Correct: 474, RSSI: -650, flag: 1 +phy> +phy> wifiscwout -e 1 -c 1 -p 0 +I (98308) phy: wifi single carrier tx out, single carrier is in 1 channel, power is about (2 +phy> +phy> esp_ble_tx -p 8 -n 1 -l 37 -t 2 -s 0x71764129 -r 0 -m 0 +I (319138) phy: fcc_le_tx_syncw: txpwr=8,chan=1,len=37,data_type=2,syncw=0x71764129,rate=0,tx_ +phy> +phy> cmdstop +I (321208) phy: rw done! ce9 +phy> +phy> esp_ble_rx -n 1 -s 0x71764129 -r 0 +I (2898) phy: RW LE V9 RX PER +phy> +phy> cmdstop +I (381241) phy: 3 0 0 0 3 0 0 0 0 0 p -263 -86 -279 a8 -100 -77 +phy> +phy> get_rx_result +I (383871) cmd_phy: Total: 3, Correct: 0, RSSI: 0, flag: 2 +phy> +phy> bt_tx_tone -e 1 -n 1 -p 0 +I (56008) phy: BT TX TONE START! +phy> +``` + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. + diff --git a/examples/phy/cert_test/main/CMakeLists.txt b/examples/phy/cert_test/main/CMakeLists.txt new file mode 100644 index 0000000000..4daa822628 --- /dev/null +++ b/examples/phy/cert_test/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "cert_test.c" + "cmd_phy.c" + INCLUDE_DIRS ".") diff --git a/examples/phy/cert_test/main/cert_test.c b/examples/phy/cert_test/main/cert_test.c new file mode 100644 index 0000000000..4e8e3c0405 --- /dev/null +++ b/examples/phy/cert_test/main/cert_test.c @@ -0,0 +1,57 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nvs_flash.h" + +#include "esp_console.h" +#include "cmd_system.h" + +#include "cmd_phy.h" +#include "esp_phy_cert_test.h" + +void app_main(void) +{ + ESP_ERROR_CHECK(nvs_flash_init()); + + esp_console_repl_t *repl = NULL; + esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); + repl_config.prompt = "phy>"; + +#if CONFIG_ESP_CONSOLE_UART + esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl)); +#elif CONFIG_ESP_CONSOLE_USB_CDC + esp_console_dev_usb_cdc_config_t cdc_config = ESP_CONSOLE_DEV_CDC_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_console_new_repl_usb_cdc(&cdc_config, &repl_config, &repl)); +#elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG + esp_console_dev_usb_serial_jtag_config_t usbjtag_config = ESP_CONSOLE_DEV_USB_SERIAL_JTAG_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_console_new_repl_usb_serial_jtag(&usbjtag_config, &repl_config, &repl)); +#endif + + /* Register commands */ + register_system(); + +#if CONFIG_ESP_PHY_ENABLE_CERT_TEST + register_phy_cmd(); + + /* rftest.a requirements */ + esp_wifi_power_domain_on(); + + esp_phy_rftest_config(1); + esp_phy_rftest_init(); +#endif + + printf("\n ==================================================\n"); + printf(" | RF certification test |\n"); + printf(" | |\n"); + printf(" | 1. Print 'help' to gain overview of commands |\n"); + printf(" | 2. Wi-Fi certification test |\n"); + printf(" | 3. Bluetooth certification test |\n"); + printf(" | |\n"); + printf(" =================================================\n\n"); + + ESP_ERROR_CHECK(esp_console_start_repl(repl)); +} diff --git a/examples/phy/cert_test/main/cmd_phy.c b/examples/phy/cert_test/main/cmd_phy.c new file mode 100644 index 0000000000..4672a866ae --- /dev/null +++ b/examples/phy/cert_test/main/cmd_phy.c @@ -0,0 +1,525 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_console.h" +#include "argtable3/argtable3.h" +#include "esp_phy_cert_test.h" +#include "cmd_phy.h" + +#define TAG "cmd_phy" + +#if CONFIG_ESP_PHY_ENABLE_CERT_TEST + +static phy_args_t phy_args; +#if SOC_WIFI_SUPPORTED +static phy_wifi_tx_t phy_wifi_tx_args; +static phy_wifi_rx_t phy_wifi_rx_args; +static phy_wifiscwout_t phy_wifiscwout_args; +#endif +#if SOC_BT_SUPPORTED +static phy_ble_tx_t phy_ble_tx_args; +static phy_ble_rx_t phy_ble_rx_args; +static phy_bt_tx_tone_t phy_bt_tx_tone_args; +#endif + +static int esp_phy_tx_contin_en_func(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &phy_args); + if (nerrors != 0) { + arg_print_errors(stderr, phy_args.end, argv[0]); + return 1; + } + + if (phy_args.enable->count == 1) { + esp_phy_tx_contin_en(phy_args.enable->ival[0]); + } else { + ESP_LOGW(TAG, "Please enter the enable parameter"); + } + return 0; +} + +static int esp_phy_cmdstop_func(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &phy_args); + if (nerrors != 0) { + arg_print_errors(stderr, phy_args.end, argv[0]); + return 1; + } + + esp_phy_test_start_stop(0); + + return 0; +} + +static int esp_phy_get_rx_result_func(int argc, char **argv) +{ + esp_phy_rx_result_t rx_result; + int nerrors = arg_parse(argc, argv, (void **) &phy_args); + if (nerrors != 0) { + arg_print_errors(stderr, phy_args.end, argv[0]); + return 1; + } + + esp_phy_get_rx_result(&rx_result); + + ESP_LOGI(TAG, "Total: %lu, Correct: %lu, RSSI: %d, flag: %lu", rx_result.phy_rx_total_count, + rx_result.phy_rx_correct_count, rx_result.phy_rx_rssi, rx_result.phy_rx_result_flag); + + return 0; +} + +#if SOC_WIFI_SUPPORTED +void cert_wifi_tx(void *arg) +{ + phy_wifi_tx_s *cmd = (phy_wifi_tx_s*)arg; + + esp_phy_test_start_stop(3); + esp_phy_wifi_tx(cmd->channel, cmd->rate, cmd->backoff, cmd->length_byte, cmd->packet_delay, cmd->packet_num); + + vTaskDelete(NULL); +} + +void cert_wifi_rx(void *arg) +{ + phy_wifi_rx_s *cmd = (phy_wifi_rx_s*)arg; + + esp_phy_test_start_stop(3); + esp_phy_wifi_rx(cmd->channel, cmd->rate); + + vTaskDelete(NULL); +} + +static int esp_phy_cbw40m_en_func(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &phy_args); + if (nerrors != 0) { + arg_print_errors(stderr, phy_args.end, argv[0]); + return 1; + } + if (phy_args.enable->count == 1) { + esp_phy_cbw40m_en(phy_args.enable->ival[0]); + } else { + ESP_LOGW(TAG, "Please enter the enable parameter"); + } + return 0; +} + +static int esp_phy_wifi_tx_func(int argc, char **argv) +{ + phy_wifi_tx_s cmd; + int nerrors = arg_parse(argc, argv, (void **) &phy_wifi_tx_args); + if (nerrors != 0) { + arg_print_errors(stderr, phy_wifi_tx_args.end, argv[0]); + return 1; + } + + if (phy_wifi_tx_args.channel->count == 1) { + cmd.channel = phy_wifi_tx_args.channel->ival[0]; + } else { + cmd.channel = 1; + ESP_LOGW(TAG, "Default channel is 1"); + } + + if (phy_wifi_tx_args.rate->count == 1) { + cmd.rate = phy_wifi_tx_args.rate->ival[0]; + } else { + cmd.rate = PHY_RATE_1M; + ESP_LOGW(TAG, "Default rate is PHY_RATE_1M"); + } + + if (phy_wifi_tx_args.attenuation->count == 1) { + cmd.backoff = phy_wifi_tx_args.attenuation->ival[0]; + } else { + cmd.backoff = 0; + ESP_LOGW(TAG, "Default backoff is 0"); + } + + if (phy_wifi_tx_args.length_byte->count == 1) { + cmd.length_byte = phy_wifi_tx_args.length_byte->ival[0]; + } else { + cmd.length_byte = 1000; + ESP_LOGW(TAG, "Default length_byte is 1000"); + } + + if (phy_wifi_tx_args.packet_delay->count == 1) { + cmd.packet_delay = phy_wifi_tx_args.packet_delay->ival[0]; + } else { + cmd.packet_delay = 1000; + ESP_LOGW(TAG, "Default packet_delay is 1000"); + } + + if (phy_wifi_tx_args.packet_num->count == 1) { + cmd.packet_num = phy_wifi_tx_args.packet_num->ival[0]; + } else { + cmd.packet_num = 0; + ESP_LOGW(TAG, "Default packet_num is 0"); + } + + xTaskCreate(cert_wifi_tx, "cert_wifi_tx", 1024 * 10, (void *)&cmd, 10, NULL); + + return 0; +} + +static int esp_phy_wifi_rx_func(int argc, char **argv) +{ + phy_wifi_tx_s cmd; + int nerrors = arg_parse(argc, argv, (void **) &phy_wifi_rx_args); + if (nerrors != 0) { + arg_print_errors(stderr, phy_wifi_rx_args.end, argv[0]); + return 1; + } + + if (phy_wifi_rx_args.channel->count == 1) { + cmd.channel = phy_wifi_rx_args.channel->ival[0]; + } else { + cmd.channel = 1; + ESP_LOGW(TAG, "Default channel is 1"); + } + + if (phy_wifi_rx_args.rate->count == 1) { + cmd.rate = phy_wifi_rx_args.rate->ival[0]; + } else { + cmd.rate = PHY_RATE_1M; + ESP_LOGW(TAG, "Default rate is PHY_RATE_1M"); + } + + xTaskCreate(cert_wifi_rx, "cert_wifi_rx", 1024 * 20, (void *)&cmd, 10, NULL); + return 0; +} + +static int esp_phy_wifiscwout_func(int argc, char **argv) +{ + uint32_t enable; + uint32_t channel; + uint32_t attenuation; + int nerrors = arg_parse(argc, argv, (void **) &phy_wifiscwout_args); + if (nerrors != 0) { + arg_print_errors(stderr, phy_wifiscwout_args.end, argv[0]); + return 1; + } + + if (phy_wifiscwout_args.enable->count == 1) { + enable = phy_wifiscwout_args.enable->ival[0]; + } else { + enable = 1; + ESP_LOGW(TAG, "Default enable is 1"); + } + + if (phy_wifiscwout_args.channel->count == 1) { + channel = phy_wifiscwout_args.channel->ival[0]; + } else { + channel = 1; + ESP_LOGW(TAG, "Default channel is 1"); + } + + if (phy_wifiscwout_args.attenuation->count == 1) { + attenuation = phy_wifiscwout_args.attenuation->ival[0]; + } else { + attenuation = 0; + ESP_LOGW(TAG, "Default attenuation is 0"); + } + + esp_phy_wifi_tx_tone(enable, channel, attenuation); + + return 0; +} +#endif + +#if SOC_BT_SUPPORTED +void cert_ble_tx(void *arg) +{ + phy_ble_tx_s *cmd = (phy_ble_tx_s *)arg; + + esp_phy_test_start_stop(3); + esp_phy_ble_tx(cmd->txpwr, cmd->channel, cmd->len, cmd->data_type, cmd->syncw, cmd->rate, cmd->tx_num_in); + + vTaskDelete(NULL); +} + +void cert_ble_rx(void *arg) +{ + phy_ble_rx_s *cmd = (phy_ble_rx_s *)arg; + + esp_phy_test_start_stop(3); + esp_phy_ble_rx(cmd->channel, cmd->syncw, cmd->rate); + + vTaskDelete(NULL); +} + +static int esp_phy_ble_tx_func(int argc, char **argv) +{ + phy_ble_tx_s cmd; + int nerrors = arg_parse(argc, argv, (void **) &phy_ble_tx_args); + if (nerrors != 0) { + arg_print_errors(stderr, phy_ble_tx_args.end, argv[0]); + return 1; + } + + if (phy_ble_tx_args.txpwr->count == 1) { + cmd.txpwr = phy_ble_tx_args.txpwr->ival[0]; + } else { + cmd.txpwr = 8; + ESP_LOGW(TAG, "Default txpwr is 8"); + } + + if (phy_ble_tx_args.channel->count == 1) { + cmd.channel = phy_ble_tx_args.channel->ival[0]; + } else { + cmd.channel = 1; + ESP_LOGW(TAG, "Default channel is 1"); + } + + if (phy_ble_tx_args.len->count == 1) { + cmd.len = phy_ble_tx_args.len->ival[0]; + } else { + cmd.len = 37; + ESP_LOGW(TAG, "Default len is 37"); + } + + if (phy_ble_tx_args.data_type->count == 1) { + cmd.data_type = phy_ble_tx_args.data_type->ival[0]; + } else { + cmd.data_type = PHY_BLE_TYPE_prbs9; + ESP_LOGW(TAG, "Default data_type is PHY_BLE_TYPE_prbs9"); + } + + if (phy_ble_tx_args.syncw->count == 1) { + cmd.syncw = phy_ble_tx_args.syncw->ival[0]; + } else { + cmd.syncw = 0x71764129; + ESP_LOGW(TAG, "Default syncw is 0x71764129"); + } + + if (phy_ble_tx_args.rate->count == 1) { + cmd.rate = phy_ble_tx_args.rate->ival[0]; + } else { + cmd.rate = PHY_BLE_RATE_1M; + ESP_LOGW(TAG, "Default rate is PHY_BLE_RATE_1M"); + } + + if (phy_ble_tx_args.tx_num_in->count == 1) { + cmd.tx_num_in = phy_ble_tx_args.tx_num_in->ival[0]; + } else { + cmd.tx_num_in = 0; + ESP_LOGW(TAG, "Default tx_num_in is 0"); + } + + xTaskCreate(cert_ble_tx, "cert_ble_tx", 4096, (void *)&cmd, 10, NULL); + + return 0; +} + +static int esp_phy_ble_rx_func(int argc, char **argv) +{ + phy_ble_rx_s cmd; + int nerrors = arg_parse(argc, argv, (void **) &phy_ble_rx_args); + if (nerrors != 0) { + arg_print_errors(stderr, phy_ble_rx_args.end, argv[0]); + return 1; + } + + if (phy_ble_rx_args.channel->count == 1) { + cmd.channel = phy_ble_tx_args.channel->ival[0]; + } else { + cmd.channel = 1; + ESP_LOGW(TAG, "Default channel is 1"); + } + + if (phy_ble_rx_args.syncw->count == 1) { + cmd.syncw = phy_ble_rx_args.syncw->ival[0]; + } else { + cmd.syncw = 0x71764129; + ESP_LOGW(TAG, "Default syncw is 0x71764129"); + } + + if (phy_ble_rx_args.rate->count == 1) { + cmd.rate = phy_ble_rx_args.rate->ival[0]; + } else { + cmd.rate = PHY_BLE_RATE_1M; + ESP_LOGW(TAG, "Default rate is PHY_BLE_RATE_1M"); + } + + xTaskCreate(cert_ble_rx, "cert_ble_rx", 4096, (void *)&cmd, 10, NULL); + + return 0; +} + +static int esp_phy_bt_tx_tone_func(int argc, char **argv) +{ + uint32_t start; + uint32_t channel; + uint32_t attenuation; + int nerrors = arg_parse(argc, argv, (void **) &phy_bt_tx_tone_args); + if (nerrors != 0) { + arg_print_errors(stderr, phy_bt_tx_tone_args.end, argv[0]); + return 1; + } + + if (phy_bt_tx_tone_args.start->count == 1) { + start = phy_bt_tx_tone_args.start->ival[0]; + } else { + start = 1; + ESP_LOGW(TAG, "Default start is 1"); + } + + if (phy_bt_tx_tone_args.channel->count == 1) { + channel = phy_bt_tx_tone_args.channel->ival[0]; + } else { + channel = 1; + ESP_LOGW(TAG, "Default channel is 1"); + } + + if (phy_bt_tx_tone_args.attenuation->count == 1) { + attenuation = phy_bt_tx_tone_args.attenuation->ival[0]; + } else { + attenuation = 0; + ESP_LOGW(TAG, "Default backoff is 0"); + } + + esp_phy_bt_tx_tone(start, channel, attenuation); + + return 0; +} +#endif + +void register_phy_cmd(void) +{ + phy_args.enable = arg_int0(NULL, NULL, "", "enable"); + phy_args.end = arg_end(1); + + const esp_console_cmd_t tx_contin_cmd = { + .command = "tx_contin_en", + .help = "TX Continuous mode, 1: enable, 0: disable", + .hint = NULL, + .func = &esp_phy_tx_contin_en_func, + .argtable = &phy_args + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&tx_contin_cmd) ); + + const esp_console_cmd_t cmdstop_cmd = { + .command = "cmdstop", + .help = "TX/RX test stop command", + .hint = NULL, + .func = &esp_phy_cmdstop_func, + .argtable = NULL + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&cmdstop_cmd) ); + + const esp_console_cmd_t get_rx_result = { + .command = "get_rx_result", + .help = "Get RX information", + .hint = NULL, + .func = &esp_phy_get_rx_result_func, + .argtable = NULL + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&get_rx_result) ); + +#if SOC_WIFI_SUPPORTED + const esp_console_cmd_t cbw40m_cmd = { + .command = "cbw40m_en", + .help = "HT40/HT20 mode selection, 0: HT20, 1: HT40", + .hint = NULL, + .func = &esp_phy_cbw40m_en_func, + .argtable = &phy_args + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&cbw40m_cmd) ); + + phy_wifi_tx_args.channel = arg_int0("n", "channel" , "" , "channel setting, 1~14"); + phy_wifi_tx_args.rate = arg_int0("r", "rate" , "" , "rate setting"); + phy_wifi_tx_args.attenuation = arg_int0("p", "attenuation" , "" , "Transmit power attenuation"); + phy_wifi_tx_args.length_byte = arg_int0("l", "length_byte" , "" , "TX packet length configuration"); + phy_wifi_tx_args.packet_delay= arg_int0("d", "packet_delay", "", "TX packet interval configuration"); + phy_wifi_tx_args.packet_num = arg_int0("c", "packet_num" , "" , "The number of packets to send"); + phy_wifi_tx_args.end = arg_end(1); + + const esp_console_cmd_t esp_tx_cmd = { + .command = "esp_tx", + .help = "WiFi TX command", + .hint = NULL, + .func = &esp_phy_wifi_tx_func, + .argtable = &phy_wifi_tx_args + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&esp_tx_cmd) ); + + phy_wifi_rx_args.channel = arg_int0("n", "channel", "", "channel setting, 1~14"); + phy_wifi_rx_args.rate = arg_int0("r", "rate" , "" , "rate setting"); + phy_wifi_rx_args.end = arg_end(1); + + const esp_console_cmd_t esp_rx_cmd = { + .command = "esp_rx", + .help = "WiFi RX command", + .hint = NULL, + .func = &esp_phy_wifi_rx_func, + .argtable = &phy_wifi_rx_args + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&esp_rx_cmd) ); + + phy_wifiscwout_args.enable = arg_int0("e", "start" , "" , "enable CW"); + phy_wifiscwout_args.channel = arg_int0("c", "channel" , "" , "channel setting, 1~14"); + phy_wifiscwout_args.attenuation = arg_int0("p", "attenuation", "", "Transmit power attenuation"); + phy_wifiscwout_args.end = arg_end(1); + + const esp_console_cmd_t wifiscwout_cmd = { + .command = "wifiscwout", + .help = "Wi-Fi CW TX command", + .hint = NULL, + .func = &esp_phy_wifiscwout_func, + .argtable = &phy_wifiscwout_args + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&wifiscwout_cmd) ); +#endif + +#if SOC_BT_SUPPORTED + phy_ble_tx_args.txpwr = arg_int0("p", "txpwr" , "" , "Transmit power level setting"); + phy_ble_tx_args.channel = arg_int0("n", "channel" , "" , "TX channel setting, range is 0~39"); + phy_ble_tx_args.len = arg_int0("l", "len" , "" , "Payload length setting, range is 0-255"); + phy_ble_tx_args.data_type = arg_int0("t", "data_type", "", "Data type setting"); + phy_ble_tx_args.syncw = arg_int0("s", "syncw" , "" , "Packet identification"); + phy_ble_tx_args.rate = arg_int0("r", "rate" , "" , "TX rate setting,0: 1M; 1: 2M;2: 125K;3: 500K"); + phy_ble_tx_args.tx_num_in = arg_int0("m", "tx_num_in", "", "TX mode setting"); + phy_ble_tx_args.end = arg_end(1); + + const esp_console_cmd_t esp_ble_tx_cmd = { + .command = "esp_ble_tx", + .help = "BLE TX command", + .hint = NULL, + .func = &esp_phy_ble_tx_func, + .argtable = &phy_ble_tx_args + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&esp_ble_tx_cmd) ); + + phy_ble_rx_args.channel = arg_int0("n", "channel", "", "RX channel setting, range is 0~39"); + phy_ble_rx_args.syncw = arg_int0("s", "syncw" , "" , "Packet identification"); + phy_ble_rx_args.rate = arg_int0("r", "rate" , "" , "RX rate setting,0: 1M;1: 2M;2: 125K;3: 500K"); + phy_ble_rx_args.end = arg_end(1); + + const esp_console_cmd_t esp_ble_rx_cmd = { + .command = "esp_ble_rx", + .help = "BLE RX command", + .hint = NULL, + .func = &esp_phy_ble_rx_func, + .argtable = &phy_ble_rx_args + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&esp_ble_rx_cmd) ); + + phy_bt_tx_tone_args.start = arg_int0("e", "start" , "" , "enable CW, 1 means transmit, 0 means stop transmitting"); + phy_bt_tx_tone_args.channel = arg_int0("n", "channel", "", "Single carrier transmission channel selection"); + phy_bt_tx_tone_args.attenuation = arg_int0("p", "power" , "" , "CW power attenuation parameter"); + phy_bt_tx_tone_args.end = arg_end(1); + + const esp_console_cmd_t bt_tx_tone_cmd = { + .command = "bt_tx_tone", + .help = "Single carrier TX command", + .hint = NULL, + .func = &esp_phy_bt_tx_tone_func, + .argtable = &phy_bt_tx_tone_args + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&bt_tx_tone_cmd) ); +#endif +} +#endif diff --git a/examples/phy/cert_test/main/cmd_phy.h b/examples/phy/cert_test/main/cmd_phy.h new file mode 100644 index 0000000000..9f05f65d04 --- /dev/null +++ b/examples/phy/cert_test/main/cmd_phy.h @@ -0,0 +1,105 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_phy_cert_test.h" + +typedef struct { + struct arg_int *enable; + struct arg_end *end; +} phy_args_t; + +#if SOC_WIFI_SUPPORTED +typedef struct { + struct arg_int *channel; + struct arg_int *rate; + struct arg_int *attenuation; + struct arg_int *length_byte; + struct arg_int *packet_delay; + struct arg_int *packet_num; + struct arg_end *end; +} phy_wifi_tx_t; + +typedef struct { + struct arg_int *channel; + struct arg_int *rate; + struct arg_end *end; +} phy_wifi_rx_t; + +typedef struct { + struct arg_int *enable; + struct arg_int *channel; + struct arg_int *attenuation; + struct arg_end *end; +} phy_wifiscwout_t; + +typedef struct { + uint32_t channel; + esp_phy_wifi_rate_t rate; + int8_t backoff; + uint32_t length_byte; + uint32_t packet_delay; + uint32_t packet_num; +} phy_wifi_tx_s; + +typedef struct { + uint32_t channel; + esp_phy_wifi_rate_t rate; +} phy_wifi_rx_s; +#endif + +#if SOC_BT_SUPPORTED +typedef struct { + struct arg_int *txpwr; + struct arg_int *channel; + struct arg_int *len; + struct arg_int *data_type; + struct arg_int *syncw; + struct arg_int *rate; + struct arg_int *tx_num_in; + struct arg_end *end; +} phy_ble_tx_t; + +typedef struct { + struct arg_int *channel; + struct arg_int *syncw; + struct arg_int *rate; + struct arg_end *end; +} phy_ble_rx_t; + +typedef struct { + struct arg_int *start; + struct arg_int *channel; + struct arg_int *attenuation; + struct arg_end *end; +} phy_bt_tx_tone_t; + +typedef struct { + uint32_t txpwr; + uint32_t channel; + uint32_t len; + esp_phy_ble_type_t data_type; + uint32_t syncw; + esp_phy_ble_rate_t rate; + uint32_t tx_num_in; +} phy_ble_tx_s; + +typedef struct { + uint32_t channel; + uint32_t syncw; + esp_phy_ble_rate_t rate; +} phy_ble_rx_s; +#endif + +void register_phy_cmd(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/phy/cert_test/sdkconfig.ci b/examples/phy/cert_test/sdkconfig.ci new file mode 100644 index 0000000000..905254449c --- /dev/null +++ b/examples/phy/cert_test/sdkconfig.ci @@ -0,0 +1,5 @@ +CONFIG_ESP_INT_WDT=n +CONFIG_ESP_TASK_WDT_EN=n + +CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION=y +CONFIG_ESP_PHY_ENABLE_CERT_TEST=y diff --git a/examples/phy/cert_test/sdkconfig.defaults b/examples/phy/cert_test/sdkconfig.defaults new file mode 100644 index 0000000000..b0ce7b5c29 --- /dev/null +++ b/examples/phy/cert_test/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_ESP_TASK_WDT_EN=n + +CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION=y +CONFIG_ESP_PHY_ENABLE_CERT_TEST=y