From 19f7eb959c43b1254e00e4d693610ebfa604bf33 Mon Sep 17 00:00:00 2001 From: luweike Date: Tue, 3 Dec 2024 15:55:59 +0800 Subject: [PATCH] docs: remove old wifi.rst files after document split --- docs/conf_common.py | 2 +- docs/en/api-guides/index.rst | 2 +- docs/en/api-guides/performance/speed.rst | 4 +- docs/en/api-guides/wifi-driver/index.rst | 16 + docs/en/api-guides/wifi-driver/overview.rst | 1325 +++++ .../wifi-driver/security-and-roaming.rst | 86 + .../wifi-driver/station-scenarios.rst | 898 ++++ .../wifi-driver/wifi-mac-protocols.rst | 94 + docs/en/api-guides/wifi-driver/wifi-modes.rst | 100 + .../wifi-performance-and-power-save.rst | 1647 +++++++ .../wifi-driver/wifi-vendor-features.rst | 236 + docs/en/api-guides/wifi-expansion.rst | 2 +- docs/en/api-guides/wifi-security.rst | 71 +- docs/en/api-guides/wifi.rst | 4280 ----------------- docs/page_redirects.txt | 1 + docs/zh_CN/api-guides/index.rst | 2 +- docs/zh_CN/api-guides/performance/speed.rst | 4 +- docs/zh_CN/api-guides/wifi-driver/index.rst | 16 + .../zh_CN/api-guides/wifi-driver/overview.rst | 1325 +++++ .../wifi-driver/security-and-roaming.rst | 86 + .../wifi-driver/station-scenarios.rst | 898 ++++ .../wifi-driver/wifi-mac-protocols.rst | 94 + .../api-guides/wifi-driver/wifi-modes.rst | 100 + .../wifi-performance-and-power-save.rst | 1646 +++++++ .../wifi-driver/wifi-vendor-features.rst | 236 + docs/zh_CN/api-guides/wifi-security.rst | 74 +- docs/zh_CN/api-guides/wifi.rst | 4249 ---------------- 27 files changed, 8930 insertions(+), 8564 deletions(-) create mode 100644 docs/en/api-guides/wifi-driver/index.rst create mode 100644 docs/en/api-guides/wifi-driver/overview.rst create mode 100644 docs/en/api-guides/wifi-driver/security-and-roaming.rst create mode 100644 docs/en/api-guides/wifi-driver/station-scenarios.rst create mode 100644 docs/en/api-guides/wifi-driver/wifi-mac-protocols.rst create mode 100644 docs/en/api-guides/wifi-driver/wifi-modes.rst create mode 100644 docs/en/api-guides/wifi-driver/wifi-performance-and-power-save.rst create mode 100644 docs/en/api-guides/wifi-driver/wifi-vendor-features.rst delete mode 100644 docs/en/api-guides/wifi.rst create mode 100644 docs/zh_CN/api-guides/wifi-driver/index.rst create mode 100644 docs/zh_CN/api-guides/wifi-driver/overview.rst create mode 100644 docs/zh_CN/api-guides/wifi-driver/security-and-roaming.rst create mode 100644 docs/zh_CN/api-guides/wifi-driver/station-scenarios.rst create mode 100644 docs/zh_CN/api-guides/wifi-driver/wifi-mac-protocols.rst create mode 100644 docs/zh_CN/api-guides/wifi-driver/wifi-modes.rst create mode 100644 docs/zh_CN/api-guides/wifi-driver/wifi-performance-and-power-save.rst create mode 100644 docs/zh_CN/api-guides/wifi-driver/wifi-vendor-features.rst delete mode 100644 docs/zh_CN/api-guides/wifi.rst diff --git a/docs/conf_common.py b/docs/conf_common.py index 48f608f56f..bfd02a94c3 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -89,7 +89,7 @@ BLUFI_DOCS = ['api-guides/ble/blufi.rst', 'api-reference/bluetooth/esp_blufi.rst WIFI_DOCS = [ 'api-guides/low-power-mode/low-power-mode-wifi.rst', - 'api-guides/wifi.rst', + 'api-guides/wifi-driver/**', 'api-guides/wifi-security.rst', 'api-guides/wireshark-user-guide.rst', 'api-reference/network/esp_now.rst', diff --git a/docs/en/api-guides/index.rst b/docs/en/api-guides/index.rst index 244cd14ab4..e9f63ce099 100644 --- a/docs/en/api-guides/index.rst +++ b/docs/en/api-guides/index.rst @@ -48,7 +48,7 @@ API Guides host-apps :SOC_USB_OTG_SUPPORTED and not esp32p4 and not esp32h4: usb-otg-console :SOC_USB_SERIAL_JTAG_SUPPORTED: usb-serial-jtag-console - :SOC_WIFI_SUPPORTED: wifi + :SOC_WIFI_SUPPORTED: wifi-driver/index :SOC_WIFI_SUPPORTED: wifi-security wifi-expansion :SOC_WIFI_SUPPORTED or SOC_BT_SUPPORTED or SOC_IEEE802154_SUPPORTED: phy diff --git a/docs/en/api-guides/performance/speed.rst b/docs/en/api-guides/performance/speed.rst index 07b21fce4a..cc00a20423 100644 --- a/docs/en/api-guides/performance/speed.rst +++ b/docs/en/api-guides/performance/speed.rst @@ -204,7 +204,7 @@ Common priorities are: - FreeRTOS Timer Task to handle FreeRTOS timer callbacks is created when the scheduler initializes and has minimum task priority (1, :ref:`configurable `). - :doc:`/api-reference/system/esp_event` system task to manage the default system event loop and execute callbacks has high priority (20, ``ESP_TASK_EVENT_PRIO``). This configuration is only used if the application calls :cpp:func:`esp_event_loop_create_default`. It is possible to call :cpp:func:`esp_event_loop_create` with a custom task configuration instead. - :doc:`/api-guides/lwip` TCP/IP task has high priority (18, ``ESP_TASK_TCPIP_PRIO``). - :SOC_WIFI_SUPPORTED: - :doc:`/api-guides/wifi` task has high priority (23). + :SOC_WIFI_SUPPORTED: - :doc:`/api-guides/wifi-driver/index` task has high priority (23). :SOC_WIFI_SUPPORTED: - Wi-Fi wpa_supplicant component may create dedicated tasks while the Wi-Fi Protected Setup (WPS), WPA2 EAP-TLS, Device Provisioning Protocol (DPP) or BSS Transition Management (BTM) features are in use. These tasks all have low priority (2). :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/controller_vhci` task has high priority (23, ``ESP_TASK_BT_CONTROLLER_PRIO``). The Bluetooth Controller needs to respond to requests with low latency, so it should always be among the highest priority task in the system. :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/nimble/index` task has high priority (21). @@ -220,7 +220,7 @@ Common priorities are: - FreeRTOS Timer Task to handle FreeRTOS timer callbacks is created when the scheduler initializes and has minimum task priority (1, :ref:`configurable `). This task is pinned to Core 0. - :doc:`/api-reference/system/esp_event` system task to manage the default system event loop and execute callbacks has high priority (20, ``ESP_TASK_EVENT_PRIO``) and it is pinned to Core 0. This configuration is only used if the application calls :cpp:func:`esp_event_loop_create_default`, it is possible to call :cpp:func:`esp_event_loop_create` with a custom task configuration instead. - :doc:`/api-guides/lwip` TCP/IP task has high priority (18, ``ESP_TASK_TCPIP_PRIO``) and is not pinned to any core (:ref:`configurable`). - :SOC_WIFI_SUPPORTED: - :doc:`/api-guides/wifi` task has high priority (23) and is pinned to Core 0 by default (:ref:`configurable`). + :SOC_WIFI_SUPPORTED: - :doc:`/api-guides/wifi-driver/index` task has high priority (23) and is pinned to Core 0 by default (:ref:`configurable`). :SOC_WIFI_SUPPORTED: - Wi-Fi wpa_supplicant component may create dedicated tasks while the Wi-Fi Protected Setup (WPS), WPA2 EAP-TLS, Device Provisioning Protocol (DPP) or BSS Transition Management (BTM) features are in use. These tasks all have low priority (2) and are not pinned to any core. :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/controller_vhci` task has high priority (23, ``ESP_TASK_BT_CONTROLLER_PRIO``) and is pinned to Core 0 by default (:ref:`configurable <{IDF_TARGET_CONTROLLER_CORE_CONFIG}>`). The Bluetooth Controller needs to respond to requests with low latency, so it should always be among the highest priority task assigned to a single CPU. :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/nimble/index` task has high priority (21) and is pinned to Core 0 by default (:ref:`configurable `). diff --git a/docs/en/api-guides/wifi-driver/index.rst b/docs/en/api-guides/wifi-driver/index.rst new file mode 100644 index 0000000000..8b716733c0 --- /dev/null +++ b/docs/en/api-guides/wifi-driver/index.rst @@ -0,0 +1,16 @@ +############# +Wi-Fi Driver +############# + +:link_to_translation:`zh_CN:[中文]` + +.. toctree:: + :maxdepth: 2 + + overview + station-scenarios + wifi-modes + wifi-mac-protocols + security-and-roaming + wifi-performance-and-power-save + wifi-vendor-features diff --git a/docs/en/api-guides/wifi-driver/overview.rst b/docs/en/api-guides/wifi-driver/overview.rst new file mode 100644 index 0000000000..14ed5e01a5 --- /dev/null +++ b/docs/en/api-guides/wifi-driver/overview.rst @@ -0,0 +1,1325 @@ +Overview +========== + +:link_to_translation:`zh_CN:[中文]` + +{IDF_TARGET_NAME} Wi-Fi Feature List +------------------------------------ + +The following features are supported: + +.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 + + - 4 virtual Wi-Fi interfaces, which are STA, AP, Sniffer and reserved + - Station-only mode, AP-only mode, station/AP-coexistence mode + - IEEE 802.11b, IEEE 802.11g, IEEE 802.11n, and APIs to configure the protocol mode + - WPA/WPA2/WPA3/WPA2-Enterprise/WPA3-Enterprise/WAPI/WPS and DPP + - AMSDU, AMPDU, HT40, QoS, and other key features + - Modem-sleep + - The Espressif-specific ESP-NOW protocol and Long Range mode, which supports up to **1 km** of data traffic + - Up to 20 MBit/s TCP throughput and 30 MBit/s UDP throughput over the air + - Sniffer + - Both fast scan and all-channel scan + - Multiple antennas + - Channel state information + + +.. only:: esp32c2 + + - 3 virtual Wi-Fi interfaces, which are STA, AP and Sniffer + - Station-only mode, AP-only mode, station/AP-coexistence mode + - IEEE 802.11b, IEEE 802.11g, IEEE 802.11n, and APIs to configure the protocol mode + - WPA/WPA2/WPA3/WPA2-Enterprise/WPA3-Enterprise/WPS and DPP + - AMPDU, QoS, and other key features + - Modem-sleep + - Up to 20 MBit/s TCP throughput and 30 MBit/s UDP throughput over the air + - Sniffer + - Both fast scan and all-channel scan + - Multiple antennas + + +.. only:: esp32c6 + + - 4 virtual Wi-Fi interfaces, which are STA, AP, Sniffer and reserved + - Station-only mode, AP-only mode, station/AP-coexistence mode + - IEEE 802.11b, IEEE 802.11g, IEEE 802.11n, IEEE 802.11ax, and APIs to configure the protocol mode + - WPA/WPA2/WPA3/WPA2-Enterprise/WPA3-Enterprise/WAPI/WPS and DPP + - AMSDU, AMPDU, HT40, QoS, and other key features + - Modem-sleep + - The Espressif-specific ESP-NOW protocol and Long Range mode, which supports up to **1 km** of data traffic + - Up to 20 MBit/s TCP throughput and 30 MBit/s UDP throughput over the air + - Sniffer + - Both fast scan and all-channel scan + - Multiple antennas + - Channel state information + - Individual TWT and Broadcast TWT + - Downlink MU-MIMO + - OFDMA + - BSS Color + + +.. only:: esp32c5 + + - 4 virtual Wi-Fi interfaces, which are STA, AP, Sniffer and reserved + - Station-only mode, AP-only mode, station/AP-coexistence mode + - IEEE 802.11b, IEEE 802.11g, IEEE 802.11n, IEEE 802.11a, IEEE 802.11ac, IEEE 802.11ax, and APIs to configure the protocol mode + - WPA/WPA2/WPA3/WPA2-Enterprise/WPA3-Enterprise/WAPI/WPS and DPP + - AMSDU, AMPDU, HT40, QoS, and other key features + - Modem-sleep + - The Espressif-specific ESP-NOW protocol and Long Range mode (only supported on 2.4 GHz band), which supports up to **1 km** of data traffic + - Up to 20 MBit/s TCP throughput and 30 MBit/s UDP throughput over the air + - Sniffer + - Both fast scan and all-channel scan + - Multiple antennas + - Channel state information + - Individual TWT and Broadcast TWT + - Downlink MU-MIMO + - OFDMA + - BSS Color +.. only:: SOC_WIFI_NAN_SUPPORT + + - Wi-Fi Aware (NAN) + + +How To Write a Wi-Fi Application +---------------------------------- + +Preparation ++++++++++++ + +Generally, the most effective way to begin your own Wi-Fi application is to select an example which is similar to your own application, and port the useful part into your project. It is not a MUST, but it is strongly recommended that you take some time to read this article first, especially if you want to program a robust Wi-Fi application. + +This article is supplementary to the Wi-Fi APIs/Examples. It describes the principles of using the Wi-Fi APIs, the limitations of the current Wi-Fi API implementation, and the most common pitfalls in using Wi-Fi. This article also reveals some design details of the Wi-Fi driver. We recommend you to select an :example:`example `. + +- :example:`wifi/getting_started/station` demonstrates how to use the station functionality to connect to an AP. + +- :example:`wifi/getting_started/softAP` demonstrates how to use the SoftAP functionality to configure {IDF_TARGET_NAME} as an AP. + +- :example:`wifi/scan` demonstrates how to scan for available APs, configure the scan settings, and display the scan results. + +- :example:`wifi/fast_scan` demonstrates how to perform fast and all channel scans for nearby APs, set thresholds for signal strength and authentication modes, and connect to the best fitting AP based on signal strength and authentication mode. + +- :example:`wifi/wps` demonstrates how to use the WPS enrollee feature to simplify the process of connecting to a Wi-Fi router, with options for PIN or PBC modes. + +- :example:`wifi/wps_softap_registrar` demonstrates how to use the WPS registrar feature on SoftAP mode, simplifying the process of connecting to a Wi-Fi SoftAP from a station. + +- :example:`wifi/smart_config` demonstrates how to use the smartconfig feature to connect to a target AP using the ESPTOUCH app. + +- :example:`wifi/power_save` demonstrates how to use the power save mode in station mode. + +- :example:`wifi/softap_sta` demonstrates how to configure {IDF_TARGET_NAME} to function as both an AP and a station simultaneously, effectively enabling it to act as a Wi-Fi NAT router. + +- :example:`wifi/iperf` demonstrates how to implement the protocol used by the iPerf performance measurement tool, allowing for performance measurement between two chips or between a single chip and a computer running the iPerf tool, with specific instructions for testing station/soft-AP TCP/UDP RX/TX throughput. + +- :example:`wifi/roaming/roaming_app` demonstrates how to use the Wi-Fi Roaming App functionality to efficiently roam between compatible APs. + +- :example:`wifi/roaming/roaming_11kvr` demonstrates how to implement roaming using 11k and 11v APIs. + +.. only:: SOC_WIFI_HE_SUPPORT + + - :example:`wifi/itwt` demonstrates how to use the iTWT feature, which only works in station mode and under different power save modes, with commands for setup, teardown, and suspend, and also shows the difference in current consumption when iTWT is enabled or disabled. + +Setting Wi-Fi Compile-time Options +++++++++++++++++++++++++++++++++++++ + +Refer to :ref:`wifi-menuconfig`. + +Init Wi-Fi ++++++++++++ + +Refer to :ref:`wifi-station-general-scenario` and :ref:`wifi-ap-general-scenario`. + +Start/Connect Wi-Fi +++++++++++++++++++++ + +Refer to :ref:`wifi-station-general-scenario` and :ref:`wifi-ap-general-scenario`. + +Event-Handling +++++++++++++++ + +Generally, it is easy to write code in "sunny-day" scenarios, such as :ref:`wifi-event-sta-start` and :ref:`wifi-event-sta-connected`. The hard part is to write routines in "rainy-day" scenarios, such as :ref:`wifi-event-sta-disconnected`. Good handling of "rainy-day" scenarios is fundamental to robust Wi-Fi applications. Refer to :ref:`wifi-event-description`, :ref:`wifi-station-general-scenario`, and :ref:`wifi-ap-general-scenario`. See also the :doc:`overview of the Event Loop Library in ESP-IDF <../../api-reference/system/esp_event>`. + +Write Error-Recovery Routines Correctly at All Times +++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Just like the handling of "rainy-day" scenarios, a good error-recovery routine is also fundamental to robust Wi-Fi applications. Refer to :ref:`wifi-api-error-code`. + + +.. _wifi-api-error-code: + +{IDF_TARGET_NAME} Wi-Fi API Error Code +-------------------------------------- + +All of the {IDF_TARGET_NAME} Wi-Fi APIs have well-defined return values, namely, the error code. The error code can be categorized into: + + - No errors, e.g., :c:macro:`ESP_OK` means that the API returns successfully. + - Recoverable errors, such as :c:macro:`ESP_ERR_NO_MEM`. + - Non-recoverable, non-critical errors. + - Non-recoverable, critical errors. + +Whether the error is critical or not depends on the API and the application scenario, and it is defined by the API user. + +**The primary principle to write a robust application with Wi-Fi API is to always check the error code and write the error-handling code.** Generally, the error-handling code can be used: + + - For recoverable errors, in which case you can write a recoverable-error code. For example, when :cpp:func:`esp_wifi_start()` returns :c:macro:`ESP_ERR_NO_MEM`, the recoverable-error code vTaskDelay can be called in order to get a microseconds' delay for another try. + - For non-recoverable, yet non-critical errors, in which case printing the error code is a good method for error handling. + - For non-recoverable and also critical errors, in which case "assert" may be a good method for error handling. For example, if :cpp:func:`esp_wifi_set_mode()` returns ``ESP_ERR_WIFI_NOT_INIT``, it means that the Wi-Fi driver is not initialized by :cpp:func:`esp_wifi_init()` successfully. You can detect this kind of error very quickly in the application development phase. + +In :component_file:`esp_common/include/esp_err.h`, ``ESP_ERROR_CHECK`` checks the return values. It is a rather commonplace error-handling code and can be used as the default error-handling code in the application development phase. However, it is strongly recommended that API users write their own error-handling code. + + +{IDF_TARGET_NAME} Wi-Fi API Parameter Initialization +---------------------------------------------------- + +When initializing struct parameters for the API, one of two approaches should be followed: + +- Explicitly set all fields of the parameter. +- Use get API to get current configuration first, then set application specific fields. + +Initializing or getting the entire structure is very important, because most of the time the value 0 indicates that the default value is used. More fields may be added to the struct in the future and initializing these to zero ensures the application will still work correctly after ESP-IDF is updated to a new release. + + +.. _wifi-programming-model: + +{IDF_TARGET_NAME} Wi-Fi Programming Model +----------------------------------------- + +The {IDF_TARGET_NAME} Wi-Fi programming model is depicted as follows: + +.. blockdiag:: + :caption: Wi-Fi Programming Model + :align: center + + blockdiag wifi-programming-model { + + # global attributes + node_height = 60; + node_width = 100; + span_width = 100; + span_height = 60; + default_shape = roundedbox; + default_group_color = none; + + # node labels + TCP_STACK [label="TCP\n stack", fontsize=12]; + EVNT_TASK [label="Event\n task", fontsize=12]; + APPL_TASK [label="Application\n task", width = 120, fontsize=12]; + WIFI_DRV [label="Wi-Fi\n Driver", width = 120, fontsize=12]; + KNOT [shape=none]; + + # node connections + labels + TCP_STACK -> EVNT_TASK [label=event]; + EVNT_TASK -> APPL_TASK [label="callback\n or event"]; + + # arrange nodes vertically + group { + label = "default handler"; + orientation = portrait; + EVNT_TASK <- WIFI_DRV [label=event]; + } + + # intermediate node + group { + label = "user handler"; + orientation = portrait; + APPL_TASK -- KNOT; + } + WIFI_DRV <- KNOT [label="API\n call"]; + } + + +The Wi-Fi driver can be considered a black box that knows nothing about high-layer code, such as the TCP/IP stack, application task, and event task. The application task (code) generally calls :doc:`Wi-Fi driver APIs <../../api-reference/network/esp_wifi>` to initialize Wi-Fi and handles Wi-Fi events when necessary. Wi-Fi driver receives API calls, handles them, and posts events to the application. + +Wi-Fi event handling is based on the :doc:`esp_event library <../../api-reference/system/esp_event>`. Events are sent by the Wi-Fi driver to the :ref:`default event loop `. Application may handle these events in callbacks registered using :cpp:func:`esp_event_handler_register()`. Wi-Fi events are also handled by :doc:`esp_netif component <../../api-reference/network/esp_netif>` to provide a set of default behaviors. For example, when Wi-Fi station connects to an AP, esp_netif will automatically start the DHCP client by default. + + +.. _wifi-event-description: + +{IDF_TARGET_NAME} Wi-Fi Event Description +----------------------------------------- + +WIFI_EVENT_WIFI_READY +++++++++++++++++++++++++++++++++++++ + +The Wi-Fi driver will never generate this event, which, as a result, can be ignored by the application event callback. This event may be removed in future releases. + +.. _wifi-event-scan-done: + +WIFI_EVENT_SCAN_DONE +++++++++++++++++++++++++++++++++++++ + +The scan-done event is triggered by :cpp:func:`esp_wifi_scan_start()` and will arise in the following scenarios: + + - The scan is completed, e.g., the target AP is found successfully, or all channels have been scanned. + - The scan is stopped by :cpp:func:`esp_wifi_scan_stop()`. + - The :cpp:func:`esp_wifi_scan_start()` is called before the scan is completed. A new scan will override the current scan and a scan-done event will be generated. + +The scan-done event will not arise in the following scenarios: + + - It is a blocked scan. + - The scan is caused by :cpp:func:`esp_wifi_connect()`. + +Upon receiving this event, the event task does nothing. The application event callback needs to call :cpp:func:`esp_wifi_scan_get_ap_num()` and :cpp:func:`esp_wifi_scan_get_ap_records()` to fetch the scanned AP list and trigger the Wi-Fi driver to free the internal memory which is allocated during the scan **(do not forget to do this!)**. +Refer to :ref:`wifi-scan` for a more detailed description. + +.. _wifi-event-sta-start: + +WIFI_EVENT_STA_START +++++++++++++++++++++++++++++++++++++ + +If :cpp:func:`esp_wifi_start()` returns :c:macro:`ESP_OK` and the current Wi-Fi mode is station or station/AP, then this event will arise. Upon receiving this event, the event task will initialize the LwIP network interface (netif). Generally, the application event callback needs to call :cpp:func:`esp_wifi_connect()` to connect to the configured AP. + +WIFI_EVENT_STA_STOP +++++++++++++++++++++++++++++++++++++ + +If :cpp:func:`esp_wifi_stop()` returns :c:macro:`ESP_OK` and the current Wi-Fi mode is station or station/AP, then this event will arise. Upon receiving this event, the event task will release the station's IP address, stop the DHCP client, remove TCP/UDP-related connections, and clear the LwIP station netif, etc. The application event callback generally does not need to do anything. + +.. _wifi-event-sta-connected: + +WIFI_EVENT_STA_CONNECTED +++++++++++++++++++++++++++++++++++++ + +If :cpp:func:`esp_wifi_connect()` returns :c:macro:`ESP_OK` and the station successfully connects to the target AP, the connection event will arise. Upon receiving this event, the event task starts the DHCP client and begins the DHCP process of getting the IP address. Then, the Wi-Fi driver is ready for sending and receiving data. This moment is good for beginning the application work, provided that the application does not depend on LwIP, namely the IP address. However, if the application is LwIP-based, then you need to wait until the *got ip* event comes in. + +.. _wifi-event-sta-disconnected: + +WIFI_EVENT_STA_DISCONNECTED +++++++++++++++++++++++++++++++++++++ + +This event can be generated in the following scenarios: + + - When :cpp:func:`esp_wifi_disconnect()` or :cpp:func:`esp_wifi_stop()` is called and the station is already connected to the AP. + - When :cpp:func:`esp_wifi_connect()` is called, but the Wi-Fi driver fails to set up a connection with the AP due to certain reasons, e.g., the scan fails to find the target AP or the authentication times out. If there are more than one AP with the same SSID, the disconnected event will be raised after the station fails to connect all of the found APs. + - When the Wi-Fi connection is disrupted because of specific reasons, e.g., the station continuously loses N beacons, the AP kicks off the station, or the AP's authentication mode is changed. + +Upon receiving this event, the default behaviors of the event task are: + +- Shutting down the station's LwIP netif. +- Notifying the LwIP task to clear the UDP/TCP connections which cause the wrong status to all sockets. For socket-based applications, the application callback can choose to close all sockets and re-create them, if necessary, upon receiving this event. + +The most common event handle code for this event in application is to call :cpp:func:`esp_wifi_connect()` to reconnect the Wi-Fi. However, if the event is raised because :cpp:func:`esp_wifi_disconnect()` is called, the application should not call :cpp:func:`esp_wifi_connect()` to reconnect. It is the application's responsibility to distinguish whether the event is caused by :cpp:func:`esp_wifi_disconnect()` or other reasons. Sometimes a better reconnection strategy is required. Refer to :ref:`wifi-reconnect` and :ref:`scan-when-wifi-is-connecting`. + +Another thing that deserves attention is that the default behavior of LwIP is to abort all TCP socket connections on receiving the disconnect. In most cases, it is not a problem. However, for some special applications, this may not be what they want. Consider the following scenarios: + +- The application creates a TCP connection to maintain the application-level keep-alive data that is sent out every 60 seconds. +- Due to certain reasons, the Wi-Fi connection is cut off, and the `WIFI_EVENT_STA_DISCONNECTED`_ is raised. According to the current implementation, all TCP connections will be removed and the keep-alive socket will be in a wrong status. However, since the application designer believes that the network layer should **ignore** this error at the Wi-Fi layer, the application does not close the socket. +- Five seconds later, the Wi-Fi connection is restored because :cpp:func:`esp_wifi_connect()` is called in the application event callback function. **Moreover, the station connects to the same AP and gets the same IPV4 address as before**. +- Sixty seconds later, when the application sends out data with the keep-alive socket, the socket returns an error and the application closes the socket and re-creates it when necessary. + +In above scenarios, ideally, the application sockets and the network layer should not be affected, since the Wi-Fi connection only fails temporarily and recovers very quickly. + +.. _ip-event-sta-got-ip: + +IP_EVENT_STA_GOT_IP +++++++++++++++++++++++++++++++++++++ + +This event arises when the DHCP client successfully gets the IPV4 address from the DHCP server, or when the IPV4 address is changed. The event means that everything is ready and the application can begin its tasks (e.g., creating sockets). + +The IPV4 may be changed because of the following reasons: + + - The DHCP client fails to renew/rebind the IPV4 address, and the station's IPV4 is reset to 0. + - The DHCP client rebinds to a different address. + - The static-configured IPV4 address is changed. + +Whether the IPV4 address is changed or not is indicated by the field ``ip_change`` of ``ip_event_got_ip_t``. + +The socket is based on the IPV4 address, which means that, if the IPV4 changes, all sockets relating to this IPV4 will become abnormal. Upon receiving this event, the application needs to close all sockets and recreate the application when the IPV4 changes to a valid one. + +IP_EVENT_GOT_IP6 +++++++++++++++++++++++++++++++++++++ + +This event arises when the IPV6 SLAAC support auto-configures an address for the {IDF_TARGET_NAME}, or when this address changes. The event means that everything is ready and the application can begin its tasks, e.g., creating sockets. + +IP_EVENT_STA_LOST_IP +++++++++++++++++++++++++++++++++++++ + +This event arises when the IPV4 address becomes invalid. + +IP_EVENT_STA_LOST_IP does not arise immediately after the Wi-Fi disconnects. Instead, it starts an IPV4 address lost timer (configurable via :ref:`CONFIG_ESP_NETIF_LOST_IP_TIMER_ENABLE` and :ref:`CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL`). If the IPV4 address is got before the timer expires, IP_EVENT_STA_LOST_IP does not happen. Otherwise, the event arises when the IPV4 address lost timer expires. + +Generally, the application can ignore this event, because it is just a debug event to inform that the IPV4 address is lost. + +WIFI_EVENT_AP_START +++++++++++++++++++++++++++++++++++++ + +Similar to `WIFI_EVENT_STA_START`_. + +WIFI_EVENT_AP_STOP +++++++++++++++++++++++++++++++++++++ + +Similar to `WIFI_EVENT_STA_STOP`_. + +WIFI_EVENT_AP_STACONNECTED +++++++++++++++++++++++++++++++++++++ + +Every time a station is connected to {IDF_TARGET_NAME} AP, the `WIFI_EVENT_AP_STACONNECTED`_ will arise. Upon receiving this event, the event task will do nothing, and the application callback can also ignore it. However, you may want to do something, for example, to get the info of the connected STA. + +WIFI_EVENT_AP_STADISCONNECTED +++++++++++++++++++++++++++++++++++++ + +This event can happen in the following scenarios: + + - The application calls :cpp:func:`esp_wifi_disconnect()`, or :cpp:func:`esp_wifi_deauth_sta()`, to manually disconnect the station. + - The Wi-Fi driver kicks off the station, e.g., because the AP has not received any packets in the past five minutes. The time can be modified by :cpp:func:`esp_wifi_set_inactive_time()`. + - The station kicks off the AP. + +When this event happens, the event task will do nothing, but the application event callback needs to do something, e.g., close the socket which is related to this station. + +WIFI_EVENT_AP_PROBEREQRECVED +++++++++++++++++++++++++++++++++++++ + +This event is disabled by default. The application can enable it via API :cpp:func:`esp_wifi_set_event_mask()`. +When this event is enabled, it will be raised each time the AP receives a probe request. + +.. _wifi-event-sta-beacon-timeout: + +WIFI_EVENT_STA_BEACON_TIMEOUT +++++++++++++++++++++++++++++++++++++ + +If the station does not receive the beacon of the connected AP within the inactive time, the beacon timeout happens, the :ref:`wifi-event-sta-beacon-timeout` will arise. The application can set inactive time via API :cpp:func:`esp_wifi_set_inactive_time()`. + +.. _wifi-event-connectionless-module-wake-interval-start: + +WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +The :ref:`wifi-event-connectionless-module-wake-interval-start` will arise at the start of connectionless module `Interval`. See :ref:`connectionless module power save `. + + + +{IDF_TARGET_MAX_CONN_STA_NUM:default="15", esp32c2="4", esp32c3="10", esp32c6="10"} + +{IDF_TARGET_SUB_MAX_NUM_FROM_KEYS:default="2", esp32c3="7", esp32c6="7"} + +.. _wifi-configuration: + +{IDF_TARGET_NAME} Wi-Fi Configuration +------------------------------------- + +All configurations will be stored into flash when the Wi-Fi NVS is enabled; otherwise, refer to :ref:`wifi-nvs-flash`. + +Wi-Fi Mode ++++++++++++++++++++++++++ +Call :cpp:func:`esp_wifi_set_mode()` to set the Wi-Fi mode. + +.. list-table:: + :header-rows: 1 + :widths: 15 50 + + * - Mode + - Description + * - ``WIFI_MODE_NULL`` + - NULL mode: in this mode, the internal data struct is not allocated to the station and the AP, while both the station and AP interfaces are not initialized for RX/TX Wi-Fi data. Generally, this mode is used for Sniffer, or when you only want to stop both the station and the AP without calling :cpp:func:`esp_wifi_deinit()` to unload the whole Wi-Fi driver. + * - ``WIFI_MODE_STA`` + - Station mode: in this mode, :cpp:func:`esp_wifi_start()` will init the internal station data, while the station’s interface is ready for the RX and TX Wi-Fi data. After :cpp:func:`esp_wifi_connect()`, the station will connect to the target AP. + * - ``WIFI_MODE_AP`` + - AP mode: in this mode, :cpp:func:`esp_wifi_start()` will init the internal AP data, while the AP’s interface is ready for RX/TX Wi-Fi data. Then, the Wi-Fi driver starts broad-casting beacons, and the AP is ready to get connected to other stations. + * - ``WIFI_MODE_APSTA`` + - Station/AP coexistence mode: in this mode, :cpp:func:`esp_wifi_start()` will simultaneously initialize both the station and the AP. This is done in station mode and AP mode. Please note that the channel of the external AP, which the ESP station is connected to, has higher priority over the ESP AP channel. + + +.. only:: esp32c5 + + Wi-Fi Band Mode Configuration + ++++++++++++++++++++++++++++++ + + The Wi-Fi band mode used by {IDF_TARGET_NAME} can be set via the function :cpp:func:`esp_wifi_set_band_mode()`. + + .. list-table:: + :header-rows: 1 + :widths: 15 50 + + * - Mode + - Description + * - ``WIFI_BAND_MODE_2G_ONLY`` + - **2.4 GHz band mode**: The device operates only on 2.4 GHz band channels. + * - ``WIFI_BAND_MODE_5G_ONLY`` + - **5 GHz band mode**: The device operates only on 5 GHz band channels. + * - ``WIFI_BAND_MODE_AUTO`` + - **2.4 GHz + 5 GHz auto mode**: The device automatically selects either the 2.4 GHz or 5 GHz band based on the connected AP or SoftAP configuration. + + .. note:: + - ``WIFI_BAND_MODE_AUTO`` does not mean simultaneous dual-band support; it only allows automatic band selection. + + When operating in ``WIFI_BAND_MODE_AUTO`` mode, protocols and bandwidth can be configured separately for the 2.4 GHz and 5 GHz bands: + + - Use the function :cpp:func:`esp_wifi_set_protocols()` to set the supported protocol types for each band (e.g., 802.11b/g/n/ac/ax); + + - Use the function :cpp:func:`esp_wifi_set_bandwidths()` to set the bandwidth for each band (e.g., 20 MHz, 40 MHz). + +.. only:: esp32c5 + + AP Choose + +++++++++++++++++++++++++ + + When the device scans multiple APs with the same SSID, {IDF_TARGET_NAME} selects the most suitable AP to connect to based on signal strength (RSSI) and band information. The default policy usually prefers the AP with higher RSSI; however, in environments where 2.4 GHz and 5 GHz coexist, this can cause the device to favor the 2.4 GHz band, ignoring the performance benefits of the 5 GHz band. + + To address this, ESP-IDF provides the field :cpp:member:`rssi_5g_adjustment` in the :cpp:type:`wifi_scan_threshold_t` structure to optimize the priority of selecting 5 GHz APs. + + .. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Field + - Description + * - ``rssi_5g_adjustment`` + - Used to adjust priority between 2.4 GHz and 5 GHz APs with the same SSID. The default value is ``10``, meaning when the 5 GHz AP's RSSI is within 10 dB lower than the 2.4 GHz AP, the 5 GHz AP will be preferred. Properly setting this parameter helps the device prioritize 5 GHz networks that offer better bandwidth and interference resistance when signal strengths are close. + + Example: + + Suppose the device scans the following two APs with the SSID "MyWiFi": + + - 2.4 GHz AP: RSSI = -60 dBm + - 5 GHz AP: RSSI = -68 dBm + + Since ``rssi_5g_adjustment = 10`` (default) and ``-68 > -60 - 10`` holds true, the device will prioritize connecting to the 5 GHz AP. + + .. note:: + + This parameter only takes effect when scanning results contain APs with the same SSID on both 2.4 GHz and 5 GHz bands. Its purpose is to avoid always connecting to a 2.4 GHz network with slightly stronger signal but poorer performance. + + +.. _station-basic-configuration: + +Station Basic Configuration ++++++++++++++++++++++++++++++++++++++++++++++++ + +API :cpp:func:`esp_wifi_set_config()` can be used to configure the station. And the configuration will be stored in NVS. The table below describes the fields in detail. + +.. list-table:: + :header-rows: 1 + :widths: 15 50 + + * - Field + - Description + * - ssid + - This is the SSID of the target AP, to which the station wants to connect. + * - password + - Password of the target AP. + * - scan_method + - For ``WIFI_FAST_SCAN`` scan, the scan ends when the first matched AP is found. For ``WIFI_ALL_CHANNEL_SCAN``, the scan finds all matched APs on all channels. The default scan is ``WIFI_FAST_SCAN``. + * - bssid_set + - If bssid_set is 0, the station connects to the AP whose SSID is the same as the field “ssid”, while the field “bssid” is ignored. In all other cases, the station connects to the AP whose SSID is the same as the “ssid” field, while its BSSID is the same the “bssid” field . + * - bssid + - This is valid only when bssid_set is 1; see field “bssid_set”. + * - channel + - If the channel is 0, the station scans the channel 1 ~ N to search for the target AP; otherwise, the station starts by scanning the channel whose value is the same as that of the “channel” field, and then scans the channel 1 ~ N but skip the specific channel to find the target AP. For example, if the channel is 3, the scan order will be 3, 1, 2, 4,..., N. If you do not know which channel the target AP is running on, set it to 0. + * - sort_method + - This field is only for ``WIFI_ALL_CHANNEL_SCAN``. + + If the sort_method is ``WIFI_CONNECT_AP_BY_SIGNAL``, all matched APs are sorted by signal, and the AP with the best signal will be connected firstly. For example, the station wants to connect an AP whose SSID is “apxx”. If the scan finds two APs whose SSID equals to “apxx”, and the first AP’s signal is -90 dBm while the second AP’s signal is -30 dBm, the station connects the second AP firstly, and it would not connect the first one unless it fails to connect the second one. + + If the sort_method is ``WIFI_CONNECT_AP_BY_SECURITY``, all matched APs are sorted by security. For example, the station wants to connect an AP whose SSID is “apxx”. If the scan finds two APs whose SSID is “apxx”, and the security of the first found AP is open while the second one is WPA2, the station connects to the second AP firstly, and it would not connect the first one unless it fails to connect the second one. + * - threshold + - The threshold is used to filter the found AP. If the RSSI or security mode is less than the configured threshold, the AP will be discarded. + + If the RSSI is set to 0, it means the default threshold and the default RSSI threshold are -127 dBm. If the authmode threshold is set to 0, it means the default threshold and the default authmode threshold are open. + + +.. attention:: + + WEP/WPA security modes are deprecated in IEEE 802.11-2016 specifications and are recommended not to be used. These modes can be rejected using authmode threshold by setting threshold as WPA2 by threshold.authmode as ``WIFI_AUTH_WPA2_PSK``. + +AP Basic Configuration ++++++++++++++++++++++++++++++++++++++ + +API :cpp:func:`esp_wifi_set_config()` can be used to configure the AP. And the configuration will be stored in NVS. The table below describes the fields in detail. + +.. only:: esp32 or esp32s2 or esp32s3 or esp32c3 or esp32c5 or esp32c6 + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - Field + - Description + * - ssid + - SSID of AP; if the ssid[0] is 0xFF and ssid[1] is 0xFF, the AP defaults the SSID to ``ESP_aabbcc``, where “aabbcc” is the last three bytes of the AP MAC. + * - password + - Password of AP; if the auth mode is ``WIFI_AUTH_OPEN``, this field will be ignored. + * - ssid_len + - Length of SSID; if ssid_len is 0, check the SSID until there is a termination character. If ssid_len > 32, change it to 32; otherwise, set the SSID length according to ssid_len. + * - channel + - Channel of AP; if the channel is out of range, the Wi-Fi driver will return error. So, please make sure the channel is within the required range. For more details, refer to `Wi-Fi Country Code`_. + * - authmode + - Auth mode of ESP AP; currently, ESP AP does not support AUTH_WEP. If the authmode is an invalid value, AP defaults the value to ``WIFI_AUTH_OPEN``. + * - ssid_hidden + - If ssid_hidden is 1, AP does not broadcast the SSID; otherwise, it does broadcast the SSID. + * - max_connection + - The max number of stations allowed to connect in, the default value is 10. ESP Wi-Fi supports up to {IDF_TARGET_MAX_CONN_STA_NUM} (``ESP_WIFI_MAX_CONN_NUM``) Wi-Fi connections. Please note that ESP AP and ESP-NOW share the same encryption hardware keys, so the max_connection parameter will be affected by the :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`. The total number of encryption hardware keys is 17, if :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM` <= {IDF_TARGET_SUB_MAX_NUM_FROM_KEYS}, the max_connection can be set up to {IDF_TARGET_MAX_CONN_STA_NUM}, otherwise the max_connection can be set up to (17 - :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`). + * - beacon_interval + - Beacon interval; the value is 100 ~ 60000 ms, with default value being 100 ms. If the value is out of range, AP defaults it to 100 ms. + + +.. only:: esp32c2 + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - Field + - Description + * - ssid + - SSID of AP; if the ssid[0] is 0xFF and ssid[1] is 0xFF, the AP defaults the SSID to ``ESP_aabbcc``, where “aabbcc” is the last three bytes of the AP MAC. + * - password + - Password of AP; if the auth mode is ``WIFI_AUTH_OPEN``, this field will be ignored. + * - ssid_len + - Length of SSID; if ssid_len is 0, check the SSID until there is a termination character. If ssid_len > 32, change it to 32; otherwise, set the SSID length according to ssid_len. + * - channel + - Channel of AP; if the channel is out of range, the Wi-Fi driver defaults to channel 1. So, please make sure the channel is within the required range. For more details, refer to `Wi-Fi Country Code`_. + * - authmode + - Auth mode of ESP AP; currently, ESP AP does not support AUTH_WEP. If the authmode is an invalid value, AP defaults the value to ``WIFI_AUTH_OPEN``. + * - ssid_hidden + - If ssid_hidden is 1, AP does not broadcast the SSID; otherwise, it does broadcast the SSID. + * - max_connection + - The max number of stations allowed to connect in, the default value is 2. ESP Wi-Fi supports up to {IDF_TARGET_MAX_CONN_STA_NUM} (``ESP_WIFI_MAX_CONN_NUM``) Wi-Fi connections. Please note that ESP AP and ESP-NOW share the same encryption hardware keys, so the max_connection parameter will be affected by the :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`. The total number of encryption hardware keys is {IDF_TARGET_MAX_CONN_STA_NUM}, the max_connection can be set up to ({IDF_TARGET_MAX_CONN_STA_NUM} - :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`). + * - beacon_interval + - Beacon interval; the value is 100 ~ 60000 ms, with default value being 100 ms. If the value is out of range, AP defaults it to 100 ms. + + +Wi-Fi Protocol Mode ++++++++++++++++++++++++++ + +Currently, the ESP-IDF supports the following protocol modes: + +.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - Protocol Mode + - Description + * - 802.11b + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B)`` to set the station/AP to 802.11b-only mode. + * - 802.11bg + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` to set the station/AP to 802.11bg mode. + * - 802.11g + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` and esp_wifi_config_11b_rate(ifx, true) to set the station/AP to 802.11g mode. + * - 802.11bgn + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` to set the station/ AP to BGN mode. + * - 802.11gn + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` and esp_wifi_config_11b_rate(ifx, true) to set the station/AP to 802.11gn mode. + * - 802.11 BGNLR + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_LR)`` to set the station/AP to BGN and the LR mode. + * - 802.11 LR + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_LR)`` to set the station/AP only to the LR mode. + + **This mode is an Espressif-patented mode which can achieve a one-kilometer line of sight range. Please make sure both the station and the AP are connected to an ESP device.** + +.. only:: esp32c6 + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - Protocol Mode + - Description + * - 802.11b + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B)`` to set the station/AP to 802.11b-only mode. + * - 802.11bg + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` to set the station/AP to 802.11bg mode. + * - 802.11g + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` and ``esp_wifi_config_11b_rate(ifx, true)`` to set the station/AP to 802.11g mode. + * - 802.11bgn + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` to set the station/ AP to BGN mode. + * - 802.11gn + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` and esp_wifi_config_11b_rate(ifx, true) to set the station/AP to 802.11gn mode. + * - 802.11 BGNLR + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_LR)`` to set the station/AP to BGN and the LR mode. + * - 802.11bgnax + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_11AX)`` to set the station/ AP to 802.11bgnax mode. + * - 802.11 BGNAXLR + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_11AX|WIFI_PROTOCOL_LR)`` to set the station/ AP to 802.11bgnax and LR mode. + * - 802.11 LR + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_LR)`` to set the station/AP only to the LR mode. + + **This mode is an Espressif-patented mode which can achieve a one-kilometer line of sight range. Please make sure both the station and the AP are connected to an ESP device.** + + +.. only:: esp32c5 + + - **2.4 GHz band**: Supports 802.11b, 802.11bg, 802.11bgn, 802.11bgnax, and Espressif's proprietary LR mode. + - **5 GHz band**: Supports 802.11a, 802.11an, 802.11anac, and 802.11anacax. + + {IDF_TARGET_NAME} supports configuring Wi-Fi protocol modes for the 2.4 GHz and 5 GHz bands separately. It is recommended to use :cpp:func:`esp_wifi_set_protocols()` for this purpose. The legacy API :cpp:func:`esp_wifi_set_protocol()` is also supported. + + **Recommended Usage** + + Use the new API :cpp:func:`esp_wifi_set_protocols()` to configure each band independently: + + .. code-block:: c + + // Set 2.4 GHz to use 802.11bgnax, and 5 GHz to use 802.11anacax + wifi_protocols_t protocols = { + .ghz_2g = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX, + .ghz_5g = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AC | WIFI_PROTOCOL_11AX, + }; + esp_wifi_set_protocols(WIFI_IF_STA, &protocols); + + **Legacy Usage** + + Use the legacy API :cpp:func:`esp_wifi_set_protocol()` to configure the protocol mode for 2.4 GHz band or 5 GHz band: + + .. code-block:: c + + // Set band mode to 2.4 GHz band + esp_wifi_set_band_mode(WIFI_BAND_MODE_2G_ONLY); + + // Set protocol of station to 802.11bgnax + uint8_t protocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX; + esp_wifi_set_protocol(WIFI_IF_STA, protocol); + + .. note:: + + - The new API `esp_wifi_set_protocols()` allows configuring both bands simultaneously and is recommended for use on {IDF_TARGET_NAME}. + - The function ``esp_wifi_set_protocol()`` is suitable for single-band scenarios, such as when ``WIFI_BAND_MODE_2G_ONLY`` or ``WIFI_BAND_MODE_5G_ONLY`` is used. It only takes effect on the currently connected band. For example, if the interface is operating on the 5 GHz band, any configuration for the 2.4 GHz band will be ignored. + - If the configuration includes unsupported protocol combinations, the function will return an error. + - To enable Espressif's proprietary LR mode, make sure to include `WIFI_PROTOCOL_LR` in the 2.4 GHz protocol configuration. + + +.. only:: esp32c2 + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - Protocol Mode + - Description + * - 802.11b + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B)`` to set the station/AP to 802.11b-only mode. + * - 802.11bg + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` to set the station/AP to 802.11bg mode. + * - 802.11g + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G) and esp_wifi_config_11b_rate(ifx, true)`` to set the station/AP to 802.11g mode. + * - 802.11bgn + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` to set the station/ AP to BGN mode. + * - 802.11gn + - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` and ``esp_wifi_config_11b_rate(ifx, true)`` to set the station/AP to 802.11gn mode. + + +Wi-Fi Bandwidth Mode +++++++++++++++++++++++ + +.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 + + {IDF_TARGET_NAME} currently supports 20 MHz and 40 MHz bandwidth modes, which are used in combination with protocol modes. Common combinations include: + + - **HT20**: 802.11n with 20 MHz bandwidth + - **HT40**: 802.11n with 40 MHz bandwidth + + .. note:: + + - The 40 MHz bandwidth mode is only supported in 802.11n mode. + + Applications can use the :cpp:func:`esp_wifi_set_bandwidth()` API to set the bandwidth mode of the current interface. + + Example: + + .. code-block:: c + + // Set STA interface protocol to 802.11bgn + uint8_t protocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N; + esp_wifi_set_protocol(WIFI_IF_STA, protocol); + + // Set STA interface bandwidth to 40 MHz + esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40); + +.. only:: esp32c6 + + {IDF_TARGET_NAME} currently supports 20 MHz and 40 MHz bandwidth modes, which are used in combination with protocol modes. Common combinations include: + + - **HT20**: 802.11n with 20 MHz bandwidth + - **HT40**: 802.11n with 40 MHz bandwidth + - **HE20**: 802.11ax with 20 MHz bandwidth + + .. note:: + + - The 40 MHz bandwidth mode is only supported in 802.11n mode. + + Applications can use the :cpp:func:`esp_wifi_set_bandwidth()` API to set the bandwidth mode of the current interface. + + Example: + + .. code-block:: c + + // Set protocol of station to 802.11bgn + uint8_t protocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N; + esp_wifi_set_protocol(WIFI_IF_STA, protocol); + + // Set bandwidth of station to 40 MHz + esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40); + +.. only:: esp32c5 + + {IDF_TARGET_NAME} currently supports two bandwidth modes, 20 MHz and 40 MHz, which are used in combination with protocol modes. Common combinations include: + + - **HT20**: 802.11n/11an, 20 MHz bandwidth + - **HT40**: 802.11n/11an, 40 MHz bandwidth + - **HE20**: 802.11ax, 20 MHz bandwidth + + .. note:: + + - The 40 MHz bandwidth mode is only supported under 802.11n (2.4 GHz) or 802.11an (5 GHz) modes. + + Applications can use the :cpp:func:`esp_wifi_set_bandwidths()` API to set independent bandwidths for 2.4 GHz and 5 GHz bands. + + Example: + + .. code-block:: c + + // Set 2.4 GHz to use 802.11bgnax, and 5 GHz to use 802.11an + wifi_protocols_t protocols = { + .ghz_2g = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX, + .ghz_5g = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N, + }; + esp_wifi_set_protocols(WIFI_IF_STA, &protocols); + + // Set bandwidth to 20 MHz for 2.4 GHz band and 40 MHz for 5 GHz band + wifi_bandwidths_t bw = { + .ghz_2g = WIFI_BW_HT20, + .ghz_5g = WIFI_BW_HT40 + }; + esp_wifi_set_bandwidths(WIFI_IF_STA, &bw); + + .. note:: + + - When `.ghz_2g` is set to 0, only the 5 GHz bandwidth is updated, and the 2.4 GHz bandwidth remains unchanged. + - When `.ghz_5g` is set to 0, only the 2.4 GHz bandwidth is updated, and the 5 GHz bandwidth remains unchanged. + + **Legacy Usage** + + Use the legacy API :cpp:func:`esp_wifi_set_bandwidth()` to configure the bandwidth of the 2.4 GHz or 5 GHz band: + + .. code-block:: c + + // Set band mode to 5 GHz band + esp_wifi_set_band_mode(WIFI_BAND_MODE_5G_ONLY); + + // Set protocol of the station interface to 802.11an + uint8_t protocol = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N; + esp_wifi_set_protocol(WIFI_IF_STA, protocol); + + // Set bandwidth of the station interface to 40 MHz + esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40); + + .. note:: + + - The new API :cpp:func:`esp_wifi_set_bandwidths()` can configure both 2.4 GHz and 5 GHz bandwidths simultaneously, and is recommended for use on {IDF_TARGET_NAME}. + - ``esp_wifi_set_bandwidth()`` is suitable for single-band scenarios, such as ``WIFI_BAND_MODE_2G_ONLY`` or ``WIFI_BAND_MODE_5G_ONLY`` modes. It only affects the currently connected band. For example, if the interface is on the 5 GHz band, any 2.4 GHz bandwidth settings will be ignored. + - If the configured bandwidth is not supported on the current band, the function will return an error. + +.. only:: esp32c2 + + {IDF_TARGET_NAME} currently supports only 20 MHz bandwidth mode. + +.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 or esp32c5 or esp32c6 + + Long Range (LR) + +++++++++++++++++++++++++ + + Long Range (LR) mode is an Espressif-patented Wi-Fi mode which can achieve a one-kilometer line of sight range. Compared to the traditional 802.11b mode, it has better reception sensitivity, stronger anti-interference ability, and longer transmission distance. + + LR Compatibility + ************************* + + Since LR is an Espressif-unique Wi-Fi mode operating on the 2.4 GHz band, only ESP32-series chips (excluding the ESP32-C2) support LR data transmission and reception. To ensure compatibility, the ESP32 devices should NOT use LR data rates when connected to non-LR-capable devices. This can be enforced by configuring the appropriate Wi-Fi mode: + + - If the negotiated mode supports LR, ESP32 devices may transmit data at LR rates. + - Otherwise, they must default to traditional Wi-Fi data rates. + + The following table depicts the Wi-Fi mode negotiation on 2.4 GHz band: + + .. only:: esp32 or esp32s2 or esp32c3 or esp32s3 + + +-------+-----+----+---+-------+------+-----+----+ + |AP\STA | BGN | BG | B | BGNLR | BGLR | BLR | LR | + +=======+=====+====+===+=======+======+=====+====+ + | BGN | BGN | BG | B | BGN | BG | B | - | + +-------+-----+----+---+-------+------+-----+----+ + | BG | BG | BG | B | BG | BG | B | - | + +-------+-----+----+---+-------+------+-----+----+ + | B | B | B | B | B | B | B | - | + +-------+-----+----+---+-------+------+-----+----+ + | BGNLR | - | - | - | BGNLR | BGLR | BLR | LR | + +-------+-----+----+---+-------+------+-----+----+ + | BGLR | - | - | - | BGLR | BGLR | BLR | LR | + +-------+-----+----+---+-------+------+-----+----+ + | BLR | - | - | - | BLR | BLR | BLR | LR | + +-------+-----+----+---+-------+------+-----+----+ + | LR | - | - | - | LR | LR | LR | LR | + +-------+-----+----+---+-------+------+-----+----+ + + .. only:: esp32c5 or esp32c6 + + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | AP\STA | BGNAX | BGN | BG | B | BGNAXLR | BGNLR | BGLR | BLR | LR | + +=========+=======+=====+====+===+=========+=======+======+=====+====+ + | BGNAX | BGAX | BGN | BG | B | BGAX | BGN | BG | B | - | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | BGN | BGN | BGN | BG | B | BGN | BGN | BG | B | - | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | BG | BG | BG | BG | B | BG | BG | BG | B | - | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | B | B | B | B | B | B | B | B | B | - | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | BGNAXLR | - | - | - | - | BGAXLR | BGNLR | BGLR | BLR | LR | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | BGNLR | - | - | - | - | BGNLR | BGNLR | BGLR | BLR | LR | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | BGLR | - | - | - | - | BGLR | BGLR | BGLR | BLR | LR | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | BLR | - | - | - | - | BLR | BLR | BLR | BLR | LR | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | LR | - | - | - | - | LR | LR | LR | LR | LR | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + + In the above table, the row is the Wi-Fi mode of AP and the column is the Wi-Fi mode of station. The "-" indicates Wi-Fi mode of the AP and station are not compatible. + + According to the table, the following conclusions can be drawn: + + - For LR-enabled AP of {IDF_TARGET_NAME}, it is incompatible with traditional 802.11 mode, because the beacon is sent in LR mode. + - For LR-enabled station of {IDF_TARGET_NAME} whose mode is NOT LR-only mode, it is compatible with traditional 802.11 mode. + - If both station and AP are ESP32 series chips devices (except ESP32-C2) and both of them have enabled LR mode, the negotiated mode supports LR. + + If the negotiated Wi-Fi mode supports both traditional 802.11 mode and LR mode, it is the Wi-Fi driver's responsibility to automatically select the best data rate in different Wi-Fi modes and the application can ignore it. + + LR Impacts to Traditional Wi-Fi Device + *************************************** + + The data transmission in LR rate has no impacts on the traditional Wi-Fi device because: + + - The CCA and backoff process in LR mode are consistent with 802.11 specification. + - The traditional Wi-Fi device can detect the LR signal via CCA and do backoff. + + In other words, the transmission impact in LR mode is similar to that in 802.11b mode. + + LR Transmission Distance + ************************* + + The reception sensitivity gain of LR is about 4 dB larger than that of the traditional 802.11b mode. Theoretically, the transmission distance is about 2 to 2.5 times the distance of 11B. + + LR Throughput + ************************* + + The LR rate has very limited throughput, because the raw PHY data rate LR is 1/2 Mbps and 1/4 Mbps. + + When to Use LR + ************************* + + The general conditions for using LR are: + + - Both the AP and station are Espressif devices. + - Long distance Wi-Fi connection and data transmission is required. + - Data throughput requirements are very small, such as remote device control. + + +.. only:: esp32c5 + + Dynamic Frequency Selection (DFS) + +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + In the 5 GHz Wi-Fi band, certain channels (e.g., channels 52–144) share spectrum with critical systems such as weather radars. To avoid interference with these systems, Wi-Fi devices must perform specific detection and channel switching mechanisms before operating on these channels—this is known as **Dynamic Frequency Selection (DFS)**. + + Enabling DFS allows devices to access more 5 GHz channels, thereby increasing network capacity and reducing interference. This is especially beneficial in high-density deployments or applications that require high bandwidth. The range of DFS channels may vary by country or region; see :component_file:`esp_wifi/regulatory/esp_wifi_regulatory.txt` for details. + + {IDF_TARGET_NAME} supports DFS channels in the 5 GHz band, but only supports **passive radar detection**. + + .. list-table:: + :header-rows: 1 + :widths: 20 60 + + * - Type + - Description + * - Passive Radar Detection Supported + - During scanning, the device can listen to DFS channels, detect access points (APs) operating on DFS channels, and connect to them. If the AP detects radar signals and switches to another channel using Channel Switch Announcement (CSA), {IDF_TARGET_NAME} will follow the AP to the new channel. + * - Active Radar Detection Not Supported + - {IDF_TARGET_NAME} **does not support** active radar detection and therefore cannot operate as a DFS AP in SoftAP mode. + + .. note:: + + - In STA mode, {IDF_TARGET_NAME} can connect to APs operating on DFS channels, provided those channels are detected during scanning. + - In SoftAP mode, {IDF_TARGET_NAME} is not allowed to operate on DFS channels to comply with regulatory requirements. + - In STA+SoftAP coexistence mode: + + 1. If the STA connects to an AP on a DFS channel, the SoftAP is allowed to switch to the same DFS channel using CSA (Channel Switch Announcement). + 2. When the STA disconnects, the SoftAP will switch back to a non-DFS channel via CSA to remain compliant with regulations. + +.. + +.. _wifi-country-code: + +Wi-Fi Country Code +++++++++++++++++++++++++++++ + +.. only:: esp32 or esp32c2 or esp32s2 or esp32c3 or esp32s3 or esp32c6 + + Call :cpp:func:`esp_wifi_set_country()` to set the country info. The table below describes the fields in detail. Please consult local 2.4 GHz RF operating regulations before configuring these fields. + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - Field + - Description + * - cc[3] + - Country code string. This attribute identifies the country or noncountry entity in which the station/AP is operating. If it is a country, the first two octets of this string is the two-character country info as described in the document ISO/IEC3166-1. The third octet is one of the following: + + - an ASCII space character, which means the regulations under which the station/AP is operating encompass all environments for the current frequency band in the country. + - an ASCII ‘O’ character, which means the regulations under which the station/AP is operating are for an outdoor environment only. + - an ASCII ‘I’ character, which means the regulations under which the station/AP is operating are for an indoor environment only. + - an ASCII ‘X’ character, which means the station/AP is operating under a noncountry entity. The first two octets of the noncountry entity is two ASCII ‘XX’ characters. + - the binary representation of the Operating Class table number currently in use. Refer to Annex E of IEEE Std 802.11-2020. + + * - schan + - Start channel. It is the minimum channel number of the regulations under which the station/AP can operate. + * - nchan + - Total number of channels as per the regulations. For example, if the schan=1, nchan=13, then the station/AP can send data from channel 1 to 13. + * - policy + - Country policy. This field controls which country info will be used if the configured country info is in conflict with the connected AP’s. For more details on related policies, see the following section. + + + The default country info is:: + + wifi_country_t config = { + .cc = "01", + .schan = 1, + .nchan = 11, + .policy = WIFI_COUNTRY_POLICY_AUTO, + }; + + If the Wi-Fi Mode is station/AP coexist mode, they share the same configured country info. Sometimes, the country info of AP, to which the station is connected, is different from the country info of configured. For example, the configured station has country info:: + + wifi_country_t config = { + .cc = "JP", + .schan = 1, + .nchan = 14, + .policy = WIFI_COUNTRY_POLICY_AUTO, + }; + + but the connected AP has country info:: + + wifi_country_t config = { + .cc = "CN", + .schan = 1, + .nchan = 13, + ; + + then country info of connected AP's is used. + + The following table depicts which country info is used in different Wi-Fi modes and different country policies, and it also describes the impact on active scan. + + .. list-table:: + :header-rows: 1 + :widths: 15 15 35 + + * - Wi-Fi Mode + - Policy + - Description + * - Station + - WIFI_COUNTRY_POLICY_AUTO + - If the connected AP has country IE in its beacon, the country info equals to the country info in beacon. Otherwise, use the default country info. + + For scan: + + Use active scan from 1 to 11 and use passive scan from 12 to 14. + + Always keep in mind that if an AP with hidden SSID and station is set to a passive scan channel, the passive scan will not find it. In other words, if the application hopes to find the AP with hidden SSID in every channel, the policy of country info should be configured to WIFI_COUNTRY_POLICY_MANUAL. + + * - Station + - WIFI_COUNTRY_POLICY_MANUAL + - Always use the configured country info. + + For scan: + + Use active scan from schan to schan+nchan-1. + + * - AP + - WIFI_COUNTRY_POLICY_AUTO + - Always use the configured country info. + + * - AP + - WIFI_COUNTRY_POLICY_MANUAL + - Always use the configured country info. + + * - Station/AP-coexistence + - WIFI_COUNTRY_POLICY_AUTO + - Station: Same as station mode with policy WIFI_COUNTRY_POLICY_AUTO. + AP: If the station does not connect to any external AP, the AP uses the configured country info. If the station connects to an external AP, the AP has the same country info as the station. + + * - Station/AP-coexistence + - WIFI_COUNTRY_POLICY_MANUAL + - Station: Same as station mode with policy WIFI_COUNTRY_POLICY_MANUAL. + AP: Same as AP mode with policy WIFI_COUNTRY_POLICY_MANUAL. + +.. only:: esp32c5 + + The :cpp:func:`esp_wifi_set_country()` function is used to set the country/region information. The table below details the meaning of each field. Before configuring these fields, please refer to local 2.4 GHz and 5 GHz RF regulations. + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - Field + - Description + * - cc[3] + - Country/region code string identifying the country or region of the station/AP, or a non-country entity. If it is a country/region, the first two bytes comply with the ISO/IEC 3166-1 two-letter country code standard. The third byte has the following meanings: + + - Space character (ASCII): The country/region allows usage of the respective frequency band in all environments. + - Character `'O'`: Usage allowed only in outdoor environments. + - Character `'I'`: Usage allowed only in indoor environments. + - Character `'X'`: Non-country entity, in which case the first two characters should be `'XX'`. + - Binary operational class number, referring to IEEE Std 802.11-2020 Appendix E. + + * - schan + - Start channel number, indicating the minimum channel allowed in the 2.4 GHz band for the configured country/region. + * - nchan + - Number of channels. Defines the total number of allowed channels in the 2.4 GHz band. For example, if `schan = 1` and `nchan = 13`, then channels 1 through 13 are allowed. + * - policy + - Country/region policy. When the configured country/region conflicts with that of the connected AP, this field determines which information to use. Details are explained below. + * - wifi_5g_channel_mask + - Bitmask indicating allowed 5 GHz channels for the station/AP. The mapping between channel numbers and bits can be found in :cpp:enum:`wifi_5g_channel_bit_t`. + + A default configuration example:: + + wifi_country_t config = { + .cc = "01", + .schan = 1, + .nchan = 11, + .wifi_5g_channel_mask = 0xfe, + .policy = WIFI_COUNTRY_POLICY_AUTO, + }; + + When Wi-Fi is in station/AP coexistence mode, both use the same country/region information. Sometimes, the connected AP's country/region information may differ from the station's preset. For example: + + Station configuration:: + + wifi_country_t config = { + .cc = "JP", + .schan = 1, + .nchan = 14, + .wifi_5g_channel_mask = 0xfe, + .policy = WIFI_COUNTRY_POLICY_AUTO, + }; + + Connected AP configuration:: + + wifi_country_t config = { + .cc = "CN", + .schan = 1, + .nchan = 13, + }; + + In this case, the connected AP's country/region information will be used. + + The following table explains which country/region information is used under different Wi-Fi modes and policies, as well as differences in scanning behavior: + + .. list-table:: + :header-rows: 1 + :widths: 15 15 35 + + * - Wi-Fi Mode + - Policy + - Description + * - Station mode + - WIFI_COUNTRY_POLICY_AUTO + - If the connected AP's beacon contains country/region information IE, that information is used; otherwise, the default configuration is used. + + Scanning behavior: + + - 2.4 GHz band: active scanning on channels 1–11, passive scanning on channels 12–14; + - 5 GHz band: active scanning on non-DFS channels, passive scanning on DFS channels. + + Note: If an AP with a hidden SSID is on a passive scan channel, scanning may not discover that AP. To discover hidden SSIDs on all channels, use `WIFI_COUNTRY_POLICY_MANUAL`. + + * - Station mode + - WIFI_COUNTRY_POLICY_MANUAL + - Always use the configured country/region information. + + Scanning behavior: + + - 2.4 GHz band: scan channels from `schan` to `schan + nchan - 1`; + - 5 GHz band: scan channels supported as indicated by `wifi_5g_channel_mask`. + + * - AP mode + - WIFI_COUNTRY_POLICY_AUTO + - Always use the configured country/region information. + * - AP mode + - WIFI_COUNTRY_POLICY_MANUAL + - Always use the configured country/region information. + * - Station/AP coexistence mode + - WIFI_COUNTRY_POLICY_AUTO + - Same behavior as station mode with `WIFI_COUNTRY_POLICY_AUTO`. + + If the station is not connected to any AP, the AP uses the configured country/region information; + if the station is connected to an external AP, the AP uses the country/region information obtained by the station. + + * - Station/AP coexistence mode + - WIFI_COUNTRY_POLICY_MANUAL + - Same behavior as station mode with `WIFI_COUNTRY_POLICY_MANUAL`. The AP always uses the configured country/region information. + + +Home Channel +************************* + +In AP mode, the home channel is defined as the AP channel. In station mode, home channel is defined as the channel of AP which the station is connected to. In station/AP-coexistence mode, the home channel of AP and station must be the same, and if they are different, the station's home channel is always in priority. For example, assume that the AP is on channel 6, and the station connects to an AP whose channel is 9. Since the station's home channel has higher priority, the AP needs to switch its channel from 6 to 9 to make sure that it has the same home channel as the station. While switching channel, the {IDF_TARGET_NAME} in AP mode will notify the connected stations about the channel migration using a Channel Switch Announcement (CSA). Station that supports channel switching will transit without disconnecting and reconnecting to the AP. + + +.. _wifi-menuconfig: + +Wi-Fi Menuconfig +----------------- + +.. _wifi-buffer-configure: + +Wi-Fi Buffer Configure ++++++++++++++++++++++++ + +If you are going to modify the default number or type of buffer, it would be helpful to also have an overview of how the buffer is allocated/freed in the data path. The following diagram shows this process in the TX direction: + +.. blockdiag:: + :caption: TX Buffer Allocation + :align: center + + blockdiag buffer_allocation_tx { + + # global attributes + node_height = 60; + node_width = 100; + span_width = 50; + span_height = 20; + default_shape = roundedbox; + + # labels of diagram nodes + APPL_TASK [label="Application\n task", fontsize=12]; + LwIP_TASK [label="LwIP\n task", fontsize=12]; + WIFI_TASK [label="Wi-Fi\n task", fontsize=12]; + + # labels of description nodes + APPL_DESC [label="1> User data", width=120, height=25, shape=note, color=yellow]; + LwIP_DESC [label="2> Pbuf", width=120, height=25, shape=note, color=yellow]; + WIFI_DESC [label="3> Dynamic (Static)\n TX Buffer", width=150, height=40, shape=note, color=yellow]; + + # node connections + APPL_TASK -> LwIP_TASK -> WIFI_TASK + APPL_DESC -> LwIP_DESC -> WIFI_DESC [style=none] + } + + +Description: + + - The application allocates the data which needs to be sent out. + - The application calls TCPIP-/Socket-related APIs to send the user data. These APIs will allocate a PBUF used in LwIP, and make a copy of the user data. + - When LwIP calls a Wi-Fi API to send the PBUF, the Wi-Fi API will allocate a "Dynamic Tx Buffer" or "Static Tx Buffer", make a copy of the LwIP PBUF, and finally send the data. + +The following diagram shows how buffer is allocated/freed in the RX direction: + +.. blockdiag:: + :caption: RX Buffer Allocation + :align: center + + blockdiag buffer_allocation_rx { + + # global attributes + node_height = 60; + node_width = 100; + span_width = 40; + span_height = 20; + default_shape = roundedbox; + + # labels of diagram nodes + APPL_TASK [label="Application\n task", fontsize=12]; + LwIP_TASK [label="LwIP\n task", fontsize=12]; + WIFI_TASK [label="Wi-Fi\n task", fontsize=12]; + WIFI_INTR [label="Wi-Fi\n interrupt", fontsize=12]; + + # labels of description nodes + APPL_DESC [label="4> User\n Data Buffer", height=40, shape=note, color=yellow]; + LwIP_DESC [label="3> Pbuf", height=40, shape=note, color=yellow]; + WIFI_DESC [label="2> Dynamic\n RX Buffer", height=40, shape=note, color=yellow]; + INTR_DESC [label="1> Static\n RX Buffer", height=40, shape=note, color=yellow]; + + # node connections + APPL_TASK <- LwIP_TASK <- WIFI_TASK <- WIFI_INTR + APPL_DESC <- LwIP_DESC <- WIFI_DESC <- INTR_DESC [style=none] + } + +Description: + + - The Wi-Fi hardware receives a packet over the air and puts the packet content to the "Static Rx Buffer", which is also called "RX DMA Buffer". + - The Wi-Fi driver allocates a "Dynamic Rx Buffer", makes a copy of the "Static Rx Buffer", and returns the "Static Rx Buffer" to hardware. + - The Wi-Fi driver delivers the packet to the upper-layer (LwIP), and allocates a PBUF for holding the "Dynamic Rx Buffer". + - The application receives data from LwIP. + +The diagram shows the configuration of the Wi-Fi internal buffer. + +.. list-table:: + :header-rows: 1 + :widths: 10 10 10 10 25 + + * - Buffer Type + - Alloc Type + - Default + - Configurable + - Description + * - Static RX Buffer (Hardware RX Buffer) + - Static + - 10 * 1600 Bytes + - Yes + - This is a kind of DMA memory. It is initialized in :cpp:func:`esp_wifi_init()` and freed in :cpp:func:`esp_wifi_deinit()`. The ‘Static Rx Buffer’ forms the hardware receiving list. Upon receiving a frame over the air, hardware writes the frame into the buffer and raises an interrupt to the CPU. Then, the Wi-Fi driver reads the content from the buffer and returns the buffer back to the list. + + If needs be, the application can reduce the memory statically allocated by Wi-Fi. It can reduce this value from 10 to 6 to save 6400 Bytes of memory. It is not recommended to reduce the configuration to a value less than 6 unless the AMPDU feature is disabled. + * - Dynamic RX Buffer + - Dynamic + - 32 + - Yes + - The buffer length is variable and it depends on the received frames’ length. When the Wi-Fi driver receives a frame from the ‘Hardware Rx Buffer’, the ‘Dynamic Rx Buffer’ needs to be allocated from the heap. The number of the Dynamic Rx Buffer, configured in the menuconfig, is used to limit the total un-freed Dynamic Rx Buffer number. + * - Dynamic TX Buffer + - Dynamic + - 32 + - Yes + - This is a kind of DMA memory. It is allocated to the heap. When the upper-layer (LwIP) sends packets to the Wi-Fi driver, it firstly allocates a ‘Dynamic TX Buffer’ and makes a copy of the upper-layer buffer. + + The Dynamic and Static TX Buffers are mutually exclusive. + * - Static TX Buffer + - Static + - 16 * 1600Bytes + - Yes + - This is a kind of DMA memory. It is initialized in :cpp:func:`esp_wifi_init()` and freed in :cpp:func:`esp_wifi_deinit()`. When the upper-layer (LwIP) sends packets to the Wi-Fi driver, it firstly allocates a ‘Static TX Buffer’ and makes a copy of the upper-layer buffer. + + The Dynamic and Static TX Buffer are mutually exclusive. + + The TX buffer must be a DMA buffer. For this reason, if PSRAM is enabled, the TX buffer must be static. + * - Management Short Buffer + - Dynamic + - 8 + - NO + - Wi-Fi driver’s internal buffer. + * - Management Long Buffer + - Dynamic + - 32 + - NO + - Wi-Fi driver’s internal buffer. + * - Management Long Long Buffer + - Dynamic + - 32 + - NO + - Wi-Fi driver’s internal buffer. + +.. _wifi-nvs-flash: + +Wi-Fi NVS Flash ++++++++++++++++++++++ + +If the Wi-Fi NVS flash is enabled, all Wi-Fi configurations set via the Wi-Fi APIs will be stored into flash, and the Wi-Fi driver will start up with these configurations the next time it powers on/reboots. However, the application can choose to disable the Wi-Fi NVS flash if it does not need to store the configurations into persistent memory, or has its own persistent storage, or simply due to debugging reasons, etc. + + +Troubleshooting +---------------- + +Please refer to a separate document with :doc:`../wireshark-user-guide`. + +.. toctree:: + :hidden: + + ../wireshark-user-guide diff --git a/docs/en/api-guides/wifi-driver/security-and-roaming.rst b/docs/en/api-guides/wifi-driver/security-and-roaming.rst new file mode 100644 index 0000000000..098878d638 --- /dev/null +++ b/docs/en/api-guides/wifi-driver/security-and-roaming.rst @@ -0,0 +1,86 @@ +Security and Roaming +============================ + +:link_to_translation:`zh_CN:[中文]` + + +Supported Wi-Fi Security Modes +-------------------------------- + +{IDF_TARGET_NAME} supports the following Wi-Fi security modes. For detailed configuration and usage, refer to :doc:`Wi-Fi Security <../wifi-security>`. + +- Open +- WEP +- WPA-Personal +- WPA2-Personal +- WPA3-Personal +- Wi-Fi Enterprise + + +Wi-Fi Easy Connect™ (DPP) +-------------------------- + +Wi-Fi Easy Connect\ :sup:`TM` (or Device Provisioning Protocol) is a secure and standardized provisioning protocol for configuring Wi-Fi devices. More information can be found in :doc:`esp_dpp <../../api-reference/network/esp_dpp>`. + + +WPS Enrollee +------------------------- + +{IDF_TARGET_NAME} supports WPS enrollee feature in Wi-Fi mode :cpp:enumerator:`WIFI_MODE_STA` or :cpp:enumerator:`WIFI_MODE_APSTA`. Currently, {IDF_TARGET_NAME} supports WPS enrollee type PBC and PIN. + + +Wireless Network Management +---------------------------- + +Wireless Network Management allows client devices to exchange information about the network topology, including information related to RF environment. This makes each client network-aware, facilitating overall improvement in the performance of the wireless network. It is part of 802.11v specification. It also enables the client to support Network assisted Roaming. +- Network assisted Roaming: Enables WLAN to send messages to associated clients, resulting clients to associate with APs with better link metrics. This is useful for both load balancing and in directing poorly connected clients. + +Current implementation of 802.11v includes support for BSS transition management frames. + +Radio Resource Measurement +--------------------------- + +Radio Resource Measurement (802.11k) is intended to improve the way traffic is distributed within a network. In a WLAN, each device normally connects to the access point (AP) that provides the strongest signal. Depending on the number and geographic locations of the subscribers, this arrangement can sometimes lead to excessive demand on one AP and underutilization of others, resulting in degradation of overall network performance. In a network conforming to 802.11k, if the AP having the strongest signal is loaded to its full capacity, a wireless device can be moved to one of the underutilized APs. Even though the signal may be weaker, the overall throughput is greater because more efficient use is made of the network resources. + +Current implementation of 802.11k includes support for beacon measurement report, link measurement report, and neighbor request. + +Refer ESP-IDF example :idf_file:`examples/wifi/roaming/README.md` to set up and use these APIs. Example code only demonstrates how these APIs can be used, and the application should define its own algorithm and cases as required. + +Fast BSS Transition +--------------------------- + +Fast BSS transition (802.11r FT), is a standard to permit continuous connectivity aboard wireless devices in motion, with fast and secure client transitions from one Basic Service Set (abbreviated BSS, and also known as a base station or more colloquially, an access point) to another performed in a nearly seamless manner **avoiding 802.1i 4 way handshake** . 802.11r specifies transitions between access points by redefining the security key negotiation protocol, allowing both the negotiation and requests for wireless resources to occur in parallel. The key derived from the server to be cached in the wireless network, so that a reasonable number of future connections can be based on the cached key, avoiding the 802.1X process + + +{IDF_TARGET_NAME} station supports FT for WPA2-PSK networks. Do note that {IDF_TARGET_NAME} station only support FT over the air protocol only. + +A config option :ref:`CONFIG_ESP_WIFI_11R_SUPPORT` and configuration parameter :cpp:type:`ft_enabled` in :cpp:type:`wifi_sta_config_t` is provided to enable 802.11r support for station. Refer ESP-IDF example :idf_file:`examples/wifi/roaming/README.md` for further details. + +.. only:: SOC_WIFI_FTM_SUPPORT + + Wi-Fi Location + ------------------------------- + + Wi-Fi Location will improve the accuracy of a device's location data beyond the Access Point, which will enable creation of new and feature-rich applications and services such as geo-fencing, network management, and navigation. One of the protocols used to determine the device location with respect to the Access Point is Fine Timing Measurement which calculates Time-of-Flight of a Wi-Fi frame. + + Fine Timing Measurement (FTM) + +++++++++++++++++++++++++++++ + + FTM is used to measure Wi-Fi Round Trip Time (Wi-Fi RTT) which is the time a Wi-Fi signal takes to travel from a device to another device and back again. Using Wi-Fi RTT, the distance between the devices can be calculated with a simple formula of `RTT * c / 2`, where c is the speed of light. + + FTM uses timestamps given by Wi-Fi interface hardware at the time of arrival or departure of frames exchanged between a pair of devices. One entity called FTM Initiator (mostly a station device) discovers the FTM Responder (can be a station or an Access Point) and negotiates to start an FTM procedure. The procedure uses multiple Action frames sent in bursts and its ACK's to gather the timestamps data. FTM Initiator gathers the data in the end to calculate an average Round-Trip-Time. + + {IDF_TARGET_NAME} supports FTM in below configuration: + + - {IDF_TARGET_NAME} as FTM Initiator in station mode. + - {IDF_TARGET_NAME} as FTM Responder in AP mode. + +.. only:: esp32c6 + + {IDF_TARGET_NAME} ECO1 and older versions do not support FTM Initiator mode. + +.. attention:: + + Distance measurement using RTT is not accurate, and factors such as RF interference, multi-path travel, antenna orientation, and lack of calibration increase these inaccuracies. For better results, it is suggested to perform FTM between two ESP32 chip series devices as station and AP. + + Refer to ESP-IDF example :idf_file:`examples/wifi/ftm/README.md` for steps on how to set up and perform FTM. diff --git a/docs/en/api-guides/wifi-driver/station-scenarios.rst b/docs/en/api-guides/wifi-driver/station-scenarios.rst new file mode 100644 index 0000000000..8063481c33 --- /dev/null +++ b/docs/en/api-guides/wifi-driver/station-scenarios.rst @@ -0,0 +1,898 @@ +Station Scenarios +========================= + +:link_to_translation:`zh_CN:[中文]` + +.. _wifi-station-general-scenario: + +{IDF_TARGET_NAME} Wi-Fi Station General Scenario +------------------------------------------------- + +Below is a "big scenario" which describes some small scenarios in station mode: + +.. seqdiag:: + :caption: Sample Wi-Fi Event Scenarios in Station Mode + :align: center + + seqdiag sample-scenarios-station-mode { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 140; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + MAIN_TASK [label = "Main\ntask"]; + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + LwIP_TASK [label = "LwIP\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + === 1. Init Phase === + MAIN_TASK -> LwIP_TASK [label="1.1> Create / init LwIP"]; + MAIN_TASK -> EVENT_TASK [label="1.2> Create / init event"]; + MAIN_TASK -> WIFI_TASK [label="1.3> Create / init Wi-Fi"]; + MAIN_TASK -> APP_TASK [label="1.4> Create app task"]; + === 2. Configure Phase === + MAIN_TASK -> WIFI_TASK [label="2> Configure Wi-Fi"]; + === 3. Start Phase === + MAIN_TASK -> WIFI_TASK [label="3.1> Start Wi-Fi"]; + EVENT_TASK <- WIFI_TASK [label="3.2> WIFI_EVENT_STA_START"]; + APP_TASK <- EVENT_TASK [label="3.3> WIFI_EVENT_STA_START"]; + === 4. Connect Phase === + APP_TASK -> WIFI_TASK [label="4.1> Connect Wi-Fi"]; + EVENT_TASK <- WIFI_TASK [label="4.2> WIFI_EVENT_STA_CONNECTED"]; + APP_TASK <- EVENT_TASK [label="4.3> WIFI_EVENT_STA_CONNECTED"]; + === 5. Got IP Phase === + EVENT_TASK -> LwIP_TASK [label="5.1> Start DHCP client"]; + EVENT_TASK <- LwIP_TASK [label="5.2> IP_EVENT_STA_GOT_IP"]; + APP_TASK <- EVENT_TASK [label="5.3> IP_EVENT_STA_GOT_IP"]; + APP_TASK -> APP_TASK [label="5.4> socket related init"]; + === 6. Disconnect Phase === + EVENT_TASK <- WIFI_TASK [label="6.1> WIFI_EVENT_STA_DISCONNECTED"]; + APP_TASK <- EVENT_TASK [label="6.2> WIFI_EVENT_STA_DISCONNECTED"]; + APP_TASK -> APP_TASK [label="6.3> disconnect handling"]; + === 7. IP Change Phase === + EVENT_TASK <- LwIP_TASK [label="7.1> IP_EVENT_STA_GOT_IP"]; + APP_TASK <- EVENT_TASK [label="7.2> IP_EVENT_STA_GOT_IP"]; + APP_TASK -> APP_TASK [label="7.3> Socket error handling"]; + === 8. Deinit Phase === + APP_TASK -> WIFI_TASK [label="8.1> Disconnect Wi-Fi"]; + APP_TASK -> WIFI_TASK [label="8.2> Stop Wi-Fi"]; + APP_TASK -> WIFI_TASK [label="8.3> Deinit Wi-Fi"]; + } + + +1. Wi-Fi/LwIP Init Phase +++++++++++++++++++++++++++++++ + + - s1.1: The main task calls :cpp:func:`esp_netif_init()` to create an LwIP core task and initialize LwIP-related work. + + - s1.2: The main task calls :cpp:func:`esp_event_loop_create()` to create a system Event task and initialize an application event's callback function. In the scenario above, the application event's callback function does nothing but relaying the event to the application task. + + - s1.3: The main task calls :cpp:func:`esp_netif_create_default_wifi_ap()` or :cpp:func:`esp_netif_create_default_wifi_sta()` to create default network interface instance binding station or AP with TCP/IP stack. + + - s1.4: The main task calls :cpp:func:`esp_wifi_init()` to create the Wi-Fi driver task and initialize the Wi-Fi driver. + + - s1.5: The main task calls OS API to create the application task. + +Step 1.1 ~ 1.5 is a recommended sequence that initializes a Wi-Fi-/LwIP-based application. However, it is **NOT** a must-follow sequence, which means that you can create the application task in step 1.1 and put all other initialization in the application task. Moreover, you may not want to create the application task in the initialization phase if the application task depends on the sockets. Rather, you can defer the task creation until the IP is obtained. + +2. Wi-Fi Configuration Phase ++++++++++++++++++++++++++++++++ + +Once the Wi-Fi driver is initialized, you can start configuring the Wi-Fi driver. In this scenario, the mode is station, so you may need to call :cpp:func:`esp_wifi_set_mode` (WIFI_MODE_STA) to configure the Wi-Fi mode as station. You can call other `esp_wifi_set_xxx` APIs to configure more settings, such as the protocol mode, the country code, and the bandwidth. Refer to :ref:`wifi-configuration`. + +Generally, the Wi-Fi driver should be configured before the Wi-Fi connection is set up. But this is **NOT** mandatory, which means that you can configure the Wi-Fi connection anytime, provided that the Wi-Fi driver is initialized successfully. However, if the configuration does not need to change after the Wi-Fi connection is set up, you should configure the Wi-Fi driver at this stage, because the configuration APIs (such as :cpp:func:`esp_wifi_set_protocol()`) will cause the Wi-Fi to reconnect, which may not be desirable. + +If the Wi-Fi NVS flash is enabled by menuconfig, all Wi-Fi configuration in this phase, or later phases, will be stored into flash. When the board powers on/reboots, you do not need to configure the Wi-Fi driver from scratch. You only need to call ``esp_wifi_get_xxx`` APIs to fetch the configuration stored in flash previously. You can also configure the Wi-Fi driver if the previous configuration is not what you want. + +3. Wi-Fi Start Phase +++++++++++++++++++++++++++++++++ + + - s3.1: Call :cpp:func:`esp_wifi_start()` to start the Wi-Fi driver. + - s3.2: The Wi-Fi driver posts :ref:`wifi-event-sta-start` to the event task; then, the event task will do some common things and will call the application event callback function. + - s3.3: The application event callback function relays the :ref:`wifi-event-sta-start` to the application task. We recommend that you call :cpp:func:`esp_wifi_connect()`. However, you can also call :cpp:func:`esp_wifi_connect()` in other phrases after the :ref:`wifi-event-sta-start` arises. + +4. Wi-Fi Connect Phase ++++++++++++++++++++++++++++++++++ + + - s4.1: Once :cpp:func:`esp_wifi_connect()` is called, the Wi-Fi driver will start the internal scan/connection process. + + - s4.2: If the internal scan/connection process is successful, the :ref:`wifi-event-sta-connected` will be generated. In the event task, it starts the DHCP client, which will finally trigger the DHCP process. + + - s4.3: In the above-mentioned scenario, the application event callback will relay the event to the application task. Generally, the application needs to do nothing, and you can do whatever you want, e.g., print a log. + +In step 4.2, the Wi-Fi connection may fail because, for example, the password is wrong, or the AP is not found. In a case like this, :ref:`wifi-event-sta-disconnected` will arise and the reason for such a failure will be provided. For handling events that disrupt Wi-Fi connection, please refer to phase 6. + +5. Wi-Fi 'Got IP' Phase ++++++++++++++++++++++++++++++++++ + + - s5.1: Once the DHCP client is initialized in step 4.2, the *got IP* phase will begin. + - s5.2: If the IP address is successfully received from the DHCP server, then :ref:`ip-event-sta-got-ip` will arise and the event task will perform common handling. + - s5.3: In the application event callback, :ref:`ip-event-sta-got-ip` is relayed to the application task. For LwIP-based applications, this event is very special and means that everything is ready for the application to begin its tasks, e.g., creating the TCP/UDP socket. A very common mistake is to initialize the socket before :ref:`ip-event-sta-got-ip` is received. **DO NOT start the socket-related work before the IP is received.** + +6. Wi-Fi Disconnect Phase ++++++++++++++++++++++++++++++++++ + + - s6.1: When the Wi-Fi connection is disrupted, e.g., the AP is powered off or the RSSI is poor, :ref:`wifi-event-sta-disconnected` will arise. This event may also arise in phase 3. Here, the event task will notify the LwIP task to clear/remove all UDP/TCP connections. Then, all application sockets will be in a wrong status. In other words, no socket can work properly when this event happens. + - s6.2: In the scenario described above, the application event callback function relays :ref:`wifi-event-sta-disconnected` to the application task. The recommended actions are: 1) call :cpp:func:`esp_wifi_connect()` to reconnect the Wi-Fi, 2) close all sockets, and 3) re-create them if necessary. For details, please refer to :ref:`wifi-event-sta-disconnected`. + +7. Wi-Fi IP Change Phase +++++++++++++++++++++++++++++++++++ + + - s7.1: If the IP address is changed, the :ref:`ip-event-sta-got-ip` will arise with "ip_change" set to true. + - s7.2: **This event is important to the application. When it occurs, the timing is good for closing all created sockets and recreating them.** + + +8. Wi-Fi Deinit Phase +++++++++++++++++++++++++++++ + + - s8.1: Call :cpp:func:`esp_wifi_disconnect()` to disconnect the Wi-Fi connectivity. + - s8.2: Call :cpp:func:`esp_wifi_stop()` to stop the Wi-Fi driver. + - s8.3: Call :cpp:func:`esp_wifi_deinit()` to unload the Wi-Fi driver. + + +.. _wifi-scan: + +{IDF_TARGET_NAME} Wi-Fi Scan +----------------------------- + +Currently, the :cpp:func:`esp_wifi_scan_start()` API is supported only in station or station/AP mode. + +Scan Type ++++++++++++++++++++++++++ + +.. list-table:: + :header-rows: 1 + :widths: 15 50 + + * - Mode + - Description + * - Active Scan + - Scan by sending a probe request. The default scan is an active scan. + * - Passive Scan + - No probe request is sent out. Just switch to the specific channel and wait for a beacon. Application can enable it via the scan_type field of :cpp:type:`wifi_scan_config_t`. + * - Foreground Scan + - This scan is applicable when there is no Wi-Fi connection in station mode. Foreground or background scanning is controlled by the Wi-Fi driver and cannot be configured by the application. + * - Background Scan + - This scan is applicable when there is a Wi-Fi connection in station mode or in station/AP mode. Whether it is a foreground scan or background scan depends on the Wi-Fi driver and cannot be configured by the application. + * - All-Channel Scan + - It scans all of the channels. If the channel field of :cpp:type:`wifi_scan_config_t` is set to 0, it is an all-channel scan. + * - Specific Channel Scan + - It scans specific channels only. If the channel field of :cpp:type:`wifi_scan_config_t` set to 1-14, it is a specific-channel scan. + +The scan modes in above table can be combined arbitrarily, so there are in total 8 different scans: + + - All-Channel Background Active Scan + - All-Channel Background Passive Scan + - All-Channel Foreground Active Scan + - All-Channel Foreground Passive Scan + - Specific-Channel Background Active Scan + - Specific-Channel Background Passive Scan + - Specific-Channel Foreground Active Scan + - Specific-Channel Foreground Passive Scan + +Scan Configuration ++++++++++++++++++++++++++++++++++++++++ + +The scan type and other per-scan attributes are configured by :cpp:func:`esp_wifi_scan_start()`. The table below provides a detailed description of :cpp:type:`wifi_scan_config_t`. + +.. list-table:: + :header-rows: 1 + :widths: 15 50 + + * - Field + - Description + * - ssid + - If the SSID is not NULL, it is only the AP with the same SSID that can be scanned. + * - bssid + - If the BSSID is not NULL, it is only the AP with the same BSSID that can be scanned. + * - channel + - If “channel” is 0, there will be an all-channel scan; otherwise, there will be a specific-channel scan. + * - show_hidden + - If “show_hidden” is 0, the scan ignores the AP with a hidden SSID; otherwise, the scan considers the hidden AP a normal one. + * - scan_type + - If “scan_type” is WIFI_SCAN_TYPE_ACTIVE, the scan is “active”; otherwise, it is a “passive” one. + * - scan_time + - This field is used to control how long the scan dwells on each channel. + + For passive scans, scan_time.passive designates the dwell time for each channel. + + For active scans, dwell times for each channel are listed in the table below. Here, min is short for scan time.active.min and max is short for scan_time.active.max. + + - min=0, max=0: scan dwells on each channel for 120 ms. + - min>0, max=0: scan dwells on each channel for 120 ms. + - min=0, max>0: scan dwells on each channel for ``max`` ms. + - min>0, max>0: the minimum time the scan dwells on each channel is ``min`` ms. If no AP is found during this time frame, the scan switches to the next channel. Otherwise, the scan dwells on the channel for ``max`` ms. + + If you want to improve the performance of the scan, you can try to modify these two parameters. + + +There are also some global scan attributes which are configured by API :cpp:func:`esp_wifi_set_config()`, refer to :ref:`Station Basic Configuration `. + +Scan All APs on All Channels (Foreground) ++++++++++++++++++++++++++++++++++++++++++++++ + +Scenario: + +.. seqdiag:: + :caption: Foreground Scan of all Wi-Fi Channels + :align: center + + seqdiag foreground-scan-all-channels { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 160; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + APP_TASK -> WIFI_TASK [label="1.1 > Configure country code"]; + APP_TASK -> WIFI_TASK [label="1.2 > Scan configuration"]; + WIFI_TASK -> WIFI_TASK [label="2.1 > Scan channel 1"]; + WIFI_TASK -> WIFI_TASK [label="2.2 > Scan channel 2"]; + WIFI_TASK -> WIFI_TASK [label="..."]; + WIFI_TASK -> WIFI_TASK [label="2.x > Scan channel N"]; + EVENT_TASK <- WIFI_TASK [label="3.1 > WIFI_EVENT_SCAN_DONE"]; + APP_TASK <- EVENT_TASK [label="3.2 > WIFI_EVENT_SCAN_DONE"]; + } + + +The scenario above describes an all-channel, foreground scan. The foreground scan can only occur in station mode where the station does not connect to any AP. Whether it is a foreground or background scan is totally determined by the Wi-Fi driver, and cannot be configured by the application. + +Detailed scenario description: + +Scan Configuration Phase +************************** + + - s1.1: Call :cpp:func:`esp_wifi_set_country()` to set the country info if the default country info is not what you want. Refer to :ref:`Wi-Fi Country Code `. + - s1.2: Call :cpp:func:`esp_wifi_scan_start()` to configure the scan. To do so, you can refer to `Scan Configuration`_. Since this is an all-channel scan, just set the SSID/BSSID/channel to 0. + + +Wi-Fi Driver's Internal Scan Phase +************************************** + + - s2.1: The Wi-Fi driver switches to channel 1. In this case, the scan type is WIFI_SCAN_TYPE_ACTIVE, and a probe request is broadcasted. Otherwise, the Wi-Fi will wait for a beacon from the APs. The Wi-Fi driver will stay in channel 1 for some time. The dwell time is configured in min/max time, with the default value being 120 ms. + - s2.2: The Wi-Fi driver switches to channel 2 and performs the same operation as in step 2.1. + - s2.3: The Wi-Fi driver scans the last channel N, where N is determined by the country code which is configured in step 1.1. + +Scan-Done Event Handling Phase +********************************* + + - s3.1: When all channels are scanned, :ref:`wifi-event-scan-done` will arise. + - s3.2: The application's event callback function notifies the application task that :ref:`wifi-event-scan-done` is received. :cpp:func:`esp_wifi_scan_get_ap_num()` is called to get the number of APs that have been found in this scan. Then, it allocates enough entries and calls :cpp:func:`esp_wifi_scan_get_ap_records()` to get the AP records. Please note that the AP records in the Wi-Fi driver will be freed once :cpp:func:`esp_wifi_scan_get_ap_records()` is called. Do not call :cpp:func:`esp_wifi_scan_get_ap_records()` twice for a single scan-done event. If :cpp:func:`esp_wifi_scan_get_ap_records()` is not called when the scan-done event occurs, the AP records allocated by the Wi-Fi driver will not be freed. So, make sure you call :cpp:func:`esp_wifi_scan_get_ap_records()`, yet only once. + +Scan All APs on All Channels (Background) +++++++++++++++++++++++++++++++++++++++++++ + +Scenario: + +.. seqdiag:: + :caption: Background Scan of all Wi-Fi Channels + :align: center + + seqdiag background-scan-all-channels { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 160; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + APP_TASK -> WIFI_TASK [label="1.1 > Configure country code"]; + APP_TASK -> WIFI_TASK [label="1.2 > Scan configuration"]; + WIFI_TASK -> WIFI_TASK [label="2.1 > Scan channel 1"]; + WIFI_TASK -> WIFI_TASK [label="2.2 > Back to home channel H"]; + WIFI_TASK -> WIFI_TASK [label="2.3 > Scan channel 2"]; + WIFI_TASK -> WIFI_TASK [label="2.4 > Back to home channel H"]; + WIFI_TASK -> WIFI_TASK [label="..."]; + WIFI_TASK -> WIFI_TASK [label="2.x-1 > Scan channel N"]; + WIFI_TASK -> WIFI_TASK [label="2.x > Back to home channel H"]; + EVENT_TASK <- WIFI_TASK [label="3.1 > WIFI_EVENT_SCAN_DONE"]; + APP_TASK <- EVENT_TASK [label="3.2 > WIFI_EVENT_SCAN_DONE"]; + } + +The scenario above is an all-channel background scan. Compared to `Scan All APs on All Channels (Foreground)`_ , the difference in the all-channel background scan is that the Wi-Fi driver will scan the back-to-home channel for 30 ms before it switches to the next channel to give the Wi-Fi connection a chance to transmit/receive data. + +Scan for Specific AP on All Channels ++++++++++++++++++++++++++++++++++++++++ + +Scenario: + +.. seqdiag:: + :caption: Scan of specific Wi-Fi Channels + :align: center + + seqdiag scan-specific-channels { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 160; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + APP_TASK -> WIFI_TASK [label="1.1 > Configure country code"]; + APP_TASK -> WIFI_TASK [label="1.2 > Scan configuration"]; + WIFI_TASK -> WIFI_TASK [label="2.1 > Scan channel C1"]; + WIFI_TASK -> WIFI_TASK [label="2.2 > Scan channel C2"]; + WIFI_TASK -> WIFI_TASK [label="..."]; + WIFI_TASK -> WIFI_TASK [label="2.x > Scan channel CN, or the AP is found"]; + EVENT_TASK <- WIFI_TASK [label="3.1 > WIFI_EVENT_SCAN_DONE"]; + APP_TASK <- EVENT_TASK [label="3.2 > WIFI_EVENT_SCAN_DONE"]; + } + +This scan is similar to `Scan All APs on All Channels (Foreground)`_. The differences are: + + - s1.1: In step 1.2, the target AP will be configured to SSID/BSSID. + - s2.1 ~ s2.N: Each time the Wi-Fi driver scans an AP, it will check whether it is a target AP or not. If the scan is ``WIFI_FAST_SCAN`` scan and the target AP is found, then the scan-done event will arise and scanning will end; otherwise, the scan will continue. Please note that the first scanned channel may not be channel 1, because the Wi-Fi driver optimizes the scanning sequence. + +It is a possible situation that there are multiple APs that match the target AP info, e.g., two APs with the SSID of "ap" are scanned. In this case, if the scan is ``WIFI_FAST_SCAN``, then only the first scanned "ap" will be found. If the scan is ``WIFI_ALL_CHANNEL_SCAN``, both "ap" will be found and the station will connect the "ap" according to the configured strategy. Refer to :ref:`Station Basic Configuration `. + +You can scan a specific AP, or all of them, in any given channel. These two scenarios are very similar. + +.. _scan-in-wifi-connect: + +Scan in Wi-Fi Connect ++++++++++++++++++++++++++ + +When :cpp:func:`esp_wifi_connect()` is called, the Wi-Fi driver will try to scan the configured AP first. The scan in "Wi-Fi Connect" is the same as `Scan for Specific AP On All Channels`_, except that no scan-done event will be generated when the scan is completed. If the target AP is found, the Wi-Fi driver will start the Wi-Fi connection; otherwise, :ref:`wifi-event-sta-disconnected` will be generated. Refer to `Scan for Specific AP On All Channels`_. + +Scan in Blocked Mode +++++++++++++++++++++ + +If the block parameter of :cpp:func:`esp_wifi_scan_start()` is true, then the scan is a blocked one, and the application task will be blocked until the scan is done. The blocked scan is similar to an unblocked one, except that no scan-done event will arise when the blocked scan is completed. + +Parallel Scan ++++++++++++++ + +Two application tasks may call :cpp:func:`esp_wifi_scan_start()` at the same time, or the same application task calls :cpp:func:`esp_wifi_scan_start()` before it gets a scan-done event. Both scenarios can happen. **However, the Wi-Fi driver does not support multiple concurrent scans adequately. As a result, concurrent scans should be avoided.** Support for concurrent scan will be enhanced in future releases, as the {IDF_TARGET_NAME}'s Wi-Fi functionality improves continuously. + +.. _scan-when-wifi-is-connecting: + +Scan When Wi-Fi Is Connecting ++++++++++++++++++++++++++++++++ + +The :cpp:func:`esp_wifi_scan_start()` fails immediately if the Wi-Fi is connecting, because the connecting has higher priority than the scan. If scan fails because of connecting, the recommended strategy is to delay for some time and retry scan again. The scan will succeed once the connecting is completed. + +However, the retry/delay strategy may not work all the time. Considering the following scenarios: + +- The station is connecting a non-existing AP or it connects the existing AP with a wrong password, it always raises the event :ref:`wifi-event-sta-disconnected`. +- The application calls :cpp:func:`esp_wifi_connect()` to reconnect on receiving the disconnect event. +- Another application task, e.g., the console task, calls :cpp:func:`esp_wifi_scan_start()` to do scan, the scan always fails immediately because the station keeps connecting. +- When scan fails, the application simply delays for some time and retries the scan. + +In the above scenarios, the scan will never succeed because the connecting is in process. So if the application supports similar scenario, it needs to implement a better reconnection strategy. For example: + +- The application can choose to define a maximum continuous reconnection counter and stop reconnecting once the counter reaches the maximum. +- The application can choose to reconnect immediately in the first N continuous reconnection, then give a delay sometime and reconnect again. + +The application can define its own reconnection strategy to avoid the scan starve to death. Refer to :ref:`wifi-reconnect`. + +.. _wifi-station-connecting-scenario: + +{IDF_TARGET_NAME} Wi-Fi Station Connecting Scenario +---------------------------------------------------- + +This scenario depicts the case if only one target AP is found in the scan phase. For scenarios where more than one AP with the same SSID is found, refer to :ref:`wifi-station-connecting-when-multiple-aps-are-found`. + +Generally, the application can ignore the connecting process. Below is a brief introduction to the process for those who are really interested. + +Scenario: + +.. seqdiag:: + :caption: Wi-Fi Station Connecting Process + :align: center + + seqdiag station-connecting-process { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 160; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + EVENT_TASK [label = "Event\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + AP [label = "AP"]; + + === 1. Scan Phase === + WIFI_TASK -> WIFI_TASK [label="1.1 > Scan"]; + EVENT_TASK <- WIFI_TASK [label="1.2 > WIFI_EVENT_STA_DISCONNECTED"]; + === 2. Auth Phase === + WIFI_TASK -> AP [label="2.1 > Auth request"]; + EVENT_TASK <- WIFI_TASK [label="2.2 > WIFI_EVENT_STA_DISCONNECTED"]; + WIFI_TASK <- AP [label="2.3 > Auth response"]; + EVENT_TASK <- WIFI_TASK [label="2.4 > WIFI_EVENT_STA_DISCONNECTED"]; + === 3. Assoc Phase === + WIFI_TASK -> AP [label="3.1 > Assoc request"]; + EVENT_TASK <- WIFI_TASK [label="3.2 > WIFI_EVENT_STA_DISCONNECTED"]; + WIFI_TASK <- AP [label="3.3 > Assoc response"]; + EVENT_TASK <- WIFI_TASK [label="3.4 > WIFI_EVENT_STA_DISCONNECTED"]; + === 4. 4-way Handshake Phase === + EVENT_TASK <- WIFI_TASK [label="4.1 > WIFI_EVENT_STA_DISCONNECTED"]; + WIFI_TASK <- AP [label="4.2 > 1/4 EAPOL"]; + WIFI_TASK -> AP [label="4.3 > 2/4 EAPOL"]; + EVENT_TASK <- WIFI_TASK [label="4.4 > WIFI_EVENT_STA_DISCONNECTED"]; + WIFI_TASK <- AP [label="4.5 > 3/4 EAPOL"]; + WIFI_TASK -> AP [label="4.6 > 4/4 EAPOL"]; + EVENT_TASK <- WIFI_TASK [label="4.7 > WIFI_EVENT_STA_CONNECTED"]; + } + + +Scan Phase ++++++++++++++++++++++ + + - s1.1: The Wi-Fi driver begins scanning in "Wi-Fi Connect". Refer to :ref:`scan-in-wifi-connect` for more details. + - s1.2: If the scan fails to find the target AP, :ref:`wifi-event-sta-disconnected` will arise and the reason code could either be ``WIFI_REASON_NO_AP_FOUND`` or ``WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY`` or ``WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD`` or ``WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD`` depending of the Station's configuration. Refer to `Wi-Fi Reason Code`_. + +Auth Phase ++++++++++++++++++++++ + + - s2.1: The authentication request packet is sent and the auth timer is enabled. + - s2.2: If the authentication response packet is not received before the authentication timer times out, :ref:`wifi-event-sta-disconnected` will arise and the reason code will be ``WIFI_REASON_AUTH_EXPIRE``. Refer to `Wi-Fi Reason Code`_. + - s2.3: The auth-response packet is received and the auth-timer is stopped. + - s2.4: The AP rejects authentication in the response and :ref:`wifi-event-sta-disconnected` arises, while the reason code is ``WIFI_REASON_AUTH_FAIL`` or the reasons specified by the AP. Refer to `Wi-Fi Reason Code`_. + +Association Phase ++++++++++++++++++++++ + + - s3.1: The association request is sent and the association timer is enabled. + - s3.2: If the association response is not received before the association timer times out, :ref:`wifi-event-sta-disconnected` will arise and the reason code will be ``WIFI_REASON_DISASSOC_DUE_TO_INACTIVITY``. Refer to `Wi-Fi Reason Code`_. + - s3.3: The association response is received and the association timer is stopped. + - s3.4: The AP rejects the association in the response and :ref:`wifi-event-sta-disconnected` arises, while the reason code is the one specified in the association response. Refer to `Wi-Fi Reason Code`_. + + +Four-way Handshake Phase +++++++++++++++++++++++++++ + + - s4.1: The handshake timer is enabled, and the 1/4 EAPOL is not received before the handshake timer expires. :ref:`wifi-event-sta-disconnected` will arise and the reason code will be ``WIFI_REASON_HANDSHAKE_TIMEOUT``. Refer to `Wi-Fi Reason Code`_. + - s4.2: The 1/4 EAPOL is received. + - s4.3: The station replies 2/4 EAPOL. + - s4.4: If the 3/4 EAPOL is not received before the handshake timer expires, :ref:`wifi-event-sta-disconnected` will arise and the reason code will be ``WIFI_REASON_HANDSHAKE_TIMEOUT``. Refer to `Wi-Fi Reason Code`_. + - s4.5: The 3/4 EAPOL is received. + - s4.6: The station replies 4/4 EAPOL. + - s4.7: The station raises :ref:`wifi-event-sta-connected`. + + +.. _esp_wifi_reason_code: + +Wi-Fi Reason Code ++++++++++++++++++++++ + +The table below shows the reason-code defined in {IDF_TARGET_NAME}. The first column is the macro name defined in :component_file:`esp_wifi/include/esp_wifi_types.h`. The common prefix ``WIFI_REASON`` is removed, which means that ``UNSPECIFIED`` actually stands for ``WIFI_REASON_UNSPECIFIED`` and so on. The second column is the value of the reason. This reason value is same as defined in section 9.4.1.7 of IEEE 802.11-2020. (For more information, refer to the standard mentioned above.) The last column describes the reason. Reason-codes starting from 200 are Espressif defined reason-codes and are not part of IEEE 802.11-2020.\ + +Also note that REASON_NO_AP_FOUND_XXX codes are mentioned in increasing order of importance. So if a single AP has a combination of the above reasons for failure, the more important one will be reported. Additionally, if there are multiple APs that satisfy the identifying criteria and connecting to all of them fails for different reasons mentioned above, then the reason code reported is for the AP that failed connection due to the least important reason code, as it was the one closest to a successful connection.\ + +Following reason codes are renamed to their shorter form to wrap the table in page width. + +- TRANSMISSION_LINK_ESTABLISHMENT_FAILED : TX_LINK_EST_FAILED +- NO_AP_FOUND_W_COMPATIBLE_SECURITY : NO_AP_FOUND_SECURITY +- NO_AP_FOUND_IN_AUTHMODE_THRESHOLD : NO_AP_FOUND_AUTHMODE +- NO_AP_FOUND_IN_RSSI_THRESHOLD : NO_AP_FOUND_RSSI + +.. list-table:: + :header-rows: 1 + :widths: 41 10 49 + :class: longtable + + * - Reason code + - Value + - Description + * - UNSPECIFIED + - 1 + - Generally, it means an internal failure, e.g., the memory runs out, the internal TX fails, or the reason is received from the remote side. + * - AUTH_EXPIRE + - 2 + - The previous authentication is no longer valid. + + For the ESP station, this reason is reported when: + + - auth is timed out. + - the reason is received from the AP. + + For the ESP AP, this reason is reported when: + + - the AP has not received any packets from the station in the past five minutes. + - the AP is stopped by calling :cpp:func:`esp_wifi_stop()`. + - the station is de-authed by calling :cpp:func:`esp_wifi_deauth_sta()`. + * - AUTH_LEAVE + - 3 + - De-authenticated, because the sending station is leaving (or has left). + + For the ESP station, this reason is reported when: + + - it is received from the AP. + * - DISASSOC_DUE_TO_INACTIVITY + - 4 + - Disassociated due to inactivity. + + For the ESP station, this reason is reported when: + + - assoc is timed out. + - it is received from the AP. + + * - ASSOC_TOOMANY + - 5 + - Disassociated, because the AP is unable to handle all currently associated STAs at the same time. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + + For the ESP AP, this reason is reported when: + + - the stations associated with the AP reach the maximum number that the AP can support. + * - CLASS2_FRAME_FROM_NONAUTH_STA + - 6 + - Class-2 frame received from a non-authenticated STA. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + + For the ESP AP, this reason is reported when: + + - the AP receives a packet with data from a non-authenticated station. + * - CLASS3_FRAME_FROM_NONASSOC_STA + - 7 + - Class-3 frame received from a non-associated STA. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + + For the ESP AP, this reason is reported when: + + - the AP receives a packet with data from a non-associated station. + * - ASSOC_LEAVE + - 8 + - Disassociated, because the sending station is leaving (or has left) BSS. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + - the station is disconnected by :cpp:func:`esp_wifi_disconnect()` and other APIs. + * - ASSOC_NOT_AUTHED + - 9 + - station requesting (re)association is not authenticated by the responding STA. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + + For the ESP AP, this reason is reported when: + + - the AP receives packets with data from an associated, yet not authenticated, station. + * - DISASSOC_PWRCAP_BAD + - 10 + - Disassociated, because the information in the Power Capability element is unacceptable. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + * - DISASSOC_SUPCHAN_BAD + - 11 + - Disassociated, because the information in the Supported Channels element is unacceptable. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + * - BSS_TRANSITION_DISASSOC + - 12 + - AP wants us to move to another AP, sent as a part of BTM procedure. Please note that when station is sending BTM request and moving to another AP, ROAMING reason code will be reported instead of this. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + * - IE_INVALID + - 13 + - Invalid element, i.e., an element whose content does not meet the specifications of the Standard in frame formats clause. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + + For the ESP AP, this reason is reported when: + + - the AP parses a wrong WPA or RSN IE. + * - MIC_FAILURE + - 14 + - Message integrity code (MIC) failure. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + * - 4WAY_HANDSHAKE_TIMEOUT + - 15 + - Four-way handshake times out. For legacy reasons, in ESP this reason code is replaced with ``WIFI_REASON_HANDSHAKE_TIMEOUT``. + + For the ESP station, this reason is reported when: + + - the handshake times out. + - it is received from the AP. + * - GROUP_KEY_UPDATE_TIMEOUT + - 16 + - Group-Key Handshake times out. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + * - IE_IN_4WAY_DIFFERS + - 17 + - The element in the four-way handshake is different from the (Re-)Association Request/Probe and Response/Beacon frame. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + - the station finds that the four-way handshake IE differs from the IE in the (Re-)Association Request/Probe and Response/Beacon frame. + * - GROUP_CIPHER_INVALID + - 18 + - Invalid group cipher. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + * - PAIRWISE_CIPHER_INVALID + - 19 + - Invalid pairwise cipher. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + * - AKMP_INVALID + - 20 + - Invalid AKMP. + + For the ESP station, this reason is reported when: + - it is received from the AP. + * - UNSUPP_RSN_IE_VERSION + - 21 + - Unsupported RSNE version. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + * - INVALID_RSN_IE_CAP + - 22 + - Invalid RSNE capabilities. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + * - 802_1X_AUTH_FAILED + - 23 + - IEEE 802.1X. authentication failed. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + + For the ESP AP, this reason is reported when: + + - IEEE 802.1X. authentication fails. + * - CIPHER_SUITE_REJECTED + - 24 + - Cipher suite rejected due to security policies. + + For the ESP station, this reason is reported when: + + - it is received from the AP. + * - TDLS_PEER_UNREACHABLE + - 25 + - TDLS direct-link teardown due to TDLS peer STA unreachable via the TDLS direct link. + * - TDLS_UNSPECIFIED + - 26 + - TDLS direct-link teardown for unspecified reason. + * - SSP_REQUESTED_DISASSOC + - 27 + - Disassociated because session terminated by SSP request. + * - NO_SSP_ROAMING_AGREEMENT + - 28 + - Disassociated because of lack of SSP roaming agreement. + * - BAD_CIPHER_OR_AKM + - 29 + - Requested service rejected because of SSP cipher suite or AKM requirement. + * - NOT_AUTHORIZED_THIS_LOCATION + - 30 + - Requested service not authorized in this location. + * - SERVICE_CHANGE_PRECLUDES_TS + - 31 + - TS deleted because QoS AP lacks sufficient bandwidth for this QoS STA due to a change in BSS service characteristics or operational mode (e.g., an HT BSS change from 40 MHz channel to 20 MHz channel). + * - UNSPECIFIED_QOS + - 32 + - Disassociated for unspecified, QoS-related reason. + * - NOT_ENOUGH_BANDWIDTH + - 33 + - Disassociated because QoS AP lacks sufficient bandwidth for this QoS STA. + * - MISSING_ACKS + - 34 + - Disassociated because excessive number of frames need to be acknowledged, but are not acknowledged due to AP transmissions and/or poor channel conditions. + * - EXCEEDED_TXOP + - 35 + - Disassociated because STA is transmitting outside the limits of its TXOPs. + * - STA_LEAVING + - 36 + - Requesting STA is leaving the BSS (or resetting). + * - END_BA + - 37 + - Requesting STA is no longer using the stream or session. + * - UNKNOWN_BA + - 38 + - Requesting STA received frames using a mechanism for which a setup has not been completed. + * - TIMEOUT + - 39 + - Requested from peer STA due to timeout + * - Reserved + - 40 ~ 45 + - Reserved as per IEEE80211-2020 specifications. + * - PEER_INITIATED + - 46 + - In a Disassociation frame: Disassociated because authorized access limit reached. + * - AP_INITIATED + - 47 + - In a Disassociation frame: Disassociated due to external service requirements. + * - INVALID_FT_ACTION_FRAME_COUNT + - 48 + - Invalid FT Action frame count. + * - INVALID_PMKID + - 49 + - Invalid pairwise master key identifier (PMKID). + * - INVALID_MDE + - 50 + - Invalid MDE. + * - INVALID_FTE + - 51 + - Invalid FTE + * - TX_LINK_EST_FAILED + - 67 + - TRANSMISSION_LINK_ESTABLISHMENT_FAILED will be reported when Transmission link establishment in alternative channel failed. + * - ALTERATIVE_CHANNEL_OCCUPIED + - 68 + - The alternative channel is occupied. + * - BEACON_TIMEOUT + - 200 + - Espressif-specific Wi-Fi reason code: when the station loses N beacons continuously, it will disrupt the connection and report this reason. + * - NO_AP_FOUND + - 201 + - Espressif-specific Wi-Fi reason code: when the station fails to scan the target AP, this reason code will be reported. In case of security mismatch or station's configuration mismatch, new reason codes NO_AP_FOUND_XXX will be reported. + * - AUTH_FAIL + - 202 + - Espressif-specific Wi-Fi reason code: the authentication fails, but not because of a timeout. + * - ASSOC_FAIL + - 203 + - Espressif-specific Wi-Fi reason code: the association fails, but not because of DISASSOC_DUE_TO_INACTIVITY or ASSOC_TOOMANY. + * - HANDSHAKE_TIMEOUT + - 204 + - Espressif-specific Wi-Fi reason code: the handshake fails for the same reason as that in WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT. + * - CONNECTION_FAIL + - 205 + - Espressif-specific Wi-Fi reason code: the connection to the AP has failed. + * - AP_TSF_RESET + - 206 + - Espressif-specific Wi-Fi reason code: the disconnection happened due to AP's TSF reset. + * - ROAMING + - 207 + - Espressif-specific Wi-Fi reason code: the station is roaming to another AP, this reason code is just for info, station will automatically move to another AP. + * - ASSOC_COMEBACK_TIME_TOO_LONG + - 208 + - Espressif-specific Wi-Fi reason code: This reason code will be reported when Assoc comeback time in association response is too high. + * - SA_QUERY_TIMEOUT + - 209 + - Espressif-specific Wi-Fi reason code: This reason code will be reported when AP did not reply of SA query sent by ESP station. + * - NO_AP_FOUND_SECURITY + - 210 + - Espressif-specific Wi-Fi reason code: NO_AP_FOUND_W_COMPATIBLE_SECURITY will be reported if an AP that fits identifying criteria (e.g. ssid) is found but the connection is rejected due to incompatible security configuration. These situations could be: + + - The Access Point is offering WEP security, but our station's password is not WEP-compliant. + - The station is configured in Open mode; however, the Access Point is broadcasting in secure mode. + - The Access Point uses Enterprise security, but we haven't set up the corresponding enterprise configuration, and vice versa. + - SAE-PK is configured in the station configuration, but the Access Point does not support SAE-PK. + - SAE-H2E is configured in the station configuration; however, the AP only supports WPA3-PSK or WPA3-WPA2-PSK. + - The station is configured in secure mode (Password or Enterprise mode); however, an Open AP is found during the scan. + - SAE HnP is configured in the station configuration; however, the AP supports H2E only. + - H2E is disabled in the station configuration; however, the AP is WPA3-EXT-PSK, which requires H2E support. + - The Access Point requires PMF, but the station is not configured for PMF capable/required. + - The station configuration requires PMF, but the AP is not configured for PMF capable/required. + - The Access Point is using unsupported group management/pairwise ciphers. + - OWE is not enabled in the station configuration, but the discovered AP is using OWE only mode. + - The Access Point is broadcasting an invalid RSNXE in its beacons. + - The Access Point is in Independent BSS mode. + + * - NO_AP_FOUND_AUTHMODE + - 211 + - Espressif-specific Wi-Fi reason code: NO_AP_FOUND_IN_AUTHMODE_THRESHOLD will be reported if an AP that fit identifying criteria (e.g. ssid) is found but the authmode threhsold set in the wifi_config_t is not met. + * - NO_AP_FOUND_RSSI + - 212 + - Espressif-specific Wi-Fi reason code: NO_AP_FOUND_IN_RSSI_THRESHOLD will be reported if an AP that fits identifying criteria (e.g. ssid) is found but the RSSI threhsold set in the wifi_config_t is not met. + +Wi-Fi Reason code related to wrong password +++++++++++++++++++++++++++++++++++++++++++++++ + +The table below shows the Wi-Fi reason-code may related to wrong password. + +.. list-table:: + :header-rows: 1 + :widths: 5 10 40 + + * - Reason code + - Value + - Description + * - 4WAY_HANDSHAKE_TIMEOUT + - 15 + - Four-way handshake times out. Setting wrong password when STA connecting to an encrypted AP. + * - NO_AP_FOUND + - 201 + - This may related to wrong password in the two scenarios: + + - Setting password when STA connecting to an unencrypted AP. + - Does not set password when STA connecting to an encrypted AP. + * - HANDSHAKE_TIMEOUT + - 204 + - Four-way handshake fails. + +Wi-Fi Reason code related to low RSSI +++++++++++++++++++++++++++++++++++++++++++++++ + +The table below shows the Wi-Fi reason-code may related to low RSSI. + +.. list-table:: + :header-rows: 1 + :widths: 5 10 40 + + * - Reason code + - Value + - Description + * - NO_AP_FOUND_IN_RSSI_THRESHOLD + - 212 + - The station fails to scan the target AP due to low RSSI + * - HANDSHAKE_TIMEOUT + - 204 + - Four-way handshake fails. + +.. _wifi-station-connecting-when-multiple-aps-are-found: + +{IDF_TARGET_NAME} Wi-Fi Station Connecting When Multiple APs Are Found +---------------------------------------------------------------------- + +This scenario is similar as :ref:`wifi-station-connecting-scenario`. The difference is that the station will not raise the event :ref:`wifi-event-sta-disconnected` unless it fails to connect all of the found APs. + +.. _wifi-reconnect: + +Wi-Fi Reconnect +----------------- + +The station may disconnect due to many reasons, e.g., the connected AP is restarted. It is the application's responsibility to reconnect. The recommended reconnection strategy is to call :cpp:func:`esp_wifi_connect()` on receiving event :ref:`wifi-event-sta-disconnected`. + +Sometimes the application needs more complex reconnection strategy: + +- If the disconnect event is raised because the :cpp:func:`esp_wifi_disconnect()` is called, the application may not want to do the reconnection. +- If the :cpp:func:`esp_wifi_scan_start()` may be called at anytime, a better reconnection strategy is necessary. Refer to :ref:`scan-when-wifi-is-connecting`. + +Another thing that need to be considered is that the reconnection may not connect the same AP if there are more than one APs with the same SSID. The reconnection always select current best APs to connect. + +Wi-Fi Beacon Timeout +--------------------------- + +The beacon timeout mechanism is used by {IDF_TARGET_NAME} station to detect whether the AP is alive or not. If the station does not receive the beacon of the connected AP within the inactive time, the beacon timeout happens. The application can set inactive time via API :cpp:func:`esp_wifi_set_inactive_time()`. + +After the beacon times out, the station sends 5 probe requests to the AP. If still no probe response or beacon is received from AP, the station disconnects from the AP and raises the event :ref:`wifi-event-sta-disconnected`. + +It should be considered that the timer used for beacon timeout will be reset during the scanning process. It means that the scan process will affect the triggering of the event :ref:`wifi-event-sta-beacon-timeout`. diff --git a/docs/en/api-guides/wifi-driver/wifi-mac-protocols.rst b/docs/en/api-guides/wifi-driver/wifi-mac-protocols.rst new file mode 100644 index 0000000000..7714d3a667 --- /dev/null +++ b/docs/en/api-guides/wifi-driver/wifi-mac-protocols.rst @@ -0,0 +1,94 @@ +Wi-Fi MAC Protocols +========================== + +:link_to_translation:`zh_CN:[中文]` + +Wi-Fi HT20/40 +-------------- + +.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 or esp32c5 or esp32c6 + + {IDF_TARGET_NAME} supports Wi-Fi bandwidth HT20 or HT40 and does not support HT20/40 coexist. :cpp:func:`esp_wifi_set_bandwidth()` can be used to change the default bandwidth of station or AP. The default bandwidth for {IDF_TARGET_NAME} station and AP is HT40. + + In station mode, the actual bandwidth is firstly negotiated during the Wi-Fi connection. It is HT40 only if both the station and the connected AP support HT40, otherwise it is HT20. If the bandwidth of connected AP is changes, the actual bandwidth is negotiated again without Wi-Fi disconnecting. + + Similarly, in AP mode, the actual bandwidth is negotiated between AP and the stations that connect to the AP. It is HT40 if the AP and one of the stations support HT40, otherwise it is HT20. + + In station/AP coexist mode, the station/AP can configure HT20/40 separately. If both station and AP are negotiated to HT40, the HT40 channel should be the channel of station because the station always has higher priority than AP in {IDF_TARGET_NAME}. For example, the configured bandwidth of AP is HT40, the configured primary channel is 6, and the configured secondary channel is 10. The station is connected to an router whose primary channel is 6 and secondary channel is 2, then the actual channel of AP is changed to primary 6 and secondary 2 automatically. + + Theoretically, the HT40 can gain better throughput because the maximum raw physical (PHY) data rate for HT40 is 150 Mbps while it is 72 Mbps for HT20. However, if the device is used in some special environment, e.g., there are too many other Wi-Fi devices around the {IDF_TARGET_NAME} device, the performance of HT40 may be degraded. So if the applications need to support same or similar scenarios, it is recommended that the bandwidth is always configured to HT20. + +.. only:: esp32c5 + + .. note:: + + When operating in the 2.4 GHz + 5 GHz band mode (``WIFI_BAND_MODE_AUTO``), can use the function :cpp:func:`esp_wifi_set_bandwidths()` to configure the bandwidth for the 2.4 GHz and 5 GHz bands separately. + + +.. only:: esp32c2 + + {IDF_TARGET_NAME} supports Wi-Fi bandwidth HT20 and does not support Wi-Fi bandwidth HT40 or HT20/40 coexist. + +Wi-Fi QoS +------------------------- + +{IDF_TARGET_NAME} supports all the mandatory features required in WFA Wi-Fi QoS Certification. + +Four ACs (Access Category) are defined in Wi-Fi specification, and each AC has its own priority to access the Wi-Fi channel. Moreover, a map rule is defined to map the QoS priority of other protocol, e.g., 802.11D or TCP/IP precedence is mapped to Wi-Fi AC. + +The table below describes how the IP Precedences are mapped to Wi-Fi ACs in {IDF_TARGET_NAME}. It also indicates whether the AMPDU is supported for this AC. The table is sorted from high to low priority. That is to say, the AC_VO has the highest priority. + ++------------------+------------------------+-----------------+ +| IP Precedence | Wi-Fi AC | Support AMPDU? | ++==================+========================+=================+ +| 6, 7 | AC_VO (Voice) | No | ++------------------+------------------------+-----------------+ +| 4, 5 | AC_VI (Video) | Yes | ++------------------+------------------------+-----------------+ +| 3, 0 | AC_BE (Best Effort) | Yes | ++------------------+------------------------+-----------------+ +| 1, 2 | AC_BK (Background) | Yes | ++------------------+------------------------+-----------------+ + +The application can make use of the QoS feature by configuring the IP precedence via socket option IP_TOS. Here is an example to make the socket to use VI queue:: + + const int ip_precedence_vi = 4; + const int ip_precedence_offset = 5; + int priority = (ip_precedence_vi << ip_precedence_offset); + setsockopt(socket_id, IPPROTO_IP, IP_TOS, &priority, sizeof(priority)); + +Theoretically, the higher priority AC has better performance than the lower priority AC. However, it is not always true. Here are some suggestions about how to use the Wi-Fi QoS: + + - Some really important application traffic can be put into the AC_VO queue. But avoid using the AC_VO queue for heavy traffic, as it may impact the management frames which also use this queue. Eventually, it is worth noting that the AC_VO queue does not support AMPDU, and its performance with heavy traffic is no better than other queues. + - Avoid using more than two precedences supported by different AMPDUs, e.g., when socket A uses precedence 0, socket B uses precedence 1, and socket C uses precedence 2. This can be a bad design because it may need much more memory. To be specific, the Wi-Fi driver may generate a Block Ack session for each precedence and it needs more memory if the Block Ack session is set up. + + +Wi-Fi Aggregate MAC Protocol Data Unit (AMPDU) +---------------------------------------------------- + +{IDF_TARGET_NAME} supports both receiving and transmitting AMPDU, and the AMPDU can greatly improve the Wi-Fi throughput. + +Generally, the AMPDU should be enabled. Disabling AMPDU is usually for debugging purposes. + + +Wi-Fi AMSDU +------------------------- + +.. only:: not SOC_SPIRAM_SUPPORTED + + {IDF_TARGET_NAME} supports receiving AMSDU. + +.. only:: SOC_SPIRAM_SUPPORTED + + {IDF_TARGET_NAME} supports receiving and transmitting AMSDU. AMSDU TX is disabled by default, since enable AMSDU TX need more memory. Select :ref:`CONFIG_ESP_WIFI_AMSDU_TX_ENABLED` to enable AMSDU Tx feature, it depends on :ref:`CONFIG_SPIRAM`. + +Wi-Fi Fragment +------------------------- + +.. only:: not SOC_WIFI_TXOP_SUPPORT + + {IDF_TARGET_NAME} supports Wi-Fi receiving fragment, but does not support Wi-Fi transmitting fragment. + +.. only:: SOC_WIFI_TXOP_SUPPORT + + {IDF_TARGET_NAME} supports Wi-Fi receiving and transmitting fragment. diff --git a/docs/en/api-guides/wifi-driver/wifi-modes.rst b/docs/en/api-guides/wifi-driver/wifi-modes.rst new file mode 100644 index 0000000000..27e6db5668 --- /dev/null +++ b/docs/en/api-guides/wifi-driver/wifi-modes.rst @@ -0,0 +1,100 @@ +Wi-Fi Modes +=================================== + +:link_to_translation:`zh_CN:[中文]` + +.. _wifi-ap-general-scenario: + +{IDF_TARGET_NAME} Wi-Fi AP General Scenario +--------------------------------------------- + +Below is a "big scenario" which describes some small scenarios in AP mode: + + .. seqdiag:: + :caption: Sample Wi-Fi Event Scenarios in AP Mode + :align: center + + seqdiag sample-scenarios-soft-ap-mode { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 140; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + MAIN_TASK [label = "Main\ntask"]; + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + LwIP_TASK [label = "LwIP\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + === 1. Init Phase === + MAIN_TASK -> LwIP_TASK [label="1.1> Create / init LwIP"]; + MAIN_TASK -> EVENT_TASK [label="1.2> Create / init event"]; + MAIN_TASK -> WIFI_TASK [label="1.3> Create / init Wi-Fi"]; + MAIN_TASK -> APP_TASK [label="1.4> Create app task"]; + === 2. Configure Phase === + MAIN_TASK -> WIFI_TASK [label="2> Configure Wi-Fi"]; + === 3. Start Phase === + MAIN_TASK -> WIFI_TASK [label="3.1> Start Wi-Fi"]; + EVENT_TASK <- WIFI_TASK [label="3.2> WIFI_EVENT_AP_START"]; + APP_TASK <- EVENT_TASK [label="3.3> WIFI_EVENT_AP_START"]; + === 4. Connect Phase === + EVENT_TASK <- WIFI_TASK [label="4.1> WIFI_EVENT_AP_STACONNECTED"]; + APP_TASK <- EVENT_TASK [label="4.2> WIFI_EVENT_AP_STACONNECTED"]; + === 5. Disconnect Phase === + EVENT_TASK <- WIFI_TASK [label="5.1> WIFI_EVENT_AP_STADISCONNECTED"]; + APP_TASK <- EVENT_TASK [label="5.2> WIFI_EVENT_AP_STADISCONNECTED"]; + APP_TASK -> APP_TASK [label="5.3> disconnect handling"]; + === 6. Deinit Phase === + APP_TASK -> WIFI_TASK [label="6.1> Disconnect Wi-Fi"]; + APP_TASK -> WIFI_TASK [label="6.2> Stop Wi-Fi"]; + APP_TASK -> WIFI_TASK [label="6.3> Deinit Wi-Fi"]; + } + + +Wi-Fi Sniffer Mode +--------------------------- + +The Wi-Fi sniffer mode can be enabled by :cpp:func:`esp_wifi_set_promiscuous`. If the sniffer mode is enabled, the following packets **can** be dumped to the application: + + - 802.11 Management frame. + - 802.11 Data frame, including MPDU, AMPDU, and AMSDU. + - 802.11 MIMO frame, for MIMO frame, the sniffer only dumps the length of the frame. + - 802.11 Control frame. + - 802.11 CRC error frame. + +The following packets will **NOT** be dumped to the application: + + - Other 802.11 error frames. + +For frames that the sniffer **can** dump, the application can additionally decide which specific type of packets can be filtered to the application by using :cpp:func:`esp_wifi_set_promiscuous_filter()` and :cpp:func:`esp_wifi_set_promiscuous_ctrl_filter()`. By default, it will filter all 802.11 data and management frames to the application. If you want to filter the 802.11 control frames, the filter parameter in :cpp:func:`esp_wifi_set_promiscuous_filter()` should include `WIFI_PROMIS_FILTER_MASK_CTRL` type, and if you want to differentiate control frames further, then call :cpp:func:`esp_wifi_set_promiscuous_ctrl_filter()`. + +The Wi-Fi sniffer mode can be enabled in the Wi-Fi mode of :cpp:enumerator:`WIFI_MODE_NULL`, :cpp:enumerator:`WIFI_MODE_STA`, :cpp:enumerator:`WIFI_MODE_AP`, or :cpp:enumerator:`WIFI_MODE_APSTA`. In other words, the sniffer mode is active when the station is connected to the AP, or when the AP has a Wi-Fi connection. Please note that the sniffer has a **great impact** on the throughput of the station or AP Wi-Fi connection. Generally, the sniffer should be enabled **only if** the station/AP Wi-Fi connection does not experience heavy traffic. + +Another noteworthy issue about the sniffer is the callback :cpp:type:`wifi_promiscuous_cb_t`. The callback will be called directly in the Wi-Fi driver task, so if the application has a lot of work to do for each filtered packet, the recommendation is to post an event to the application task in the callback and defer the real work to the application task. + + +.. only:: SOC_WIFI_NAN_SUPPORT + + Wi-Fi Aware\ :sup:`TM` (NAN) + ---------------------------- + + Wi-Fi Aware\ :sup:`TM` or NAN (Neighbor Awareness Networking) is a protocol that allows Wi-Fi devices to discover services in their proximity. NAN uses direct device-to-device communication and does not require any Internet or AP connection. + + Multiple NAN devices in the vicinity will form a NAN cluster which allows them to communicate with each other. NAN devices in a cluster synchronise their clocks and listen to each other periodically on Channel 6. Devices can advertise (Publish) or seek for (Subscribe) services within their NAN Cluster using Service Discovery protocols. Matching of services is done by service name and optionally matching filters. Once a Subscriber gets a match with a Publisher, it can either send a message (Follow-up) or establish a datapath (NDP) with the Publisher. After NDP is setup both devices will obtain an IPv6 address and can use it for communication. + + Please note that NAN Datapath security is not supported i.e., the data packets will go out unencrypted. NAN uses a separate interface for Discovery and Datapath, which is other than that used for STA and AP. NAN operates in standalone mode, which means co-existence with STA or AP interface is not supported. + + Refer to ESP-IDF examples :idf_file:`examples/wifi/wifi_aware/nan_publisher/README.md` and :idf_file:`examples/wifi/wifi_aware/nan_subscriber/README.md` to setup a NAN Publisher and Subscriber. + + + Unsynchronized Service Discovery (USD) + -------------------------------------------- + + Unsynchronized Service Discovery (USD) is a mechanism for devices to discover the services that have been made discoverable on new devices that enter the RF environment, without requiring synchronization between the devices. + + USD uses Service Info field in the SDEA of a Publish and Follow-up message to convey the service specific information. + + Refer to ESP-IDF examples :idf_file:`examples/wifi/wifi_aware/usd_publisher/README.md` and :idf_file:`examples/wifi/wifi_aware/usd_subscriber/README.md` to setup a NAN-USD Publisher and Subscriber. diff --git a/docs/en/api-guides/wifi-driver/wifi-performance-and-power-save.rst b/docs/en/api-guides/wifi-driver/wifi-performance-and-power-save.rst new file mode 100644 index 0000000000..21ae29644a --- /dev/null +++ b/docs/en/api-guides/wifi-driver/wifi-performance-and-power-save.rst @@ -0,0 +1,1647 @@ +Wi-Fi Performance and Power Save +====================================== + +:link_to_translation:`zh_CN:[中文]` + +.. _wifi-buffer-usage: + +Wi-Fi Buffer Usage +-------------------------- + +This section is only about the dynamic buffer configuration. + +Why Buffer Configuration Is Important ++++++++++++++++++++++++++++++++++++++++ + +In order to get a high-performance system, consider the memory usage/configuration carefully for the following reasons: + + - the available memory in {IDF_TARGET_NAME} is limited. + - currently, the default type of buffer in LwIP and Wi-Fi drivers is "dynamic", **which means that both the LwIP and Wi-Fi share memory with the application**. Programmers should always keep this in mind; otherwise, they will face a memory issue, such as "running out of heap memory". + - it is very dangerous to run out of heap memory, as this will cause {IDF_TARGET_NAME} an "undefined behavior". Thus, enough heap memory should be reserved for the application, so that it never runs out of it. + - the Wi-Fi throughput heavily depends on memory-related configurations, such as the TCP window size and Wi-Fi RX/TX dynamic buffer number. + - the peak heap memory that the {IDF_TARGET_NAME} LwIP/Wi-Fi may consume depends on a number of factors, such as the maximum TCP/UDP connections that the application may have. + - the total memory that the application requires is also an important factor when considering memory configuration. + +Due to these reasons, there is not a good-for-all application configuration. Rather, it is recommended to consider memory configurations separately for every different application. + +Dynamic vs. Static Buffer +++++++++++++++++++++++++++++++ + +The default type of buffer in Wi-Fi drivers is "dynamic". Most of the time the dynamic buffer can significantly save memory. However, it makes the application programming a little more difficult, because in this case the application needs to consider memory usage in Wi-Fi. + +lwIP also allocates buffers at the TCP/IP layer, and this buffer allocation is also dynamic. See :ref:`lwIP documentation section about memory use and performance `. + +Peak Wi-Fi Dynamic Buffer +++++++++++++++++++++++++++++++ + +The Wi-Fi driver supports several types of buffer (refer to :ref:`wifi-buffer-configure`). However, this section is about the usage of the dynamic Wi-Fi buffer only. +The peak heap memory that Wi-Fi consumes is the **theoretically-maximum memory** that the Wi-Fi driver consumes. Generally, the peak memory depends on: + +- :math:`b_{rx}` the number of dynamic RX buffers that are configured +- :math:`b_{tx}` the number of dynamic TX buffers that are configured +- :math:`m_{rx}` the maximum packet size that the Wi-Fi driver can receive +- :math:`m_{tx}` the maximum packet size that the Wi-Fi driver can send + +So, the peak memory that the Wi-Fi driver consumes (:math:`p`) can be calculated with the following formula: + +.. math:: + + p = (b_{rx} * m_{rx}) + (b_{tx} * m_{tx}) + +Generally, the dynamic TX long buffers and dynamic TX long long buffers can be ignored, because they are management frames which only have a small impact on the system. + + +{IDF_TARGET_NAME} Wi-Fi Throughput +----------------------------------- + +The table below shows the best throughput results gained in Espressif's lab and in a shielded box. + +.. only:: esp32 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 10 25 + + * - Type/Throughput + - Air In Lab + - Shield-box + - Test Tool + - IDF Version (commit ID) + * - Raw 802.11 Packet RX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - Raw 802.11 Packet TX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - UDP RX + - 30 MBit/s + - 85 MBit/s + - iperf example + - 15575346 + * - UDP TX + - 30 MBit/s + - 75 MBit/s + - iperf example + - 15575346 + * - TCP RX + - 20 MBit/s + - 65 MBit/s + - iperf example + - 15575346 + * - TCP TX + - 20 MBit/s + - 75 MBit/s + - iperf example + - 15575346 + + When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32`. + +.. only:: esp32s2 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 10 25 + + * - Type/Throughput + - Air In Lab + - Shield-box + - Test Tool + - IDF Version (commit ID) + * - Raw 802.11 Packet RX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - Raw 802.11 Packet TX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - UDP RX + - 30 MBit/s + - 70 MBit/s + - iperf example + - 15575346 + * - UDP TX + - 30 MBit/s + - 50 MBit/s + - iperf example + - 15575346 + * - TCP RX + - 20 MBit/s + - 32 MBit/s + - iperf example + - 15575346 + * - TCP TX + - 20 MBit/s + - 37 MBit/s + - iperf example + - 15575346 + + When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32s2`. + +.. only:: esp32c3 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - Type/Throughput + - Air In Lab + - Shield-box + - Test Tool + - IDF Version (commit ID) + * - Raw 802.11 Packet RX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - Raw 802.11 Packet TX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - UDP RX + - 30 MBit/s + - 50 MBit/s + - iperf example + - 15575346 + * - UDP TX + - 30 MBit/s + - 40 MBit/s + - iperf example + - 15575346 + * - TCP RX + - 20 MBit/s + - 35 MBit/s + - iperf example + - 15575346 + * - TCP TX + - 20 MBit/s + - 37 MBit/s + - iperf example + - 15575346 + + When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c3`. + +.. only:: esp32c5 + + - 2.4 GHz band + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - Type/Throughput + - Air In Lab + - Shield-box + - Test Tool + - IDF Version (commit ID) + * - Raw 802.11 Packet RX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - Raw 802.11 Packet TX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - UDP RX + - 30 MBit/s + - 68 MBit/s + - iperf example + - 7ff0a07d + * - UDP TX + - 30 MBit/s + - 63 MBit/s + - iperf example + - 7ff0a07d + * - TCP RX + - 20 MBit/s + - 59 MBit/s + - iperf example + - 7ff0a07d + * - TCP TX + - 20 MBit/s + - 49 MBit/s + - iperf example + - 7ff0a07d + + - 5 GHz band + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - Type/Throughput + - Air In Lab + - Shield-box + - Test Tool + - IDF Version (commit ID) + * - Raw 802.11 Packet RX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - Raw 802.11 Packet TX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - UDP RX + - 30 MBit/s + - 71 MBit/s + - iperf example + - 7ff0a07d + * - UDP TX + - 30 MBit/s + - 64 MBit/s + - iperf example + - 7ff0a07d + * - TCP RX + - 20 MBit/s + - 61 MBit/s + - iperf example + - 7ff0a07d + * - TCP TX + - 20 MBit/s + - 50 MBit/s + - iperf example + - 7ff0a07d + + When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c5`. + +.. only:: esp32c6 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - Type/Throughput + - Air In Lab + - Shield-box + - Test Tool + - IDF Version (commit ID) + * - Raw 802.11 Packet RX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - Raw 802.11 Packet TX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - UDP RX + - 30 MBit/s + - 63 MBit/s + - iperf example + - 7ff0a07d + * - UDP TX + - 30 MBit/s + - 51 MBit/s + - iperf example + - 7ff0a07d + * - TCP RX + - 20 MBit/s + - 46 MBit/s + - iperf example + - 7ff0a07d + * - TCP TX + - 20 MBit/s + - 43 MBit/s + - iperf example + - 7ff0a07d + + When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c6`. + +.. only:: esp32c61 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - Type/Throughput + - Air In Lab + - Shield-box + - Test Tool + - IDF Version (commit ID) + * - Raw 802.11 Packet RX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - Raw 802.11 Packet TX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - UDP RX + - 30 MBit/s + - 68 MBit/s + - iperf example + - 7ff0a07d + * - UDP TX + - 30 MBit/s + - 53 MBit/s + - iperf example + - 7ff0a07d + * - TCP RX + - 20 MBit/s + - 45 MBit/s + - iperf example + - 7ff0a07d + * - TCP TX + - 20 MBit/s + - 37 MBit/s + - iperf example + - 7ff0a07d + + When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c61`. + +.. only:: esp32s3 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - Type/Throughput + - Air In Lab + - Shield-box + - Test Tool + - IDF Version (commit ID) + * - Raw 802.11 Packet RX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - Raw 802.11 Packet TX + - N/A + - **130 MBit/s** + - Internal tool + - NA + * - UDP RX + - 30 MBit/s + - 88 MBit/s + - iperf example + - 15575346 + * - UDP TX + - 30 MBit/s + - 98 MBit/s + - iperf example + - 15575346 + * - TCP RX + - 20 MBit/s + - 73 MBit/s + - iperf example + - 15575346 + * - TCP TX + - 20 MBit/s + - 83 MBit/s + - iperf example + - 15575346 + + When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32s3`. + + +.. _How-to-improve-Wi-Fi-performance: + +How to Improve Wi-Fi Performance +---------------------------------- + +The performance of {IDF_TARGET_NAME} Wi-Fi is affected by many parameters, and there are mutual constraints between each parameter. A proper configuration cannot only improve performance, but also increase available memory for applications and improve stability. + +This section briefly explains the operating mode of the Wi-Fi/LwIP protocol stack and the role of each parameter. It also gives several recommended configuration ranks to help choose the appropriate rank according to the usage scenario. + +Protocol Stack Operation Mode +++++++++++++++++++++++++++++++++++ + +.. figure:: ../../../_static/api-guides-WiFi-driver-how-to-improve-WiFi-performance.png + :align: center + + {IDF_TARGET_NAME} datapath + +The {IDF_TARGET_NAME} protocol stack is divided into four layers: Application, LwIP, Wi-Fi, and Hardware. + + - During receiving, hardware puts the received packet into DMA buffer, and then transfers it into the RX buffer of Wi-Fi and LwIP in turn for related protocol processing, and finally to the application layer. The Wi-Fi RX buffer and the LwIP RX buffer shares the same buffer by default. In other words, the Wi-Fi forwards the packet to LwIP by reference by default. + + - During sending, the application copies the messages to be sent into the TX buffer of the LwIP layer for TCP/IP encapsulation. The messages will then be passed to the TX buffer of the Wi-Fi layer for MAC encapsulation and wait to be sent. + +Parameters +++++++++++++++ + +Increasing the size or number of the buffers mentioned above properly can improve Wi-Fi performance. Meanwhile, it will reduce available memory to the application. The following is an introduction to the parameters that users need to configure: + +**RX direction:** + + - :ref:`CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM` + This parameter indicates the number of DMA buffer at the hardware layer. Increasing this parameter will increase the sender's one-time receiving throughput, thereby improving the Wi-Fi protocol stack ability to handle burst traffic. + + - :ref:`CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM` + This parameter indicates the number of RX buffer in the Wi-Fi layer. Increasing this parameter will improve the performance of packet reception. This parameter needs to match the RX buffer size of the LwIP layer. + + - :ref:`CONFIG_ESP_WIFI_RX_BA_WIN` + This parameter indicates the size of the AMPDU BA Window at the receiving end. This parameter should be configured to the smaller value between twice of :ref:`CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM` and :ref:`CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM`. + + - :ref:`CONFIG_LWIP_TCP_WND_DEFAULT` + This parameter represents the RX buffer size of the LwIP layer for each TCP stream. Its value should be configured to the value of WIFI_DYNAMIC_RX_BUFFER_NUM (KB) to reach a high and stable performance. Meanwhile, in case of multiple streams, this value needs to be reduced proportionally. + +**TX direction:** + + - :ref:`CONFIG_ESP_WIFI_TX_BUFFER` + This parameter indicates the type of TX buffer, it is recommended to configure it as a dynamic buffer, which can make full use of memory. + + - :ref:`CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM` + This parameter indicates the number of TX buffer on the Wi-Fi layer. Increasing this parameter will improve the performance of packet sending. The parameter value needs to match the TX buffer size of the LwIP layer. + + - :ref:`CONFIG_LWIP_TCP_SND_BUF_DEFAULT` + This parameter represents the TX buffer size of the LwIP layer for each TCP stream. Its value should be configured to the value of WIFI_DYNAMIC_TX_BUFFER_NUM (KB) to reach a high and stable performance. In case of multiple streams, this value needs to be reduced proportionally. + +**Throughput optimization by placing code in IRAM:** + +.. only:: esp32 or esp32s2 + + - :ref:`CONFIG_ESP_WIFI_IRAM_OPT` + If this option is enabled, some Wi-Fi functions are moved to IRAM, improving throughput. This increases IRAM usage by 15 kB. + + - :ref:`CONFIG_ESP_WIFI_RX_IRAM_OPT` + If this option is enabled, some Wi-Fi RX functions are moved to IRAM, improving throughput. This increases IRAM usage by 16 kB. + + - :ref:`CONFIG_LWIP_IRAM_OPTIMIZATION` + If this option is enabled, some LwIP functions are moved to IRAM, improving throughput. This increases IRAM usage by 13 kB. + +.. only:: esp32c6 + + - :ref:`CONFIG_ESP_WIFI_IRAM_OPT` + If this option is enabled, some Wi-Fi functions are moved to IRAM, improving throughput. This increases IRAM usage by 13 kB. + + - :ref:`CONFIG_ESP_WIFI_RX_IRAM_OPT` + If this option is enabled, some Wi-Fi RX functions are moved to IRAM, improving throughput. This increases IRAM usage by 7 kB. + + - :ref:`CONFIG_LWIP_IRAM_OPTIMIZATION` + If this option is enabled, some LwIP functions are moved to IRAM, improving throughput. This increases IRAM usage by 14 kB. + +.. only:: esp32s2 + + **CACHE:** + + - :ref:`CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE` + Configure the size of the instruction Cache. + + - :ref:`CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_SIZE` + Configure the width of the instruction Cache bus. + +.. only:: esp32s3 + + **CACHE:** + + - :ref:`CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE` + Configure the size of the instruction Cache. + + - :ref:`CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE` + Configure the size of the instruction Cache bus. + + - :ref:`CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS` + Configure the associated ways of the instruction Cache. + + - :ref:`CONFIG_ESP32S3_DATA_CACHE_SIZE` + Configure the size of the Data Cache. + + - :ref:`CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE` + Configure the line size of the Data Cache. + + - :ref:`CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS` + Configure the associated ways of the Data Cache. + +.. note:: + The buffer size mentioned above is fixed as 1.6 KB. + +How to Configure Parameters +++++++++++++++++++++++++++++ + +The memory of {IDF_TARGET_NAME} is shared by protocol stack and applications. + +Here, several configuration ranks are given. In most cases, the user should select a suitable rank for parameter configuration according to the size of the memory occupied by the application. + +The parameters not mentioned in the following table should be set to the default. + +.. only:: esp32 + + .. list-table:: + :header-rows: 1 + :widths: 10 5 5 10 5 5 10 5 + + * - Rank + - Iperf + - TX prior + - High-performance + - RX prior + - Default + - Memory saving + - Minimum + * - Available memory (KB) + - 37.1 + - 113.8 + - 123.3 + - 145.5 + - 144.5 + - 170.2 + - 185.2 + * - WIFI_STATIC_RX_BUFFER_NUM + - 16 + - 6 + - 6 + - 6 + - 6 + - 6 + - 4 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 64 + - 16 + - 24 + - 34 + - 20 + - 12 + - 8 + * - WIFI_DYNAMIC_TX_BUFFER_NUM + - 64 + - 28 + - 24 + - 18 + - 20 + - 12 + - 8 + * - WIFI_RX_BA_WIN + - 32 + - 8 + - 12 + - 12 + - 10 + - 6 + - Disable + * - TCP_SND_BUF_DEFAULT (KB) + - 65 + - 28 + - 24 + - 18 + - 20 + - 12 + - 8 + * - TCP_WND_DEFAULT (KB) + - 65 + - 16 + - 24 + - 34 + - 20 + - 12 + - 8 + * - WIFI_IRAM_OPT + - ENABLE + - ENABLE + - ENABLE + - ENABLE + - ENABLE + - ENABLE + - ENABLE + * - WIFI_RX_IRAM_OPT + - ENABLE + - ENABLE + - ENABLE + - ENABLE + - ENABLE + - ENABLE + - ENABLE + * - LWIP_IRAM_OPTIMIZATION + - ENABLE + - ENABLE + - ENABLE + - ENABLE + - ENABLE + - ENABLE + - ENABLE + * - TCP TX throughput (Mbit/s) + - 74.6 + - 50.8 + - 46.5 + - 39.9 + - 44.2 + - 33.8 + - 25.6 + * - TCP RX throughput (Mbit/s) + - 63.6 + - 35.5 + - 42.3 + - 48.5 + - 40.5 + - 30.1 + - 27.8 + * - UDP TX throughput (Mbit/s) + - 76.2 + - 75.1 + - 74.1 + - 72.4 + - 69.6 + - 64.1 + - 36.5 + * - UDP RX throughput (Mbit/s) + - 83.1 + - 66.3 + - 75.1 + - 75.6 + - 73.1 + - 65.3 + - 54.7 + + +.. only:: esp32s2 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 10 10 10 + + * - Rank + - Iperf + - High-performance + - Default + - Memory saving + - Minimum + * - Available memory (KB) + - 4.1 + - 24.2 + - 78.4 + - 86.5 + - 116.4 + * - WIFI_STATIC_RX_BUFFER_NUM + - 8 + - 6 + - 6 + - 4 + - 3 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 24 + - 18 + - 12 + - 8 + - 6 + * - WIFI_DYNAMIC_TX_BUFFER_NUM + - 24 + - 18 + - 12 + - 8 + - 6 + * - WIFI_RX_BA_WIN + - 12 + - 9 + - 6 + - 4 + - 3 + * - TCP_SND_BUF_DEFAULT (KB) + - 24 + - 18 + - 12 + - 8 + - 6 + * - TCP_WND_DEFAULT (KB) + - 24 + - 18 + - 12 + - 8 + - 6 + * - WIFI_IRAM_OPT + - ENABLE + - ENABLE + - ENABLE + - ENABLE + - DISABLE + * - WIFI_RX_IRAM_OPT + - ENABLE + - ENABLE + - ENABLE + - DISABLE + - DISABLE + * - LWIP_IRAM_OPTIMIZATION + - ENABLE + - ENABLE + - DISABLE + - DISABLE + - DISABLE + * - INSTRUCTION_CACHE + - 16 + - 16 + - 16 + - 16 + - 8 + * - INSTRUCTION_CACHE_LINE + - 16 + - 16 + - 16 + - 16 + - 16 + * - TCP TX throughput (Mbit/s) + - 37.6 + - 33.1 + - 22.5 + - 12.2 + - 5.5 + * - TCP RX throughput (Mbit/s) + - 31.5 + - 28.1 + - 20.1 + - 13.1 + - 7.2 + * - UDP TX throughput (Mbit/s) + - 58.1 + - 57.3 + - 28.1 + - 22.6 + - 8.7 + * - UDP RX throughput (Mbit/s) + - 78.1 + - 66.7 + - 65.3 + - 53.8 + - 28.5 + +.. only:: esp32c3 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 + + * - Rank + - Iperf + - Default + - Minimum + * - Available memory (KB) + - 59 + - 160 + - 180 + * - WIFI_STATIC_RX_BUFFER_NUM + - 20 + - 8 + - 3 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 40 + - 16 + - 6 + * - WIFI_DYNAMIC_TX_BUFFER_NUM + - 40 + - 16 + - 6 + * - WIFI_RX_BA_WIN + - 32 + - 16 + - 6 + * - TCP_SND_BUF_DEFAULT (KB) + - 40 + - 16 + - 6 + * - TCP_WND_DEFAULT (KB) + - 40 + - 16 + - 6 + * - LWIP_IRAM_OPTIMIZATION + - ENABLE + - ENABLE + - DISABLE + * - TCP TX throughput (Mbit/s) + - 38.1 + - 27.2 + - 20.4 + * - TCP RX throughput (Mbit/s) + - 35.3 + - 24.2 + - 17.4 + * - UDP TX throughput (Mbit/s) + - 40.6 + - 38.9 + - 34.1 + * - UDP RX throughput (Mbit/s) + - 52.4 + - 44.5 + - 44.2 + +.. only:: esp32c6 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 + + * - Rank + - Iperf + - Default + - Minimum + * - Available memory (KB) + - 223 + - 276 + - 299 + * - WIFI_STATIC_RX_BUFFER_NUM + - 20 + - 8 + - 3 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 40 + - 16 + - 6 + * - WIFI_DYNAMIC_TX_BUFFER_NUM + - 40 + - 16 + - 6 + * - WIFI_RX_BA_WIN + - 32 + - 16 + - 6 + * - TCP_SND_BUF_DEFAULT (KB) + - 40 + - 16 + - 6 + * - TCP_WND_DEFAULT (KB) + - 40 + - 16 + - 6 + * - LWIP_IRAM_OPTIMIZATION + - ENABLE + - ENABLE + - DISABLE + * - TCP TX throughput (Mbit/s) + - 30.5 + - 25.9 + - 16.4 + * - TCP RX throughput (Mbit/s) + - 27.8 + - 21.6 + - 14.3 + * - UDP TX throughput (Mbit/s) + - 37.8 + - 36.1 + - 34.6 + * - UDP RX throughput (Mbit/s) + - 41.5 + - 36.8 + - 36.7 + +.. only:: esp32c2 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 + + * - Rank + - Iperf + - Default + - Minimum + * - Available memory (KB) + - 37 + - 56 + - 84 + * - WIFI_STATIC_RX_BUFFER_NUM + - 14 + - 7 + - 3 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 18 + - 14 + - 6 + * - WIFI_DYNAMIC_TX_BUFFER_NUM + - 18 + - 14 + - 6 + * - WIFI_RX_BA_WIN + - 16 + - 12 + - 6 + * - TCP_SND_BUF_DEFAULT (KB) + - 18 + - 14 + - 6 + * - TCP_WND_DEFAULT (KB) + - 18 + - 14 + - 6 + * - LWIP_IRAM_OPTIMIZATION + - ENABLE + - ENABLE + - DISABLE + * - TCP TX throughput (Mbit/s) + - 21.6 + - 21.4 + - 14.3 + * - TCP RX throughput (Mbit/s) + - 19.1 + - 17.9 + - 12.4 + * - UDP TX throughput (Mbit/s) + - 26.4 + - 26.3 + - 25.0 + * - UDP RX throughput (Mbit/s) + - 32.3 + - 31.5 + - 27.7 + +.. only:: esp32s3 + + .. list-table:: + :header-rows: 1 + :widths: 25 20 25 25 + + * - Rank + - Iperf + - Default + - Minimum + * - Available memory (KB) + - 133.9 + - 183.9 + - 273.6 + * - WIFI_STATIC_RX_BUFFER_NUM + - 24 + - 8 + - 3 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 64 + - 32 + - 6 + * - WIFI_DYNAMIC_TX_BUFFER_NUM + - 64 + - 32 + - 6 + * - WIFI_RX_BA_WIN + - 32 + - 16 + - 6 + * - TCP_SND_BUF_DEFAULT (KB) + - 64 + - 32 + - 6 + * - TCP_WND_DEFAULT (KB) + - 64 + - 32 + - 6 + * - WIFI_IRAM_OPT + - ENABLE + - ENABLE + - ENABLE + * - WIFI_RX_IRAM_OPT + - ENABLE + - ENABLE + - ENABLE + * - LWIP_IRAM_OPTIMIZATION + - ENABLE + - ENABLE + - DISABLE + * - INSTRUCTION_CACHE + - 32 + - 32 + - 16 + * - INSTRUCTION_CACHE_LINE + - 32 + - 32 + - 32 + * - INSTRUCTION_CACHE_WAYS + - 8 + - 8 + - 4 + * - TCP TX throughput (Mbit/s) + - 83.93 + - 64.28 + - 23.17 + * - TCP RX throughput (Mbit/s) + - 73.98 + - 60.39 + - 18.11 + * - UDP TX throughput (Mbit/s) + - 98.69 + - 96.28 + - 48.78 + * - UDP RX throughput (Mbit/s) + - 88.58 + - 86.57 + - 59.45 + +.. only:: esp32 or esp32s3 + + .. note:: + The test was performed with a single stream in a shielded box using an ASUS RT-N66U router. + {IDF_TARGET_NAME}'s CPU is dual core with 240 MHz. {IDF_TARGET_NAME}'s flash is in QIO mode with 80 MHz. + +.. only:: esp32s2 + + .. note:: + The test was performed with a single stream in a shielded box using an ASUS RT-N66U router. + {IDF_TARGET_NAME}'s CPU is single core with 240 MHz. {IDF_TARGET_NAME}'s flash is in QIO mode with 80 MHz. + +.. only:: esp32c3 + + .. note:: + The test was performed with a single stream in a shielded box using an ASUS RT-N66U router. + {IDF_TARGET_NAME}'s CPU is single core with 160 MHz. {IDF_TARGET_NAME}'s flash is in QIO mode with 80 MHz. + +.. only:: esp32c6 + + .. note:: + The test was performed with a single stream in a shielded box using an XIAOMI AX-6000 router. + {IDF_TARGET_NAME}'s CPU is single core with 160 MHz. {IDF_TARGET_NAME}'s flash is in QIO mode with 80 MHz. + +.. only:: esp32c2 + + .. note:: + The test was performed with a single stream in a shielded box using an Redmi RM2100 router. + {IDF_TARGET_NAME}'s CPU is single core with 120 MHz. {IDF_TARGET_NAME}'s flash is in QIO mode with 60 MHz. + +.. only:: esp32 + + **Ranks:** + + - **Iperf rank** + {IDF_TARGET_NAME} extreme performance rank used to test extreme performance. + + - **High-performance rank** + The {IDF_TARGET_NAME}'s high-performance configuration rank, suitable for scenarios where the application occupies less memory and has high-performance requirements. In this rank, users can choose to use the RX prior rank or the TX prior rank according to the usage scenario. + + - **Default rank** + {IDF_TARGET_NAME}'s default configuration rank, the available memory, and performance are in balance. + + - **Memory saving rank** + This rank is suitable for scenarios where the application requires a large amount of memory, and the transceiver performance will be reduced in this rank. + + - **Minimum rank** + This is the minimum configuration rank of {IDF_TARGET_NAME}. The protocol stack only uses the necessary memory for running. It is suitable for scenarios where there is no requirement for performance and the application requires lots of space. + +.. only:: esp32s2 + + **Ranks:** + + - **Iperf rank** + {IDF_TARGET_NAME} extreme performance rank used to test extreme performance. + + - **High-performance rank** + The {IDF_TARGET_NAME}'s high-performance configuration rank, suitable for scenarios where the application occupies less memory and has high-performance requirements. + + - **Default rank** + {IDF_TARGET_NAME}'s default configuration rank, the available memory, and performance are in balance. + + - **Memory saving rank** + This rank is suitable for scenarios where the application requires a large amount of memory, and the transceiver performance will be reduced in this rank. + + - **Minimum rank** + This is the minimum configuration rank of {IDF_TARGET_NAME}. The protocol stack only uses the necessary memory for running. It is suitable for scenarios where there is no requirement for performance and the application requires lots of space. + +.. only:: esp32c3 or esp32s3 or esp32c6 + + **Ranks:** + + - **Iperf rank** + {IDF_TARGET_NAME} extreme performance rank used to test extreme performance. + + - **Default rank** + {IDF_TARGET_NAME}'s default configuration rank, the available memory, and performance are in balance. + + - **Minimum rank** + This is the minimum configuration rank of {IDF_TARGET_NAME}. The protocol stack only uses the necessary memory for running. It is suitable for scenarios where there is no requirement for performance and the application requires lots of space. + +.. only:: SOC_SPIRAM_SUPPORTED + + Using PSRAM + ++++++++++++++++++++++++++++ + + PSRAM is generally used when the application takes up a lot of memory. In this mode, the :ref:`CONFIG_ESP_WIFI_TX_BUFFER` is forced to be static. :ref:`CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM` indicates the number of DMA buffers at the hardware layer, and increasing this parameter can improve performance. + The following are the recommended ranks for using PSRAM: + + .. only:: esp32 + + .. list-table:: + :header-rows: 1 + :widths: 15 10 10 15 10 + + * - Rank + - Iperf + - Default + - Memory saving + - Minimum + * - Available memory (KB) + - 113.8 + - 152.4 + - 181.2 + - 202.6 + * - WIFI_STATIC_RX_BUFFER_NUM + - 16 + - 8 + - 4 + - 2 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 128 + - 128 + - 128 + - 128 + * - WIFI_STATIC_TX_BUFFER_NUM + - 16 + - 8 + - 4 + - 2 + * - WIFI_RX_BA_WIN + - 16 + - 16 + - 8 + - Disable + * - TCP_SND_BUF_DEFAULT (KB) + - 65 + - 65 + - 65 + - 65 + * - TCP_WND_DEFAULT (KB) + - 65 + - 65 + - 65 + - 65 + * - WIFI_IRAM_OPT + - ENABLE + - ENABLE + - ENABLE + - DISABLE + * - WIFI_RX_IRAM_OPT + - ENABLE + - ENABLE + - DISABLE + - DISABLE + * - LWIP_IRAM_OPTIMIZATION + - ENABLE + - DISABLE + - DISABLE + - DISABLE + * - TCP TX throughput (Mbit/s) + - 37.5 + - 31.7 + - 21.7 + - 14.6 + * - TCP RX throughput (Mbit/s) + - 31.5 + - 29.8 + - 26.5 + - 21.1 + * - UDP TX throughput (Mbit/s) + - 69.1 + - 31.5 + - 27.1 + - 24.1 + * - UDP RX throughput (Mbit/s) + - 40.1 + - 38.5 + - 37.5 + - 36.9 + + .. only:: esp32s2 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 10 15 + + * - Rank + - Iperf + - Default + - Memory saving + - Minimum + * - Available memory (KB) + - 70.6 + - 96.4 + - 118.8 + - 148.2 + * - WIFI_STATIC_RX_BUFFER_NUM + - 8 + - 8 + - 6 + - 4 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 64 + - 64 + - 64 + - 64 + * - WIFI_STATIC_TX_BUFFER_NUM + - 16 + - 8 + - 6 + - 4 + * - WIFI_RX_BA_WIN + - 16 + - 6 + - 6 + - Disable + * - TCP_SND_BUF_DEFAULT (KB) + - 32 + - 32 + - 32 + - 32 + * - TCP_WND_DEFAULT (KB) + - 32 + - 32 + - 32 + - 32 + * - WIFI_IRAM_OPT + - ENABLE + - ENABLE + - ENABLE + - DISABLE + * - WIFI_RX_IRAM_OPT + - ENABLE + - ENABLE + - DISABLE + - DISABLE + * - LWIP_IRAM_OPTIMIZATION + - ENABLE + - DISABLE + - DISABLE + - DISABLE + * - INSTRUCTION_CACHE + - 16 + - 16 + - 16 + - 8 + * - INSTRUCTION_CACHE_LINE + - 16 + - 16 + - 16 + - 16 + * - DATA_CACHE + - 8 + - 8 + - 8 + - 8 + * - DATA_CACHE_LINE + - 32 + - 32 + - 32 + - 32 + * - TCP TX throughput (Mbit/s) + - 40.1 + - 29.2 + - 20.1 + - 8.9 + * - TCP RX throughput (Mbit/s) + - 21.9 + - 16.8 + - 14.8 + - 9.6 + * - UDP TX throughput (Mbit/s) + - 50.1 + - 25.7 + - 22.4 + - 10.2 + * - UDP RX throughput (Mbit/s) + - 45.3 + - 43.1 + - 28.5 + - 15.1 + + .. note:: + Reaching peak performance may cause task watchdog. It is a normal phenomenon considering the CPU may have no time for lower priority tasks. + + .. only:: esp32s3 + + **PSRAM with 4 lines:** + + .. list-table:: + :header-rows: 1 + :widths: 25 20 25 25 25 + + * - Rank + - Iperf + - Default + - Memory saving + - Minimum + * - Available memory (KB) + - 50.3 + - 158.7 + - 198.2 + - 228.9 + * - WIFI_STATIC_RX_BUFFER_NUM + - 24 + - 8 + - 6 + - 4 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 85 + - 64 + - 32 + - 32 + * - WIFI_STATIC_TX_BUFFER_NUM + - 32 + - 32 + - 6 + - 4 + * - WIFI_RX_BA_WIN + - 32 + - 16 + - 12 + - Disable + * - TCP_SND_BUF_DEFAULT (KB) + - 85 + - 32 + - 32 + - 32 + * - TCP_WND_DEFAULT (KB) + - 85 + - 32 + - 32 + - 32 + * - WIFI_IRAM_OPT + - ENABLE + - ENABLE + - ENABLE + - DISABLE + * - WIFI_RX_IRAM_OPT + - ENABLE + - ENABLE + - DISABLE + - DISABLE + * - LWIP_IRAM_OPTIMIZATION + - ENABLE + - DISABLE + - DISABLE + - DISABLE + * - LWIP_UDP_RECVMBOX_SIZE + - 16 + - 16 + - 16 + - 16 + * - INSTRUCTION_CACHE + - 32 + - 16 + - 16 + - 16 + * - INSTRUCTION_CACHE_LINE + - 32 + - 16 + - 16 + - 16 + * - INSTRUCTION_CACHE_WAYS + - 8 + - 8 + - 8 + - 8 + * - DATA_CACHE + - 64 + - 16 + - 16 + - 16 + * - DATA_CACHE_LINE + - 32 + - 32 + - 32 + - 32 + * - DATA_CACHE_WAYS + - 8 + - 8 + - 8 + - 8 + * - TCP TX throughput (Mbit/s) + - 93.1 + - 62.5 + - 41.3 + - 42.7 + * - TCP RX throughput (Mbit/s) + - 88.9 + - 46.5 + - 46.2 + - 37.9 + * - UDP TX throughput (Mbit/s) + - 106.4 + - 106.2 + - 60.7 + - 50 + * - UDP RX throughput (Mbit/s) + - 99.8 + - 92.6 + - 94.3 + - 53.3 + + **PSRAM with 8 lines:** + + .. list-table:: + :header-rows: 1 + :widths: 25 20 25 25 25 + + * - Rank + - Iperf + - Default + - Memory saving + - Minimum + * - Available memory (KB) + - 49.1 + - 151.3 + - 215.3 + - 243.6 + * - WIFI_STATIC_RX_BUFFER_NUM + - 24 + - 8 + - 6 + - 4 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 85 + - 64 + - 32 + - 32 + * - WIFI_STATIC_TX_BUFFER_NUM + - 32 + - 32 + - 6 + - 4 + * - WIFI_RX_BA_WIN + - 32 + - 16 + - 12 + - Disable + * - TCP_SND_BUF_DEFAULT (KB) + - 85 + - 32 + - 32 + - 32 + * - TCP_WND_DEFAULT (KB) + - 85 + - 32 + - 32 + - 32 + * - WIFI_IRAM_OPT + - ENABLE + - ENABLE + - ENABLE + - DISABLE + * - WIFI_RX_IRAM_OPT + - ENABLE + - ENABLE + - DISABLE + - DISABLE + * - LWIP_IRAM_OPTIMIZATION + - ENABLE + - DISABLE + - DISABLE + - DISABLE + * - LWIP_UDP_RECVMBOX_SIZE + - 16 + - 16 + - 16 + - 16 + * - INSTRUCTION_CACHE + - 32 + - 16 + - 16 + - 16 + * - INSTRUCTION_CACHE_LINE + - 32 + - 16 + - 16 + - 16 + * - INSTRUCTION_CACHE_WAYS + - 8 + - 8 + - 8 + - 8 + * - DATA_CACHE + - 64 + - 16 + - 16 + - 16 + * - DATA_CACHE_LINE + - 32 + - 32 + - 32 + - 32 + * - DATA_CACHE_WAYS + - 8 + - 8 + - 8 + - 8 + * - TCP TX throughput (Mbit/s) + - 93.3 + - 58.4 + - 37.1 + - 35.6 + * - TCP RX throughput (Mbit/s) + - 86.1 + - 43.6 + - 42.5 + - 35 + * - UDP TX throughput (Mbit/s) + - 104.7 + - 82.2 + - 60.4 + - 47.9 + * - UDP RX throughput (Mbit/s) + - 104.6 + - 104.8 + - 104 + - 55.7 + + +{IDF_TARGET_NAME} Wi-Fi Power-saving Mode +----------------------------------------- + +This subsection will briefly introduce the concepts and usage related to Wi-Fi Power Saving Mode, for a more detailed introduction please refer to the :doc:`Low Power Mode User Guide <../../api-guides/low-power-mode/index>`. + +Station Sleep +++++++++++++++++++++++ + +Currently, {IDF_TARGET_NAME} Wi-Fi supports the Modem-sleep mode which refers to the legacy power-saving mode in the IEEE 802.11 protocol. Modem-sleep mode works in station-only mode and the station must connect to the AP first. If the Modem-sleep mode is enabled, station will switch between active and sleep state periodically. In sleep state, RF, PHY and BB are turned off in order to reduce power consumption. Station can keep connection with AP in modem-sleep mode. + +Modem-sleep mode includes minimum and maximum power-saving modes. In minimum power-saving mode, station wakes up every DTIM to receive beacon. Broadcast data will not be lost because it is transmitted after DTIM. However, it cannot save much more power if DTIM is short for DTIM is determined by AP. + +In maximum power-saving mode, station wakes up in every listen interval to receive beacon. This listen interval can be set to be longer than the AP DTIM period. Broadcast data may be lost because station may be in sleep state at DTIM time. If listen interval is longer, more power is saved, but broadcast data is more easy to lose. Listen interval can be configured by calling API :cpp:func:`esp_wifi_set_config()` before connecting to AP. + +Call ``esp_wifi_set_ps(WIFI_PS_MIN_MODEM)`` to enable Modem-sleep minimum power-saving mode or ``esp_wifi_set_ps(WIFI_PS_MAX_MODEM)`` to enable Modem-sleep maximum power-saving mode after calling :cpp:func:`esp_wifi_init()`. When station connects to AP, Modem-sleep will start. When station disconnects from AP, Modem-sleep will stop. + +Call ``esp_wifi_set_ps(WIFI_PS_NONE)`` to disable Modem-sleep mode entirely. Disabling it increases power consumption, but minimizes the delay in receiving Wi-Fi data in real time. When Modem-sleep mode is enabled, the delay in receiving Wi-Fi data may be the same as the DTIM cycle (minimum power-saving mode) or the listening interval (maximum power-saving mode). + +.. only:: SOC_SUPPORT_COEXISTENCE + + Note that in coexist mode, Wi-Fi will remain active only during Wi-Fi time slice, and sleep during non Wi-Fi time slice even if ``esp_wifi_set_ps(WIFI_PS_NONE)`` is called. Please refer to :ref:`coexist policy `. + +The default Modem-sleep mode is WIFI_PS_MIN_MODEM. + +AP Sleep ++++++++++++++++++++++++++++++++ + +Currently, {IDF_TARGET_NAME} AP does not support all of the power-saving feature defined in Wi-Fi specification. To be specific, the AP only caches unicast data for the stations connect to this AP, but does not cache the multicast data for the stations. If stations connected to the {IDF_TARGET_NAME} AP are power-saving enabled, they may experience multicast packet loss. + +In the future, all power-saving features will be supported on {IDF_TARGET_NAME} AP. + +Disconnected State Sleep ++++++++++++++++++++++++++++++++ + +Disconnected state is the duration without Wi-Fi connection between :cpp:func:`esp_wifi_start` to :cpp:func:`esp_wifi_stop`. + +Currently, {IDF_TARGET_NAME} Wi-Fi supports sleep mode in disconnected state if running at station mode. This feature could be configured by Menuconfig choice :ref:`CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE`. + +If :ref:`CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE` is enabled, RF, PHY and BB would be turned off in disconnected state when IDLE. The current would be same with current at modem-sleep. + +The choice :ref:`CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE` would be selected by default, while it would be selected forcefully in Menuconfig at coexistence mode. + +.. _connectionless-module-power-save: + +Connectionless Modules Power-saving +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Connectionless modules are those Wi-Fi modules not relying on Wi-Fi connection, e.g ESP-NOW, DPP, FTM. These modules start from :cpp:func:`esp_wifi_start`, working until :cpp:func:`esp_wifi_stop`. + +Currently, if ESP-NOW works at station mode, its supported to sleep at both connected state and disconnected state. + +Connectionless Modules TX +******************************* + +For each connectionless module, its supported to TX at any sleeping time without any extra configuration. + +Meanwhile, :cpp:func:`esp_wifi_80211_tx` is supported at sleep as well. + +Connectionless Modules RX +******************************* + +For each connectionless module, two parameters shall be configured to RX at sleep, which are `Window` and `Interval`. + +At the start of `Interval` time, RF, PHY, BB would be turned on and kept for `Window` time. Connectionless Module could RX in the duration. + +**Interval** + + - There is only one `Interval`. Its configured by :cpp:func:`esp_wifi_set_connectionless_interval`. The unit is milliseconds. + + - The default value of `Interval` is `ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE`. + + - Event :ref:`wifi-event-connectionless-module-wake-interval-start` would be posted at the start of `Interval`. Since `Window` also starts at that moment, its recommended to TX in that event. + + - At connected state, the start of `Interval` would be aligned with TBTT. To improve the packet reception success rate in connectionless modules, the sender and receiver can be connected to the same AP, and packets can be transmitted within the event :ref:`wifi-event-connectionless-module-wake-interval-start`. This synchronization helps align the connectionless modules transmission window. + + .. only:: esp32 + + On the ESP32, TBTT timing is affected by DFS(Dynamic Frequency Scaling). To synchronize the connectionless modules transmission window using TBTT on the ESP32, DFS must be disabled. + +**Window** + + - Each connectionless module has its own `Window` after start. Connectionless Modules Power-saving would work with the max one among them. + + - `Window` is configured by :cpp:func:`module_name_set_wake_window`. The unit is milliseconds. + + - The default value of `Window` is the maximum. + +.. table:: RF, PHY and BB usage under different circumstances + + +----------------------+-----------------------------------------------------+---------------------------------------------------------------------------+ + | | Interval | + + +-----------------------------------------------------+---------------------------------------------------------------------------+ + | | ``ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE`` | 1 - maximum | + +--------+-------------+-----------------------------------------------------+---------------------------------------------------------------------------+ + | Window | 0 | not used | + + +-------------+-----------------------------------------------------+---------------------------------------------------------------------------+ + | | 1 - maximum | default mode | used periodically (Window < Interval) / used all time (Window ≥ Interval) | + +--------+-------------+-----------------------------------------------------+---------------------------------------------------------------------------+ + +Default Mode +******************************* + +If `Interval` is ``ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE`` with non-zero `Window`, Connectionless Modules Power-saving would work in default mode. + +In default mode, RF, PHY, BB would be kept on if no coexistence with non-Wi-Fi protocol. + +With coexistence, RF, PHY, BB resources are allocated by coexistence module to Wi-Fi connectionless module and non-Wi-Fi module, using time-division method. In default mode, Wi-Fi connectionless module is allowed to use RF, BB, PHY periodically under a stable performance. + +Its recommended to configure Connectionless Modules Power-saving to default mode if there is Wi-Fi connectionless module coexists with non-Wi-Fi module. diff --git a/docs/en/api-guides/wifi-driver/wifi-vendor-features.rst b/docs/en/api-guides/wifi-driver/wifi-vendor-features.rst new file mode 100644 index 0000000000..35749a581a --- /dev/null +++ b/docs/en/api-guides/wifi-driver/wifi-vendor-features.rst @@ -0,0 +1,236 @@ +Wi-Fi Vendor Features +=================================== + +:link_to_translation:`zh_CN:[中文]` + +.. only:: SOC_WIFI_MESH_SUPPORT + + ESP-WIFI-MESH + ------------------------- + + For details, see the :doc:`ESP-WIFI-MESH <../esp-wifi-mesh>`. + + +Wi-Fi 80211 Packet Send +--------------------------- + +The :cpp:func:`esp_wifi_80211_tx()` API can be used to: + + - Send the beacon, probe request, probe response, and action frame. + - Send the non-QoS data frame. + +It cannot be used for sending encrypted or QoS frames. + +Preconditions of Using :cpp:func:`esp_wifi_80211_tx()` +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + - The Wi-Fi mode is station, or AP, or station/AP. + - Either ``esp_wifi_set_promiscuous(true)``, or :cpp:func:`esp_wifi_start()`, or both of these APIs return :c:macro:`ESP_OK`. This is because Wi-Fi hardware must be initialized before :cpp:func:`esp_wifi_80211_tx()` is called. In {IDF_TARGET_NAME}, both ``esp_wifi_set_promiscuous(true)`` and :cpp:func:`esp_wifi_start()` can trigger the initialization of Wi-Fi hardware. + - The parameters of :cpp:func:`esp_wifi_80211_tx()` are hereby correctly provided. + +Data Rate ++++++++++++++++++++++++++++++++++++++++++++++++ + + - The default data rate is 1 Mbps. + - Can set any rate through :cpp:func:`esp_wifi_config_80211_tx_rate()` API. + - Can set any bandwidth through :cpp:func:`esp_wifi_set_bandwidth()` API. + +Side-Effects to Avoid in Different Scenarios ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Theoretically, if the side-effects the API imposes on the Wi-Fi driver or other stations/APs are not considered, a raw 802.11 packet can be sent over the air with any destination MAC, any source MAC, any BSSID, or any other types of packet. However, robust or useful applications should avoid such side-effects. The table below provides some tips and recommendations on how to avoid the side-effects of :cpp:func:`esp_wifi_80211_tx()` in different scenarios. + +.. list-table:: + :header-rows: 1 + :widths: 10 50 + + * - Scenario + - Description + * - No Wi-Fi connection + - In this scenario, no Wi-Fi connection is set up, so there are no side-effects on the Wi-Fi driver. If ``en_sys_seq==true``, the Wi-Fi driver is responsible for the sequence control. If ``en_sys_seq==false``, the application needs to ensure that the buffer has the correct sequence. + + Theoretically, the MAC address can be any address. However, this may impact other stations/APs with the same MAC/BSSID. + + Side-effect example#1 The application calls :cpp:func:`esp_wifi_80211_tx()` to send a beacon with BSSID == mac_x in AP mode, but the mac_x is not the MAC of the AP interface. Moreover, there is another AP, e.g., “other-AP”, whose BSSID is mac_x. If this happens, an “unexpected behavior” may occur, because the stations which connect to the “other-AP” cannot figure out whether the beacon is from the “other-AP” or the :cpp:func:`esp_wifi_80211_tx()`. + + To avoid the above-mentioned side-effects, it is recommended that: + + - If :cpp:func:`esp_wifi_80211_tx` is called in station mode, the first MAC should be a multicast MAC or the exact target-device’s MAC, while the second MAC should be that of the station interface. + + - If :cpp:func:`esp_wifi_80211_tx` is called in AP mode, the first MAC should be a multicast MAC or the exact target-device’s MAC, while the second MAC should be that of the AP interface. + + The recommendations above are only for avoiding side-effects and can be ignored when there are good reasons. + + * - Have Wi-Fi connection + - When the Wi-Fi connection is already set up, and the sequence is controlled by the application, the latter may impact the sequence control of the Wi-Fi connection as a whole. So, the ``en_sys_seq`` need to be true, otherwise ``ESP_ERR_INVALID_ARG`` is returned. + + The MAC-address recommendations in the “No Wi-Fi connection” scenario also apply to this scenario. + + If the Wi-Fi mode is station mode, the MAC address1 is the MAC of AP to which the station is connected, and the MAC address2 is the MAC of station interface, it is said that the packet is sent from the station to AP. Otherwise, if the Wi-Fi is in AP mode, the MAC address1 is the MAC of the station that connects to this AP, and the MAC address2 is the MAC of AP interface, it is said that the packet is sent from the AP to station. To avoid conflicting with Wi-Fi connections, the following checks are applied: + + - If the packet type is data and is sent from the station to AP, the ToDS bit in IEEE 80211 frame control should be 1 and the FromDS bit should be 0. Otherwise, the packet will be discarded by Wi-Fi driver. + + - If the packet type is data and is sent from the AP to station, the ToDS bit in IEEE 80211 frame control should be 0 and the FromDS bit should be 1. Otherwise, the packet will be discarded by Wi-Fi driver. + + - If the packet is sent from station to AP or from AP to station, the Power Management, More Data, and Re-Transmission bits should be 0. Otherwise, the packet will be discarded by Wi-Fi driver. + + ``ESP_ERR_INVALID_ARG`` is returned if any check fails. + + +Wi-Fi Vendor IE Configuration +----------------------------------- + +By default, all Wi-Fi management frames are processed by the Wi-Fi driver, and the application can ignore them. However, some applications may have to handle the beacon, probe request, probe response, and other management frames. For example, if you insert some vendor-specific IE into the management frames, it is only the management frames which contain this vendor-specific IE that will be processed. In {IDF_TARGET_NAME}, :cpp:func:`esp_wifi_set_vendor_ie()` and :cpp:func:`esp_wifi_set_vendor_ie_cb()` are responsible for this kind of tasks. + + +.. only:: SOC_WIFI_CSI_SUPPORT + + Wi-Fi Channel State Information + ------------------------------------ + + .. only:: esp32 or esp32s2 or esp32c3 or esp32s3 + + Channel state information (CSI) refers to the channel information of a Wi-Fi connection. In {IDF_TARGET_NAME}, this information consists of channel frequency responses of sub-carriers and is estimated when packets are received from the transmitter. Each channel frequency response of sub-carrier is recorded by two bytes of signed characters. The first one is imaginary part and the second one is real part. There are up to three fields of channel frequency responses according to the type of received packet. They are legacy long training field (LLTF), high throughput LTF (HT-LTF), and space time block code HT-LTF (STBC-HT-LTF). For different types of packets which are received on channels with different state, the sub-carrier index and total bytes of signed characters of CSI are shown in the following table. + + +-------------+--------------------+-----------------------------------------+--------------------------------------------------------+----------------------------------------------------------+ + | channel | secondary channel | none | below | above | + +-------------+--------------------+-------------+---------------------------+----------+---------------------------------------------+----------+-----------------------------------------------+ + | packet | signal mode | non HT | HT | non HT | HT | non HT | HT | + + +--------------------+-------------+---------------------------+----------+-----------------+---------------------------+----------+-------------------+---------------------------+ + | information | channel bandwidth | 20 MHz | 20 MHz | 20 MHz | 20 MHz | 40 MHz | 20 MHz | 20 MHz | 40 MHz | + + +--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ + | | STBC | non STBC | non STBC | STBC | non STBC | non STBC | STBC | non STBC | STBC | non STBC | non STBC | STBC | non STBC | STBC | + +-------------+--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ + | sub-carrier | LLTF | 0~31, -32~-1| 0~31, -32~-1| 0~31, -32~-1| 0~63 | 0~63 | 0~63 | 0~63 | 0~63 | -64~-1 | -64~-1 | -64~-1 | -64~-1 | -64~-1 | + + +--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ + | index | HT-LTF | - | 0~31, -32~-1| 0~31, -32~-1| - | 0~63 | 0~62 | 0~63, -64~-1| 0~60, -60~-1| - | -64~-1 | -62~-1 | 0~63, -64~-1| 0~60, -60~-1| + + +--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ + | | STBC-HT-LTF | - | - | 0~31, -32~-1| - | - | 0~62 | - | 0~60, -60~-1| - | - | -62~-1 | - | 0~60, -60~-1| + +-------------+--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ + | total bytes | 128 | 256 | 384 | 128 | 256 | 380 | 384 | 612 | 128 | 256 | 376 | 384 | 612 | + +----------------------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ + + All of the information in the table can be found in the structure wifi_csi_info_t. + + - Secondary channel refers to secondary_channel field of rx_ctrl field. + - Signal mode of packet refers to sig_mode field of rx_ctrl field. + - Channel bandwidth refers to cwb field of rx_ctrl field. + - STBC refers to stbc field of rx_ctrl field. + - Total bytes refers to len field. + - The CSI data corresponding to each Long Training Field (LTF) type is stored in a buffer starting from the buf field. Each item is stored as two bytes: imaginary part followed by real part. The order of each item is the same as the sub-carrier in the table. The order of LTF is: LLTF, HT-LTF, STBC-HT-LTF. However, all 3 LTFs may not be present, depending on the channel and packet information (see above). + - If first_word_invalid field of :cpp:type:`wifi_csi_info_t` is true, it means that the first four bytes of CSI data is invalid due to a hardware limitation in {IDF_TARGET_NAME}. + - More information like RSSI, noise floor of RF, receiving time and antenna is in the rx_ctrl field. + + When imaginary part and real part data of sub-carrier are used, please refer to the table below. + + +-----------------+-------------------+------------------------------+--------------------------+ + | PHY standard | Sub-carrier range | Pilot sub-carrier | Sub-carrier (total/data) | + +=================+===================+==============================+==========================+ + | 802.11a/g | -26 to +26 | -21, -7, +7, +21 | 52 total, 48 usable | + +-----------------+-------------------+------------------------------+--------------------------+ + | 802.11n, 20 MHz | -28 to +28 | -21, -7, +7, +21 | 56 total, 52 usable | + +-----------------+-------------------+------------------------------+--------------------------+ + | 802.11n, 40 MHz | -57 to +57 | -53, -25, -11, +11, +25, +53 | 114 total, 108 usable | + +-----------------+-------------------+------------------------------+--------------------------+ + + .. note:: + + - For STBC packet, CSI is provided for every space-time stream without CSD (cyclic shift delay). As each cyclic shift on the additional chains shall be -200 ns, only the CSD angle of first space-time stream is recorded in sub-carrier 0 of HT-LTF and STBC-HT-LTF for there is no channel frequency response in sub-carrier 0. CSD[10:0] is 11 bits, ranging from -pi to pi. + + - If LLTF, HT-LTF, or STBC-HT-LTF is not enabled by calling API :cpp:func:`esp_wifi_set_csi_config()`, the total bytes of CSI data will be fewer than that in the table. For example, if LLTF and HT-LTF is not enabled and STBC-HT-LTF is enabled, when a packet is received with the condition above/HT/40MHz/STBC, the total bytes of CSI data is 244 ((61 + 60) * 2 + 2 = 244. The result is aligned to four bytes, and the last two bytes are invalid). + + .. only:: esp32c5 + + Channel state information (CSI) refers to the channel information of a Wi-Fi connection. In {IDF_TARGET_NAME}, this information consists of channel frequency responses of sub-carriers and is estimated when packets are received from the transmitter. Each channel frequency response of sub-carrier is recorded by two bytes of signed characters. The first one is imaginary part and the second one is real part. Except for the IEEE 802.11g mode, all other modes have two LTF sequences (LLTF + HT/VHT/HE-LTF). {IDF_TARGET_NAME} can determine whether to include LLTF or HT/VHT/HE-LTF through ``acquire_csi_force_lltf`` field of :cpp:struct:`wifi_csi_acquire_config_t`. For different types of packets which are received on channels with different state, the sub-carrier index and total bytes of signed characters of CSI are shown in the following table. + + +-------------+-------------------+--------------------------------------------+-----------------------------------+--------------------------------------------------------------------------+--------------------------------------------------------------------------+ + | channel | secondary channel | none | below | above | + +-------------+-------------------+--------------+-----------------------------+-----------------------------------+--------------+-----------------------------------------------------------+--------------+-----------------------------------------------------------+ + | packet | signal mode | non HT | HT | HE | non HT | HT | non HT | HT | + | +-------------------+--------------+-----------------------------+-----------------------------------+--------------+-----------------------------+-----------------------------+--------------+-----------------------------+-----------------------------+ + | information | channel bandwidth | 20 MHz | 20 MHz | 20 MHz | 20 MHz | 20 MHz | 40 MHz | 20 MHz | 20 MHz | 40 MHz | + | +-------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + | | STBC | non STBC | non STBC | STBC | non STBC | STBC | non STBC | non STBC | STBC | none STBC | STBC | non STBC | non STBC | STBC | non STBC | STBC | + +-------------+-------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + | sub-carrier | LLTF | 0~26, -26~-1 | — | — | — | — | 0~52 | — | — | — | — | -53~-1 | — | — | — | — | + | +-------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + | index | HT-LTF (HT-LTF1) | — | 0~28, -28~-1 | 0~28, -28~-1 | — | — | — | 0~56 | 0~56 | 0~58, -58~-1 | 0~58, -58~-1 | — | -57~-1 | -57~-1 | 0~58, -58~-1 | 0~58, -58~-1 | + | +-------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + | | HT-LTF2 | — | — | 0~28, -28~-1 | — | — | — | — | 0~56 | — | 0~58, -58~-1 | — | — | -57~-1 | — | 0~58, -58~-1 | + | +-------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + | | HE-LTF (HE-LTF1) | — | — | — | 0~122, -122~1 | Determined by | — | — | — | — | — | — | — | — | — | — | + | +-------------------+--------------+--------------+--------------+---------------+ +--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + | | HE-LTF2 | — | — | — | — | wifi_csi_config_t | — | — | — | — | — | — | — | — | — | — | + +-------------+-------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + | total bytes | 106 | 114 | 228 | 490 | 490 | 106 | 114 | 228 | 234 | 468 | 106 | 114 | 228 | 234 | 468 | + +---------------------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + + .. note:: + + - In HT/VHT/HE modes, there are two LTF sequences: LLTF + HT/VHT/HE-LTF. If the ``acquire_csi_force_lltf`` field of :cpp:struct:`wifi_csi_acquire_config_t` is set to false, the CSI data will only contain HT/VHT/HE-LTF (as shown in the table above); otherwise, the CSI data will only contain LLTF. The sub-carrier index and total bytes for LLTF in HT/VHT/HE modes are the same as those for LLTF in non-HT modes. + - In VHT mode, the sub-carrier index and total bytes are the same as those in HT mode. + + All of the information in the table can be found in the structure :cpp:type:`wifi_csi_info_t`. + + - Secondary channel refers to ``second`` field of ``rx_ctrl`` field. + - signal mode of packet refers to ``cur_bb_format`` field of ``rx_ctrl`` field. + - total bytes refers to ``len`` field + - The CSI data corresponding to each Long Training Field (LTF) type is stored in a buffer starting from the buf field. Each item is stored as two bytes: imaginary part followed by real part. The order of each item is the same as the sub-carrier in the table. + - If ``first_word_invalid`` of :cpp:type:`wifi_csi_info_t` is true, it means that the first four bytes of CSI data is invalid due to a hardware limitation in {IDF_TARGET_NAME}. + - If ``rx_channel_estimate_info_vld`` of ``rx_ctrl`` field is 1, indicates that the CSI data is valid; otherwise, the CSI data is invalid. + - More information like RSSI, noise floor of RF, receiving time and antenna is in the ``rx_ctrl`` field. + + For STBC packets, the subcarrier indices of HE-LTF1 and HE-LTF2 are determined by ``acquire_csi_he_stbc_mode`` field of :cpp:type:`wifi_csi_config_t`. Please refer to the table below for details. + + +---------------------+----------------------+----------------------+ + | acquire_csi_he_stbc | HE-LTF1 | HE-LTF2 | + +---------------------+----------------------+----------------------+ + | 0 | -122~-1, 0~122 | — | + +---------------------+----------------------+----------------------+ + | 1 | — | -122~-1, 0~122 | + +---------------------+----------------------+----------------------+ + | 2 | Sample evenly among the HE-LTF1 and HE-LTF2 | + +---------------------+----------------------+----------------------+ + + When imaginary part and real part data of sub-carrier are used, please refer to the table below. + + +-----------------------+-------------------+------------------------------------------+------------------------------+ + | PHY standard | Sub-carrier range | Invalid sub-carrier | Sub-carrier (total/data) | + +=======================+===================+==========================================+==============================+ + | 802.11a/g | -26 to +26 | 0 | 53 total, 52 usable | + +-----------------------+-------------------+------------------------------------------+------------------------------+ + | 802.11n, 20 MHz | -28 to +28 | 0 | 57 total, 56 usable | + +-----------------------+-------------------+------------------------------------------+------------------------------+ + | 802.11n, 40 MHz | -58 to +58 | -1, 0, 1 | 117 total, 114 usable | + +-----------------------+-------------------+------------------------------------------+------------------------------+ + | 802.11ac, 20 MHz | -28 to +28 | 0 | 57 total, 56 usable | + +-----------------------+-------------------+------------------------------------------+------------------------------+ + | 802.11ax, 20 MHz (SU) | -122 to + 122 | -1, 0, 1 | 245 total, 242 usable | + +-----------------------+-------------------+------------------------------------------+------------------------------+ + + .. note:: + + - When the PHY is 802.11ax, please refer to the protocol for sub-carrier range and invalid sub-carrier for MU packets. + + .. note:: + + - For STBC packet, CSI is provided for every space-time stream without CSD (cyclic shift delay). As each cyclic shift on the additional chains shall be -200 ns, only the CSD angle of first space-time stream is recorded in sub-carrier 0 of HT-LTF1 (HE-LTF1) and HT-LTF2 (HE-LTF2) for there is no channel frequency response in sub-carrier 0. CSD[10:0] is 11 bits, ranging from -pi to pi. + + + Wi-Fi Channel State Information Configure + ------------------------------------------- + + To use Wi-Fi CSI, the following steps need to be done. + + - Select Wi-Fi CSI in menuconfig. Go to ``Menuconfig`` > ``Components config`` > ``Wi-Fi`` > ``Wi-Fi CSI (Channel State Information)``. + - Set CSI receiving callback function by calling API :cpp:func:`esp_wifi_set_csi_rx_cb()`. + - Configure CSI by calling API :cpp:func:`esp_wifi_set_csi_config()`. + - Enable CSI by calling API :cpp:func:`esp_wifi_set_csi()`. + + The CSI receiving callback function runs from Wi-Fi task. So, do not do lengthy operations in the callback function. Instead, post necessary data to a queue and handle it from a lower priority task. Because station does not receive any packet when it is disconnected and only receives packets from AP when it is connected, it is suggested to enable sniffer mode to receive more CSI data by calling :cpp:func:`esp_wifi_set_promiscuous()`. + + +Wi-Fi Multiple Antennas +------------------------ + +Please refer to the :doc:`PHY <../../api-guides/phy>`. diff --git a/docs/en/api-guides/wifi-expansion.rst b/docs/en/api-guides/wifi-expansion.rst index 8beb81bc22..376424c5d9 100644 --- a/docs/en/api-guides/wifi-expansion.rst +++ b/docs/en/api-guides/wifi-expansion.rst @@ -9,7 +9,7 @@ Wi-Fi Expansion .. only:: SOC_WIFI_SUPPORTED - {IDF_TARGET_NAME} does support Wi-Fi functionality natively, please refer to :doc:`wifi` documentation. Even though Wi-Fi is supported on {IDF_TARGET_NAME}, it is possible to expand it and use another instance of Wi-Fi expansion interfaces using `esp_wifi_remote `_ component. + {IDF_TARGET_NAME} does support Wi-Fi functionality natively, please refer to :doc:`wifi-driver/index` documentation. Even though Wi-Fi is supported on {IDF_TARGET_NAME}, it is possible to expand it and use another instance of Wi-Fi expansion interfaces using `esp_wifi_remote `_ component. {IDF_TARGET_NAME} esp_wifi_remote diff --git a/docs/en/api-guides/wifi-security.rst b/docs/en/api-guides/wifi-security.rst index ec01f17157..81101ed192 100644 --- a/docs/en/api-guides/wifi-security.rst +++ b/docs/en/api-guides/wifi-security.rst @@ -43,28 +43,73 @@ Wi-Fi Enterprise --------------------------------- Introduction -++++++++++++ +++++++++++++++ -Enterprise security is the secure authentication mechanism for enterprise wireless networks. It uses the RADIUS server for authentication of network users before connecting to the Access Point (AP). The authentication process is based on 802.1X policy and comes with different Extended Authentication Protocol (EAP) methods such as TLS, TTLS, PEAP, and EAP-FAST. RADIUS server authenticates the users based on their credentials (username and password), digital certificates, or both. +Wi-Fi Enterprise provides secure authentication mechanisms for enterprise wireless networks. It is based on the IEEE 802.1X standard and requires a RADIUS server to authenticate network users before they connect to an Access Point (AP). Depending on the Extended Authentication Protocol (EAP) method used, authentication can rely on user credentials (username and password), digital certificates, or both. + +When {IDF_TARGET_NAME}, operating in station mode, connects to an Enterprise AP, it initiates an authentication request. The AP forwards this request to the configured RADIUS server, which validates the station based on the selected EAP method and configured parameters. .. note:: {IDF_TARGET_NAME} supports Wi-Fi Enterprise only in station mode. -{IDF_TARGET_NAME} supports **WPA2-Enterprise** and **WPA3-Enterprise**. WPA3-Enterprise builds upon the foundation of WPA2-Enterprise with the additional requirement of using Protected Management Frames (PMF) and server certificate validation on all WPA3 connections. **WPA3-Enterprise also offers an additional secure mode using 192-bit minimum-strength security protocols and cryptographic tools to better protect sensitive data.** The 192-bit security mode offered by WPA3-Enterprise ensures the right combination of cryptographic tools is used and sets a consistent baseline of security within a WPA3 network. WPA3-Enterprise 192-bit mode is only supported by modules having :c:macro:`SOC_WIFI_GCMP_SUPPORT` support. Enable :ref:`CONFIG_ESP_WIFI_SUITE_B_192` flag to support WPA3-Enterprise with 192-bit mode. +WPA2-Enterprise and WPA3-Enterprise +++++++++++++++++++++++++++++++++++++++ -{IDF_TARGET_NAME} supports the following EAP methods: - - EAP-TLS: This is a certificate-based method and only requires SSID and EAP-IDF. - - PEAP: This is a Protected EAP method. Usernames and passwords are mandatory. - - EAP-TTLS: This is a credential-based method. Only server authentication is mandatory while user authentication is optional. Username and Password are mandatory. It supports different Phase2 methods, such as: - - PAP: Password Authentication Protocol. - - CHAP: Challenge Handshake Authentication Protocol. - - MSCHAP and MSCHAP-V2. - - EAP-FAST: This is an authentication method based on Protected Access Credentials (PAC) which also uses identity and password. Currently, :ref:`CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT` flag should be disabled to use this feature. +{IDF_TARGET_NAME} supports both **WPA2-Enterprise** and **WPA3-Enterprise**. -- :example:`wifi/wifi_eap_fast` demonstrates how to connect {IDF_TARGET_NAME} to an AP with Wi-Fi Enterprise authentication using EAP-FAST, including the installation of a CA certificate, setting user credentials, enabling Wi-Fi Enterprise mode, and handling connection to the AP. +**WPA2-Enterprise** provides authentication using 802.1X/EAP and relies on secure credentials or certificates. For secure connectivity, the AP and station negotiate and agree on an appropriate cipher suite. {IDF_TARGET_NAME} supports the following: + +- 802.1X/EAP (WPA) AKM method +- AES-CCM cipher suite +- Additional cipher suites supported by mbedtls when the `USE_MBEDTLS_CRYPTO` flag is enabled + +**WPA3-Enterprise** enhances WPA2-Enterprise by requiring Protected Management Frames (PMF) and mandatory server certificate validation on all WPA3 connections. + +WPA3-Enterprise also introduces an additional secure mode using **192-bit minimum-strength security protocols** (“Suite B”). This mode ensures a consistent baseline of cryptographic strength. + +- WPA3-Enterprise 192-bit mode is supported only on modules that have :c:macro:`SOC_WIFI_GCMP_SUPPORT`. +- To enable WPA3-Enterprise 192-bit mode, configure :ref:`CONFIG_ESP_WIFI_SUITE_B_192`. + +Supported EAP Methods ++++++++++++++++++++++++++ + +{IDF_TARGET_NAME} supports multiple EAP methods for Enterprise authentication. These methods may require different combinations of SSID, identity, username/password, CA certificate, or client certificate. + +The following EAP methods are supported: + +- **EAP-TLS** + + Certificate-based method requiring SSID and EAP identity. Client certificates are used for authentication. + +- **PEAP** + + A Protected EAP method requiring a username and password. + +- **EAP-TTLS** + + A credential-based method. Server authentication is mandatory; user authentication is optional depending on the Phase 2 method. Username and password are typically required. Supported Phase 2 methods include: + + - PAP: Password Authentication Protocol + - CHAP: Challenge Handshake Authentication Protocol + - MSCHAP + - MSCHAP-V2 + +- **EAP-FAST** + + An authentication method based on Protected Access Credentials (PAC), requiring an identity and password. To use EAP-FAST, :ref:`CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT` must be **disabled**. + +Examples +++++++++++ + +- :example:`wifi/wifi_eap_fast` + + Demonstrates connecting {IDF_TARGET_NAME} to an AP using EAP-FAST, including CA certificate installation, credential configuration, enabling Enterprise mode, and connecting to the AP. + +- :example:`wifi/wifi_enterprise` + + Demonstrates connecting {IDF_TARGET_NAME} using EAP-TLS, EAP-PEAP, and EAP-TTLS. For details on generating certificates with OpenSSL and running the example, refer to :example_file:`wifi/wifi_enterprise/README.md`. -- :example:`wifi/wifi_enterprise` demonstrates how to connect {IDF_TARGET_NAME} to an AP with Wi-Fi Enterprise authentication using other EAP methods, such as EAP-TLS, EAP-PEAP, EAP-TTLS. For details on generating certificates with OpenSSL commands and running the example, refer to :example_file:`wifi/wifi_enterprise/README.md`. WPA3-Personal ------------- diff --git a/docs/en/api-guides/wifi.rst b/docs/en/api-guides/wifi.rst deleted file mode 100644 index b744fa74e2..0000000000 --- a/docs/en/api-guides/wifi.rst +++ /dev/null @@ -1,4280 +0,0 @@ -Wi-Fi Driver -============= - -:link_to_translation:`zh_CN:[中文]` - -{IDF_TARGET_MAX_CONN_STA_NUM:default="15", esp32c2="4", esp32c3="10", esp32c6="10"} - -{IDF_TARGET_SUB_MAX_NUM_FROM_KEYS:default="2", esp32c3="7", esp32c6="7"} - -{IDF_TARGET_NAME} Wi-Fi Feature List ------------------------------------- - -The following features are supported: - -.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 - - - 4 virtual Wi-Fi interfaces, which are STA, AP, Sniffer and reserved. - - Station-only mode, AP-only mode, station/AP-coexistence mode - - IEEE 802.11b, IEEE 802.11g, IEEE 802.11n, and APIs to configure the protocol mode - - WPA/WPA2/WPA3/WPA2-Enterprise/WPA3-Enterprise/WAPI/WPS and DPP - - AMSDU, AMPDU, HT40, QoS, and other key features - - Modem-sleep - - The Espressif-specific ESP-NOW protocol and Long Range mode, which supports up to **1 km** of data traffic - - Up to 20 MBit/s TCP throughput and 30 MBit/s UDP throughput over the air - - Sniffer - - Both fast scan and all-channel scan - - Multiple antennas - - Channel state information - -.. only:: esp32c2 - - - 3 virtual Wi-Fi interfaces, which are STA, AP and Sniffer. - - Station-only mode, AP-only mode, station/AP-coexistence mode - - IEEE 802.11b, IEEE 802.11g, IEEE 802.11n, and APIs to configure the protocol mode - - WPA/WPA2/WPA3/WPA2-Enterprise/WPA3-Enterprise/WPS and DPP - - AMPDU, QoS, and other key features - - Modem-sleep - - Up to 20 MBit/s TCP throughput and 30 MBit/s UDP throughput over the air - - Sniffer - - Both fast scan and all-channel scan - - Multiple antennas - -.. only:: esp32c6 - - - 4 virtual Wi-Fi interfaces, which are STA, AP, Sniffer and reserved. - - Station-only mode, AP-only mode, station/AP-coexistence mode - - IEEE 802.11b, IEEE 802.11g, IEEE 802.11n, IEEE 802.11ax, and APIs to configure the protocol mode - - WPA/WPA2/WPA3/WPA2-Enterprise/WPA3-Enterprise/WAPI/WPS and DPP - - AMSDU, AMPDU, HT40, QoS, and other key features - - Modem-sleep - - The Espressif-specific ESP-NOW protocol and Long Range mode, which supports up to **1 km** of data traffic - - Up to 20 MBit/s TCP throughput and 30 MBit/s UDP throughput over the air - - Sniffer - - Both fast scan and all-channel scan - - Multiple antennas - - Channel state information - - Individual TWT and Broadcast TWT - - Downlink MU-MIMO - - OFDMA - - BSS Color - -.. only:: esp32c5 - - - 4 virtual Wi-Fi interfaces, which are STA, AP, Sniffer and reserved. - - Station-only mode, AP-only mode, station/AP-coexistence mode - - IEEE 802.11b, IEEE 802.11g, IEEE 802.11n, IEEE 802.11a, IEEE 802.11ac, IEEE 802.11ax, and APIs to configure the protocol mode - - WPA/WPA2/WPA3/WPA2-Enterprise/WPA3-Enterprise/WAPI/WPS and DPP - - AMSDU, AMPDU, HT40, QoS, and other key features - - Modem-sleep - - The Espressif-specific ESP-NOW protocol and Long Range mode (only supported on 2.4 GHz band), which supports up to **1 km** of data traffic - - Up to 20 MBit/s TCP throughput and 30 MBit/s UDP throughput over the air - - Sniffer - - Both fast scan and all-channel scan - - Multiple antennas - - Channel state information - - Individual TWT and Broadcast TWT - - Downlink MU-MIMO - - OFDMA - - BSS Color -.. only:: SOC_WIFI_NAN_SUPPORT - - - Wi-Fi Aware (NAN) - - -How To Write a Wi-Fi Application ----------------------------------- - -Preparation -+++++++++++ - -Generally, the most effective way to begin your own Wi-Fi application is to select an example which is similar to your own application, and port the useful part into your project. It is not a MUST, but it is strongly recommended that you take some time to read this article first, especially if you want to program a robust Wi-Fi application. - -This article is supplementary to the Wi-Fi APIs/Examples. It describes the principles of using the Wi-Fi APIs, the limitations of the current Wi-Fi API implementation, and the most common pitfalls in using Wi-Fi. This article also reveals some design details of the Wi-Fi driver. We recommend you to select an :example:`example `. - -- :example:`wifi/getting_started/station` demonstrates how to use the station functionality to connect to an AP. - -- :example:`wifi/getting_started/softAP` demonstrates how to use the SoftAP functionality to configure {IDF_TARGET_NAME} as an AP. - -- :example:`wifi/scan` demonstrates how to scan for available APs, configure the scan settings, and display the scan results. - -- :example:`wifi/fast_scan` demonstrates how to perform fast and all channel scans for nearby APs, set thresholds for signal strength and authentication modes, and connect to the best fitting AP based on signal strength and authentication mode. - -- :example:`wifi/wps` demonstrates how to use the WPS enrollee feature to simplify the process of connecting to a Wi-Fi router, with options for PIN or PBC modes. - -- :example:`wifi/wps_softap_registrar` demonstrates how to use the WPS registrar feature on SoftAP mode, simplifying the process of connecting to a Wi-Fi SoftAP from a station. - -- :example:`wifi/smart_config` demonstrates how to use the smartconfig feature to connect to a target AP using the ESPTOUCH app. - -- :example:`wifi/power_save` demonstrates how to use the power save mode in station mode. - -- :example:`wifi/softap_sta` demonstrates how to configure {IDF_TARGET_NAME} to function as both an AP and a station simultaneously, effectively enabling it to act as a Wi-Fi NAT router. - -- :example:`wifi/iperf` demonstrates how to implement the protocol used by the iPerf performance measurement tool, allowing for performance measurement between two chips or between a single chip and a computer running the iPerf tool, with specific instructions for testing station/soft-AP TCP/UDP RX/TX throughput. - -- :example:`wifi/roaming/roaming_app` demonstrates how to use the Wi-Fi Roaming App functionality to efficiently roam between compatible APs. - -- :example:`wifi/roaming/roaming_11kvr` demonstrates how to implement roaming using 11k and 11v APIs. - -.. only:: SOC_WIFI_HE_SUPPORT - - - :example:`wifi/itwt` demonstrates how to use the iTWT feature, which only works in station mode and under different power save modes, with commands for setup, teardown, and suspend, and also shows the difference in current consumption when iTWT is enabled or disabled. - -Setting Wi-Fi Compile-time Options -++++++++++++++++++++++++++++++++++++ - -Refer to `Wi-Fi Menuconfig`_. - -Init Wi-Fi -+++++++++++ - -Refer to `{IDF_TARGET_NAME} Wi-Fi station General Scenario`_ and `{IDF_TARGET_NAME} Wi-Fi AP General Scenario`_. - -Start/Connect Wi-Fi -++++++++++++++++++++ - -Refer to `{IDF_TARGET_NAME} Wi-Fi station General Scenario`_ and `{IDF_TARGET_NAME} Wi-Fi AP General Scenario`_. - -Event-Handling -++++++++++++++ - -Generally, it is easy to write code in "sunny-day" scenarios, such as `WIFI_EVENT_STA_START`_ and `WIFI_EVENT_STA_CONNECTED`_. The hard part is to write routines in "rainy-day" scenarios, such as `WIFI_EVENT_STA_DISCONNECTED`_. Good handling of "rainy-day" scenarios is fundamental to robust Wi-Fi applications. Refer to `{IDF_TARGET_NAME} Wi-Fi Event Description`_, `{IDF_TARGET_NAME} Wi-Fi station General Scenario`_, and `{IDF_TARGET_NAME} Wi-Fi AP General Scenario`_. See also the :doc:`overview of the Event Loop Library in ESP-IDF <../api-reference/system/esp_event>`. - -Write Error-Recovery Routines Correctly at All Times -++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Just like the handling of "rainy-day" scenarios, a good error-recovery routine is also fundamental to robust Wi-Fi applications. Refer to `{IDF_TARGET_NAME} Wi-Fi API Error Code`_. - - -{IDF_TARGET_NAME} Wi-Fi API Error Code --------------------------------------- - -All of the {IDF_TARGET_NAME} Wi-Fi APIs have well-defined return values, namely, the error code. The error code can be categorized into: - - - No errors, e.g., :c:macro:`ESP_OK` means that the API returns successfully. - - Recoverable errors, such as :c:macro:`ESP_ERR_NO_MEM`. - - Non-recoverable, non-critical errors. - - Non-recoverable, critical errors. - -Whether the error is critical or not depends on the API and the application scenario, and it is defined by the API user. - -**The primary principle to write a robust application with Wi-Fi API is to always check the error code and write the error-handling code.** Generally, the error-handling code can be used: - - - For recoverable errors, in which case you can write a recoverable-error code. For example, when :cpp:func:`esp_wifi_start()` returns :c:macro:`ESP_ERR_NO_MEM`, the recoverable-error code vTaskDelay can be called in order to get a microseconds' delay for another try. - - For non-recoverable, yet non-critical errors, in which case printing the error code is a good method for error handling. - - For non-recoverable and also critical errors, in which case "assert" may be a good method for error handling. For example, if :cpp:func:`esp_wifi_set_mode()` returns ``ESP_ERR_WIFI_NOT_INIT``, it means that the Wi-Fi driver is not initialized by :cpp:func:`esp_wifi_init()` successfully. You can detect this kind of error very quickly in the application development phase. - -In :component_file:`esp_common/include/esp_err.h`, ``ESP_ERROR_CHECK`` checks the return values. It is a rather commonplace error-handling code and can be used as the default error-handling code in the application development phase. However, it is strongly recommended that API users write their own error-handling code. - -{IDF_TARGET_NAME} Wi-Fi API Parameter Initialization ----------------------------------------------------- - -When initializing struct parameters for the API, one of two approaches should be followed: - -- Explicitly set all fields of the parameter. -- Use get API to get current configuration first, then set application specific fields. - -Initializing or getting the entire structure is very important, because most of the time the value 0 indicates that the default value is used. More fields may be added to the struct in the future and initializing these to zero ensures the application will still work correctly after ESP-IDF is updated to a new release. - -.. _wifi-programming-model: - -{IDF_TARGET_NAME} Wi-Fi Programming Model ------------------------------------------ - -The {IDF_TARGET_NAME} Wi-Fi programming model is depicted as follows: - -.. blockdiag:: - :caption: Wi-Fi Programming Model - :align: center - - blockdiag wifi-programming-model { - - # global attributes - node_height = 60; - node_width = 100; - span_width = 100; - span_height = 60; - default_shape = roundedbox; - default_group_color = none; - - # node labels - TCP_STACK [label="TCP\n stack", fontsize=12]; - EVNT_TASK [label="Event\n task", fontsize=12]; - APPL_TASK [label="Application\n task", width = 120, fontsize=12]; - WIFI_DRV [label="Wi-Fi\n Driver", width = 120, fontsize=12]; - KNOT [shape=none]; - - # node connections + labels - TCP_STACK -> EVNT_TASK [label=event]; - EVNT_TASK -> APPL_TASK [label="callback\n or event"]; - - # arrange nodes vertically - group { - label = "default handler"; - orientation = portrait; - EVNT_TASK <- WIFI_DRV [label=event]; - } - - # intermediate node - group { - label = "user handler"; - orientation = portrait; - APPL_TASK -- KNOT; - } - WIFI_DRV <- KNOT [label="API\n call"]; - } - - -The Wi-Fi driver can be considered a black box that knows nothing about high-layer code, such as the TCP/IP stack, application task, and event task. The application task (code) generally calls :doc:`Wi-Fi driver APIs <../api-reference/network/esp_wifi>` to initialize Wi-Fi and handles Wi-Fi events when necessary. Wi-Fi driver receives API calls, handles them, and posts events to the application. - -Wi-Fi event handling is based on the :doc:`esp_event library <../api-reference/system/esp_event>`. Events are sent by the Wi-Fi driver to the :ref:`default event loop `. Application may handle these events in callbacks registered using :cpp:func:`esp_event_handler_register()`. Wi-Fi events are also handled by :doc:`esp_netif component <../api-reference/network/esp_netif>` to provide a set of default behaviors. For example, when Wi-Fi station connects to an AP, esp_netif will automatically start the DHCP client by default. - - -{IDF_TARGET_NAME} Wi-Fi Event Description ------------------------------------------ - -WIFI_EVENT_WIFI_READY -++++++++++++++++++++++++++++++++++++ - -The Wi-Fi driver will never generate this event, which, as a result, can be ignored by the application event callback. This event may be removed in future releases. - -WIFI_EVENT_SCAN_DONE -++++++++++++++++++++++++++++++++++++ - -The scan-done event is triggered by :cpp:func:`esp_wifi_scan_start()` and will arise in the following scenarios: - - - The scan is completed, e.g., the target AP is found successfully, or all channels have been scanned. - - The scan is stopped by :cpp:func:`esp_wifi_scan_stop()`. - - The :cpp:func:`esp_wifi_scan_start()` is called before the scan is completed. A new scan will override the current scan and a scan-done event will be generated. - -The scan-done event will not arise in the following scenarios: - - - It is a blocked scan. - - The scan is caused by :cpp:func:`esp_wifi_connect()`. - -Upon receiving this event, the event task does nothing. The application event callback needs to call :cpp:func:`esp_wifi_scan_get_ap_num()` and :cpp:func:`esp_wifi_scan_get_ap_records()` to fetch the scanned AP list and trigger the Wi-Fi driver to free the internal memory which is allocated during the scan **(do not forget to do this!)**. -Refer to `{IDF_TARGET_NAME} Wi-Fi Scan`_ for a more detailed description. - -WIFI_EVENT_STA_START -++++++++++++++++++++++++++++++++++++ - -If :cpp:func:`esp_wifi_start()` returns :c:macro:`ESP_OK` and the current Wi-Fi mode is station or station/AP, then this event will arise. Upon receiving this event, the event task will initialize the LwIP network interface (netif). Generally, the application event callback needs to call :cpp:func:`esp_wifi_connect()` to connect to the configured AP. - -WIFI_EVENT_STA_STOP -++++++++++++++++++++++++++++++++++++ - -If :cpp:func:`esp_wifi_stop()` returns :c:macro:`ESP_OK` and the current Wi-Fi mode is station or station/AP, then this event will arise. Upon receiving this event, the event task will release the station's IP address, stop the DHCP client, remove TCP/UDP-related connections, and clear the LwIP station netif, etc. The application event callback generally does not need to do anything. - -WIFI_EVENT_STA_CONNECTED -++++++++++++++++++++++++++++++++++++ - -If :cpp:func:`esp_wifi_connect()` returns :c:macro:`ESP_OK` and the station successfully connects to the target AP, the connection event will arise. Upon receiving this event, the event task starts the DHCP client and begins the DHCP process of getting the IP address. Then, the Wi-Fi driver is ready for sending and receiving data. This moment is good for beginning the application work, provided that the application does not depend on LwIP, namely the IP address. However, if the application is LwIP-based, then you need to wait until the *got ip* event comes in. - -WIFI_EVENT_STA_DISCONNECTED -++++++++++++++++++++++++++++++++++++ - -This event can be generated in the following scenarios: - - - When :cpp:func:`esp_wifi_disconnect()` or :cpp:func:`esp_wifi_stop()` is called and the station is already connected to the AP. - - When :cpp:func:`esp_wifi_connect()` is called, but the Wi-Fi driver fails to set up a connection with the AP due to certain reasons, e.g., the scan fails to find the target AP or the authentication times out. If there are more than one AP with the same SSID, the disconnected event will be raised after the station fails to connect all of the found APs. - - When the Wi-Fi connection is disrupted because of specific reasons, e.g., the station continuously loses N beacons, the AP kicks off the station, or the AP's authentication mode is changed. - -Upon receiving this event, the default behaviors of the event task are: - -- Shutting down the station's LwIP netif. -- Notifying the LwIP task to clear the UDP/TCP connections which cause the wrong status to all sockets. For socket-based applications, the application callback can choose to close all sockets and re-create them, if necessary, upon receiving this event. - -The most common event handle code for this event in application is to call :cpp:func:`esp_wifi_connect()` to reconnect the Wi-Fi. However, if the event is raised because :cpp:func:`esp_wifi_disconnect()` is called, the application should not call :cpp:func:`esp_wifi_connect()` to reconnect. It is the application's responsibility to distinguish whether the event is caused by :cpp:func:`esp_wifi_disconnect()` or other reasons. Sometimes a better reconnection strategy is required. Refer to `Wi-Fi Reconnect`_ and `Scan When Wi-Fi Is Connecting`_. - -Another thing that deserves attention is that the default behavior of LwIP is to abort all TCP socket connections on receiving the disconnect. In most cases, it is not a problem. However, for some special applications, this may not be what they want. Consider the following scenarios: - -- The application creates a TCP connection to maintain the application-level keep-alive data that is sent out every 60 seconds. -- Due to certain reasons, the Wi-Fi connection is cut off, and the `WIFI_EVENT_STA_DISCONNECTED`_ is raised. According to the current implementation, all TCP connections will be removed and the keep-alive socket will be in a wrong status. However, since the application designer believes that the network layer should **ignore** this error at the Wi-Fi layer, the application does not close the socket. -- Five seconds later, the Wi-Fi connection is restored because :cpp:func:`esp_wifi_connect()` is called in the application event callback function. **Moreover, the station connects to the same AP and gets the same IPV4 address as before**. -- Sixty seconds later, when the application sends out data with the keep-alive socket, the socket returns an error and the application closes the socket and re-creates it when necessary. - -In above scenarios, ideally, the application sockets and the network layer should not be affected, since the Wi-Fi connection only fails temporarily and recovers very quickly. - -IP_EVENT_STA_GOT_IP -++++++++++++++++++++++++++++++++++++ - -This event arises when the DHCP client successfully gets the IPV4 address from the DHCP server, or when the IPV4 address is changed. The event means that everything is ready and the application can begin its tasks (e.g., creating sockets). - -The IPV4 may be changed because of the following reasons: - - - The DHCP client fails to renew/rebind the IPV4 address, and the station's IPV4 is reset to 0. - - The DHCP client rebinds to a different address. - - The static-configured IPV4 address is changed. - -Whether the IPV4 address is changed or not is indicated by the field ``ip_change`` of ``ip_event_got_ip_t``. - -The socket is based on the IPV4 address, which means that, if the IPV4 changes, all sockets relating to this IPV4 will become abnormal. Upon receiving this event, the application needs to close all sockets and recreate the application when the IPV4 changes to a valid one. - -IP_EVENT_GOT_IP6 -++++++++++++++++++++++++++++++++++++ - -This event arises when the IPV6 SLAAC support auto-configures an address for the {IDF_TARGET_NAME}, or when this address changes. The event means that everything is ready and the application can begin its tasks, e.g., creating sockets. - -IP_EVENT_STA_LOST_IP -++++++++++++++++++++++++++++++++++++ - -This event arises when the IPV4 address becomes invalid. - -IP_EVENT_STA_LOST_IP does not arise immediately after the Wi-Fi disconnects. Instead, it starts an IPV4 address lost timer (configurable via :ref:`CONFIG_ESP_NETIF_LOST_IP_TIMER_ENABLE` and :ref:`CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL`). If the IPV4 address is got before the timer expires, IP_EVENT_STA_LOST_IP does not happen. Otherwise, the event arises when the IPV4 address lost timer expires. - -Generally, the application can ignore this event, because it is just a debug event to inform that the IPV4 address is lost. - -WIFI_EVENT_AP_START -++++++++++++++++++++++++++++++++++++ - -Similar to `WIFI_EVENT_STA_START`_. - -WIFI_EVENT_AP_STOP -++++++++++++++++++++++++++++++++++++ - -Similar to `WIFI_EVENT_STA_STOP`_. - -WIFI_EVENT_AP_STACONNECTED -++++++++++++++++++++++++++++++++++++ - -Every time a station is connected to {IDF_TARGET_NAME} AP, the `WIFI_EVENT_AP_STACONNECTED`_ will arise. Upon receiving this event, the event task will do nothing, and the application callback can also ignore it. However, you may want to do something, for example, to get the info of the connected STA. - -WIFI_EVENT_AP_STADISCONNECTED -++++++++++++++++++++++++++++++++++++ - -This event can happen in the following scenarios: - - - The application calls :cpp:func:`esp_wifi_disconnect()`, or :cpp:func:`esp_wifi_deauth_sta()`, to manually disconnect the station. - - The Wi-Fi driver kicks off the station, e.g., because the AP has not received any packets in the past five minutes. The time can be modified by :cpp:func:`esp_wifi_set_inactive_time()`. - - The station kicks off the AP. - -When this event happens, the event task will do nothing, but the application event callback needs to do something, e.g., close the socket which is related to this station. - -WIFI_EVENT_AP_PROBEREQRECVED -++++++++++++++++++++++++++++++++++++ - -This event is disabled by default. The application can enable it via API :cpp:func:`esp_wifi_set_event_mask()`. -When this event is enabled, it will be raised each time the AP receives a probe request. - -WIFI_EVENT_STA_BEACON_TIMEOUT -++++++++++++++++++++++++++++++++++++ - -If the station does not receive the beacon of the connected AP within the inactive time, the beacon timeout happens, the `WIFI_EVENT_STA_BEACON_TIMEOUT`_ will arise. The application can set inactive time via API :cpp:func:`esp_wifi_set_inactive_time()`. - -WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -The `WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START`_ will arise at the start of connectionless module `Interval`. See :ref:`connectionless module power save `. - -{IDF_TARGET_NAME} Wi-Fi Station General Scenario ------------------------------------------------- - -Below is a "big scenario" which describes some small scenarios in station mode: - -.. seqdiag:: - :caption: Sample Wi-Fi Event Scenarios in Station Mode - :align: center - - seqdiag sample-scenarios-station-mode { - activation = none; - node_width = 80; - node_height = 60; - edge_length = 140; - span_height = 5; - default_shape = roundedbox; - default_fontsize = 12; - - MAIN_TASK [label = "Main\ntask"]; - APP_TASK [label = "App\ntask"]; - EVENT_TASK [label = "Event\ntask"]; - LwIP_TASK [label = "LwIP\ntask"]; - WIFI_TASK [label = "Wi-Fi\ntask"]; - - === 1. Init Phase === - MAIN_TASK -> LwIP_TASK [label="1.1> Create / init LwIP"]; - MAIN_TASK -> EVENT_TASK [label="1.2> Create / init event"]; - MAIN_TASK -> WIFI_TASK [label="1.3> Create / init Wi-Fi"]; - MAIN_TASK -> APP_TASK [label="1.4> Create app task"]; - === 2. Configure Phase === - MAIN_TASK -> WIFI_TASK [label="2> Configure Wi-Fi"]; - === 3. Start Phase === - MAIN_TASK -> WIFI_TASK [label="3.1> Start Wi-Fi"]; - EVENT_TASK <- WIFI_TASK [label="3.2> WIFI_EVENT_STA_START"]; - APP_TASK <- EVENT_TASK [label="3.3> WIFI_EVENT_STA_START"]; - === 4. Connect Phase === - APP_TASK -> WIFI_TASK [label="4.1> Connect Wi-Fi"]; - EVENT_TASK <- WIFI_TASK [label="4.2> WIFI_EVENT_STA_CONNECTED"]; - APP_TASK <- EVENT_TASK [label="4.3> WIFI_EVENT_STA_CONNECTED"]; - === 5. Got IP Phase === - EVENT_TASK -> LwIP_TASK [label="5.1> Start DHCP client"]; - EVENT_TASK <- LwIP_TASK [label="5.2> IP_EVENT_STA_GOT_IP"]; - APP_TASK <- EVENT_TASK [label="5.3> IP_EVENT_STA_GOT_IP"]; - APP_TASK -> APP_TASK [label="5.4> socket related init"]; - === 6. Disconnect Phase === - EVENT_TASK <- WIFI_TASK [label="6.1> WIFI_EVENT_STA_DISCONNECTED"]; - APP_TASK <- EVENT_TASK [label="6.2> WIFI_EVENT_STA_DISCONNECTED"]; - APP_TASK -> APP_TASK [label="6.3> disconnect handling"]; - === 7. IP Change Phase === - EVENT_TASK <- LwIP_TASK [label="7.1> IP_EVENT_STA_GOT_IP"]; - APP_TASK <- EVENT_TASK [label="7.2> IP_EVENT_STA_GOT_IP"]; - APP_TASK -> APP_TASK [label="7.3> Socket error handling"]; - === 8. Deinit Phase === - APP_TASK -> WIFI_TASK [label="8.1> Disconnect Wi-Fi"]; - APP_TASK -> WIFI_TASK [label="8.2> Stop Wi-Fi"]; - APP_TASK -> WIFI_TASK [label="8.3> Deinit Wi-Fi"]; - } - - -1. Wi-Fi/LwIP Init Phase -++++++++++++++++++++++++++++++ - - - s1.1: The main task calls :cpp:func:`esp_netif_init()` to create an LwIP core task and initialize LwIP-related work. - - - s1.2: The main task calls :cpp:func:`esp_event_loop_create()` to create a system Event task and initialize an application event's callback function. In the scenario above, the application event's callback function does nothing but relaying the event to the application task. - - - s1.3: The main task calls :cpp:func:`esp_netif_create_default_wifi_ap()` or :cpp:func:`esp_netif_create_default_wifi_sta()` to create default network interface instance binding station or AP with TCP/IP stack. - - - s1.4: The main task calls :cpp:func:`esp_wifi_init()` to create the Wi-Fi driver task and initialize the Wi-Fi driver. - - - s1.5: The main task calls OS API to create the application task. - -Step 1.1 ~ 1.5 is a recommended sequence that initializes a Wi-Fi-/LwIP-based application. However, it is **NOT** a must-follow sequence, which means that you can create the application task in step 1.1 and put all other initialization in the application task. Moreover, you may not want to create the application task in the initialization phase if the application task depends on the sockets. Rather, you can defer the task creation until the IP is obtained. - -2. Wi-Fi Configuration Phase -+++++++++++++++++++++++++++++++ - -Once the Wi-Fi driver is initialized, you can start configuring the Wi-Fi driver. In this scenario, the mode is station, so you may need to call :cpp:func:`esp_wifi_set_mode` (WIFI_MODE_STA) to configure the Wi-Fi mode as station. You can call other `esp_wifi_set_xxx` APIs to configure more settings, such as the protocol mode, the country code, and the bandwidth. Refer to `{IDF_TARGET_NAME} Wi-Fi Configuration`_. - -Generally, the Wi-Fi driver should be configured before the Wi-Fi connection is set up. But this is **NOT** mandatory, which means that you can configure the Wi-Fi connection anytime, provided that the Wi-Fi driver is initialized successfully. However, if the configuration does not need to change after the Wi-Fi connection is set up, you should configure the Wi-Fi driver at this stage, because the configuration APIs (such as :cpp:func:`esp_wifi_set_protocol()`) will cause the Wi-Fi to reconnect, which may not be desirable. - -If the Wi-Fi NVS flash is enabled by menuconfig, all Wi-Fi configuration in this phase, or later phases, will be stored into flash. When the board powers on/reboots, you do not need to configure the Wi-Fi driver from scratch. You only need to call ``esp_wifi_get_xxx`` APIs to fetch the configuration stored in flash previously. You can also configure the Wi-Fi driver if the previous configuration is not what you want. - -3. Wi-Fi Start Phase -++++++++++++++++++++++++++++++++ - - - s3.1: Call :cpp:func:`esp_wifi_start()` to start the Wi-Fi driver. - - s3.2: The Wi-Fi driver posts `WIFI_EVENT_STA_START`_ to the event task; then, the event task will do some common things and will call the application event callback function. - - s3.3: The application event callback function relays the `WIFI_EVENT_STA_START`_ to the application task. We recommend that you call :cpp:func:`esp_wifi_connect()`. However, you can also call :cpp:func:`esp_wifi_connect()` in other phrases after the `WIFI_EVENT_STA_START`_ arises. - -4. Wi-Fi Connect Phase -+++++++++++++++++++++++++++++++++ - - - s4.1: Once :cpp:func:`esp_wifi_connect()` is called, the Wi-Fi driver will start the internal scan/connection process. - - - s4.2: If the internal scan/connection process is successful, the `WIFI_EVENT_STA_CONNECTED`_ will be generated. In the event task, it starts the DHCP client, which will finally trigger the DHCP process. - - - s4.3: In the above-mentioned scenario, the application event callback will relay the event to the application task. Generally, the application needs to do nothing, and you can do whatever you want, e.g., print a log. - -In step 4.2, the Wi-Fi connection may fail because, for example, the password is wrong, or the AP is not found. In a case like this, `WIFI_EVENT_STA_DISCONNECTED`_ will arise and the reason for such a failure will be provided. For handling events that disrupt Wi-Fi connection, please refer to phase 6. - -5. Wi-Fi 'Got IP' Phase -+++++++++++++++++++++++++++++++++ - - - s5.1: Once the DHCP client is initialized in step 4.2, the *got IP* phase will begin. - - s5.2: If the IP address is successfully received from the DHCP server, then `IP_EVENT_STA_GOT_IP`_ will arise and the event task will perform common handling. - - s5.3: In the application event callback, `IP_EVENT_STA_GOT_IP`_ is relayed to the application task. For LwIP-based applications, this event is very special and means that everything is ready for the application to begin its tasks, e.g., creating the TCP/UDP socket. A very common mistake is to initialize the socket before `IP_EVENT_STA_GOT_IP`_ is received. **DO NOT start the socket-related work before the IP is received.** - -6. Wi-Fi Disconnect Phase -+++++++++++++++++++++++++++++++++ - - - s6.1: When the Wi-Fi connection is disrupted, e.g., the AP is powered off or the RSSI is poor, `WIFI_EVENT_STA_DISCONNECTED`_ will arise. This event may also arise in phase 3. Here, the event task will notify the LwIP task to clear/remove all UDP/TCP connections. Then, all application sockets will be in a wrong status. In other words, no socket can work properly when this event happens. - - s6.2: In the scenario described above, the application event callback function relays `WIFI_EVENT_STA_DISCONNECTED`_ to the application task. The recommended actions are: 1) call :cpp:func:`esp_wifi_connect()` to reconnect the Wi-Fi, 2) close all sockets, and 3) re-create them if necessary. For details, please refer to `WIFI_EVENT_STA_DISCONNECTED`_. - -7. Wi-Fi IP Change Phase -++++++++++++++++++++++++++++++++++ - - - s7.1: If the IP address is changed, the `IP_EVENT_STA_GOT_IP`_ will arise with "ip_change" set to true. - - s7.2: **This event is important to the application. When it occurs, the timing is good for closing all created sockets and recreating them.** - - -8. Wi-Fi Deinit Phase -++++++++++++++++++++++++++++ - - - s8.1: Call :cpp:func:`esp_wifi_disconnect()` to disconnect the Wi-Fi connectivity. - - s8.2: Call :cpp:func:`esp_wifi_stop()` to stop the Wi-Fi driver. - - s8.3: Call :cpp:func:`esp_wifi_deinit()` to unload the Wi-Fi driver. - - -{IDF_TARGET_NAME} Wi-Fi AP General Scenario ---------------------------------------------- - -Below is a "big scenario" which describes some small scenarios in AP mode: - - .. seqdiag:: - :caption: Sample Wi-Fi Event Scenarios in AP Mode - :align: center - - seqdiag sample-scenarios-soft-ap-mode { - activation = none; - node_width = 80; - node_height = 60; - edge_length = 140; - span_height = 5; - default_shape = roundedbox; - default_fontsize = 12; - - MAIN_TASK [label = "Main\ntask"]; - APP_TASK [label = "App\ntask"]; - EVENT_TASK [label = "Event\ntask"]; - LwIP_TASK [label = "LwIP\ntask"]; - WIFI_TASK [label = "Wi-Fi\ntask"]; - - === 1. Init Phase === - MAIN_TASK -> LwIP_TASK [label="1.1> Create / init LwIP"]; - MAIN_TASK -> EVENT_TASK [label="1.2> Create / init event"]; - MAIN_TASK -> WIFI_TASK [label="1.3> Create / init Wi-Fi"]; - MAIN_TASK -> APP_TASK [label="1.4> Create app task"]; - === 2. Configure Phase === - MAIN_TASK -> WIFI_TASK [label="2> Configure Wi-Fi"]; - === 3. Start Phase === - MAIN_TASK -> WIFI_TASK [label="3.1> Start Wi-Fi"]; - EVENT_TASK <- WIFI_TASK [label="3.2> WIFI_EVENT_AP_START"]; - APP_TASK <- EVENT_TASK [label="3.3> WIFI_EVENT_AP_START"]; - === 4. Connect Phase === - EVENT_TASK <- WIFI_TASK [label="4.1> WIFI_EVENT_AP_STACONNECTED"]; - APP_TASK <- EVENT_TASK [label="4.2> WIFI_EVENT_AP_STACONNECTED"]; - === 5. Disconnect Phase === - EVENT_TASK <- WIFI_TASK [label="5.1> WIFI_EVENT_AP_STADISCONNECTED"]; - APP_TASK <- EVENT_TASK [label="5.2> WIFI_EVENT_AP_STADISCONNECTED"]; - APP_TASK -> APP_TASK [label="5.3> disconnect handling"]; - === 6. Deinit Phase === - APP_TASK -> WIFI_TASK [label="6.1> Disconnect Wi-Fi"]; - APP_TASK -> WIFI_TASK [label="6.2> Stop Wi-Fi"]; - APP_TASK -> WIFI_TASK [label="6.3> Deinit Wi-Fi"]; - } - - -{IDF_TARGET_NAME} Wi-Fi Scan ----------------------------- - -Currently, the :cpp:func:`esp_wifi_scan_start()` API is supported only in station or station/AP mode. - -Scan Type -+++++++++++++++++++++++++ - -.. list-table:: - :header-rows: 1 - :widths: 15 50 - - * - Mode - - Description - * - Active Scan - - Scan by sending a probe request. The default scan is an active scan. - * - Passive Scan - - No probe request is sent out. Just switch to the specific channel and wait for a beacon. Application can enable it via the scan_type field of :cpp:type:`wifi_scan_config_t`. - * - Foreground Scan - - This scan is applicable when there is no Wi-Fi connection in station mode. Foreground or background scanning is controlled by the Wi-Fi driver and cannot be configured by the application. - * - Background Scan - - This scan is applicable when there is a Wi-Fi connection in station mode or in station/AP mode. Whether it is a foreground scan or background scan depends on the Wi-Fi driver and cannot be configured by the application. - * - All-Channel Scan - - It scans all of the channels. If the channel field of :cpp:type:`wifi_scan_config_t` is set to 0, it is an all-channel scan. - * - Specific Channel Scan - - It scans specific channels only. If the channel field of :cpp:type:`wifi_scan_config_t` set to 1-14, it is a specific-channel scan. - -The scan modes in above table can be combined arbitrarily, so there are in total 8 different scans: - - - All-Channel Background Active Scan - - All-Channel Background Passive Scan - - All-Channel Foreground Active Scan - - All-Channel Foreground Passive Scan - - Specific-Channel Background Active Scan - - Specific-Channel Background Passive Scan - - Specific-Channel Foreground Active Scan - - Specific-Channel Foreground Passive Scan - -Scan Configuration -+++++++++++++++++++++++++++++++++++++++ - -The scan type and other per-scan attributes are configured by :cpp:func:`esp_wifi_scan_start()`. The table below provides a detailed description of :cpp:type:`wifi_scan_config_t`. - -.. list-table:: - :header-rows: 1 - :widths: 15 50 - - * - Field - - Description - * - ssid - - If the SSID is not NULL, it is only the AP with the same SSID that can be scanned. - * - bssid - - If the BSSID is not NULL, it is only the AP with the same BSSID that can be scanned. - * - channel - - If “channel” is 0, there will be an all-channel scan; otherwise, there will be a specific-channel scan. - * - show_hidden - - If “show_hidden” is 0, the scan ignores the AP with a hidden SSID; otherwise, the scan considers the hidden AP a normal one. - * - scan_type - - If “scan_type” is WIFI_SCAN_TYPE_ACTIVE, the scan is “active”; otherwise, it is a “passive” one. - * - scan_time - - This field is used to control how long the scan dwells on each channel. - - For passive scans, scan_time.passive designates the dwell time for each channel. - - For active scans, dwell times for each channel are listed in the table below. Here, min is short for scan time.active.min and max is short for scan_time.active.max. - - - min=0, max=0: scan dwells on each channel for 120 ms. - - min>0, max=0: scan dwells on each channel for 120 ms. - - min=0, max>0: scan dwells on each channel for ``max`` ms. - - min>0, max>0: the minimum time the scan dwells on each channel is ``min`` ms. If no AP is found during this time frame, the scan switches to the next channel. Otherwise, the scan dwells on the channel for ``max`` ms. - - If you want to improve the performance of the scan, you can try to modify these two parameters. - - -There are also some global scan attributes which are configured by API :cpp:func:`esp_wifi_set_config()`, refer to `Station Basic Configuration`_ - -Scan All APs on All Channels (Foreground) -+++++++++++++++++++++++++++++++++++++++++++++ - -Scenario: - -.. seqdiag:: - :caption: Foreground Scan of all Wi-Fi Channels - :align: center - - seqdiag foreground-scan-all-channels { - activation = none; - node_width = 80; - node_height = 60; - edge_length = 160; - span_height = 5; - default_shape = roundedbox; - default_fontsize = 12; - - APP_TASK [label = "App\ntask"]; - EVENT_TASK [label = "Event\ntask"]; - WIFI_TASK [label = "Wi-Fi\ntask"]; - - APP_TASK -> WIFI_TASK [label="1.1 > Configure country code"]; - APP_TASK -> WIFI_TASK [label="1.2 > Scan configuration"]; - WIFI_TASK -> WIFI_TASK [label="2.1 > Scan channel 1"]; - WIFI_TASK -> WIFI_TASK [label="2.2 > Scan channel 2"]; - WIFI_TASK -> WIFI_TASK [label="..."]; - WIFI_TASK -> WIFI_TASK [label="2.x > Scan channel N"]; - EVENT_TASK <- WIFI_TASK [label="3.1 > WIFI_EVENT_SCAN_DONE"]; - APP_TASK <- EVENT_TASK [label="3.2 > WIFI_EVENT_SCAN_DONE"]; - } - - -The scenario above describes an all-channel, foreground scan. The foreground scan can only occur in station mode where the station does not connect to any AP. Whether it is a foreground or background scan is totally determined by the Wi-Fi driver, and cannot be configured by the application. - -Detailed scenario description: - -Scan Configuration Phase -************************** - - - s1.1: Call :cpp:func:`esp_wifi_set_country()` to set the country info if the default country info is not what you want. Refer to `Wi-Fi Country Code`_. - - s1.2: Call :cpp:func:`esp_wifi_scan_start()` to configure the scan. To do so, you can refer to `Scan Configuration`_. Since this is an all-channel scan, just set the SSID/BSSID/channel to 0. - - -Wi-Fi Driver's Internal Scan Phase -************************************** - - - s2.1: The Wi-Fi driver switches to channel 1. In this case, the scan type is WIFI_SCAN_TYPE_ACTIVE, and a probe request is broadcasted. Otherwise, the Wi-Fi will wait for a beacon from the APs. The Wi-Fi driver will stay in channel 1 for some time. The dwell time is configured in min/max time, with the default value being 120 ms. - - s2.2: The Wi-Fi driver switches to channel 2 and performs the same operation as in step 2.1. - - s2.3: The Wi-Fi driver scans the last channel N, where N is determined by the country code which is configured in step 1.1. - -Scan-Done Event Handling Phase -********************************* - - - s3.1: When all channels are scanned, `WIFI_EVENT_SCAN_DONE`_ will arise. - - s3.2: The application's event callback function notifies the application task that `WIFI_EVENT_SCAN_DONE`_ is received. :cpp:func:`esp_wifi_scan_get_ap_num()` is called to get the number of APs that have been found in this scan. Then, it allocates enough entries and calls :cpp:func:`esp_wifi_scan_get_ap_records()` to get the AP records. Please note that the AP records in the Wi-Fi driver will be freed once :cpp:func:`esp_wifi_scan_get_ap_records()` is called. Do not call :cpp:func:`esp_wifi_scan_get_ap_records()` twice for a single scan-done event. If :cpp:func:`esp_wifi_scan_get_ap_records()` is not called when the scan-done event occurs, the AP records allocated by the Wi-Fi driver will not be freed. So, make sure you call :cpp:func:`esp_wifi_scan_get_ap_records()`, yet only once. - -Scan All APs on All Channels (Background) -++++++++++++++++++++++++++++++++++++++++++ - -Scenario: - -.. seqdiag:: - :caption: Background Scan of all Wi-Fi Channels - :align: center - - seqdiag background-scan-all-channels { - activation = none; - node_width = 80; - node_height = 60; - edge_length = 160; - span_height = 5; - default_shape = roundedbox; - default_fontsize = 12; - - APP_TASK [label = "App\ntask"]; - EVENT_TASK [label = "Event\ntask"]; - WIFI_TASK [label = "Wi-Fi\ntask"]; - - APP_TASK -> WIFI_TASK [label="1.1 > Configure country code"]; - APP_TASK -> WIFI_TASK [label="1.2 > Scan configuration"]; - WIFI_TASK -> WIFI_TASK [label="2.1 > Scan channel 1"]; - WIFI_TASK -> WIFI_TASK [label="2.2 > Back to home channel H"]; - WIFI_TASK -> WIFI_TASK [label="2.3 > Scan channel 2"]; - WIFI_TASK -> WIFI_TASK [label="2.4 > Back to home channel H"]; - WIFI_TASK -> WIFI_TASK [label="..."]; - WIFI_TASK -> WIFI_TASK [label="2.x-1 > Scan channel N"]; - WIFI_TASK -> WIFI_TASK [label="2.x > Back to home channel H"]; - EVENT_TASK <- WIFI_TASK [label="3.1 > WIFI_EVENT_SCAN_DONE"]; - APP_TASK <- EVENT_TASK [label="3.2 > WIFI_EVENT_SCAN_DONE"]; - } - -The scenario above is an all-channel background scan. Compared to `Scan All APs on All Channels (Foreground)`_ , the difference in the all-channel background scan is that the Wi-Fi driver will scan the back-to-home channel for 30 ms before it switches to the next channel to give the Wi-Fi connection a chance to transmit/receive data. - -Scan for Specific AP on All Channels -+++++++++++++++++++++++++++++++++++++++ - -Scenario: - -.. seqdiag:: - :caption: Scan of specific Wi-Fi Channels - :align: center - - seqdiag scan-specific-channels { - activation = none; - node_width = 80; - node_height = 60; - edge_length = 160; - span_height = 5; - default_shape = roundedbox; - default_fontsize = 12; - - APP_TASK [label = "App\ntask"]; - EVENT_TASK [label = "Event\ntask"]; - WIFI_TASK [label = "Wi-Fi\ntask"]; - - APP_TASK -> WIFI_TASK [label="1.1 > Configure country code"]; - APP_TASK -> WIFI_TASK [label="1.2 > Scan configuration"]; - WIFI_TASK -> WIFI_TASK [label="2.1 > Scan channel C1"]; - WIFI_TASK -> WIFI_TASK [label="2.2 > Scan channel C2"]; - WIFI_TASK -> WIFI_TASK [label="..."]; - WIFI_TASK -> WIFI_TASK [label="2.x > Scan channel CN, or the AP is found"]; - EVENT_TASK <- WIFI_TASK [label="3.1 > WIFI_EVENT_SCAN_DONE"]; - APP_TASK <- EVENT_TASK [label="3.2 > WIFI_EVENT_SCAN_DONE"]; - } - -This scan is similar to `Scan All APs on All Channels (Foreground)`_. The differences are: - - - s1.1: In step 1.2, the target AP will be configured to SSID/BSSID. - - s2.1 ~ s2.N: Each time the Wi-Fi driver scans an AP, it will check whether it is a target AP or not. If the scan is ``WIFI_FAST_SCAN`` scan and the target AP is found, then the scan-done event will arise and scanning will end; otherwise, the scan will continue. Please note that the first scanned channel may not be channel 1, because the Wi-Fi driver optimizes the scanning sequence. - -It is a possible situation that there are multiple APs that match the target AP info, e.g., two APs with the SSID of "ap" are scanned. In this case, if the scan is ``WIFI_FAST_SCAN``, then only the first scanned "ap" will be found. If the scan is ``WIFI_ALL_CHANNEL_SCAN``, both "ap" will be found and the station will connect the "ap" according to the configured strategy. Refer to `Station Basic Configuration`_. - -You can scan a specific AP, or all of them, in any given channel. These two scenarios are very similar. - -Scan in Wi-Fi Connect -+++++++++++++++++++++++++ - -When :cpp:func:`esp_wifi_connect()` is called, the Wi-Fi driver will try to scan the configured AP first. The scan in "Wi-Fi Connect" is the same as `Scan for Specific AP On All Channels`_, except that no scan-done event will be generated when the scan is completed. If the target AP is found, the Wi-Fi driver will start the Wi-Fi connection; otherwise, `WIFI_EVENT_STA_DISCONNECTED`_ will be generated. Refer to `Scan for Specific AP On All Channels`_. - -Scan in Blocked Mode -++++++++++++++++++++ - -If the block parameter of :cpp:func:`esp_wifi_scan_start()` is true, then the scan is a blocked one, and the application task will be blocked until the scan is done. The blocked scan is similar to an unblocked one, except that no scan-done event will arise when the blocked scan is completed. - -Parallel Scan -+++++++++++++ - -Two application tasks may call :cpp:func:`esp_wifi_scan_start()` at the same time, or the same application task calls :cpp:func:`esp_wifi_scan_start()` before it gets a scan-done event. Both scenarios can happen. **However, the Wi-Fi driver does not support multiple concurrent scans adequately. As a result, concurrent scans should be avoided.** Support for concurrent scan will be enhanced in future releases, as the {IDF_TARGET_NAME}'s Wi-Fi functionality improves continuously. - -Scan When Wi-Fi Is Connecting -+++++++++++++++++++++++++++++++ - -The :cpp:func:`esp_wifi_scan_start()` fails immediately if the Wi-Fi is connecting, because the connecting has higher priority than the scan. If scan fails because of connecting, the recommended strategy is to delay for some time and retry scan again. The scan will succeed once the connecting is completed. - -However, the retry/delay strategy may not work all the time. Considering the following scenarios: - -- The station is connecting a non-existing AP or it connects the existing AP with a wrong password, it always raises the event `WIFI_EVENT_STA_DISCONNECTED`_. -- The application calls :cpp:func:`esp_wifi_connect()` to reconnect on receiving the disconnect event. -- Another application task, e.g., the console task, calls :cpp:func:`esp_wifi_scan_start()` to do scan, the scan always fails immediately because the station keeps connecting. -- When scan fails, the application simply delays for some time and retries the scan. - -In the above scenarios, the scan will never succeed because the connecting is in process. So if the application supports similar scenario, it needs to implement a better reconnection strategy. For example: - -- The application can choose to define a maximum continuous reconnection counter and stop reconnecting once the counter reaches the maximum. -- The application can choose to reconnect immediately in the first N continuous reconnection, then give a delay sometime and reconnect again. - -The application can define its own reconnection strategy to avoid the scan starve to death. Refer to <`Wi-Fi Reconnect`_>. - -{IDF_TARGET_NAME} Wi-Fi Station Connecting Scenario ---------------------------------------------------- - -This scenario depicts the case if only one target AP is found in the scan phase. For scenarios where more than one AP with the same SSID is found, refer to `{IDF_TARGET_NAME} Wi-Fi Station Connecting When Multiple APs Are Found`_. - -Generally, the application can ignore the connecting process. Below is a brief introduction to the process for those who are really interested. - -Scenario: - -.. seqdiag:: - :caption: Wi-Fi Station Connecting Process - :align: center - - seqdiag station-connecting-process { - activation = none; - node_width = 80; - node_height = 60; - edge_length = 160; - span_height = 5; - default_shape = roundedbox; - default_fontsize = 12; - - EVENT_TASK [label = "Event\ntask"]; - WIFI_TASK [label = "Wi-Fi\ntask"]; - AP [label = "AP"]; - - === 1. Scan Phase === - WIFI_TASK -> WIFI_TASK [label="1.1 > Scan"]; - EVENT_TASK <- WIFI_TASK [label="1.2 > WIFI_EVENT_STA_DISCONNECTED"]; - === 2. Auth Phase === - WIFI_TASK -> AP [label="2.1 > Auth request"]; - EVENT_TASK <- WIFI_TASK [label="2.2 > WIFI_EVENT_STA_DISCONNECTED"]; - WIFI_TASK <- AP [label="2.3 > Auth response"]; - EVENT_TASK <- WIFI_TASK [label="2.4 > WIFI_EVENT_STA_DISCONNECTED"]; - === 3. Assoc Phase === - WIFI_TASK -> AP [label="3.1 > Assoc request"]; - EVENT_TASK <- WIFI_TASK [label="3.2 > WIFI_EVENT_STA_DISCONNECTED"]; - WIFI_TASK <- AP [label="3.3 > Assoc response"]; - EVENT_TASK <- WIFI_TASK [label="3.4 > WIFI_EVENT_STA_DISCONNECTED"]; - === 4. 4-way Handshake Phase === - EVENT_TASK <- WIFI_TASK [label="4.1 > WIFI_EVENT_STA_DISCONNECTED"]; - WIFI_TASK <- AP [label="4.2 > 1/4 EAPOL"]; - WIFI_TASK -> AP [label="4.3 > 2/4 EAPOL"]; - EVENT_TASK <- WIFI_TASK [label="4.4 > WIFI_EVENT_STA_DISCONNECTED"]; - WIFI_TASK <- AP [label="4.5 > 3/4 EAPOL"]; - WIFI_TASK -> AP [label="4.6 > 4/4 EAPOL"]; - EVENT_TASK <- WIFI_TASK [label="4.7 > WIFI_EVENT_STA_CONNECTED"]; - } - - -Scan Phase -+++++++++++++++++++++ - - - s1.1: The Wi-Fi driver begins scanning in "Wi-Fi Connect". Refer to `Scan in Wi-Fi Connect`_ for more details. - - s1.2: If the scan fails to find the target AP, `WIFI_EVENT_STA_DISCONNECTED`_ will arise and the reason code could either be ``WIFI_REASON_NO_AP_FOUND`` or ``WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY`` or ``WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD`` or ``WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD`` depending of the Station's configuration. Refer to `Wi-Fi Reason Code`_. - -Auth Phase -+++++++++++++++++++++ - - - s2.1: The authentication request packet is sent and the auth timer is enabled. - - s2.2: If the authentication response packet is not received before the authentication timer times out, `WIFI_EVENT_STA_DISCONNECTED`_ will arise and the reason code will be ``WIFI_REASON_AUTH_EXPIRE``. Refer to `Wi-Fi Reason Code`_. - - s2.3: The auth-response packet is received and the auth-timer is stopped. - - s2.4: The AP rejects authentication in the response and `WIFI_EVENT_STA_DISCONNECTED`_ arises, while the reason code is ``WIFI_REASON_AUTH_FAIL`` or the reasons specified by the AP. Refer to `Wi-Fi Reason Code`_. - -Association Phase -+++++++++++++++++++++ - - - s3.1: The association request is sent and the association timer is enabled. - - s3.2: If the association response is not received before the association timer times out, `WIFI_EVENT_STA_DISCONNECTED`_ will arise and the reason code will be ``WIFI_REASON_DISASSOC_DUE_TO_INACTIVITY``. Refer to `Wi-Fi Reason Code`_. - - s3.3: The association response is received and the association timer is stopped. - - s3.4: The AP rejects the association in the response and `WIFI_EVENT_STA_DISCONNECTED`_ arises, while the reason code is the one specified in the association response. Refer to `Wi-Fi Reason Code`_. - - -Four-way Handshake Phase -++++++++++++++++++++++++++ - - - s4.1: The handshake timer is enabled, and the 1/4 EAPOL is not received before the handshake timer expires. `WIFI_EVENT_STA_DISCONNECTED`_ will arise and the reason code will be ``WIFI_REASON_HANDSHAKE_TIMEOUT``. Refer to `Wi-Fi Reason Code`_. - - s4.2: The 1/4 EAPOL is received. - - s4.3: The station replies 2/4 EAPOL. - - s4.4: If the 3/4 EAPOL is not received before the handshake timer expires, `WIFI_EVENT_STA_DISCONNECTED`_ will arise and the reason code will be ``WIFI_REASON_HANDSHAKE_TIMEOUT``. Refer to `Wi-Fi Reason Code`_. - - s4.5: The 3/4 EAPOL is received. - - s4.6: The station replies 4/4 EAPOL. - - s4.7: The station raises `WIFI_EVENT_STA_CONNECTED`_. - - -.. _esp_wifi_reason_code: - -Wi-Fi Reason Code -+++++++++++++++++++++ - -The table below shows the reason-code defined in {IDF_TARGET_NAME}. The first column is the macro name defined in :component_file:`esp_wifi/include/esp_wifi_types.h`. The common prefix ``WIFI_REASON`` is removed, which means that ``UNSPECIFIED`` actually stands for ``WIFI_REASON_UNSPECIFIED`` and so on. The second column is the value of the reason. This reason value is same as defined in section 9.4.1.7 of IEEE 802.11-2020. (For more information, refer to the standard mentioned above.) The last column describes the reason. Reason-codes starting from 200 are Espressif defined reason-codes and are not part of IEEE 802.11-2020.\ - -Also note that REASON_NO_AP_FOUND_XXX codes are mentioned in increasing order of importance. So if a single AP has a combination of the above reasons for failure, the more important one will be reported. Additionally, if there are multiple APs that satisfy the identifying criteria and connecting to all of them fails for different reasons mentioned above, then the reason code reported is for the AP that failed connection due to the least important reason code, as it was the one closest to a successful connection.\ - -Following reason codes are renamed to their shorter form to wrap the table in page width. - -- TRANSMISSION_LINK_ESTABLISHMENT_FAILED : TX_LINK_EST_FAILED -- NO_AP_FOUND_W_COMPATIBLE_SECURITY : NO_AP_FOUND_SECURITY -- NO_AP_FOUND_IN_AUTHMODE_THRESHOLD : NO_AP_FOUND_AUTHMODE -- NO_AP_FOUND_IN_RSSI_THRESHOLD : NO_AP_FOUND_RSSI - -.. list-table:: - :header-rows: 1 - :widths: 41 10 49 - :class: longtable - - * - Reason code - - Value - - Description - * - UNSPECIFIED - - 1 - - Generally, it means an internal failure, e.g., the memory runs out, the internal TX fails, or the reason is received from the remote side. - * - AUTH_EXPIRE - - 2 - - The previous authentication is no longer valid. - - For the ESP station, this reason is reported when: - - - auth is timed out. - - the reason is received from the AP. - - For the ESP AP, this reason is reported when: - - - the AP has not received any packets from the station in the past five minutes. - - the AP is stopped by calling :cpp:func:`esp_wifi_stop()`. - - the station is de-authed by calling :cpp:func:`esp_wifi_deauth_sta()`. - * - AUTH_LEAVE - - 3 - - De-authenticated, because the sending station is leaving (or has left). - - For the ESP station, this reason is reported when: - - - it is received from the AP. - * - DISASSOC_DUE_TO_INACTIVITY - - 4 - - Disassociated due to inactivity. - - For the ESP station, this reason is reported when: - - - assoc is timed out. - - it is received from the AP. - - * - ASSOC_TOOMANY - - 5 - - Disassociated, because the AP is unable to handle all currently associated STAs at the same time. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - - For the ESP AP, this reason is reported when: - - - the stations associated with the AP reach the maximum number that the AP can support. - * - CLASS2_FRAME_FROM_NONAUTH_STA - - 6 - - Class-2 frame received from a non-authenticated STA. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - - For the ESP AP, this reason is reported when: - - - the AP receives a packet with data from a non-authenticated station. - * - CLASS3_FRAME_FROM_NONASSOC_STA - - 7 - - Class-3 frame received from a non-associated STA. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - - For the ESP AP, this reason is reported when: - - - the AP receives a packet with data from a non-associated station. - * - ASSOC_LEAVE - - 8 - - Disassociated, because the sending station is leaving (or has left) BSS. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - - the station is disconnected by :cpp:func:`esp_wifi_disconnect()` and other APIs. - * - ASSOC_NOT_AUTHED - - 9 - - station requesting (re)association is not authenticated by the responding STA. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - - For the ESP AP, this reason is reported when: - - - the AP receives packets with data from an associated, yet not authenticated, station. - * - DISASSOC_PWRCAP_BAD - - 10 - - Disassociated, because the information in the Power Capability element is unacceptable. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - * - DISASSOC_SUPCHAN_BAD - - 11 - - Disassociated, because the information in the Supported Channels element is unacceptable. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - * - BSS_TRANSITION_DISASSOC - - 12 - - AP wants us to move to another AP, sent as a part of BTM procedure. Please note that when station is sending BTM request and moving to another AP, ROAMING reason code will be reported instead of this. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - * - IE_INVALID - - 13 - - Invalid element, i.e., an element whose content does not meet the specifications of the Standard in frame formats clause. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - - For the ESP AP, this reason is reported when: - - - the AP parses a wrong WPA or RSN IE. - * - MIC_FAILURE - - 14 - - Message integrity code (MIC) failure. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - * - 4WAY_HANDSHAKE_TIMEOUT - - 15 - - Four-way handshake times out. For legacy reasons, in ESP this reason code is replaced with ``WIFI_REASON_HANDSHAKE_TIMEOUT``. - - For the ESP station, this reason is reported when: - - - the handshake times out. - - it is received from the AP. - * - GROUP_KEY_UPDATE_TIMEOUT - - 16 - - Group-Key Handshake times out. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - * - IE_IN_4WAY_DIFFERS - - 17 - - The element in the four-way handshake is different from the (Re-)Association Request/Probe and Response/Beacon frame. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - - the station finds that the four-way handshake IE differs from the IE in the (Re-)Association Request/Probe and Response/Beacon frame. - * - GROUP_CIPHER_INVALID - - 18 - - Invalid group cipher. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - * - PAIRWISE_CIPHER_INVALID - - 19 - - Invalid pairwise cipher. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - * - AKMP_INVALID - - 20 - - Invalid AKMP. - - For the ESP station, this reason is reported when: - - it is received from the AP. - * - UNSUPP_RSN_IE_VERSION - - 21 - - Unsupported RSNE version. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - * - INVALID_RSN_IE_CAP - - 22 - - Invalid RSNE capabilities. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - * - 802_1X_AUTH_FAILED - - 23 - - IEEE 802.1X. authentication failed. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - - For the ESP AP, this reason is reported when: - - - IEEE 802.1X. authentication fails. - * - CIPHER_SUITE_REJECTED - - 24 - - Cipher suite rejected due to security policies. - - For the ESP station, this reason is reported when: - - - it is received from the AP. - * - TDLS_PEER_UNREACHABLE - - 25 - - TDLS direct-link teardown due to TDLS peer STA unreachable via the TDLS direct link. - * - TDLS_UNSPECIFIED - - 26 - - TDLS direct-link teardown for unspecified reason. - * - SSP_REQUESTED_DISASSOC - - 27 - - Disassociated because session terminated by SSP request. - * - NO_SSP_ROAMING_AGREEMENT - - 28 - - Disassociated because of lack of SSP roaming agreement. - * - BAD_CIPHER_OR_AKM - - 29 - - Requested service rejected because of SSP cipher suite or AKM requirement. - * - NOT_AUTHORIZED_THIS_LOCATION - - 30 - - Requested service not authorized in this location. - * - SERVICE_CHANGE_PRECLUDES_TS - - 31 - - TS deleted because QoS AP lacks sufficient bandwidth for this QoS STA due to a change in BSS service characteristics or operational mode (e.g., an HT BSS change from 40 MHz channel to 20 MHz channel). - * - UNSPECIFIED_QOS - - 32 - - Disassociated for unspecified, QoS-related reason. - * - NOT_ENOUGH_BANDWIDTH - - 33 - - Disassociated because QoS AP lacks sufficient bandwidth for this QoS STA. - * - MISSING_ACKS - - 34 - - Disassociated because excessive number of frames need to be acknowledged, but are not acknowledged due to AP transmissions and/or poor channel conditions. - * - EXCEEDED_TXOP - - 35 - - Disassociated because STA is transmitting outside the limits of its TXOPs. - * - STA_LEAVING - - 36 - - Requesting STA is leaving the BSS (or resetting). - * - END_BA - - 37 - - Requesting STA is no longer using the stream or session. - * - UNKNOWN_BA - - 38 - - Requesting STA received frames using a mechanism for which a setup has not been completed. - * - TIMEOUT - - 39 - - Requested from peer STA due to timeout - * - Reserved - - 40 ~ 45 - - Reserved as per IEEE80211-2020 specifications. - * - PEER_INITIATED - - 46 - - In a Disassociation frame: Disassociated because authorized access limit reached. - * - AP_INITIATED - - 47 - - In a Disassociation frame: Disassociated due to external service requirements. - * - INVALID_FT_ACTION_FRAME_COUNT - - 48 - - Invalid FT Action frame count. - * - INVALID_PMKID - - 49 - - Invalid pairwise master key identifier (PMKID). - * - INVALID_MDE - - 50 - - Invalid MDE. - * - INVALID_FTE - - 51 - - Invalid FTE - * - TX_LINK_EST_FAILED - - 67 - - TRANSMISSION_LINK_ESTABLISHMENT_FAILED will be reported when Transmission link establishment in alternative channel failed. - * - ALTERATIVE_CHANNEL_OCCUPIED - - 68 - - The alternative channel is occupied. - * - BEACON_TIMEOUT - - 200 - - Espressif-specific Wi-Fi reason code: when the station loses N beacons continuously, it will disrupt the connection and report this reason. - * - NO_AP_FOUND - - 201 - - Espressif-specific Wi-Fi reason code: when the station fails to scan the target AP, this reason code will be reported. In case of security mismatch or station's configuration mismatch, new reason codes NO_AP_FOUND_XXX will be reported. - * - AUTH_FAIL - - 202 - - Espressif-specific Wi-Fi reason code: the authentication fails, but not because of a timeout. - * - ASSOC_FAIL - - 203 - - Espressif-specific Wi-Fi reason code: the association fails, but not because of DISASSOC_DUE_TO_INACTIVITY or ASSOC_TOOMANY. - * - HANDSHAKE_TIMEOUT - - 204 - - Espressif-specific Wi-Fi reason code: the handshake fails for the same reason as that in WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT. - * - CONNECTION_FAIL - - 205 - - Espressif-specific Wi-Fi reason code: the connection to the AP has failed. - * - AP_TSF_RESET - - 206 - - Espressif-specific Wi-Fi reason code: the disconnection happened due to AP's TSF reset. - * - ROAMING - - 207 - - Espressif-specific Wi-Fi reason code: the station is roaming to another AP, this reason code is just for info, station will automatically move to another AP. - * - ASSOC_COMEBACK_TIME_TOO_LONG - - 208 - - Espressif-specific Wi-Fi reason code: This reason code will be reported when Assoc comeback time in association response is too high. - * - SA_QUERY_TIMEOUT - - 209 - - Espressif-specific Wi-Fi reason code: This reason code will be reported when AP did not reply of SA query sent by ESP station. - * - NO_AP_FOUND_SECURITY - - 210 - - Espressif-specific Wi-Fi reason code: NO_AP_FOUND_W_COMPATIBLE_SECURITY will be reported if an AP that fits identifying criteria (e.g. ssid) is found but the connection is rejected due to incompatible security configuration. These situations could be: - - - The Access Point is offering WEP security, but our station's password is not WEP-compliant. - - The station is configured in Open mode; however, the Access Point is broadcasting in secure mode. - - The Access Point uses Enterprise security, but we haven't set up the corresponding enterprise configuration, and vice versa. - - SAE-PK is configured in the station configuration, but the Access Point does not support SAE-PK. - - SAE-H2E is configured in the station configuration; however, the AP only supports WPA3-PSK or WPA3-WPA2-PSK. - - The station is configured in secure mode (Password or Enterprise mode); however, an Open AP is found during the scan. - - SAE HnP is configured in the station configuration; however, the AP supports H2E only. - - H2E is disabled in the station configuration; however, the AP is WPA3-EXT-PSK, which requires H2E support. - - The Access Point requires PMF, but the station is not configured for PMF capable/required. - - The station configuration requires PMF, but the AP is not configured for PMF capable/required. - - The Access Point is using unsupported group management/pairwise ciphers. - - OWE is not enabled in the station configuration, but the discovered AP is using OWE only mode. - - The Access Point is broadcasting an invalid RSNXE in its beacons. - - The Access Point is in Independent BSS mode. - - * - NO_AP_FOUND_AUTHMODE - - 211 - - Espressif-specific Wi-Fi reason code: NO_AP_FOUND_IN_AUTHMODE_THRESHOLD will be reported if an AP that fit identifying criteria (e.g. ssid) is found but the authmode threhsold set in the wifi_config_t is not met. - * - NO_AP_FOUND_RSSI - - 212 - - Espressif-specific Wi-Fi reason code: NO_AP_FOUND_IN_RSSI_THRESHOLD will be reported if an AP that fits identifying criteria (e.g. ssid) is found but the RSSI threhsold set in the wifi_config_t is not met. - -Wi-Fi Reason code related to wrong password -++++++++++++++++++++++++++++++++++++++++++++++ - -The table below shows the Wi-Fi reason-code may related to wrong password. - -.. list-table:: - :header-rows: 1 - :widths: 5 10 40 - - * - Reason code - - Value - - Description - * - 4WAY_HANDSHAKE_TIMEOUT - - 15 - - Four-way handshake times out. Setting wrong password when STA connecting to an encrypted AP. - * - NO_AP_FOUND - - 201 - - This may related to wrong password in the two scenarios: - - - Setting password when STA connecting to an unencrypted AP. - - Does not set password when STA connecting to an encrypted AP. - * - HANDSHAKE_TIMEOUT - - 204 - - Four-way handshake fails. - -Wi-Fi Reason code related to low RSSI -++++++++++++++++++++++++++++++++++++++++++++++ - -The table below shows the Wi-Fi reason-code may related to low RSSI. - -.. list-table:: - :header-rows: 1 - :widths: 5 10 40 - - * - Reason code - - Value - - Description - * - NO_AP_FOUND_IN_RSSI_THRESHOLD - - 212 - - The station fails to scan the target AP due to low RSSI - * - HANDSHAKE_TIMEOUT - - 204 - - Four-way handshake fails. - - -{IDF_TARGET_NAME} Wi-Fi Station Connecting When Multiple APs Are Found ----------------------------------------------------------------------- - -This scenario is similar as `{IDF_TARGET_NAME} Wi-Fi Station Connecting Scenario`_. The difference is that the station will not raise the event `WIFI_EVENT_STA_DISCONNECTED`_ unless it fails to connect all of the found APs. - -Wi-Fi Reconnect ---------------------------- - -The station may disconnect due to many reasons, e.g., the connected AP is restarted. It is the application's responsibility to reconnect. The recommended reconnection strategy is to call :cpp:func:`esp_wifi_connect()` on receiving event `WIFI_EVENT_STA_DISCONNECTED`_. - -Sometimes the application needs more complex reconnection strategy: - -- If the disconnect event is raised because the :cpp:func:`esp_wifi_disconnect()` is called, the application may not want to do the reconnection. -- If the :cpp:func:`esp_wifi_scan_start()` may be called at anytime, a better reconnection strategy is necessary. Refer to `Scan When Wi-Fi Is Connecting`_. - -Another thing that need to be considered is that the reconnection may not connect the same AP if there are more than one APs with the same SSID. The reconnection always select current best APs to connect. - -Wi-Fi Beacon Timeout ---------------------------- - -The beacon timeout mechanism is used by {IDF_TARGET_NAME} station to detect whether the AP is alive or not. If the station does not receive the beacon of the connected AP within the inactive time, the beacon timeout happens. The application can set inactive time via API :cpp:func:`esp_wifi_set_inactive_time()`. - -After the beacon times out, the station sends 5 probe requests to the AP. If still no probe response or beacon is received from AP, the station disconnects from the AP and raises the event `WIFI_EVENT_STA_DISCONNECTED`_. - -It should be considered that the timer used for beacon timeout will be reset during the scanning process. It means that the scan process will affect the triggering of the event `WIFI_EVENT_STA_BEACON_TIMEOUT`_. - -{IDF_TARGET_NAME} Wi-Fi Configuration -------------------------------------- - -All configurations will be stored into flash when the Wi-Fi NVS is enabled; otherwise, refer to `Wi-Fi NVS Flash`_. - -Wi-Fi Mode -+++++++++++++++++++++++++ -Call :cpp:func:`esp_wifi_set_mode()` to set the Wi-Fi mode. - -.. list-table:: - :header-rows: 1 - :widths: 15 50 - - * - Mode - - Description - * - ``WIFI_MODE_NULL`` - - NULL mode: in this mode, the internal data struct is not allocated to the station and the AP, while both the station and AP interfaces are not initialized for RX/TX Wi-Fi data. Generally, this mode is used for Sniffer, or when you only want to stop both the station and the AP without calling :cpp:func:`esp_wifi_deinit()` to unload the whole Wi-Fi driver. - * - ``WIFI_MODE_STA`` - - Station mode: in this mode, :cpp:func:`esp_wifi_start()` will init the internal station data, while the station’s interface is ready for the RX and TX Wi-Fi data. After :cpp:func:`esp_wifi_connect()`, the station will connect to the target AP. - * - ``WIFI_MODE_AP`` - - AP mode: in this mode, :cpp:func:`esp_wifi_start()` will init the internal AP data, while the AP’s interface is ready for RX/TX Wi-Fi data. Then, the Wi-Fi driver starts broad-casting beacons, and the AP is ready to get connected to other stations. - * - ``WIFI_MODE_APSTA`` - - Station/AP coexistence mode: in this mode, :cpp:func:`esp_wifi_start()` will simultaneously initialize both the station and the AP. This is done in station mode and AP mode. Please note that the channel of the external AP, which the ESP station is connected to, has higher priority over the ESP AP channel. - -.. only:: esp32c5 - - Wi-Fi Band Mode Configuration - ++++++++++++++++++++++++++++++ - - The Wi-Fi band mode used by {IDF_TARGET_NAME} can be set via the function :cpp:func:`esp_wifi_set_band_mode()`. - - .. list-table:: - :header-rows: 1 - :widths: 15 50 - - * - Mode - - Description - * - ``WIFI_BAND_MODE_2G_ONLY`` - - **2.4 GHz band mode**: The device operates only on 2.4 GHz band channels. - * - ``WIFI_BAND_MODE_5G_ONLY`` - - **5 GHz band mode**: The device operates only on 5 GHz band channels. - * - ``WIFI_BAND_MODE_AUTO`` - - **2.4 GHz + 5 GHz auto mode**: The device automatically selects either the 2.4 GHz or 5 GHz band based on the connected AP or SoftAP configuration. - - .. note:: - - ``WIFI_BAND_MODE_AUTO`` does not mean simultaneous dual-band support; it only allows automatic band selection. - - When operating in ``WIFI_BAND_MODE_AUTO`` mode, protocols and bandwidth can be configured separately for the 2.4 GHz and 5 GHz bands: - - - Use the function :cpp:func:`esp_wifi_set_protocols()` to set the supported protocol types for each band (e.g., 802.11b/g/n/ac/ax); - - - Use the function :cpp:func:`esp_wifi_set_bandwidths()` to set the bandwidth for each band (e.g., 20 MHz, 40 MHz). - -.. only:: esp32c5 - - AP Choose - +++++++++++++++++++++++++ - - When the device scans multiple APs with the same SSID, {IDF_TARGET_NAME} selects the most suitable AP to connect to based on signal strength (RSSI) and band information. The default policy usually prefers the AP with higher RSSI; however, in environments where 2.4 GHz and 5 GHz coexist, this can cause the device to favor the 2.4 GHz band, ignoring the performance benefits of the 5 GHz band. - - To address this, ESP-IDF provides the field :cpp:member:`rssi_5g_adjustment` in the :cpp:type:`wifi_scan_threshold_t` structure to optimize the priority of selecting 5 GHz APs. - - .. list-table:: - :header-rows: 1 - :widths: 30 70 - - * - Field - - Description - * - ``rssi_5g_adjustment`` - - Used to adjust priority between 2.4 GHz and 5 GHz APs with the same SSID. The default value is ``10``, meaning when the 5 GHz AP's RSSI is within 10 dB lower than the 2.4 GHz AP, the 5 GHz AP will be preferred. Properly setting this parameter helps the device prioritize 5 GHz networks that offer better bandwidth and interference resistance when signal strengths are close. - - Example: - - Suppose the device scans the following two APs with the SSID "MyWiFi": - - - 2.4 GHz AP: RSSI = -60 dBm - - 5 GHz AP: RSSI = -68 dBm - - Since ``rssi_5g_adjustment = 10`` (default) and ``-68 > -60 - 10`` holds true, the device will prioritize connecting to the 5 GHz AP. - - .. note:: - - This parameter only takes effect when scanning results contain APs with the same SSID on both 2.4 GHz and 5 GHz bands. Its purpose is to avoid always connecting to a 2.4 GHz network with slightly stronger signal but poorer performance. - -Station Basic Configuration -+++++++++++++++++++++++++++++++++++++ - -API :cpp:func:`esp_wifi_set_config()` can be used to configure the station. And the configuration will be stored in NVS. The table below describes the fields in detail. - -.. list-table:: - :header-rows: 1 - :widths: 15 50 - - * - Field - - Description - * - ssid - - This is the SSID of the target AP, to which the station wants to connect. - * - password - - Password of the target AP. - * - scan_method - - For ``WIFI_FAST_SCAN`` scan, the scan ends when the first matched AP is found. For ``WIFI_ALL_CHANNEL_SCAN``, the scan finds all matched APs on all channels. The default scan is ``WIFI_FAST_SCAN``. - * - bssid_set - - If bssid_set is 0, the station connects to the AP whose SSID is the same as the field “ssid”, while the field “bssid” is ignored. In all other cases, the station connects to the AP whose SSID is the same as the “ssid” field, while its BSSID is the same the “bssid” field . - * - bssid - - This is valid only when bssid_set is 1; see field “bssid_set”. - * - channel - - If the channel is 0, the station scans the channel 1 ~ N to search for the target AP; otherwise, the station starts by scanning the channel whose value is the same as that of the “channel” field, and then scans the channel 1 ~ N but skip the specific channel to find the target AP. For example, if the channel is 3, the scan order will be 3, 1, 2, 4,..., N. If you do not know which channel the target AP is running on, set it to 0. - * - sort_method - - This field is only for ``WIFI_ALL_CHANNEL_SCAN``. - - If the sort_method is ``WIFI_CONNECT_AP_BY_SIGNAL``, all matched APs are sorted by signal, and the AP with the best signal will be connected firstly. For example, the station wants to connect an AP whose SSID is “apxx”. If the scan finds two APs whose SSID equals to “apxx”, and the first AP’s signal is -90 dBm while the second AP’s signal is -30 dBm, the station connects the second AP firstly, and it would not connect the first one unless it fails to connect the second one. - - If the sort_method is ``WIFI_CONNECT_AP_BY_SECURITY``, all matched APs are sorted by security. For example, the station wants to connect an AP whose SSID is “apxx”. If the scan finds two APs whose SSID is “apxx”, and the security of the first found AP is open while the second one is WPA2, the station connects to the second AP firstly, and it would not connect the first one unless it fails to connect the second one. - * - threshold - - The threshold is used to filter the found AP. If the RSSI or security mode is less than the configured threshold, the AP will be discarded. - - If the RSSI is set to 0, it means the default threshold and the default RSSI threshold are -127 dBm. If the authmode threshold is set to 0, it means the default threshold and the default authmode threshold are open. - - -.. attention:: - - WEP/WPA security modes are deprecated in IEEE 802.11-2016 specifications and are recommended not to be used. These modes can be rejected using authmode threshold by setting threshold as WPA2 by threshold.authmode as ``WIFI_AUTH_WPA2_PSK``. - -AP Basic Configuration -+++++++++++++++++++++++++++++++++++++ - -API :cpp:func:`esp_wifi_set_config()` can be used to configure the AP. And the configuration will be stored in NVS. The table below describes the fields in detail. - -.. only:: esp32 or esp32s2 or esp32s3 or esp32c3 or esp32c5 or esp32c6 - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - Field - - Description - * - ssid - - SSID of AP; if the ssid[0] is 0xFF and ssid[1] is 0xFF, the AP defaults the SSID to ``ESP_aabbcc``, where “aabbcc” is the last three bytes of the AP MAC. - * - password - - Password of AP; if the auth mode is ``WIFI_AUTH_OPEN``, this field will be ignored. - * - ssid_len - - Length of SSID; if ssid_len is 0, check the SSID until there is a termination character. If ssid_len > 32, change it to 32; otherwise, set the SSID length according to ssid_len. - * - channel - - Channel of AP; if the channel is out of range, the Wi-Fi driver will return error. So, please make sure the channel is within the required range. For more details, refer to `Wi-Fi Country Code`_. - * - authmode - - Auth mode of ESP AP; currently, ESP AP does not support AUTH_WEP. If the authmode is an invalid value, AP defaults the value to ``WIFI_AUTH_OPEN``. - * - ssid_hidden - - If ssid_hidden is 1, AP does not broadcast the SSID; otherwise, it does broadcast the SSID. - * - max_connection - - The max number of stations allowed to connect in, the default value is 10. ESP Wi-Fi supports up to {IDF_TARGET_MAX_CONN_STA_NUM} (``ESP_WIFI_MAX_CONN_NUM``) Wi-Fi connections. Please note that ESP AP and ESP-NOW share the same encryption hardware keys, so the max_connection parameter will be affected by the :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`. The total number of encryption hardware keys is 17, if :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM` <= {IDF_TARGET_SUB_MAX_NUM_FROM_KEYS}, the max_connection can be set up to {IDF_TARGET_MAX_CONN_STA_NUM}, otherwise the max_connection can be set up to (17 - :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`). - * - beacon_interval - - Beacon interval; the value is 100 ~ 60000 ms, with default value being 100 ms. If the value is out of range, AP defaults it to 100 ms. - - -.. only:: esp32c2 - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - Field - - Description - * - ssid - - SSID of AP; if the ssid[0] is 0xFF and ssid[1] is 0xFF, the AP defaults the SSID to ``ESP_aabbcc``, where “aabbcc” is the last three bytes of the AP MAC. - * - password - - Password of AP; if the auth mode is ``WIFI_AUTH_OPEN``, this field will be ignored. - * - ssid_len - - Length of SSID; if ssid_len is 0, check the SSID until there is a termination character. If ssid_len > 32, change it to 32; otherwise, set the SSID length according to ssid_len. - * - channel - - Channel of AP; if the channel is out of range, the Wi-Fi driver defaults to channel 1. So, please make sure the channel is within the required range. For more details, refer to `Wi-Fi Country Code`_. - * - authmode - - Auth mode of ESP AP; currently, ESP AP does not support AUTH_WEP. If the authmode is an invalid value, AP defaults the value to ``WIFI_AUTH_OPEN``. - * - ssid_hidden - - If ssid_hidden is 1, AP does not broadcast the SSID; otherwise, it does broadcast the SSID. - * - max_connection - - The max number of stations allowed to connect in, the default value is 2. ESP Wi-Fi supports up to {IDF_TARGET_MAX_CONN_STA_NUM} (``ESP_WIFI_MAX_CONN_NUM``) Wi-Fi connections. Please note that ESP AP and ESP-NOW share the same encryption hardware keys, so the max_connection parameter will be affected by the :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`. The total number of encryption hardware keys is {IDF_TARGET_MAX_CONN_STA_NUM}, the max_connection can be set up to ({IDF_TARGET_MAX_CONN_STA_NUM} - :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`). - * - beacon_interval - - Beacon interval; the value is 100 ~ 60000 ms, with default value being 100 ms. If the value is out of range, AP defaults it to 100 ms. - - -Wi-Fi Protocol Mode -+++++++++++++++++++++++++ - -Currently, the ESP-IDF supports the following protocol modes: - -.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - Protocol Mode - - Description - * - 802.11b - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B)`` to set the station/AP to 802.11b-only mode. - * - 802.11bg - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` to set the station/AP to 802.11bg mode. - * - 802.11g - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` and esp_wifi_config_11b_rate(ifx, true) to set the station/AP to 802.11g mode. - * - 802.11bgn - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` to set the station/ AP to BGN mode. - * - 802.11gn - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` and esp_wifi_config_11b_rate(ifx, true) to set the station/AP to 802.11gn mode. - * - 802.11 BGNLR - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_LR)`` to set the station/AP to BGN and the LR mode. - * - 802.11 LR - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_LR)`` to set the station/AP only to the LR mode. - - **This mode is an Espressif-patented mode which can achieve a one-kilometer line of sight range. Please make sure both the station and the AP are connected to an ESP device.** - -.. only:: esp32c6 - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - Protocol Mode - - Description - * - 802.11b - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B)`` to set the station/AP to 802.11b-only mode. - * - 802.11bg - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` to set the station/AP to 802.11bg mode. - * - 802.11g - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` and ``esp_wifi_config_11b_rate(ifx, true)`` to set the station/AP to 802.11g mode. - * - 802.11bgn - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` to set the station/ AP to BGN mode. - * - 802.11gn - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` and esp_wifi_config_11b_rate(ifx, true) to set the station/AP to 802.11gn mode. - * - 802.11 BGNLR - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_LR)`` to set the station/AP to BGN and the LR mode. - * - 802.11bgnax - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_11AX)`` to set the station/ AP to 802.11bgnax mode. - * - 802.11 BGNAXLR - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_11AX|WIFI_PROTOCOL_LR)`` to set the station/ AP to 802.11bgnax and LR mode. - * - 802.11 LR - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_LR)`` to set the station/AP only to the LR mode. - - **This mode is an Espressif-patented mode which can achieve a one-kilometer line of sight range. Please make sure both the station and the AP are connected to an ESP device.** - -.. only:: esp32c5 - - - **2.4 GHz band**: Supports 802.11b, 802.11bg, 802.11bgn, 802.11bgnax, and Espressif's proprietary LR mode. - - **5 GHz band**: Supports 802.11a, 802.11an, 802.11anac, and 802.11anacax. - - {IDF_TARGET_NAME} supports configuring Wi-Fi protocol modes for the 2.4 GHz and 5 GHz bands separately. It is recommended to use :cpp:func:`esp_wifi_set_protocols()` for this purpose. The legacy API :cpp:func:`esp_wifi_set_protocol()` is also supported. - - **Recommended Usage** - - Use the new API :cpp:func:`esp_wifi_set_protocols()` to configure each band independently: - - .. code-block:: c - - // Set 2.4 GHz to use 802.11bgnax, and 5 GHz to use 802.11anacax - wifi_protocols_t protocols = { - .ghz_2g = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX, - .ghz_5g = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AC | WIFI_PROTOCOL_11AX, - }; - esp_wifi_set_protocols(WIFI_IF_STA, &protocols); - - **Legacy Usage** - - Use the legacy API :cpp:func:`esp_wifi_set_protocol()` to configure the protocol mode for 2.4 GHz band or 5 GHz band: - - .. code-block:: c - - // Set band mode to 2.4 GHz band - esp_wifi_set_band_mode(WIFI_BAND_MODE_2G_ONLY); - - // Set protocol of station to 802.11bgnax - uint8_t protocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX; - esp_wifi_set_protocol(WIFI_IF_STA, protocol); - - .. note:: - - - The new API `esp_wifi_set_protocols()` allows configuring both bands simultaneously and is recommended for use on {IDF_TARGET_NAME}. - - The function ``esp_wifi_set_protocol()`` is suitable for single-band scenarios, such as when ``WIFI_BAND_MODE_2G_ONLY`` or ``WIFI_BAND_MODE_5G_ONLY`` is used. It only takes effect on the currently connected band. For example, if the interface is operating on the 5 GHz band, any configuration for the 2.4 GHz band will be ignored. - - If the configuration includes unsupported protocol combinations, the function will return an error. - - To enable Espressif's proprietary LR mode, make sure to include `WIFI_PROTOCOL_LR` in the 2.4 GHz protocol configuration. - -.. only:: esp32c2 - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - Protocol Mode - - Description - * - 802.11b - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B)`` to set the station/AP to 802.11b-only mode. - * - 802.11bg - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` to set the station/AP to 802.11bg mode. - * - 802.11g - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G) and esp_wifi_config_11b_rate(ifx, true)`` to set the station/AP to 802.11g mode. - * - 802.11bgn - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B| WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` to set the station/ AP to BGN mode. - * - 802.11gn - - Call ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` and ``esp_wifi_config_11b_rate(ifx, true)`` to set the station/AP to 802.11gn mode. - -Wi-Fi Bandwidth Mode -++++++++++++++++++++++ - -.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 - - {IDF_TARGET_NAME} currently supports 20 MHz and 40 MHz bandwidth modes, which are used in combination with protocol modes. Common combinations include: - - - **HT20**: 802.11n with 20 MHz bandwidth - - **HT40**: 802.11n with 40 MHz bandwidth - - .. note:: - - - The 40 MHz bandwidth mode is only supported in 802.11n mode. - - Applications can use the :cpp:func:`esp_wifi_set_bandwidth()` API to set the bandwidth mode of the current interface. - - Example: - - .. code-block:: c - - // Set STA interface protocol to 802.11bgn - uint8_t protocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N; - esp_wifi_set_protocol(WIFI_IF_STA, protocol); - - // Set STA interface bandwidth to 40 MHz - esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40); - -.. only:: esp32c6 - - {IDF_TARGET_NAME} currently supports 20 MHz and 40 MHz bandwidth modes, which are used in combination with protocol modes. Common combinations include: - - - **HT20**: 802.11n with 20 MHz bandwidth - - **HT40**: 802.11n with 40 MHz bandwidth - - **HE20**: 802.11ax with 20 MHz bandwidth - - .. note:: - - - The 40 MHz bandwidth mode is only supported in 802.11n mode. - - Applications can use the :cpp:func:`esp_wifi_set_bandwidth()` API to set the bandwidth mode of the current interface. - - Example: - - .. code-block:: c - - // Set protocol of station to 802.11bgn - uint8_t protocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N; - esp_wifi_set_protocol(WIFI_IF_STA, protocol); - - // Set bandwidth of station to 40 MHz - esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40); - -.. only:: esp32c5 - - {IDF_TARGET_NAME} currently supports two bandwidth modes, 20 MHz and 40 MHz, which are used in combination with protocol modes. Common combinations include: - - - **HT20**: 802.11n/11an, 20 MHz bandwidth - - **HT40**: 802.11n/11an, 40 MHz bandwidth - - **HE20**: 802.11ax, 20 MHz bandwidth - - .. note:: - - - The 40 MHz bandwidth mode is only supported under 802.11n (2.4 GHz) or 802.11an (5 GHz) modes. - - Applications can use the :cpp:func:`esp_wifi_set_bandwidths()` API to set independent bandwidths for 2.4 GHz and 5 GHz bands. - - Example: - - .. code-block:: c - - // Set 2.4 GHz to use 802.11bgnax, and 5 GHz to use 802.11an - wifi_protocols_t protocols = { - .ghz_2g = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX, - .ghz_5g = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N, - }; - esp_wifi_set_protocols(WIFI_IF_STA, &protocols); - - // Set bandwidth to 20 MHz for 2.4 GHz band and 40 MHz for 5 GHz band - wifi_bandwidths_t bw = { - .ghz_2g = WIFI_BW_HT20, - .ghz_5g = WIFI_BW_HT40 - }; - esp_wifi_set_bandwidths(WIFI_IF_STA, &bw); - - .. note:: - - - When `.ghz_2g` is set to 0, only the 5 GHz bandwidth is updated, and the 2.4 GHz bandwidth remains unchanged. - - When `.ghz_5g` is set to 0, only the 2.4 GHz bandwidth is updated, and the 5 GHz bandwidth remains unchanged. - - **Legacy Usage** - - Use the legacy API :cpp:func:`esp_wifi_set_bandwidth()` to configure the bandwidth of the 2.4 GHz or 5 GHz band: - - .. code-block:: c - - // Set band mode to 5 GHz band - esp_wifi_set_band_mode(WIFI_BAND_MODE_5G_ONLY); - - // Set protocol of the station interface to 802.11an - uint8_t protocol = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N; - esp_wifi_set_protocol(WIFI_IF_STA, protocol); - - // Set bandwidth of the station interface to 40 MHz - esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40); - - .. note:: - - - The new API :cpp:func:`esp_wifi_set_bandwidths()` can configure both 2.4 GHz and 5 GHz bandwidths simultaneously, and is recommended for use on {IDF_TARGET_NAME}. - - ``esp_wifi_set_bandwidth()`` is suitable for single-band scenarios, such as ``WIFI_BAND_MODE_2G_ONLY`` or ``WIFI_BAND_MODE_5G_ONLY`` modes. It only affects the currently connected band. For example, if the interface is on the 5 GHz band, any 2.4 GHz bandwidth settings will be ignored. - - If the configured bandwidth is not supported on the current band, the function will return an error. - -.. only:: esp32c2 - - {IDF_TARGET_NAME} currently supports only 20 MHz bandwidth mode. - -.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 or esp32c5 or esp32c6 - - Long Range (LR) - +++++++++++++++++++++++++ - - Long Range (LR) mode is an Espressif-patented Wi-Fi mode which can achieve a one-kilometer line of sight range. Compared to the traditional 802.11b mode, it has better reception sensitivity, stronger anti-interference ability, and longer transmission distance. - - LR Compatibility - ************************* - - Since LR is an Espressif-unique Wi-Fi mode operating on the 2.4 GHz band, only ESP32-series chips (excluding the ESP32-C2) support LR data transmission and reception. To ensure compatibility, the ESP32 devices should NOT use LR data rates when connected to non-LR-capable devices. This can be enforced by configuring the appropriate Wi-Fi mode: - - - If the negotiated mode supports LR, ESP32 devices may transmit data at LR rates. - - Otherwise, they must default to traditional Wi-Fi data rates. - - The following table depicts the Wi-Fi mode negotiation on 2.4 GHz band: - - .. only:: esp32 or esp32s2 or esp32c3 or esp32s3 - - +-------+-----+----+---+-------+------+-----+----+ - |AP\STA | BGN | BG | B | BGNLR | BGLR | BLR | LR | - +=======+=====+====+===+=======+======+=====+====+ - | BGN | BGN | BG | B | BGN | BG | B | - | - +-------+-----+----+---+-------+------+-----+----+ - | BG | BG | BG | B | BG | BG | B | - | - +-------+-----+----+---+-------+------+-----+----+ - | B | B | B | B | B | B | B | - | - +-------+-----+----+---+-------+------+-----+----+ - | BGNLR | - | - | - | BGNLR | BGLR | BLR | LR | - +-------+-----+----+---+-------+------+-----+----+ - | BGLR | - | - | - | BGLR | BGLR | BLR | LR | - +-------+-----+----+---+-------+------+-----+----+ - | BLR | - | - | - | BLR | BLR | BLR | LR | - +-------+-----+----+---+-------+------+-----+----+ - | LR | - | - | - | LR | LR | LR | LR | - +-------+-----+----+---+-------+------+-----+----+ - - .. only:: esp32c5 or esp32c6 - - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | AP\STA | BGNAX | BGN | BG | B | BGNAXLR | BGNLR | BGLR | BLR | LR | - +=========+=======+=====+====+===+=========+=======+======+=====+====+ - | BGNAX | BGAX | BGN | BG | B | BGAX | BGN | BG | B | - | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | BGN | BGN | BGN | BG | B | BGN | BGN | BG | B | - | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | BG | BG | BG | BG | B | BG | BG | BG | B | - | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | B | B | B | B | B | B | B | B | B | - | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | BGNAXLR | - | - | - | - | BGAXLR | BGNLR | BGLR | BLR | LR | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | BGNLR | - | - | - | - | BGNLR | BGNLR | BGLR | BLR | LR | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | BGLR | - | - | - | - | BGLR | BGLR | BGLR | BLR | LR | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | BLR | - | - | - | - | BLR | BLR | BLR | BLR | LR | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | LR | - | - | - | - | LR | LR | LR | LR | LR | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - - In the above table, the row is the Wi-Fi mode of AP and the column is the Wi-Fi mode of station. The "-" indicates Wi-Fi mode of the AP and station are not compatible. - - According to the table, the following conclusions can be drawn: - - - For LR-enabled AP of {IDF_TARGET_NAME}, it is incompatible with traditional 802.11 mode, because the beacon is sent in LR mode. - - For LR-enabled station of {IDF_TARGET_NAME} whose mode is NOT LR-only mode, it is compatible with traditional 802.11 mode. - - If both station and AP are ESP32 series chips devices (except ESP32-C2) and both of them have enabled LR mode, the negotiated mode supports LR. - - If the negotiated Wi-Fi mode supports both traditional 802.11 mode and LR mode, it is the Wi-Fi driver's responsibility to automatically select the best data rate in different Wi-Fi modes and the application can ignore it. - - LR Impacts to Traditional Wi-Fi Device - *************************************** - - The data transmission in LR rate has no impacts on the traditional Wi-Fi device because: - - - The CCA and backoff process in LR mode are consistent with 802.11 specification. - - The traditional Wi-Fi device can detect the LR signal via CCA and do backoff. - - In other words, the transmission impact in LR mode is similar to that in 802.11b mode. - - LR Transmission Distance - ************************* - - The reception sensitivity gain of LR is about 4 dB larger than that of the traditional 802.11b mode. Theoretically, the transmission distance is about 2 to 2.5 times the distance of 11B. - - LR Throughput - ************************* - - The LR rate has very limited throughput, because the raw PHY data rate LR is 1/2 Mbps and 1/4 Mbps. - - When to Use LR - ************************* - - The general conditions for using LR are: - - - Both the AP and station are Espressif devices. - - Long distance Wi-Fi connection and data transmission is required. - - Data throughput requirements are very small, such as remote device control. - -.. only:: esp32c5 - - Dynamic Frequency Selection (DFS) - +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - In the 5 GHz Wi-Fi band, certain channels (e.g., channels 52–144) share spectrum with critical systems such as weather radars. To avoid interference with these systems, Wi-Fi devices must perform specific detection and channel switching mechanisms before operating on these channels—this is known as **Dynamic Frequency Selection (DFS)**. - - Enabling DFS allows devices to access more 5 GHz channels, thereby increasing network capacity and reducing interference. This is especially beneficial in high-density deployments or applications that require high bandwidth. The range of DFS channels may vary by country or region; see :component_file:`esp_wifi/regulatory/esp_wifi_regulatory.txt` for details. - - {IDF_TARGET_NAME} supports DFS channels in the 5 GHz band, but only supports **passive radar detection**. - - .. list-table:: - :header-rows: 1 - :widths: 20 60 - - * - Type - - Description - * - Passive Radar Detection Supported - - During scanning, the device can listen to DFS channels, detect access points (APs) operating on DFS channels, and connect to them. If the AP detects radar signals and switches to another channel using Channel Switch Announcement (CSA), {IDF_TARGET_NAME} will follow the AP to the new channel. - * - Active Radar Detection Not Supported - - {IDF_TARGET_NAME} **does not support** active radar detection and therefore cannot operate as a DFS AP in SoftAP mode. - - .. note:: - - In STA mode, {IDF_TARGET_NAME} can connect to APs operating on DFS channels, provided those channels are detected during scanning. - - In SoftAP mode, {IDF_TARGET_NAME} is not allowed to operate on DFS channels to comply with regulatory requirements. - - In STA+SoftAP coexistence mode: - 1. If the STA connects to an AP on a DFS channel, the SoftAP is allowed to switch to the same DFS channel using CSA (Channel Switch Announcement). - 2. When the STA disconnects, the SoftAP will switch back to a non-DFS channel via CSA to remain compliant with regulations. - -Wi-Fi Country Code -+++++++++++++++++++++++++ - -.. only:: esp32 or esp32c2 or esp32s2 or esp32c3 or esp32s3 or esp32c6 - - Call :cpp:func:`esp_wifi_set_country()` to set the country info. The table below describes the fields in detail. Please consult local 2.4 GHz RF operating regulations before configuring these fields. - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - Field - - Description - * - cc[3] - - Country code string. This attribute identifies the country or noncountry entity in which the station/AP is operating. If it is a country, the first two octets of this string is the two-character country info as described in the document ISO/IEC3166-1. The third octet is one of the following: - - - an ASCII space character, which means the regulations under which the station/AP is operating encompass all environments for the current frequency band in the country. - - an ASCII ‘O’ character, which means the regulations under which the station/AP is operating are for an outdoor environment only. - - an ASCII ‘I’ character, which means the regulations under which the station/AP is operating are for an indoor environment only. - - an ASCII ‘X’ character, which means the station/AP is operating under a noncountry entity. The first two octets of the noncountry entity is two ASCII ‘XX’ characters. - - the binary representation of the Operating Class table number currently in use. Refer to Annex E of IEEE Std 802.11-2020. - - * - schan - - Start channel. It is the minimum channel number of the regulations under which the station/AP can operate. - * - nchan - - Total number of channels as per the regulations. For example, if the schan=1, nchan=13, then the station/AP can send data from channel 1 to 13. - * - policy - - Country policy. This field controls which country info will be used if the configured country info is in conflict with the connected AP’s. For more details on related policies, see the following section. - - - The default country info is:: - - wifi_country_t config = { - .cc = "01", - .schan = 1, - .nchan = 11, - .policy = WIFI_COUNTRY_POLICY_AUTO, - }; - - If the Wi-Fi Mode is station/AP coexist mode, they share the same configured country info. Sometimes, the country info of AP, to which the station is connected, is different from the country info of configured. For example, the configured station has country info:: - - wifi_country_t config = { - .cc = "JP", - .schan = 1, - .nchan = 14, - .policy = WIFI_COUNTRY_POLICY_AUTO, - }; - - but the connected AP has country info:: - - wifi_country_t config = { - .cc = "CN", - .schan = 1, - .nchan = 13, - ; - - then country info of connected AP's is used. - - The following table depicts which country info is used in different Wi-Fi modes and different country policies, and it also describes the impact on active scan. - - .. list-table:: - :header-rows: 1 - :widths: 15 15 35 - - * - Wi-Fi Mode - - Policy - - Description - * - Station - - WIFI_COUNTRY_POLICY_AUTO - - If the connected AP has country IE in its beacon, the country info equals to the country info in beacon. Otherwise, use the default country info. - - For scan: - - Use active scan from 1 to 11 and use passive scan from 12 to 14. - - Always keep in mind that if an AP with hidden SSID and station is set to a passive scan channel, the passive scan will not find it. In other words, if the application hopes to find the AP with hidden SSID in every channel, the policy of country info should be configured to WIFI_COUNTRY_POLICY_MANUAL. - - * - Station - - WIFI_COUNTRY_POLICY_MANUAL - - Always use the configured country info. - - For scan: - - Use active scan from schan to schan+nchan-1. - - * - AP - - WIFI_COUNTRY_POLICY_AUTO - - Always use the configured country info. - - * - AP - - WIFI_COUNTRY_POLICY_MANUAL - - Always use the configured country info. - - * - Station/AP-coexistence - - WIFI_COUNTRY_POLICY_AUTO - - Station: Same as station mode with policy WIFI_COUNTRY_POLICY_AUTO. - AP: If the station does not connect to any external AP, the AP uses the configured country info. If the station connects to an external AP, the AP has the same country info as the station. - - * - Station/AP-coexistence - - WIFI_COUNTRY_POLICY_MANUAL - - Station: Same as station mode with policy WIFI_COUNTRY_POLICY_MANUAL. - AP: Same as AP mode with policy WIFI_COUNTRY_POLICY_MANUAL. - -.. only:: esp32c5 - - The :cpp:func:`esp_wifi_set_country()` function is used to set the country/region information. The table below details the meaning of each field. Before configuring these fields, please refer to local 2.4 GHz and 5 GHz RF regulations. - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - Field - - Description - * - cc[3] - - Country/region code string identifying the country or region of the station/AP, or a non-country entity. If it is a country/region, the first two bytes comply with the ISO/IEC 3166-1 two-letter country code standard. The third byte has the following meanings: - - - Space character (ASCII): The country/region allows usage of the respective frequency band in all environments. - - Character `'O'`: Usage allowed only in outdoor environments. - - Character `'I'`: Usage allowed only in indoor environments. - - Character `'X'`: Non-country entity, in which case the first two characters should be `'XX'`. - - Binary operational class number, referring to IEEE Std 802.11-2020 Appendix E. - - * - schan - - Start channel number, indicating the minimum channel allowed in the 2.4 GHz band for the configured country/region. - * - nchan - - Number of channels. Defines the total number of allowed channels in the 2.4 GHz band. For example, if `schan = 1` and `nchan = 13`, then channels 1 through 13 are allowed. - * - policy - - Country/region policy. When the configured country/region conflicts with that of the connected AP, this field determines which information to use. Details are explained below. - * - wifi_5g_channel_mask - - Bitmask indicating allowed 5 GHz channels for the station/AP. The mapping between channel numbers and bits can be found in :cpp:enum:`wifi_5g_channel_bit_t`. - - A default configuration example:: - - wifi_country_t config = { - .cc = "01", - .schan = 1, - .nchan = 11, - .wifi_5g_channel_mask = 0xfe, - .policy = WIFI_COUNTRY_POLICY_AUTO, - }; - - When Wi-Fi is in station/AP coexistence mode, both use the same country/region information. Sometimes, the connected AP's country/region information may differ from the station's preset. For example: - - Station configuration:: - - wifi_country_t config = { - .cc = "JP", - .schan = 1, - .nchan = 14, - .wifi_5g_channel_mask = 0xfe, - .policy = WIFI_COUNTRY_POLICY_AUTO, - }; - - Connected AP configuration:: - - wifi_country_t config = { - .cc = "CN", - .schan = 1, - .nchan = 13, - }; - - In this case, the connected AP's country/region information will be used. - - The following table explains which country/region information is used under different Wi-Fi modes and policies, as well as differences in scanning behavior: - - .. list-table:: - :header-rows: 1 - :widths: 15 15 35 - - * - Wi-Fi Mode - - Policy - - Description - * - Station mode - - WIFI_COUNTRY_POLICY_AUTO - - If the connected AP's beacon contains country/region information IE, that information is used; otherwise, the default configuration is used. - - Scanning behavior: - - - 2.4 GHz band: active scanning on channels 1–11, passive scanning on channels 12–14; - - 5 GHz band: active scanning on non-DFS channels, passive scanning on DFS channels. - - Note: If an AP with a hidden SSID is on a passive scan channel, scanning may not discover that AP. To discover hidden SSIDs on all channels, use `WIFI_COUNTRY_POLICY_MANUAL`. - - * - Station mode - - WIFI_COUNTRY_POLICY_MANUAL - - Always use the configured country/region information. - - Scanning behavior: - - - 2.4 GHz band: scan channels from `schan` to `schan + nchan - 1`; - - 5 GHz band: scan channels supported as indicated by `wifi_5g_channel_mask`. - - * - AP mode - - WIFI_COUNTRY_POLICY_AUTO - - Always use the configured country/region information. - * - AP mode - - WIFI_COUNTRY_POLICY_MANUAL - - Always use the configured country/region information. - * - Station/AP coexistence mode - - WIFI_COUNTRY_POLICY_AUTO - - Same behavior as station mode with `WIFI_COUNTRY_POLICY_AUTO`. - - If the station is not connected to any AP, the AP uses the configured country/region information; - if the station is connected to an external AP, the AP uses the country/region information obtained by the station. - - * - Station/AP coexistence mode - - WIFI_COUNTRY_POLICY_MANUAL - - Same behavior as station mode with `WIFI_COUNTRY_POLICY_MANUAL`. The AP always uses the configured country/region information. - -Home Channel -************************* - -In AP mode, the home channel is defined as the AP channel. In station mode, home channel is defined as the channel of AP which the station is connected to. In station/AP-coexistence mode, the home channel of AP and station must be the same, and if they are different, the station's home channel is always in priority. For example, assume that the AP is on channel 6, and the station connects to an AP whose channel is 9. Since the station's home channel has higher priority, the AP needs to switch its channel from 6 to 9 to make sure that it has the same home channel as the station. While switching channel, the {IDF_TARGET_NAME} in AP mode will notify the connected stations about the channel migration using a Channel Switch Announcement (CSA). Station that supports channel switching will transit without disconnecting and reconnecting to the AP. - - -Wi-Fi Vendor IE Configuration -+++++++++++++++++++++++++++++++++++ - -By default, all Wi-Fi management frames are processed by the Wi-Fi driver, and the application can ignore them. However, some applications may have to handle the beacon, probe request, probe response, and other management frames. For example, if you insert some vendor-specific IE into the management frames, it is only the management frames which contain this vendor-specific IE that will be processed. In {IDF_TARGET_NAME}, :cpp:func:`esp_wifi_set_vendor_ie()` and :cpp:func:`esp_wifi_set_vendor_ie_cb()` are responsible for this kind of tasks. - -Wi-Fi Easy Connect™ (DPP) --------------------------- - -Wi-Fi Easy Connect\ :sup:`TM` (or Device Provisioning Protocol) is a secure and standardized provisioning protocol for configuring Wi-Fi devices. More information can be found in :doc:`esp_dpp <../api-reference/network/esp_dpp>`. - -WPA2-Enterprise ---------------- - -WPA2-Enterprise is the secure authentication mechanism for enterprise wireless networks. It uses RADIUS server for authentication of network users before connecting to the Access Point. The authentication process is based on 802.1X policy and comes with different Extended Authentication Protocol (EAP) methods such as TLS, TTLS, and PEAP. RADIUS server authenticates the users based on their credentials (username and password), digital certificates, or both. When {IDF_TARGET_NAME} in station mode tries to connect an AP in enterprise mode, it sends authentication request to AP which is sent to RADIUS server by AP for authenticating the station. Based on different EAP methods, the parameters can be set in configuration which can be opened using ``idf.py menuconfig``. WPA2_Enterprise is supported by {IDF_TARGET_NAME} only in station mode. - -For establishing a secure connection, AP and station negotiate and agree on the best possible cipher suite to be used. {IDF_TARGET_NAME} supports 802.1X/EAP (WPA) method of AKM and Advanced encryption standard with Counter Mode Cipher Block Chaining Message Authentication protocol (AES-CCM) cipher suite. It also supports the cipher suites supported by mbedtls if `USE_MBEDTLS_CRYPTO` flag is set. - -{IDF_TARGET_NAME} currently supports the following EAP methods: - - EAP-TLS: This is a certificate-based method and only requires SSID and EAP-IDF. - - PEAP: This is a Protected EAP method. Username and Password are mandatory. - - EAP-TTLS: This is a credential-based method. Only server authentication is mandatory while user authentication is optional. Username and Password are mandatory. It supports different Phase2 methods, such as: - - PAP: Password Authentication Protocol. - - CHAP: Challenge Handshake Authentication Protocol. - - MSCHAP and MSCHAP-V2. - - EAP-FAST: This is an authentication method based on Protected Access Credentials (PAC) which also uses identity and password. Currently, USE_MBEDTLS_CRYPTO flag should be disabled to use this feature. - -Detailed information on creating certificates and how to run wpa2_enterprise example on {IDF_TARGET_NAME} can be found in :example:`wifi/wifi_enterprise`. - -.. only:: SOC_WIFI_NAN_SUPPORT - - Wi-Fi Aware\ :sup:`TM` (NAN) - ---------------------------- - - Wi-Fi Aware\ :sup:`TM` or NAN (Neighbor Awareness Networking) is a protocol that allows Wi-Fi devices to discover services in their proximity. NAN uses direct device-to-device communication and does not require any Internet or AP connection. - - Multiple NAN devices in the vicinity will form a NAN cluster which allows them to communicate with each other. NAN devices in a cluster synchronise their clocks and listen to each other periodically on Channel 6. Devices can advertise (Publish) or seek for (Subscribe) services within their NAN Cluster using Service Discovery protocols. Matching of services is done by service name and optionally matching filters. Once a Subscriber gets a match with a Publisher, it can either send a message (Follow-up) or establish a datapath (NDP) with the Publisher. After NDP is setup both devices will obtain an IPv6 address and can use it for communication. - - Please note that NAN Datapath security is not supported i.e., the data packets will go out unencrypted. NAN uses a separate interface for Discovery and Datapath, which is other than that used for STA and AP. NAN operates in standalone mode, which means co-existence with STA or AP interface is not supported. - - Refer to ESP-IDF examples :idf_file:`examples/wifi/wifi_aware/nan_publisher/README.md` and :idf_file:`examples/wifi/wifi_aware/nan_subscriber/README.md` to setup a NAN Publisher and Subscriber. - -Wi-Fi Aware\ :sup:`TM` (NAN): Unsynchronized Service Discovery (USD) --------------------------------------------------------------------- -Unsynchronized Service Discovery (USD) is a mechanism for devices to discover the services that have been made discoverable on new devices that enter the RF environment, without requiring synchronization between the devices. - -USD uses Service Info field in the SDEA of a Publish and Follow-up message to convey the service specific information. - -Refer to ESP-IDF examples :idf_file:`examples/wifi/wifi_aware/usd_publisher/README.md` and :idf_file:`examples/wifi/wifi_aware/usd_subscriber/README.md` to setup a NAN-USD Publisher and Subscriber. - -Wireless Network Management ----------------------------- - -Wireless Network Management allows client devices to exchange information about the network topology, including information related to RF environment. This makes each client network-aware, facilitating overall improvement in the performance of the wireless network. It is part of 802.11v specification. It also enables the client to support Network assisted Roaming. -- Network assisted Roaming: Enables WLAN to send messages to associated clients, resulting clients to associate with APs with better link metrics. This is useful for both load balancing and in directing poorly connected clients. - -Current implementation of 802.11v includes support for BSS transition management frames. - -Radio Resource Measurement ---------------------------- - -Radio Resource Measurement (802.11k) is intended to improve the way traffic is distributed within a network. In a WLAN, each device normally connects to the access point (AP) that provides the strongest signal. Depending on the number and geographic locations of the subscribers, this arrangement can sometimes lead to excessive demand on one AP and underutilization of others, resulting in degradation of overall network performance. In a network conforming to 802.11k, if the AP having the strongest signal is loaded to its full capacity, a wireless device can be moved to one of the underutilized APs. Even though the signal may be weaker, the overall throughput is greater because more efficient use is made of the network resources. - -Current implementation of 802.11k includes support for beacon measurement report, link measurement report, and neighbor request. - -Refer ESP-IDF example :idf_file:`examples/wifi/roaming/README.md` to set up and use these APIs. Example code only demonstrates how these APIs can be used, and the application should define its own algorithm and cases as required. - -Fast BSS Transition ---------------------------- -Fast BSS transition (802.11R FT), is a standard to permit continuous connectivity aboard wireless devices in motion, with fast and secure client transitions from one Basic Service Set (abbreviated BSS, and also known as a base station or more colloquially, an access point) to another performed in a nearly seamless manner **avoiding 802.1i 4 way handshake** . 802.11R specifies transitions between access points by redefining the security key negotiation protocol, allowing both the negotiation and requests for wireless resources to occur in parallel. The key derived from the server to be cached in the wireless network, so that a reasonable number of future connections can be based on the cached key, avoiding the 802.1X process - - -{IDF_TARGET_NAME} station supports FT for WPA2-PSK networks. Do note that {IDF_TARGET_NAME} station only support FT over the air protocol only. - -A config option :ref:`CONFIG_ESP_WIFI_11R_SUPPORT` and configuration parameter :cpp:type:`ft_enabled` in :cpp:type:`wifi_sta_config_t` is provided to enable 802.11R support for station. Refer ESP-IDF example :idf_file:`examples/wifi/roaming/README.md` for further details. - -.. only:: SOC_WIFI_FTM_SUPPORT - - Wi-Fi Location - ------------------------------- - - Wi-Fi Location will improve the accuracy of a device's location data beyond the Access Point, which will enable creation of new and feature-rich applications and services such as geo-fencing, network management, and navigation. One of the protocols used to determine the device location with respect to the Access Point is Fine Timing Measurement which calculates Time-of-Flight of a Wi-Fi frame. - - Fine Timing Measurement (FTM) - +++++++++++++++++++++++++++++ - - FTM is used to measure Wi-Fi Round Trip Time (Wi-Fi RTT) which is the time a Wi-Fi signal takes to travel from a device to another device and back again. Using Wi-Fi RTT, the distance between the devices can be calculated with a simple formula of `RTT * c / 2`, where c is the speed of light. - - FTM uses timestamps given by Wi-Fi interface hardware at the time of arrival or departure of frames exchanged between a pair of devices. One entity called FTM Initiator (mostly a station device) discovers the FTM Responder (can be a station or an Access Point) and negotiates to start an FTM procedure. The procedure uses multiple Action frames sent in bursts and its ACK's to gather the timestamps data. FTM Initiator gathers the data in the end to calculate an average Round-Trip-Time. - - {IDF_TARGET_NAME} supports FTM in below configuration: - - - {IDF_TARGET_NAME} as FTM Initiator in station mode. - - {IDF_TARGET_NAME} as FTM Responder in AP mode. - -.. only:: esp32c6 - - {IDF_TARGET_NAME} ECO1 and older versions do not support FTM Initiator mode. - -.. attention:: - - Distance measurement using RTT is not accurate, and factors such as RF interference, multi-path travel, antenna orientation, and lack of calibration increase these inaccuracies. For better results, it is suggested to perform FTM between two ESP32 chip series devices as station and AP. - - Refer to ESP-IDF example :idf_file:`examples/wifi/ftm/README.md` for steps on how to set up and perform FTM. - -{IDF_TARGET_NAME} Wi-Fi Power-saving Mode ------------------------------------------ - -This subsection will briefly introduce the concepts and usage related to Wi-Fi Power Saving Mode, for a more detailed introduction please refer to the :doc:`Low Power Mode User Guide <../api-guides/low-power-mode/index>` - -Station Sleep -++++++++++++++++++++++ - -Currently, {IDF_TARGET_NAME} Wi-Fi supports the Modem-sleep mode which refers to the legacy power-saving mode in the IEEE 802.11 protocol. Modem-sleep mode works in station-only mode and the station must connect to the AP first. If the Modem-sleep mode is enabled, station will switch between active and sleep state periodically. In sleep state, RF, PHY and BB are turned off in order to reduce power consumption. Station can keep connection with AP in modem-sleep mode. - -Modem-sleep mode includes minimum and maximum power-saving modes. In minimum power-saving mode, station wakes up every DTIM to receive beacon. Broadcast data will not be lost because it is transmitted after DTIM. However, it cannot save much more power if DTIM is short for DTIM is determined by AP. - -In maximum power-saving mode, station wakes up in every listen interval to receive beacon. This listen interval can be set to be longer than the AP DTIM period. Broadcast data may be lost because station may be in sleep state at DTIM time. If listen interval is longer, more power is saved, but broadcast data is more easy to lose. Listen interval can be configured by calling API :cpp:func:`esp_wifi_set_config()` before connecting to AP. - -Call ``esp_wifi_set_ps(WIFI_PS_MIN_MODEM)`` to enable Modem-sleep minimum power-saving mode or ``esp_wifi_set_ps(WIFI_PS_MAX_MODEM)`` to enable Modem-sleep maximum power-saving mode after calling :cpp:func:`esp_wifi_init()`. When station connects to AP, Modem-sleep will start. When station disconnects from AP, Modem-sleep will stop. - -Call ``esp_wifi_set_ps(WIFI_PS_NONE)`` to disable Modem-sleep mode entirely. Disabling it increases power consumption, but minimizes the delay in receiving Wi-Fi data in real time. When Modem-sleep mode is enabled, the delay in receiving Wi-Fi data may be the same as the DTIM cycle (minimum power-saving mode) or the listening interval (maximum power-saving mode). - -.. only:: SOC_SUPPORT_COEXISTENCE - - Note that in coexist mode, Wi-Fi will remain active only during Wi-Fi time slice, and sleep during non Wi-Fi time slice even if ``esp_wifi_set_ps(WIFI_PS_NONE)`` is called. Please refer to :ref:`coexist policy `. - -The default Modem-sleep mode is WIFI_PS_MIN_MODEM. - -AP Sleep -+++++++++++++++++++++++++++++++ - -Currently, {IDF_TARGET_NAME} AP does not support all of the power-saving feature defined in Wi-Fi specification. To be specific, the AP only caches unicast data for the stations connect to this AP, but does not cache the multicast data for the stations. If stations connected to the {IDF_TARGET_NAME} AP are power-saving enabled, they may experience multicast packet loss. - -In the future, all power-saving features will be supported on {IDF_TARGET_NAME} AP. - -Disconnected State Sleep -+++++++++++++++++++++++++++++++ - -Disconnected state is the duration without Wi-Fi connection between :cpp:func:`esp_wifi_start` to :cpp:func:`esp_wifi_stop`. - -Currently, {IDF_TARGET_NAME} Wi-Fi supports sleep mode in disconnected state if running at station mode. This feature could be configured by Menuconfig choice :ref:`CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE`. - -If :ref:`CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE` is enabled, RF, PHY and BB would be turned off in disconnected state when IDLE. The current would be same with current at modem-sleep. - -The choice :ref:`CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE` would be selected by default, while it would be selected forcefully in Menuconfig at coexistence mode. - -.. _connectionless-module-power-save: - -Connectionless Modules Power-saving -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Connectionless modules are those Wi-Fi modules not relying on Wi-Fi connection, e.g ESP-NOW, DPP, FTM. These modules start from :cpp:func:`esp_wifi_start`, working until :cpp:func:`esp_wifi_stop`. - -Currently, if ESP-NOW works at station mode, its supported to sleep at both connected state and disconnected state. - -Connectionless Modules TX -******************************* - -For each connectionless module, its supported to TX at any sleeping time without any extra configuration. - -Meanwhile, :cpp:func:`esp_wifi_80211_tx` is supported at sleep as well. - -Connectionless Modules RX -******************************* - -For each connectionless module, two parameters shall be configured to RX at sleep, which are `Window` and `Interval`. - -At the start of `Interval` time, RF, PHY, BB would be turned on and kept for `Window` time. Connectionless Module could RX in the duration. - -**Interval** - - - There is only one `Interval`. Its configured by :cpp:func:`esp_wifi_set_connectionless_interval`. The unit is milliseconds. - - - The default value of `Interval` is `ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE`. - - - Event `WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START`_ would be posted at the start of `Interval`. Since `Window` also starts at that moment, its recommended to TX in that event. - - - At connected state, the start of `Interval` would be aligned with TBTT. To improve the packet reception success rate in connectionless modules, the sender and receiver can be connected to the same AP, and packets can be transmitted within the event `WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START`_. This synchronization helps align the connectionless modules transmission window. - - .. only:: esp32 - - On the ESP32, TBTT timing is affected by DFS(Dynamic Frequency Scaling). To synchronize the connectionless modules transmission window using TBTT on the ESP32, DFS must be disabled. - -**Window** - - - Each connectionless module has its own `Window` after start. Connectionless Modules Power-saving would work with the max one among them. - - - `Window` is configured by :cpp:func:`module_name_set_wake_window`. The unit is milliseconds. - - - The default value of `Window` is the maximum. - -.. table:: RF, PHY and BB usage under different circumstances - - +----------------------+-----------------------------------------------------+---------------------------------------------------------------------------+ - | | Interval | - + +-----------------------------------------------------+---------------------------------------------------------------------------+ - | | ``ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE`` | 1 - maximum | - +--------+-------------+-----------------------------------------------------+---------------------------------------------------------------------------+ - | Window | 0 | not used | - + +-------------+-----------------------------------------------------+---------------------------------------------------------------------------+ - | | 1 - maximum | default mode | used periodically (Window < Interval) / used all time (Window ≥ Interval) | - +--------+-------------+-----------------------------------------------------+---------------------------------------------------------------------------+ - -Default Mode -******************************* - -If `Interval` is ``ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE`` with non-zero `Window`, Connectionless Modules Power-saving would work in default mode. - -In default mode, RF, PHY, BB would be kept on if no coexistence with non-Wi-Fi protocol. - -With coexistence, RF, PHY, BB resources are allocated by coexistence module to Wi-Fi connectionless module and non-Wi-Fi module, using time-division method. In default mode, Wi-Fi connectionless module is allowed to use RF, BB, PHY periodically under a stable performance. - -Its recommended to configure Connectionless Modules Power-saving to default mode if there is Wi-Fi connectionless module coexists with non-Wi-Fi module. - -{IDF_TARGET_NAME} Wi-Fi Throughput ------------------------------------ - -The table below shows the best throughput results gained in Espressif's lab and in a shielded box. - -.. only:: esp32 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 10 25 - - * - Type/Throughput - - Air In Lab - - Shield-box - - Test Tool - - IDF Version (commit ID) - * - Raw 802.11 Packet RX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - Raw 802.11 Packet TX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - UDP RX - - 30 MBit/s - - 85 MBit/s - - iperf example - - 15575346 - * - UDP TX - - 30 MBit/s - - 75 MBit/s - - iperf example - - 15575346 - * - TCP RX - - 20 MBit/s - - 65 MBit/s - - iperf example - - 15575346 - * - TCP TX - - 20 MBit/s - - 75 MBit/s - - iperf example - - 15575346 - - When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32`. - -.. only:: esp32s2 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 10 25 - - * - Type/Throughput - - Air In Lab - - Shield-box - - Test Tool - - IDF Version (commit ID) - * - Raw 802.11 Packet RX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - Raw 802.11 Packet TX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - UDP RX - - 30 MBit/s - - 70 MBit/s - - iperf example - - 15575346 - * - UDP TX - - 30 MBit/s - - 50 MBit/s - - iperf example - - 15575346 - * - TCP RX - - 20 MBit/s - - 32 MBit/s - - iperf example - - 15575346 - * - TCP TX - - 20 MBit/s - - 37 MBit/s - - iperf example - - 15575346 - - When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32s2`. - -.. only:: esp32c3 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - Type/Throughput - - Air In Lab - - Shield-box - - Test Tool - - IDF Version (commit ID) - * - Raw 802.11 Packet RX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - Raw 802.11 Packet TX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - UDP RX - - 30 MBit/s - - 50 MBit/s - - iperf example - - 15575346 - * - UDP TX - - 30 MBit/s - - 40 MBit/s - - iperf example - - 15575346 - * - TCP RX - - 20 MBit/s - - 35 MBit/s - - iperf example - - 15575346 - * - TCP TX - - 20 MBit/s - - 37 MBit/s - - iperf example - - 15575346 - - When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c3`. - -.. only:: esp32c5 - - - 2.4 GHz band - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - Type/Throughput - - Air In Lab - - Shield-box - - Test Tool - - IDF Version (commit ID) - * - Raw 802.11 Packet RX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - Raw 802.11 Packet TX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - UDP RX - - 30 MBit/s - - 68 MBit/s - - iperf example - - 7ff0a07d - * - UDP TX - - 30 MBit/s - - 63 MBit/s - - iperf example - - 7ff0a07d - * - TCP RX - - 20 MBit/s - - 59 MBit/s - - iperf example - - 7ff0a07d - * - TCP TX - - 20 MBit/s - - 49 MBit/s - - iperf example - - 7ff0a07d - - - 5 GHz band - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - Type/Throughput - - Air In Lab - - Shield-box - - Test Tool - - IDF Version (commit ID) - * - Raw 802.11 Packet RX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - Raw 802.11 Packet TX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - UDP RX - - 30 MBit/s - - 71 MBit/s - - iperf example - - 7ff0a07d - * - UDP TX - - 30 MBit/s - - 64 MBit/s - - iperf example - - 7ff0a07d - * - TCP RX - - 20 MBit/s - - 61 MBit/s - - iperf example - - 7ff0a07d - * - TCP TX - - 20 MBit/s - - 50 MBit/s - - iperf example - - 7ff0a07d - - When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c5`. - -.. only:: esp32c6 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - Type/Throughput - - Air In Lab - - Shield-box - - Test Tool - - IDF Version (commit ID) - * - Raw 802.11 Packet RX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - Raw 802.11 Packet TX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - UDP RX - - 30 MBit/s - - 63 MBit/s - - iperf example - - 7ff0a07d - * - UDP TX - - 30 MBit/s - - 51 MBit/s - - iperf example - - 7ff0a07d - * - TCP RX - - 20 MBit/s - - 46 MBit/s - - iperf example - - 7ff0a07d - * - TCP TX - - 20 MBit/s - - 43 MBit/s - - iperf example - - 7ff0a07d - - When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c6`. - -.. only:: esp32c61 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - Type/Throughput - - Air In Lab - - Shield-box - - Test Tool - - IDF Version (commit ID) - * - Raw 802.11 Packet RX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - Raw 802.11 Packet TX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - UDP RX - - 30 MBit/s - - 68 MBit/s - - iperf example - - 7ff0a07d - * - UDP TX - - 30 MBit/s - - 53 MBit/s - - iperf example - - 7ff0a07d - * - TCP RX - - 20 MBit/s - - 45 MBit/s - - iperf example - - 7ff0a07d - * - TCP TX - - 20 MBit/s - - 37 MBit/s - - iperf example - - 7ff0a07d - - When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c61`. - -.. only:: esp32s3 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - Type/Throughput - - Air In Lab - - Shield-box - - Test Tool - - IDF Version (commit ID) - * - Raw 802.11 Packet RX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - Raw 802.11 Packet TX - - N/A - - **130 MBit/s** - - Internal tool - - NA - * - UDP RX - - 30 MBit/s - - 88 MBit/s - - iperf example - - 15575346 - * - UDP TX - - 30 MBit/s - - 98 MBit/s - - iperf example - - 15575346 - * - TCP RX - - 20 MBit/s - - 73 MBit/s - - iperf example - - 15575346 - * - TCP TX - - 20 MBit/s - - 83 MBit/s - - iperf example - - 15575346 - - When the throughput is tested by iperf example, the sdkconfig is :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32s3`. - -Wi-Fi 80211 Packet Send ---------------------------- - -The :cpp:func:`esp_wifi_80211_tx()` API can be used to: - - - Send the beacon, probe request, probe response, and action frame. - - Send the non-QoS data frame. - -It cannot be used for sending encrypted or QoS frames. - -Preconditions of Using :cpp:func:`esp_wifi_80211_tx()` -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - - The Wi-Fi mode is station, or AP, or station/AP. - - Either ``esp_wifi_set_promiscuous(true)``, or :cpp:func:`esp_wifi_start()`, or both of these APIs return :c:macro:`ESP_OK`. This is because Wi-Fi hardware must be initialized before :cpp:func:`esp_wifi_80211_tx()` is called. In {IDF_TARGET_NAME}, both ``esp_wifi_set_promiscuous(true)`` and :cpp:func:`esp_wifi_start()` can trigger the initialization of Wi-Fi hardware. - - The parameters of :cpp:func:`esp_wifi_80211_tx()` are hereby correctly provided. - -Data Rate -+++++++++++++++++++++++++++++++++++++++++++++++ - - - The default data rate is 1 Mbps. - - Can set any rate through :cpp:func:`esp_wifi_config_80211_tx_rate()` API. - - Can set any bandwidth through :cpp:func:`esp_wifi_set_bandwidth()` API. - -Side-Effects to Avoid in Different Scenarios -+++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Theoretically, if the side-effects the API imposes on the Wi-Fi driver or other stations/APs are not considered, a raw 802.11 packet can be sent over the air with any destination MAC, any source MAC, any BSSID, or any other types of packet. However, robust or useful applications should avoid such side-effects. The table below provides some tips and recommendations on how to avoid the side-effects of :cpp:func:`esp_wifi_80211_tx()` in different scenarios. - -.. list-table:: - :header-rows: 1 - :widths: 10 50 - - * - Scenario - - Description - * - No Wi-Fi connection - - In this scenario, no Wi-Fi connection is set up, so there are no side-effects on the Wi-Fi driver. If ``en_sys_seq==true``, the Wi-Fi driver is responsible for the sequence control. If ``en_sys_seq==false``, the application needs to ensure that the buffer has the correct sequence. - - Theoretically, the MAC address can be any address. However, this may impact other stations/APs with the same MAC/BSSID. - - Side-effect example#1 The application calls :cpp:func:`esp_wifi_80211_tx()` to send a beacon with BSSID == mac_x in AP mode, but the mac_x is not the MAC of the AP interface. Moreover, there is another AP, e.g., “other-AP”, whose BSSID is mac_x. If this happens, an “unexpected behavior” may occur, because the stations which connect to the “other-AP” cannot figure out whether the beacon is from the “other-AP” or the :cpp:func:`esp_wifi_80211_tx()`. - - To avoid the above-mentioned side-effects, it is recommended that: - - - If :cpp:func:`esp_wifi_80211_tx` is called in station mode, the first MAC should be a multicast MAC or the exact target-device’s MAC, while the second MAC should be that of the station interface. - - - If :cpp:func:`esp_wifi_80211_tx` is called in AP mode, the first MAC should be a multicast MAC or the exact target-device’s MAC, while the second MAC should be that of the AP interface. - - The recommendations above are only for avoiding side-effects and can be ignored when there are good reasons. - - * - Have Wi-Fi connection - - When the Wi-Fi connection is already set up, and the sequence is controlled by the application, the latter may impact the sequence control of the Wi-Fi connection as a whole. So, the ``en_sys_seq`` need to be true, otherwise ``ESP_ERR_INVALID_ARG`` is returned. - - The MAC-address recommendations in the “No Wi-Fi connection” scenario also apply to this scenario. - - If the Wi-Fi mode is station mode, the MAC address1 is the MAC of AP to which the station is connected, and the MAC address2 is the MAC of station interface, it is said that the packet is sent from the station to AP. Otherwise, if the Wi-Fi is in AP mode, the MAC address1 is the MAC of the station that connects to this AP, and the MAC address2 is the MAC of AP interface, it is said that the packet is sent from the AP to station. To avoid conflicting with Wi-Fi connections, the following checks are applied: - - - If the packet type is data and is sent from the station to AP, the ToDS bit in IEEE 80211 frame control should be 1 and the FromDS bit should be 0. Otherwise, the packet will be discarded by Wi-Fi driver. - - - If the packet type is data and is sent from the AP to station, the ToDS bit in IEEE 80211 frame control should be 0 and the FromDS bit should be 1. Otherwise, the packet will be discarded by Wi-Fi driver. - - - If the packet is sent from station to AP or from AP to station, the Power Management, More Data, and Re-Transmission bits should be 0. Otherwise, the packet will be discarded by Wi-Fi driver. - - ``ESP_ERR_INVALID_ARG`` is returned if any check fails. - - -Wi-Fi Sniffer Mode ---------------------------- - -The Wi-Fi sniffer mode can be enabled by :cpp:func:`esp_wifi_set_promiscuous`. If the sniffer mode is enabled, the following packets **can** be dumped to the application: - - - 802.11 Management frame. - - 802.11 Data frame, including MPDU, AMPDU, and AMSDU. - - 802.11 MIMO frame, for MIMO frame, the sniffer only dumps the length of the frame. - - 802.11 Control frame. - - 802.11 CRC error frame. - -The following packets will **NOT** be dumped to the application: - - - Other 802.11 error frames. - -For frames that the sniffer **can** dump, the application can additionally decide which specific type of packets can be filtered to the application by using :cpp:func:`esp_wifi_set_promiscuous_filter()` and :cpp:func:`esp_wifi_set_promiscuous_ctrl_filter()`. By default, it will filter all 802.11 data and management frames to the application. If you want to filter the 802.11 control frames, the filter parameter in :cpp:func:`esp_wifi_set_promiscuous_filter()` should include `WIFI_PROMIS_FILTER_MASK_CTRL` type, and if you want to differentiate control frames further, then call :cpp:func:`esp_wifi_set_promiscuous_ctrl_filter()`. - -The Wi-Fi sniffer mode can be enabled in the Wi-Fi mode of :cpp:enumerator:`WIFI_MODE_NULL`, :cpp:enumerator:`WIFI_MODE_STA`, :cpp:enumerator:`WIFI_MODE_AP`, or :cpp:enumerator:`WIFI_MODE_APSTA`. In other words, the sniffer mode is active when the station is connected to the AP, or when the AP has a Wi-Fi connection. Please note that the sniffer has a **great impact** on the throughput of the station or AP Wi-Fi connection. Generally, the sniffer should be enabled **only if** the station/AP Wi-Fi connection does not experience heavy traffic. - -Another noteworthy issue about the sniffer is the callback :cpp:type:`wifi_promiscuous_cb_t`. The callback will be called directly in the Wi-Fi driver task, so if the application has a lot of work to do for each filtered packet, the recommendation is to post an event to the application task in the callback and defer the real work to the application task. - -Wi-Fi Multiple Antennas ---------------------------- -Please refer to the :doc:`PHY <../api-guides/phy>` - -.. only:: SOC_WIFI_CSI_SUPPORT - - Wi-Fi Channel State Information - ------------------------------------ - - .. only:: esp32 or esp32s2 or esp32c3 or esp32s3 - - Channel state information (CSI) refers to the channel information of a Wi-Fi connection. In {IDF_TARGET_NAME}, this information consists of channel frequency responses of sub-carriers and is estimated when packets are received from the transmitter. Each channel frequency response of sub-carrier is recorded by two bytes of signed characters. The first one is imaginary part and the second one is real part. There are up to three fields of channel frequency responses according to the type of received packet. They are legacy long training field (LLTF), high throughput LTF (HT-LTF), and space time block code HT-LTF (STBC-HT-LTF). For different types of packets which are received on channels with different state, the sub-carrier index and total bytes of signed characters of CSI are shown in the following table. - - +-------------+--------------------+-----------------------------------------+--------------------------------------------------------+----------------------------------------------------------+ - | channel | secondary channel | none | below | above | - +-------------+--------------------+-------------+---------------------------+----------+---------------------------------------------+----------+-----------------------------------------------+ - | packet | signal mode | non HT | HT | non HT | HT | non HT | HT | - + +--------------------+-------------+---------------------------+----------+-----------------+---------------------------+----------+-------------------+---------------------------+ - | information | channel bandwidth | 20 MHz | 20 MHz | 20 MHz | 20 MHz | 40 MHz | 20 MHz | 20 MHz | 40 MHz | - + +--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ - | | STBC | non STBC | non STBC | STBC | non STBC | non STBC | STBC | non STBC | STBC | non STBC | non STBC | STBC | non STBC | STBC | - +-------------+--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ - | sub-carrier | LLTF | 0~31, -32~-1| 0~31, -32~-1| 0~31, -32~-1| 0~63 | 0~63 | 0~63 | 0~63 | 0~63 | -64~-1 | -64~-1 | -64~-1 | -64~-1 | -64~-1 | - + +--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ - | index | HT-LTF | - | 0~31, -32~-1| 0~31, -32~-1| - | 0~63 | 0~62 | 0~63, -64~-1| 0~60, -60~-1| - | -64~-1 | -62~-1 | 0~63, -64~-1| 0~60, -60~-1| - + +--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ - | | STBC-HT-LTF | - | - | 0~31, -32~-1| - | - | 0~62 | - | 0~60, -60~-1| - | - | -62~-1 | - | 0~60, -60~-1| - +-------------+--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ - | total bytes | 128 | 256 | 384 | 128 | 256 | 380 | 384 | 612 | 128 | 256 | 376 | 384 | 612 | - +----------------------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ - - All of the information in the table can be found in the structure wifi_csi_info_t. - - - Secondary channel refers to secondary_channel field of rx_ctrl field. - - Signal mode of packet refers to sig_mode field of rx_ctrl field. - - Channel bandwidth refers to cwb field of rx_ctrl field. - - STBC refers to stbc field of rx_ctrl field. - - Total bytes refers to len field. - - The CSI data corresponding to each Long Training Field (LTF) type is stored in a buffer starting from the buf field. Each item is stored as two bytes: imaginary part followed by real part. The order of each item is the same as the sub-carrier in the table. The order of LTF is: LLTF, HT-LTF, STBC-HT-LTF. However, all 3 LTFs may not be present, depending on the channel and packet information (see above). - - If first_word_invalid field of :cpp:type:`wifi_csi_info_t` is true, it means that the first four bytes of CSI data is invalid due to a hardware limitation in {IDF_TARGET_NAME}. - - More information like RSSI, noise floor of RF, receiving time and antenna is in the rx_ctrl field. - - When imaginary part and real part data of sub-carrier are used, please refer to the table below. - - +-----------------+-------------------+------------------------------+--------------------------+ - | PHY standard | Sub-carrier range | Pilot sub-carrier | Sub-carrier (total/data) | - +=================+===================+==============================+==========================+ - | 802.11a/g | -26 to +26 | -21, -7, +7, +21 | 52 total, 48 usable | - +-----------------+-------------------+------------------------------+--------------------------+ - | 802.11n, 20 MHz | -28 to +28 | -21, -7, +7, +21 | 56 total, 52 usable | - +-----------------+-------------------+------------------------------+--------------------------+ - | 802.11n, 40 MHz | -57 to +57 | -53, -25, -11, +11, +25, +53 | 114 total, 108 usable | - +-----------------+-------------------+------------------------------+--------------------------+ - - .. note:: - - - For STBC packet, CSI is provided for every space-time stream without CSD (cyclic shift delay). As each cyclic shift on the additional chains shall be -200 ns, only the CSD angle of first space-time stream is recorded in sub-carrier 0 of HT-LTF and STBC-HT-LTF for there is no channel frequency response in sub-carrier 0. CSD[10:0] is 11 bits, ranging from -pi to pi. - - - If LLTF, HT-LTF, or STBC-HT-LTF is not enabled by calling API :cpp:func:`esp_wifi_set_csi_config()`, the total bytes of CSI data will be fewer than that in the table. For example, if LLTF and HT-LTF is not enabled and STBC-HT-LTF is enabled, when a packet is received with the condition above/HT/40MHz/STBC, the total bytes of CSI data is 244 ((61 + 60) * 2 + 2 = 244. The result is aligned to four bytes, and the last two bytes are invalid). - - .. only:: esp32c5 - - Channel state information (CSI) refers to the channel information of a Wi-Fi connection. In {IDF_TARGET_NAME}, this information consists of channel frequency responses of sub-carriers and is estimated when packets are received from the transmitter. Each channel frequency response of sub-carrier is recorded by two bytes of signed characters. The first one is imaginary part and the second one is real part. Except for the IEEE 802.11g mode, all other modes have two LTF sequences (LLTF + HT/VHT/HE-LTF). {IDF_TARGET_NAME} can determine whether to include LLTF or HT/VHT/HE-LTF through ``acquire_csi_force_lltf`` field of :cpp:struct:`wifi_csi_acquire_config_t`. For different types of packets which are received on channels with different state, the sub-carrier index and total bytes of signed characters of CSI are shown in the following table. - - +-------------+-------------------+--------------------------------------------+-----------------------------------+--------------------------------------------------------------------------+--------------------------------------------------------------------------+ - | channel | secondary channel | none | below | above | - +-------------+-------------------+--------------+-----------------------------+-----------------------------------+--------------+-----------------------------------------------------------+--------------+-----------------------------------------------------------+ - | packet | signal mode | non HT | HT | HE | non HT | HT | non HT | HT | - | +-------------------+--------------+-----------------------------+-----------------------------------+--------------+-----------------------------+-----------------------------+--------------+-----------------------------+-----------------------------+ - | information | channel bandwidth | 20 MHz | 20 MHz | 20 MHz | 20 MHz | 20 MHz | 40 MHz | 20 MHz | 20 MHz | 40 MHz | - | +-------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ - | | STBC | non STBC | non STBC | STBC | non STBC | STBC | non STBC | non STBC | STBC | none STBC | STBC | non STBC | non STBC | STBC | non STBC | STBC | - +-------------+-------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ - | sub-carrier | LLTF | 0~26, -26~-1 | — | — | — | — | 0~52 | — | — | — | — | -53~-1 | — | — | — | — | - | +-------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ - | index | HT-LTF (HT-LTF1) | — | 0~28, -28~-1 | 0~28, -28~-1 | — | — | — | 0~56 | 0~56 | 0~58, -58~-1 | 0~58, -58~-1 | — | -57~-1 | -57~-1 | 0~58, -58~-1 | 0~58, -58~-1 | - | +-------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ - | | HT-LTF2 | — | — | 0~28, -28~-1 | — | — | — | — | 0~56 | — | 0~58, -58~-1 | — | — | -57~-1 | — | 0~58, -58~-1 | - | +-------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ - | | HE-LTF (HE-LTF1) | — | — | — | 0~122, -122~1 | Determined by | — | — | — | — | — | — | — | — | — | — | - | +-------------------+--------------+--------------+--------------+---------------+ +--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ - | | HE-LTF2 | — | — | — | — | wifi_csi_config_t | — | — | — | — | — | — | — | — | — | — | - +-------------+-------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ - | total bytes | 106 | 114 | 228 | 490 | 490 | 106 | 114 | 228 | 234 | 468 | 106 | 114 | 228 | 234 | 468 | - +---------------------------------+--------------+--------------+--------------+---------------+-------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ - - .. note :: - - - In HT/VHT/HE modes, there are two LTF sequences: LLTF + HT/VHT/HE-LTF. If the ``acquire_csi_force_lltf`` field of :cpp:struct:`wifi_csi_acquire_config_t` is set to false, the CSI data will only contain HT/VHT/HE-LTF (as shown in the table above); otherwise, the CSI data will only contain LLTF. The sub-carrier index and total bytes for LLTF in HT/VHT/HE modes are the same as those for LLTF in non-HT modes. - - In VHT mode, the sub-carrier index and total bytes are the same as those in HT mode. - - All of the information in the table can be found in the structure :cpp:type:`wifi_csi_info_t`. - - - Secondary channel refers to ``second`` field of ``rx_ctrl`` field. - - signal mode of packet refers to ``cur_bb_format`` field of ``rx_ctrl`` field. - - total bytes refers to ``len`` field - - The CSI data corresponding to each Long Training Field (LTF) type is stored in a buffer starting from the buf field. Each item is stored as two bytes: imaginary part followed by real part. The order of each item is the same as the sub-carrier in the table. - - If ``first_word_invalid`` of :cpp:type:`wifi_csi_info_t` is true, it means that the first four bytes of CSI data is invalid due to a hardware limitation in {IDF_TARGET_NAME}. - - If ``rx_channel_estimate_info_vld`` of ``rx_ctrl`` field is 1, indicates that the CSI data is valid; otherwise, the CSI data is invalid. - - More information like RSSI, noise floor of RF, receiving time and antenna is in the ``rx_ctrl`` field. - - For STBC packets, the subcarrier indices of HE-LTF1 and HE-LTF2 are determined by ``acquire_csi_he_stbc_mode`` field of :cpp:type:`wifi_csi_config_t`. Please refer to the table below for details. - - +---------------------+----------------------+----------------------+ - | acquire_csi_he_stbc | HE-LTF1 | HE-LTF2 | - +---------------------+----------------------+----------------------+ - | 0 | -122~-1, 0~122 | — | - +---------------------+----------------------+----------------------+ - | 1 | — | -122~-1, 0~122 | - +---------------------+----------------------+----------------------+ - | 2 | Sample evenly among the HE-LTF1 and HE-LTF2 | - +---------------------+----------------------+----------------------+ - - When imaginary part and real part data of sub-carrier are used, please refer to the table below. - - +-----------------------+-------------------+------------------------------------------+------------------------------+ - | PHY standard | Sub-carrier range | Invalid sub-carrier | Sub-carrier (total/data) | - +=======================+===================+==========================================+==============================+ - | 802.11a/g | -26 to +26 | 0 | 53 total, 52 usable | - +-----------------------+-------------------+------------------------------------------+------------------------------+ - | 802.11n, 20 MHz | -28 to +28 | 0 | 57 total, 56 usable | - +-----------------------+-------------------+------------------------------------------+------------------------------+ - | 802.11n, 40 MHz | -58 to +58 | -1, 0, 1 | 117 total, 114 usable | - +-----------------------+-------------------+------------------------------------------+------------------------------+ - | 802.11ac, 20 MHz | -28 to +28 | 0 | 57 total, 56 usable | - +-----------------------+-------------------+------------------------------------------+------------------------------+ - | 802.11ax, 20 MHz (SU) | -122 to + 122 | -1, 0, 1 | 245 total, 242 usable | - +-----------------------+-------------------+------------------------------------------+------------------------------+ - - .. note:: - - - When the PHY is 802.11ax, please refer to the protocol for sub-carrier range and invalid sub-carrier for MU packets. - - .. note:: - - - For STBC packet, CSI is provided for every space-time stream without CSD (cyclic shift delay). As each cyclic shift on the additional chains shall be -200 ns, only the CSD angle of first space-time stream is recorded in sub-carrier 0 of HT-LTF1 (HE-LTF1) and HT-LTF2 (HE-LTF2) for there is no channel frequency response in sub-carrier 0. CSD[10:0] is 11 bits, ranging from -pi to pi. - - Wi-Fi Channel State Information Configure - ------------------------------------------- - - To use Wi-Fi CSI, the following steps need to be done. - - - Select Wi-Fi CSI in menuconfig. Go to ``Menuconfig`` > ``Components config`` > ``Wi-Fi`` > ``Wi-Fi CSI (Channel State Information)``. - - Set CSI receiving callback function by calling API :cpp:func:`esp_wifi_set_csi_rx_cb()`. - - Configure CSI by calling API :cpp:func:`esp_wifi_set_csi_config()`. - - Enable CSI by calling API :cpp:func:`esp_wifi_set_csi()`. - - The CSI receiving callback function runs from Wi-Fi task. So, do not do lengthy operations in the callback function. Instead, post necessary data to a queue and handle it from a lower priority task. Because station does not receive any packet when it is disconnected and only receives packets from AP when it is connected, it is suggested to enable sniffer mode to receive more CSI data by calling :cpp:func:`esp_wifi_set_promiscuous()`. - -Wi-Fi HT20/40 -------------------------- - -.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 or esp32c5 or esp32c6 - - {IDF_TARGET_NAME} supports Wi-Fi bandwidth HT20 or HT40 and does not support HT20/40 coexist. :cpp:func:`esp_wifi_set_bandwidth()` can be used to change the default bandwidth of station or AP. The default bandwidth for {IDF_TARGET_NAME} station and AP is HT40. - - In station mode, the actual bandwidth is firstly negotiated during the Wi-Fi connection. It is HT40 only if both the station and the connected AP support HT40, otherwise it is HT20. If the bandwidth of connected AP is changes, the actual bandwidth is negotiated again without Wi-Fi disconnecting. - - Similarly, in AP mode, the actual bandwidth is negotiated between AP and the stations that connect to the AP. It is HT40 if the AP and one of the stations support HT40, otherwise it is HT20. - - In station/AP coexist mode, the station/AP can configure HT20/40 separately. If both station and AP are negotiated to HT40, the HT40 channel should be the channel of station because the station always has higher priority than AP in {IDF_TARGET_NAME}. For example, the configured bandwidth of AP is HT40, the configured primary channel is 6, and the configured secondary channel is 10. The station is connected to an router whose primary channel is 6 and secondary channel is 2, then the actual channel of AP is changed to primary 6 and secondary 2 automatically. - - Theoretically, the HT40 can gain better throughput because the maximum raw physical (PHY) data rate for HT40 is 150 Mbps while it is 72 Mbps for HT20. However, if the device is used in some special environment, e.g., there are too many other Wi-Fi devices around the {IDF_TARGET_NAME} device, the performance of HT40 may be degraded. So if the applications need to support same or similar scenarios, it is recommended that the bandwidth is always configured to HT20. - -.. only:: esp32c5 - - ..note .. - - When operating in the 2.4 GHz + 5 GHz band mode (``WIFI_BAND_MODE_AUTO``), can use the function :cpp:func:`esp_wifi_set_bandwidths()` to configure the bandwidth for the 2.4 GHz and 5 GHz bands separately. - -.. only:: esp32c2 - - {IDF_TARGET_NAME} supports Wi-Fi bandwidth HT20 and does not support Wi-Fi bandwidth HT40 or HT20/40 coexist. - -Wi-Fi QoS -------------------------- - -{IDF_TARGET_NAME} supports all the mandatory features required in WFA Wi-Fi QoS Certification. - -Four ACs (Access Category) are defined in Wi-Fi specification, and each AC has its own priority to access the Wi-Fi channel. Moreover, a map rule is defined to map the QoS priority of other protocol, e.g., 802.11D or TCP/IP precedence is mapped to Wi-Fi AC. - -The table below describes how the IP Precedences are mapped to Wi-Fi ACs in {IDF_TARGET_NAME}. It also indicates whether the AMPDU is supported for this AC. The table is sorted from high to low priority. That is to say, the AC_VO has the highest priority. - -+------------------+------------------------+-----------------+ -| IP Precedence | Wi-Fi AC | Support AMPDU? | -+==================+========================+=================+ -| 6, 7 | AC_VO (Voice) | No | -+------------------+------------------------+-----------------+ -| 4, 5 | AC_VI (Video) | Yes | -+------------------+------------------------+-----------------+ -| 3, 0 | AC_BE (Best Effort) | Yes | -+------------------+------------------------+-----------------+ -| 1, 2 | AC_BK (Background) | Yes | -+------------------+------------------------+-----------------+ - -The application can make use of the QoS feature by configuring the IP precedence via socket option IP_TOS. Here is an example to make the socket to use VI queue:: - - const int ip_precedence_vi = 4; - const int ip_precedence_offset = 5; - int priority = (ip_precedence_vi << ip_precedence_offset); - setsockopt(socket_id, IPPROTO_IP, IP_TOS, &priority, sizeof(priority)); - -Theoretically, the higher priority AC has better performance than the lower priority AC. However, it is not always true. Here are some suggestions about how to use the Wi-Fi QoS: - - - Some really important application traffic can be put into the AC_VO queue. But avoid using the AC_VO queue for heavy traffic, as it may impact the management frames which also use this queue. Eventually, it is worth noting that the AC_VO queue does not support AMPDU, and its performance with heavy traffic is no better than other queues. - - Avoid using more than two precedences supported by different AMPDUs, e.g., when socket A uses precedence 0, socket B uses precedence 1, and socket C uses precedence 2. This can be a bad design because it may need much more memory. To be specific, the Wi-Fi driver may generate a Block Ack session for each precedence and it needs more memory if the Block Ack session is set up. - - -Wi-Fi AMSDU -------------------------- - -.. only:: not SOC_SPIRAM_SUPPORTED - - {IDF_TARGET_NAME} supports receiving AMSDU. - -.. only:: SOC_SPIRAM_SUPPORTED - - {IDF_TARGET_NAME} supports receiving and transmitting AMSDU. AMSDU TX is disabled by default, since enable AMSDU TX need more memory. Select :ref:`CONFIG_ESP_WIFI_AMSDU_TX_ENABLED` to enable AMSDU Tx feature, it depends on :ref:`CONFIG_SPIRAM`. - -Wi-Fi Fragment -------------------------- - -.. only:: not SOC_WIFI_TXOP_SUPPORT - - supports Wi-Fi receiving fragment, but does not support Wi-Fi transmitting fragment. - -.. only:: SOC_WIFI_TXOP_SUPPORT - - {IDF_TARGET_NAME} supports Wi-Fi receiving and transmitting fragment. - -WPS Enrollee -------------------------- - -{IDF_TARGET_NAME} supports WPS enrollee feature in Wi-Fi mode :cpp:enumerator:`WIFI_MODE_STA` or :cpp:enumerator:`WIFI_MODE_APSTA`. Currently, {IDF_TARGET_NAME} supports WPS enrollee type PBC and PIN. - -.. _wifi-buffer-usage: - -Wi-Fi Buffer Usage --------------------------- - -This section is only about the dynamic buffer configuration. - -Why Buffer Configuration Is Important -+++++++++++++++++++++++++++++++++++++++ - -In order to get a high-performance system, consider the memory usage/configuration carefully for the following reasons: - - - the available memory in {IDF_TARGET_NAME} is limited. - - currently, the default type of buffer in LwIP and Wi-Fi drivers is "dynamic", **which means that both the LwIP and Wi-Fi share memory with the application**. Programmers should always keep this in mind; otherwise, they will face a memory issue, such as "running out of heap memory". - - it is very dangerous to run out of heap memory, as this will cause {IDF_TARGET_NAME} an "undefined behavior". Thus, enough heap memory should be reserved for the application, so that it never runs out of it. - - the Wi-Fi throughput heavily depends on memory-related configurations, such as the TCP window size and Wi-Fi RX/TX dynamic buffer number. - - the peak heap memory that the {IDF_TARGET_NAME} LwIP/Wi-Fi may consume depends on a number of factors, such as the maximum TCP/UDP connections that the application may have. - - the total memory that the application requires is also an important factor when considering memory configuration. - -Due to these reasons, there is not a good-for-all application configuration. Rather, it is recommended to consider memory configurations separately for every different application. - -Dynamic vs. Static Buffer -++++++++++++++++++++++++++++++ - -The default type of buffer in Wi-Fi drivers is "dynamic". Most of the time the dynamic buffer can significantly save memory. However, it makes the application programming a little more difficult, because in this case the application needs to consider memory usage in Wi-Fi. - -lwIP also allocates buffers at the TCP/IP layer, and this buffer allocation is also dynamic. See :ref:`lwIP documentation section about memory use and performance `. - -Peak Wi-Fi Dynamic Buffer -++++++++++++++++++++++++++++++ - -The Wi-Fi driver supports several types of buffer (refer to `Wi-Fi Buffer Configure`_). However, this section is about the usage of the dynamic Wi-Fi buffer only. -The peak heap memory that Wi-Fi consumes is the **theoretically-maximum memory** that the Wi-Fi driver consumes. Generally, the peak memory depends on: - -- :math:`b_{rx}` the number of dynamic RX buffers that are configured -- :math:`b_{tx}` the number of dynamic TX buffers that are configured -- :math:`m_{rx}` the maximum packet size that the Wi-Fi driver can receive -- :math:`m_{tx}` the maximum packet size that the Wi-Fi driver can send - -So, the peak memory that the Wi-Fi driver consumes (:math:`p`) can be calculated with the following formula: - -.. math:: - - p = (b_{rx} * m_{rx}) + (b_{tx} * m_{tx}) - -Generally, the dynamic TX long buffers and dynamic TX long long buffers can be ignored, because they are management frames which only have a small impact on the system. - -.. _How-to-improve-Wi-Fi-performance: - -How to Improve Wi-Fi Performance ----------------------------------- - -The performance of {IDF_TARGET_NAME} Wi-Fi is affected by many parameters, and there are mutual constraints between each parameter. A proper configuration cannot only improve performance, but also increase available memory for applications and improve stability. - -This section briefly explains the operating mode of the Wi-Fi/LwIP protocol stack and the role of each parameter. It also gives several recommended configuration ranks to help choose the appropriate rank according to the usage scenario. - -Protocol Stack Operation Mode -++++++++++++++++++++++++++++++++++ - -.. figure:: ../../_static/api-guides-WiFi-driver-how-to-improve-WiFi-performance.png - :align: center - - {IDF_TARGET_NAME} datapath - -The {IDF_TARGET_NAME} protocol stack is divided into four layers: Application, LwIP, Wi-Fi, and Hardware. - - - During receiving, hardware puts the received packet into DMA buffer, and then transfers it into the RX buffer of Wi-Fi and LwIP in turn for related protocol processing, and finally to the application layer. The Wi-Fi RX buffer and the LwIP RX buffer shares the same buffer by default. In other words, the Wi-Fi forwards the packet to LwIP by reference by default. - - - During sending, the application copies the messages to be sent into the TX buffer of the LwIP layer for TCP/IP encapsulation. The messages will then be passed to the TX buffer of the Wi-Fi layer for MAC encapsulation and wait to be sent. - -Parameters -++++++++++++++ - -Increasing the size or number of the buffers mentioned above properly can improve Wi-Fi performance. Meanwhile, it will reduce available memory to the application. The following is an introduction to the parameters that users need to configure: - -**RX direction:** - - - :ref:`CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM` - This parameter indicates the number of DMA buffer at the hardware layer. Increasing this parameter will increase the sender's one-time receiving throughput, thereby improving the Wi-Fi protocol stack ability to handle burst traffic. - - - :ref:`CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM` - This parameter indicates the number of RX buffer in the Wi-Fi layer. Increasing this parameter will improve the performance of packet reception. This parameter needs to match the RX buffer size of the LwIP layer. - - - :ref:`CONFIG_ESP_WIFI_RX_BA_WIN` - This parameter indicates the size of the AMPDU BA Window at the receiving end. This parameter should be configured to the smaller value between twice of :ref:`CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM` and :ref:`CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM`. - - - :ref:`CONFIG_LWIP_TCP_WND_DEFAULT` - This parameter represents the RX buffer size of the LwIP layer for each TCP stream. Its value should be configured to the value of WIFI_DYNAMIC_RX_BUFFER_NUM (KB) to reach a high and stable performance. Meanwhile, in case of multiple streams, this value needs to be reduced proportionally. - -**TX direction:** - - - :ref:`CONFIG_ESP_WIFI_TX_BUFFER` - This parameter indicates the type of TX buffer, it is recommended to configure it as a dynamic buffer, which can make full use of memory. - - - :ref:`CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM` - This parameter indicates the number of TX buffer on the Wi-Fi layer. Increasing this parameter will improve the performance of packet sending. The parameter value needs to match the TX buffer size of the LwIP layer. - - - :ref:`CONFIG_LWIP_TCP_SND_BUF_DEFAULT` - This parameter represents the TX buffer size of the LwIP layer for each TCP stream. Its value should be configured to the value of WIFI_DYNAMIC_TX_BUFFER_NUM (KB) to reach a high and stable performance. In case of multiple streams, this value needs to be reduced proportionally. - -**Throughput optimization by placing code in IRAM:** - -.. only:: esp32 or esp32s2 - - - :ref:`CONFIG_ESP_WIFI_IRAM_OPT` - If this option is enabled, some Wi-Fi functions are moved to IRAM, improving throughput. This increases IRAM usage by 15 kB. - - - :ref:`CONFIG_ESP_WIFI_RX_IRAM_OPT` - If this option is enabled, some Wi-Fi RX functions are moved to IRAM, improving throughput. This increases IRAM usage by 16 kB. - - - :ref:`CONFIG_LWIP_IRAM_OPTIMIZATION` - If this option is enabled, some LwIP functions are moved to IRAM, improving throughput. This increases IRAM usage by 13 kB. - -.. only:: esp32c6 - - - :ref:`CONFIG_ESP_WIFI_IRAM_OPT` - If this option is enabled, some Wi-Fi functions are moved to IRAM, improving throughput. This increases IRAM usage by 13 kB. - - - :ref:`CONFIG_ESP_WIFI_RX_IRAM_OPT` - If this option is enabled, some Wi-Fi RX functions are moved to IRAM, improving throughput. This increases IRAM usage by 7 kB. - - - :ref:`CONFIG_LWIP_IRAM_OPTIMIZATION` - If this option is enabled, some LwIP functions are moved to IRAM, improving throughput. This increases IRAM usage by 14 kB. - -.. only:: esp32s2 - - **CACHE:** - - - :ref:`CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE` - Configure the size of the instruction Cache. - - - :ref:`CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_SIZE` - Configure the width of the instruction Cache bus. - -.. only:: esp32s3 - - **CACHE:** - - - :ref:`CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE` - Configure the size of the instruction Cache. - - - :ref:`CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE` - Configure the size of the instruction Cache bus. - - - :ref:`CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS` - Configure the associated ways of the instruction Cache. - - - :ref:`CONFIG_ESP32S3_DATA_CACHE_SIZE` - Configure the size of the Data Cache. - - - :ref:`CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE` - Configure the line size of the Data Cache. - - - :ref:`CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS` - Configure the associated ways of the Data Cache. - -.. note:: - The buffer size mentioned above is fixed as 1.6 KB. - -How to Configure Parameters -++++++++++++++++++++++++++++ - -The memory of {IDF_TARGET_NAME} is shared by protocol stack and applications. - -Here, several configuration ranks are given. In most cases, the user should select a suitable rank for parameter configuration according to the size of the memory occupied by the application. - -The parameters not mentioned in the following table should be set to the default. - -.. only:: esp32 - - .. list-table:: - :header-rows: 1 - :widths: 10 5 5 10 5 5 10 5 - - * - Rank - - Iperf - - TX prior - - High-performance - - RX prior - - Default - - Memory saving - - Minimum - * - Available memory (KB) - - 37.1 - - 113.8 - - 123.3 - - 145.5 - - 144.5 - - 170.2 - - 185.2 - * - WIFI_STATIC_RX_BUFFER_NUM - - 16 - - 6 - - 6 - - 6 - - 6 - - 6 - - 4 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 64 - - 16 - - 24 - - 34 - - 20 - - 12 - - 8 - * - WIFI_DYNAMIC_TX_BUFFER_NUM - - 64 - - 28 - - 24 - - 18 - - 20 - - 12 - - 8 - * - WIFI_RX_BA_WIN - - 32 - - 8 - - 12 - - 12 - - 10 - - 6 - - Disable - * - TCP_SND_BUF_DEFAULT (KB) - - 65 - - 28 - - 24 - - 18 - - 20 - - 12 - - 8 - * - TCP_WND_DEFAULT (KB) - - 65 - - 16 - - 24 - - 34 - - 20 - - 12 - - 8 - * - WIFI_IRAM_OPT - - ENABLE - - ENABLE - - ENABLE - - ENABLE - - ENABLE - - ENABLE - - ENABLE - * - WIFI_RX_IRAM_OPT - - ENABLE - - ENABLE - - ENABLE - - ENABLE - - ENABLE - - ENABLE - - ENABLE - * - LWIP_IRAM_OPTIMIZATION - - ENABLE - - ENABLE - - ENABLE - - ENABLE - - ENABLE - - ENABLE - - ENABLE - * - TCP TX throughput (Mbit/s) - - 74.6 - - 50.8 - - 46.5 - - 39.9 - - 44.2 - - 33.8 - - 25.6 - * - TCP RX throughput (Mbit/s) - - 63.6 - - 35.5 - - 42.3 - - 48.5 - - 40.5 - - 30.1 - - 27.8 - * - UDP TX throughput (Mbit/s) - - 76.2 - - 75.1 - - 74.1 - - 72.4 - - 69.6 - - 64.1 - - 36.5 - * - UDP RX throughput (Mbit/s) - - 83.1 - - 66.3 - - 75.1 - - 75.6 - - 73.1 - - 65.3 - - 54.7 - - -.. only:: esp32s2 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 10 10 10 - - * - Rank - - Iperf - - High-performance - - Default - - Memory saving - - Minimum - * - Available memory (KB) - - 4.1 - - 24.2 - - 78.4 - - 86.5 - - 116.4 - * - WIFI_STATIC_RX_BUFFER_NUM - - 8 - - 6 - - 6 - - 4 - - 3 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 24 - - 18 - - 12 - - 8 - - 6 - * - WIFI_DYNAMIC_TX_BUFFER_NUM - - 24 - - 18 - - 12 - - 8 - - 6 - * - WIFI_RX_BA_WIN - - 12 - - 9 - - 6 - - 4 - - 3 - * - TCP_SND_BUF_DEFAULT (KB) - - 24 - - 18 - - 12 - - 8 - - 6 - * - TCP_WND_DEFAULT (KB) - - 24 - - 18 - - 12 - - 8 - - 6 - * - WIFI_IRAM_OPT - - ENABLE - - ENABLE - - ENABLE - - ENABLE - - DISABLE - * - WIFI_RX_IRAM_OPT - - ENABLE - - ENABLE - - ENABLE - - DISABLE - - DISABLE - * - LWIP_IRAM_OPTIMIZATION - - ENABLE - - ENABLE - - DISABLE - - DISABLE - - DISABLE - * - INSTRUCTION_CACHE - - 16 - - 16 - - 16 - - 16 - - 8 - * - INSTRUCTION_CACHE_LINE - - 16 - - 16 - - 16 - - 16 - - 16 - * - TCP TX throughput (Mbit/s) - - 37.6 - - 33.1 - - 22.5 - - 12.2 - - 5.5 - * - TCP RX throughput (Mbit/s) - - 31.5 - - 28.1 - - 20.1 - - 13.1 - - 7.2 - * - UDP TX throughput (Mbit/s) - - 58.1 - - 57.3 - - 28.1 - - 22.6 - - 8.7 - * - UDP RX throughput (Mbit/s) - - 78.1 - - 66.7 - - 65.3 - - 53.8 - - 28.5 - -.. only:: esp32c3 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 - - * - Rank - - Iperf - - Default - - Minimum - * - Available memory (KB) - - 59 - - 160 - - 180 - * - WIFI_STATIC_RX_BUFFER_NUM - - 20 - - 8 - - 3 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 40 - - 16 - - 6 - * - WIFI_DYNAMIC_TX_BUFFER_NUM - - 40 - - 16 - - 6 - * - WIFI_RX_BA_WIN - - 32 - - 16 - - 6 - * - TCP_SND_BUF_DEFAULT (KB) - - 40 - - 16 - - 6 - * - TCP_WND_DEFAULT (KB) - - 40 - - 16 - - 6 - * - LWIP_IRAM_OPTIMIZATION - - ENABLE - - ENABLE - - DISABLE - * - TCP TX throughput (Mbit/s) - - 38.1 - - 27.2 - - 20.4 - * - TCP RX throughput (Mbit/s) - - 35.3 - - 24.2 - - 17.4 - * - UDP TX throughput (Mbit/s) - - 40.6 - - 38.9 - - 34.1 - * - UDP RX throughput (Mbit/s) - - 52.4 - - 44.5 - - 44.2 - -.. only:: esp32c6 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 - - * - Rank - - Iperf - - Default - - Minimum - * - Available memory (KB) - - 223 - - 276 - - 299 - * - WIFI_STATIC_RX_BUFFER_NUM - - 20 - - 8 - - 3 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 40 - - 16 - - 6 - * - WIFI_DYNAMIC_TX_BUFFER_NUM - - 40 - - 16 - - 6 - * - WIFI_RX_BA_WIN - - 32 - - 16 - - 6 - * - TCP_SND_BUF_DEFAULT (KB) - - 40 - - 16 - - 6 - * - TCP_WND_DEFAULT (KB) - - 40 - - 16 - - 6 - * - LWIP_IRAM_OPTIMIZATION - - ENABLE - - ENABLE - - DISABLE - * - TCP TX throughput (Mbit/s) - - 30.5 - - 25.9 - - 16.4 - * - TCP RX throughput (Mbit/s) - - 27.8 - - 21.6 - - 14.3 - * - UDP TX throughput (Mbit/s) - - 37.8 - - 36.1 - - 34.6 - * - UDP RX throughput (Mbit/s) - - 41.5 - - 36.8 - - 36.7 - -.. only:: esp32c2 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 - - * - Rank - - Iperf - - Default - - Minimum - * - Available memory (KB) - - 37 - - 56 - - 84 - * - WIFI_STATIC_RX_BUFFER_NUM - - 14 - - 7 - - 3 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 18 - - 14 - - 6 - * - WIFI_DYNAMIC_TX_BUFFER_NUM - - 18 - - 14 - - 6 - * - WIFI_RX_BA_WIN - - 16 - - 12 - - 6 - * - TCP_SND_BUF_DEFAULT (KB) - - 18 - - 14 - - 6 - * - TCP_WND_DEFAULT (KB) - - 18 - - 14 - - 6 - * - LWIP_IRAM_OPTIMIZATION - - ENABLE - - ENABLE - - DISABLE - * - TCP TX throughput (Mbit/s) - - 21.6 - - 21.4 - - 14.3 - * - TCP RX throughput (Mbit/s) - - 19.1 - - 17.9 - - 12.4 - * - UDP TX throughput (Mbit/s) - - 26.4 - - 26.3 - - 25.0 - * - UDP RX throughput (Mbit/s) - - 32.3 - - 31.5 - - 27.7 - -.. only:: esp32s3 - - .. list-table:: - :header-rows: 1 - :widths: 25 20 25 25 - - * - Rank - - Iperf - - Default - - Minimum - * - Available memory (KB) - - 133.9 - - 183.9 - - 273.6 - * - WIFI_STATIC_RX_BUFFER_NUM - - 24 - - 8 - - 3 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 64 - - 32 - - 6 - * - WIFI_DYNAMIC_TX_BUFFER_NUM - - 64 - - 32 - - 6 - * - WIFI_RX_BA_WIN - - 32 - - 16 - - 6 - * - TCP_SND_BUF_DEFAULT (KB) - - 64 - - 32 - - 6 - * - TCP_WND_DEFAULT (KB) - - 64 - - 32 - - 6 - * - WIFI_IRAM_OPT - - ENABLE - - ENABLE - - ENABLE - * - WIFI_RX_IRAM_OPT - - ENABLE - - ENABLE - - ENABLE - * - LWIP_IRAM_OPTIMIZATION - - ENABLE - - ENABLE - - DISABLE - * - INSTRUCTION_CACHE - - 32 - - 32 - - 16 - * - INSTRUCTION_CACHE_LINE - - 32 - - 32 - - 32 - * - INSTRUCTION_CACHE_WAYS - - 8 - - 8 - - 4 - * - TCP TX throughput (Mbit/s) - - 83.93 - - 64.28 - - 23.17 - * - TCP RX throughput (Mbit/s) - - 73.98 - - 60.39 - - 18.11 - * - UDP TX throughput (Mbit/s) - - 98.69 - - 96.28 - - 48.78 - * - UDP RX throughput (Mbit/s) - - 88.58 - - 86.57 - - 59.45 - -.. only:: esp32 or esp32s3 - - .. note:: - The test was performed with a single stream in a shielded box using an ASUS RT-N66U router. - {IDF_TARGET_NAME}'s CPU is dual core with 240 MHz. {IDF_TARGET_NAME}'s flash is in QIO mode with 80 MHz. - -.. only:: esp32s2 - - .. note:: - The test was performed with a single stream in a shielded box using an ASUS RT-N66U router. - {IDF_TARGET_NAME}'s CPU is single core with 240 MHz. {IDF_TARGET_NAME}'s flash is in QIO mode with 80 MHz. - -.. only:: esp32c3 - - .. note:: - The test was performed with a single stream in a shielded box using an ASUS RT-N66U router. - {IDF_TARGET_NAME}'s CPU is single core with 160 MHz. {IDF_TARGET_NAME}'s flash is in QIO mode with 80 MHz. - -.. only:: esp32c6 - - .. note:: - The test was performed with a single stream in a shielded box using an XIAOMI AX-6000 router. - {IDF_TARGET_NAME}'s CPU is single core with 160 MHz. {IDF_TARGET_NAME}'s flash is in QIO mode with 80 MHz. - -.. only:: esp32c2 - - .. note:: - The test was performed with a single stream in a shielded box using an Redmi RM2100 router. - {IDF_TARGET_NAME}'s CPU is single core with 120 MHz. {IDF_TARGET_NAME}'s flash is in QIO mode with 60 MHz. - -.. only:: esp32 - - **Ranks:** - - - **Iperf rank** - {IDF_TARGET_NAME} extreme performance rank used to test extreme performance. - - - **High-performance rank** - The {IDF_TARGET_NAME}'s high-performance configuration rank, suitable for scenarios where the application occupies less memory and has high-performance requirements. In this rank, users can choose to use the RX prior rank or the TX prior rank according to the usage scenario. - - - **Default rank** - {IDF_TARGET_NAME}'s default configuration rank, the available memory, and performance are in balance. - - - **Memory saving rank** - This rank is suitable for scenarios where the application requires a large amount of memory, and the transceiver performance will be reduced in this rank. - - - **Minimum rank** - This is the minimum configuration rank of {IDF_TARGET_NAME}. The protocol stack only uses the necessary memory for running. It is suitable for scenarios where there is no requirement for performance and the application requires lots of space. - -.. only:: esp32s2 - - **Ranks:** - - - **Iperf rank** - {IDF_TARGET_NAME} extreme performance rank used to test extreme performance. - - - **High-performance rank** - The {IDF_TARGET_NAME}'s high-performance configuration rank, suitable for scenarios where the application occupies less memory and has high-performance requirements. - - - **Default rank** - {IDF_TARGET_NAME}'s default configuration rank, the available memory, and performance are in balance. - - - **Memory saving rank** - This rank is suitable for scenarios where the application requires a large amount of memory, and the transceiver performance will be reduced in this rank. - - - **Minimum rank** - This is the minimum configuration rank of {IDF_TARGET_NAME}. The protocol stack only uses the necessary memory for running. It is suitable for scenarios where there is no requirement for performance and the application requires lots of space. - -.. only:: esp32c3 or esp32s3 or esp32c6 - - **Ranks:** - - - **Iperf rank** - {IDF_TARGET_NAME} extreme performance rank used to test extreme performance. - - - **Default rank** - {IDF_TARGET_NAME}'s default configuration rank, the available memory, and performance are in balance. - - - **Minimum rank** - This is the minimum configuration rank of {IDF_TARGET_NAME}. The protocol stack only uses the necessary memory for running. It is suitable for scenarios where there is no requirement for performance and the application requires lots of space. - -.. only:: SOC_SPIRAM_SUPPORTED - - Using PSRAM - ++++++++++++++++++++++++++++ - - PSRAM is generally used when the application takes up a lot of memory. In this mode, the :ref:`CONFIG_ESP_WIFI_TX_BUFFER` is forced to be static. :ref:`CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM` indicates the number of DMA buffers at the hardware layer, and increasing this parameter can improve performance. - The following are the recommended ranks for using PSRAM: - - .. only:: esp32 - - .. list-table:: - :header-rows: 1 - :widths: 15 10 10 15 10 - - * - Rank - - Iperf - - Default - - Memory saving - - Minimum - * - Available memory (KB) - - 113.8 - - 152.4 - - 181.2 - - 202.6 - * - WIFI_STATIC_RX_BUFFER_NUM - - 16 - - 8 - - 4 - - 2 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 128 - - 128 - - 128 - - 128 - * - WIFI_STATIC_TX_BUFFER_NUM - - 16 - - 8 - - 4 - - 2 - * - WIFI_RX_BA_WIN - - 16 - - 16 - - 8 - - Disable - * - TCP_SND_BUF_DEFAULT (KB) - - 65 - - 65 - - 65 - - 65 - * - TCP_WND_DEFAULT (KB) - - 65 - - 65 - - 65 - - 65 - * - WIFI_IRAM_OPT - - ENABLE - - ENABLE - - ENABLE - - DISABLE - * - WIFI_RX_IRAM_OPT - - ENABLE - - ENABLE - - DISABLE - - DISABLE - * - LWIP_IRAM_OPTIMIZATION - - ENABLE - - DISABLE - - DISABLE - - DISABLE - * - TCP TX throughput (Mbit/s) - - 37.5 - - 31.7 - - 21.7 - - 14.6 - * - TCP RX throughput (Mbit/s) - - 31.5 - - 29.8 - - 26.5 - - 21.1 - * - UDP TX throughput (Mbit/s) - - 69.1 - - 31.5 - - 27.1 - - 24.1 - * - UDP RX throughput (Mbit/s) - - 40.1 - - 38.5 - - 37.5 - - 36.9 - - .. only:: esp32s2 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 10 15 - - * - Rank - - Iperf - - Default - - Memory saving - - Minimum - * - Available memory (KB) - - 70.6 - - 96.4 - - 118.8 - - 148.2 - * - WIFI_STATIC_RX_BUFFER_NUM - - 8 - - 8 - - 6 - - 4 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 64 - - 64 - - 64 - - 64 - * - WIFI_STATIC_TX_BUFFER_NUM - - 16 - - 8 - - 6 - - 4 - * - WIFI_RX_BA_WIN - - 16 - - 6 - - 6 - - Disable - * - TCP_SND_BUF_DEFAULT (KB) - - 32 - - 32 - - 32 - - 32 - * - TCP_WND_DEFAULT (KB) - - 32 - - 32 - - 32 - - 32 - * - WIFI_IRAM_OPT - - ENABLE - - ENABLE - - ENABLE - - DISABLE - * - WIFI_RX_IRAM_OPT - - ENABLE - - ENABLE - - DISABLE - - DISABLE - * - LWIP_IRAM_OPTIMIZATION - - ENABLE - - DISABLE - - DISABLE - - DISABLE - * - INSTRUCTION_CACHE - - 16 - - 16 - - 16 - - 8 - * - INSTRUCTION_CACHE_LINE - - 16 - - 16 - - 16 - - 16 - * - DATA_CACHE - - 8 - - 8 - - 8 - - 8 - * - DATA_CACHE_LINE - - 32 - - 32 - - 32 - - 32 - * - TCP TX throughput (Mbit/s) - - 40.1 - - 29.2 - - 20.1 - - 8.9 - * - TCP RX throughput (Mbit/s) - - 21.9 - - 16.8 - - 14.8 - - 9.6 - * - UDP TX throughput (Mbit/s) - - 50.1 - - 25.7 - - 22.4 - - 10.2 - * - UDP RX throughput (Mbit/s) - - 45.3 - - 43.1 - - 28.5 - - 15.1 - - .. note:: - Reaching peak performance may cause task watchdog. It is a normal phenomenon considering the CPU may have no time for lower priority tasks. - - .. only:: esp32s3 - - **PSRAM with 4 lines:** - - .. list-table:: - :header-rows: 1 - :widths: 25 20 25 25 25 - - * - Rank - - Iperf - - Default - - Memory saving - - Minimum - * - Available memory (KB) - - 50.3 - - 158.7 - - 198.2 - - 228.9 - * - WIFI_STATIC_RX_BUFFER_NUM - - 24 - - 8 - - 6 - - 4 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 85 - - 64 - - 32 - - 32 - * - WIFI_STATIC_TX_BUFFER_NUM - - 32 - - 32 - - 6 - - 4 - * - WIFI_RX_BA_WIN - - 32 - - 16 - - 12 - - Disable - * - TCP_SND_BUF_DEFAULT (KB) - - 85 - - 32 - - 32 - - 32 - * - TCP_WND_DEFAULT (KB) - - 85 - - 32 - - 32 - - 32 - * - WIFI_IRAM_OPT - - ENABLE - - ENABLE - - ENABLE - - DISABLE - * - WIFI_RX_IRAM_OPT - - ENABLE - - ENABLE - - DISABLE - - DISABLE - * - LWIP_IRAM_OPTIMIZATION - - ENABLE - - DISABLE - - DISABLE - - DISABLE - * - LWIP_UDP_RECVMBOX_SIZE - - 16 - - 16 - - 16 - - 16 - * - INSTRUCTION_CACHE - - 32 - - 16 - - 16 - - 16 - * - INSTRUCTION_CACHE_LINE - - 32 - - 16 - - 16 - - 16 - * - INSTRUCTION_CACHE_WAYS - - 8 - - 8 - - 8 - - 8 - * - DATA_CACHE - - 64 - - 16 - - 16 - - 16 - * - DATA_CACHE_LINE - - 32 - - 32 - - 32 - - 32 - * - DATA_CACHE_WAYS - - 8 - - 8 - - 8 - - 8 - * - TCP TX throughput (Mbit/s) - - 93.1 - - 62.5 - - 41.3 - - 42.7 - * - TCP RX throughput (Mbit/s) - - 88.9 - - 46.5 - - 46.2 - - 37.9 - * - UDP TX throughput (Mbit/s) - - 106.4 - - 106.2 - - 60.7 - - 50 - * - UDP RX throughput (Mbit/s) - - 99.8 - - 92.6 - - 94.3 - - 53.3 - - **PSRAM with 8 lines:** - - .. list-table:: - :header-rows: 1 - :widths: 25 20 25 25 25 - - * - Rank - - Iperf - - Default - - Memory saving - - Minimum - * - Available memory (KB) - - 49.1 - - 151.3 - - 215.3 - - 243.6 - * - WIFI_STATIC_RX_BUFFER_NUM - - 24 - - 8 - - 6 - - 4 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 85 - - 64 - - 32 - - 32 - * - WIFI_STATIC_TX_BUFFER_NUM - - 32 - - 32 - - 6 - - 4 - * - WIFI_RX_BA_WIN - - 32 - - 16 - - 12 - - Disable - * - TCP_SND_BUF_DEFAULT (KB) - - 85 - - 32 - - 32 - - 32 - * - TCP_WND_DEFAULT (KB) - - 85 - - 32 - - 32 - - 32 - * - WIFI_IRAM_OPT - - ENABLE - - ENABLE - - ENABLE - - DISABLE - * - WIFI_RX_IRAM_OPT - - ENABLE - - ENABLE - - DISABLE - - DISABLE - * - LWIP_IRAM_OPTIMIZATION - - ENABLE - - DISABLE - - DISABLE - - DISABLE - * - LWIP_UDP_RECVMBOX_SIZE - - 16 - - 16 - - 16 - - 16 - * - INSTRUCTION_CACHE - - 32 - - 16 - - 16 - - 16 - * - INSTRUCTION_CACHE_LINE - - 32 - - 16 - - 16 - - 16 - * - INSTRUCTION_CACHE_WAYS - - 8 - - 8 - - 8 - - 8 - * - DATA_CACHE - - 64 - - 16 - - 16 - - 16 - * - DATA_CACHE_LINE - - 32 - - 32 - - 32 - - 32 - * - DATA_CACHE_WAYS - - 8 - - 8 - - 8 - - 8 - * - TCP TX throughput (Mbit/s) - - 93.3 - - 58.4 - - 37.1 - - 35.6 - * - TCP RX throughput (Mbit/s) - - 86.1 - - 43.6 - - 42.5 - - 35 - * - UDP TX throughput (Mbit/s) - - 104.7 - - 82.2 - - 60.4 - - 47.9 - * - UDP RX throughput (Mbit/s) - - 104.6 - - 104.8 - - 104 - - 55.7 - - -Wi-Fi Menuconfig ------------------------ - -Wi-Fi Buffer Configure -+++++++++++++++++++++++ - -If you are going to modify the default number or type of buffer, it would be helpful to also have an overview of how the buffer is allocated/freed in the data path. The following diagram shows this process in the TX direction: - -.. blockdiag:: - :caption: TX Buffer Allocation - :align: center - - blockdiag buffer_allocation_tx { - - # global attributes - node_height = 60; - node_width = 100; - span_width = 50; - span_height = 20; - default_shape = roundedbox; - - # labels of diagram nodes - APPL_TASK [label="Application\n task", fontsize=12]; - LwIP_TASK [label="LwIP\n task", fontsize=12]; - WIFI_TASK [label="Wi-Fi\n task", fontsize=12]; - - # labels of description nodes - APPL_DESC [label="1> User data", width=120, height=25, shape=note, color=yellow]; - LwIP_DESC [label="2> Pbuf", width=120, height=25, shape=note, color=yellow]; - WIFI_DESC [label="3> Dynamic (Static)\n TX Buffer", width=150, height=40, shape=note, color=yellow]; - - # node connections - APPL_TASK -> LwIP_TASK -> WIFI_TASK - APPL_DESC -> LwIP_DESC -> WIFI_DESC [style=none] - } - - -Description: - - - The application allocates the data which needs to be sent out. - - The application calls TCPIP-/Socket-related APIs to send the user data. These APIs will allocate a PBUF used in LwIP, and make a copy of the user data. - - When LwIP calls a Wi-Fi API to send the PBUF, the Wi-Fi API will allocate a "Dynamic Tx Buffer" or "Static Tx Buffer", make a copy of the LwIP PBUF, and finally send the data. - -The following diagram shows how buffer is allocated/freed in the RX direction: - -.. blockdiag:: - :caption: RX Buffer Allocation - :align: center - - blockdiag buffer_allocation_rx { - - # global attributes - node_height = 60; - node_width = 100; - span_width = 40; - span_height = 20; - default_shape = roundedbox; - - # labels of diagram nodes - APPL_TASK [label="Application\n task", fontsize=12]; - LwIP_TASK [label="LwIP\n task", fontsize=12]; - WIFI_TASK [label="Wi-Fi\n task", fontsize=12]; - WIFI_INTR [label="Wi-Fi\n interrupt", fontsize=12]; - - # labels of description nodes - APPL_DESC [label="4> User\n Data Buffer", height=40, shape=note, color=yellow]; - LwIP_DESC [label="3> Pbuf", height=40, shape=note, color=yellow]; - WIFI_DESC [label="2> Dynamic\n RX Buffer", height=40, shape=note, color=yellow]; - INTR_DESC [label="1> Static\n RX Buffer", height=40, shape=note, color=yellow]; - - # node connections - APPL_TASK <- LwIP_TASK <- WIFI_TASK <- WIFI_INTR - APPL_DESC <- LwIP_DESC <- WIFI_DESC <- INTR_DESC [style=none] - } - -Description: - - - The Wi-Fi hardware receives a packet over the air and puts the packet content to the "Static Rx Buffer", which is also called "RX DMA Buffer". - - The Wi-Fi driver allocates a "Dynamic Rx Buffer", makes a copy of the "Static Rx Buffer", and returns the "Static Rx Buffer" to hardware. - - The Wi-Fi driver delivers the packet to the upper-layer (LwIP), and allocates a PBUF for holding the "Dynamic Rx Buffer". - - The application receives data from LwIP. - -The diagram shows the configuration of the Wi-Fi internal buffer. - -.. list-table:: - :header-rows: 1 - :widths: 10 10 10 10 25 - - * - Buffer Type - - Alloc Type - - Default - - Configurable - - Description - * - Static RX Buffer (Hardware RX Buffer) - - Static - - 10 * 1600 Bytes - - Yes - - This is a kind of DMA memory. It is initialized in :cpp:func:`esp_wifi_init()` and freed in :cpp:func:`esp_wifi_deinit()`. The ‘Static Rx Buffer’ forms the hardware receiving list. Upon receiving a frame over the air, hardware writes the frame into the buffer and raises an interrupt to the CPU. Then, the Wi-Fi driver reads the content from the buffer and returns the buffer back to the list. - - If needs be, the application can reduce the memory statically allocated by Wi-Fi. It can reduce this value from 10 to 6 to save 6400 Bytes of memory. It is not recommended to reduce the configuration to a value less than 6 unless the AMPDU feature is disabled. - * - Dynamic RX Buffer - - Dynamic - - 32 - - Yes - - The buffer length is variable and it depends on the received frames’ length. When the Wi-Fi driver receives a frame from the ‘Hardware Rx Buffer’, the ‘Dynamic Rx Buffer’ needs to be allocated from the heap. The number of the Dynamic Rx Buffer, configured in the menuconfig, is used to limit the total un-freed Dynamic Rx Buffer number. - * - Dynamic TX Buffer - - Dynamic - - 32 - - Yes - - This is a kind of DMA memory. It is allocated to the heap. When the upper-layer (LwIP) sends packets to the Wi-Fi driver, it firstly allocates a ‘Dynamic TX Buffer’ and makes a copy of the upper-layer buffer. - - The Dynamic and Static TX Buffers are mutually exclusive. - * - Static TX Buffer - - Static - - 16 * 1600Bytes - - Yes - - This is a kind of DMA memory. It is initialized in :cpp:func:`esp_wifi_init()` and freed in :cpp:func:`esp_wifi_deinit()`. When the upper-layer (LwIP) sends packets to the Wi-Fi driver, it firstly allocates a ‘Static TX Buffer’ and makes a copy of the upper-layer buffer. - - The Dynamic and Static TX Buffer are mutually exclusive. - - The TX buffer must be a DMA buffer. For this reason, if PSRAM is enabled, the TX buffer must be static. - * - Management Short Buffer - - Dynamic - - 8 - - NO - - Wi-Fi driver’s internal buffer. - * - Management Long Buffer - - Dynamic - - 32 - - NO - - Wi-Fi driver’s internal buffer. - * - Management Long Long Buffer - - Dynamic - - 32 - - NO - - Wi-Fi driver’s internal buffer. - -Wi-Fi NVS Flash -+++++++++++++++++++++ - -If the Wi-Fi NVS flash is enabled, all Wi-Fi configurations set via the Wi-Fi APIs will be stored into flash, and the Wi-Fi driver will start up with these configurations the next time it powers on/reboots. However, the application can choose to disable the Wi-Fi NVS flash if it does not need to store the configurations into persistent memory, or has its own persistent storage, or simply due to debugging reasons, etc. - -Wi-Fi Aggregate MAC Protocol Data Unit (AMPDU) -++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -{IDF_TARGET_NAME} supports both receiving and transmitting AMPDU, and the AMPDU can greatly improve the Wi-Fi throughput. - -Generally, the AMPDU should be enabled. Disabling AMPDU is usually for debugging purposes. - -Troubleshooting ---------------- - -Please refer to a separate document with :doc:`wireshark-user-guide`. - -.. toctree:: - :hidden: - - wireshark-user-guide diff --git a/docs/page_redirects.txt b/docs/page_redirects.txt index 374b64ef1c..d93d439f99 100644 --- a/docs/page_redirects.txt +++ b/docs/page_redirects.txt @@ -75,6 +75,7 @@ api-guides/ulp_macros api-reference/system/ulp_macros api-guides/ulp-risc-v api-reference/system/ulp-risc-v api-guides/console api-reference/system/console api-guides/event-handling api-reference/system/esp_event +api-guides/wifi api-guides/wifi-driver/index api-reference/network/tcpip_adapter migration-guides/tcpip-adapter api-reference/system/system api-reference/system/misc_system_api diff --git a/docs/zh_CN/api-guides/index.rst b/docs/zh_CN/api-guides/index.rst index 3a1f1d22ae..69ec6e4134 100644 --- a/docs/zh_CN/api-guides/index.rst +++ b/docs/zh_CN/api-guides/index.rst @@ -48,7 +48,7 @@ API 指南 host-apps :SOC_USB_OTG_SUPPORTED and not esp32p4 and not esp32h4: usb-otg-console :SOC_USB_SERIAL_JTAG_SUPPORTED: usb-serial-jtag-console - :SOC_WIFI_SUPPORTED: wifi + :SOC_WIFI_SUPPORTED: wifi-driver/index :SOC_WIFI_SUPPORTED: wifi-security wifi-expansion :SOC_WIFI_SUPPORTED or SOC_BT_SUPPORTED or SOC_IEEE802154_SUPPORTED: phy diff --git a/docs/zh_CN/api-guides/performance/speed.rst b/docs/zh_CN/api-guides/performance/speed.rst index 0f9f49d126..a49bd3ecb8 100644 --- a/docs/zh_CN/api-guides/performance/speed.rst +++ b/docs/zh_CN/api-guides/performance/speed.rst @@ -204,7 +204,7 @@ ESP-IDF 启动的系统任务预设了固定优先级。启动时,一些任务 - FreeRTOS 初始化调度器时会创建定时器任务,用于处理 FreeRTOS 定时器的回调函数,优先级最低(1, :ref:`可配置 ` )。 - 系统任务 :doc:`/api-reference/system/esp_event` 用于管理默认的系统事件循环并执行回调函数,优先级较高 (20, ``ESP_TASK_EVENT_PRIO``)。仅在应用程序调用 :cpp:func:`esp_event_loop_create_default` 时使用此配置。可以调用 :cpp:func:`esp_event_loop_create` 添加自定义任务配置。 - :doc:`/api-guides/lwip` TCP/IP 任务优先级较高 (18, ``ESP_TASK_TCPIP_PRIO``)。 - :SOC_WIFI_SUPPORTED: - :doc:`/api-guides/wifi` 任务优先级较高 (23). + :SOC_WIFI_SUPPORTED: - :doc:`/api-guides/wifi-driver/index` 任务优先级较高 (23). :SOC_WIFI_SUPPORTED: - 使用 Wi-Fi Protected Setup (WPS)、WPA2 EAP-TLS、Device Provisioning Protocol (DPP) 或 BSS Transition Management (BTM) 等功能时,Wi-Fi wpa_supplicant 组件可能会创建优先级较低的专用任务 (2)。 :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/controller_vhci` 任务优先级较高 (23, ``ESP_TASK_BT_CONTROLLER_PRIO``)。蓝牙控制器需要以低延迟响应请求,因此其任务应始终为系统最高优先级的任务之一。 :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/nimble/index` 任务优先级较高 (21). @@ -220,7 +220,7 @@ ESP-IDF 启动的系统任务预设了固定优先级。启动时,一些任务 - FreeRTOS 初始化调度器时会创建定时器任务,用于处理 FreeRTOS 定时器的回调函数,优先级最低(1, :ref:`可配置 ` )且固定在核 0 上执行。 - 系统任务 :doc:`/api-reference/system/esp_event` 用于管理默认的系统事件循环并执行回调函数,优先级较高 (20, ``ESP_TASK_EVENT_PRIO``) 且固定在核 0 上执行。此配置仅在应用程序调用 :cpp:func:`esp_event_loop_create_default` 时使用。可以调用 :cpp:func:`esp_event_loop_create` 添加自定义任务配置。 - :doc:`/api-guides/lwip` TCP/IP 任务优先级较高 (18, ``ESP_TASK_TCPIP_PRIO``) 且并未固定在特定内核上执行( :ref:`可配置 ` )。 - :SOC_WIFI_SUPPORTED: - :doc:`/api-guides/wifi` 任务优先级较高 (23) 且默认固定在核 0 上执行( :ref:`可配置 ` )。 + :SOC_WIFI_SUPPORTED: - :doc:`/api-guides/wifi-driver/index` 任务优先级较高 (23) 且默认固定在核 0 上执行( :ref:`可配置 ` )。 :SOC_WIFI_SUPPORTED: - 使用 Wi-Fi Protected Setup (WPS)、WPA2 EAP-TLS、Device Provisioning Protocol (DPP) 或 BSS Transition Management (BTM) 等功能时,Wi-Fi wpa_supplicant 组件可能会创建优先级较低的专用任务 (2),这些任务并未固定在特定内核上执行。 :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/controller_vhci` 任务优先级较高 (23, ``ESP_TASK_BT_CONTROLLER_PRIO``) 且默认固定在核 0 上执行( :ref:`可配置 <{IDF_TARGET_CONTROLLER_CORE_CONFIG}>` )。蓝牙控制器需要以低延迟响应请求,因此其任务应始终为最高优先级的任务之一并分配给单个 CPU 执行。 :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/nimble/index` 任务优先级较高 (21) 且默认固定在核 0 上执行( :ref:`可配置 ` ). diff --git a/docs/zh_CN/api-guides/wifi-driver/index.rst b/docs/zh_CN/api-guides/wifi-driver/index.rst new file mode 100644 index 0000000000..669d2f8075 --- /dev/null +++ b/docs/zh_CN/api-guides/wifi-driver/index.rst @@ -0,0 +1,16 @@ +############### +Wi-Fi 驱动程序 +############### + +:link_to_translation:`en:[English]` + +.. toctree:: + :maxdepth: 2 + + overview + station-scenarios + wifi-modes + wifi-mac-protocols + security-and-roaming + wifi-performance-and-power-save + wifi-vendor-features diff --git a/docs/zh_CN/api-guides/wifi-driver/overview.rst b/docs/zh_CN/api-guides/wifi-driver/overview.rst new file mode 100644 index 0000000000..c81a776cfa --- /dev/null +++ b/docs/zh_CN/api-guides/wifi-driver/overview.rst @@ -0,0 +1,1325 @@ +概览 +===== + +:link_to_translation:`en:[English]` + +{IDF_TARGET_NAME} Wi-Fi 功能列表 +------------------------------------ + +{IDF_TARGET_NAME} 支持以下 Wi-Fi 功能: + +.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 + + - 支持 4 个虚拟 Wi-Fi 接口,即 STA、AP、Sniffer 和保留接口 + - 支持仅 station 模式、仅 AP 模式、station/AP 共存模式 + - 支持使用 IEEE 802.11b、IEEE 802.11g、IEEE 802.11n 和提供配置协议模式的 API + - 支持 WPA/WPA2/WPA3/WPA2-企业版/WPA3-企业版/WAPI/WPS 和 DPP + - 支持 AMSDU、AMPDU、HT40、QoS 以及其它关键功能 + - 支持 Modem-sleep + - 支持乐鑫专属 ESP-NOW 协议和长距离模式,可实现最远 **1 km** 的数据传输 + - 空中数据传输最高可达 20 MBit/s TCP 吞吐量和 30 MBit/s UDP 吞吐量 + - 支持 Sniffer + - 支持快速扫描和全信道扫描 + - 支持多天线 + - 支持获取信道状态信息 + + +.. only:: esp32c2 + + - 支持 3 个虚拟接口,即 STA、AP 和 Sniffer + - 支持仅 station 模式、仅 AP 模式、station/AP 共存模式 + - 支持使用 IEEE 802.11b、IEEE 802.11g、IEEE 802.11n 和 API 配置协议模式 + - 支持 WPA/WPA2/WPA3/WPA2-企业版/WPA3-企业版/WPS 和 DPP + - 支持 AMPDU、QoS 以及其它主要功能 + - 支持 Modem-sleep + - 空中数据传输最高可达 20 MBit/s TCP 吞吐量和 30 MBit/s UDP 吞吐量 + - 支持 Sniffer + - 支持快速扫描和全信道扫描 + - 支持多个天线 + + +.. only:: esp32c6 + + - 支持 4 个虚拟接口,即 STA、AP、Sniffer 和 reserved + - 支持仅 station 模式、仅 AP 模式、station/AP 共存模式 + - 支持使用 IEEE 802.11b、IEEE 802.11g、IEEE 802.11n、IEEE 802.11ax 和 API 配置协议模式 + - 支持 WPA/WPA2/WPA3/WPA2-企业版/WPA3-企业版/WAPI/WPS 和 DPP + - 支持 AMSDU、AMPDU、HT40、QoS 以及其它主要功能 + - 支持 Modem-sleep + - 支持乐鑫专属协议,可实现 **1 km** 数据通信量 + - 空中数据传输最高可达 20 MBit/s TCP 吞吐量和 30 MBit/s UDP 吞吐量 + - 支持 Sniffer + - 支持快速扫描和全信道扫描 + - 支持多个天线 + - 支持获取信道状态信息 + - 支持 Individual TWT 和 Broadcast TWT + - 支持下行 MU-MIMO + - 支持 OFDMA + - 支持 BSS Color + + +.. only:: esp32c5 + + - 支持 4 个虚拟接口,即 STA、AP、Sniffer 和 reserved + - 支持仅 station 模式、仅 AP 模式、station/AP 共存模式 + - 支持使用 IEEE 802.11b、IEEE 802.11g、IEEE 802.11n、IEEE 802.11a、IEEE 802.11ac、IEEE 802.11ax 和 API 配置协议模式 + - 支持 WPA/WPA2/WPA3/WPA2-企业版/WPA3-企业版/WAPI/WPS 和 DPP + - 支持 AMSDU、AMPDU、HT40、QoS 以及其它主要功能 + - 支持 Modem-sleep + - 2.4 GHz 支持乐鑫专属协议,可实现 **1 km** 数据通信量 + - 空中数据传输最高可达 20 MBit/s TCP 吞吐量和 30 MBit/s UDP 吞吐量 + - 支持 Sniffer + - 支持快速扫描和全信道扫描 + - 支持多个天线 + - 支持获取信道状态信息 + - 支持 Individual TWT 和 Broadcast TWT + - 支持下行 MU-MIMO + - 支持 OFDMA + - 支持 BSS Color +.. only:: SOC_WIFI_NAN_SUPPORT + + - Wi-Fi Aware (NAN) + + +如何编写 Wi-Fi 应用程序 +---------------------------------- + +准备工作 ++++++++++++ + +一般来说,要编写自己的 Wi-Fi 应用程序,最高效的方式是先选择一个相似的应用程序示例,然后将其中可用的部分移植到自己的项目中。如果你希望编写一个强健的 Wi-Fi 应用程序,强烈建议在开始之前先阅读本文。**非强制要求,请依个人情况而定。** + +本文将补充说明 Wi-Fi API 和 Wi-Fi 示例的相关信息,重点描述使用 Wi-Fi API 的原则、当前 Wi-Fi API 实现的限制以及使用 Wi-Fi 时的常见错误。同时,本文还介绍了 Wi-Fi 驱动程序的一些设计细节。建议选择一个示例 :example:`example ` 进行参考。 + +- :example:`wifi/getting_started/station` 演示如何使用 station 功能连接到 AP。 + +- :example:`wifi/getting_started/softAP` 演示如何使用 SoftAP 功能将 {IDF_TARGET_NAME} 配置为 AP。 + +- :example:`wifi/scan` 演示如何扫描可用的 AP,配置扫描设置,并显示扫描结果。 + +- :example:`wifi/fast_scan` 演示如何执行快速和全通道扫描,查找附近的 AP,设置信号强度的阈值和认证模式,并根据信号强度和认证模式连接到最合适的 AP。 + +- :example:`wifi/wps` 演示如何使用 WPS 入网功能,简化连接 Wi-Fi 路由器的过程,支持 PIN 或 PBC 模式。 + +- :example:`wifi/wps_softap_registrar` 演示如何在 SoftAP 模式下使用 WPS 注册器功能,从而简化从 station 连接到 Wi-Fi SoftAP 的过程。 + +- :example:`wifi/smart_config` 演示如何使用 smartconfig 功能通过 ESPTOUCH app 连接到目标 AP。 + +- :example:`wifi/power_save` 演示如何使用 station 模式的省电模式。 + +- :example:`wifi/softap_sta` 演示如何配置 {IDF_TARGET_NAME} 同时用作 AP 和 station,从而可将其用作 Wi-Fi NAT 路由器。 + +- :example:`wifi/iperf` 演示如何实现 iPerf 性能测量工具所使用的协议,允许在两个芯片之间或在单个芯片和运行 iPerf 工具的计算机之间进行性能测量,并提供测试 station/SoftAP TCP/UDP RX/TX 吞吐量的具体说明。 + +- :example:`wifi/roaming/roaming_app` 演示如何使用 Wi-Fi Roaming App 功能,在兼容的 AP 之间高效漫游。 + +- :example:`wifi/roaming/roaming_11kvr` 演示如何使用 11k 和 11v API 实现漫游功能。 + +.. only:: SOC_WIFI_HE_SUPPORT + + - :example:`wifi/itwt` 演示如何使用 iTWT 功能,该功能仅在 station 模式下工作,并在不同的省电模式下提供设置、拆卸和挂起的命令,还展示了启用和禁用 iTWT 时的电流消耗差异。 + +设置 Wi-Fi 编译时选项 ++++++++++++++++++++++++ + +请参阅 :ref:`wifi-menuconfig`。 + +Wi-Fi 初始化 ++++++++++++++++ + +请参阅 :ref:`{IDF_TARGET_NAME} Wi-Fi station 通用场景 `、:ref:`{IDF_TARGET_NAME} Wi-Fi AP 通用场景 `。 + +启动/连接 Wi-Fi +++++++++++++++++++ + +请参阅 :ref:`{IDF_TARGET_NAME} Wi-Fi station 通用场景 `、:ref:`{IDF_TARGET_NAME} Wi-Fi AP 通用场景 `。 + +事件处理 +++++++++++++++ + +通常,在理想环境下编写代码难度并不大,如 :ref:`WIFI_EVENT_STA_START `、:ref:`WIFI_EVENT_STA_CONNECTED ` 中所述。难度在于如何在现实的困难环境下编写代码,如 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 中所述。能否在后者情况下完美地解决各类事件冲突,是编写一个强健的 Wi-Fi 应用程序的根本。请参阅 :ref:`{IDF_TARGET_NAME} Wi-Fi 事件描述 `, :ref:`{IDF_TARGET_NAME} Wi-Fi station 通用场景 `, :ref:`{IDF_TARGET_NAME} Wi-Fi AP 通用场景 `。另可参阅 ESP-IDF 中的 :doc:`事件处理概述 <../../api-reference/system/esp_event>`。 + +编写错误恢复程序 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + +除了能在比较差的环境下工作,错误恢复能力也对一个强健的 Wi-Fi 应用程序至关重要。请参阅 :ref:`{IDF_TARGET_NAME} Wi-Fi API 错误代码 `。 + + +.. _wifi-api-error-code: + +{IDF_TARGET_NAME} Wi-Fi API 错误代码 +-------------------------------------- + +所有 {IDF_TARGET_NAME} Wi-Fi API 都有定义好的返回值,即错误代码。这些错误代码可分类为: + + - 无错误,例如:返回值 :c:macro:`ESP_OK` 代表 API 成功返回 + - 可恢复错误,例如::c:macro:`ESP_ERR_NO_MEM` + - 不可恢复的非关键性错误 + - 不可恢复的关键性错误 + +一个错误是否为关键性取决于其 API 和应用场景,并且由 API 用户定义。 + +**要使用 Wi-Fi API 编写一个强健的应用程序,根本原则便是要时刻检查错误代码并编写相应的错误处理代码。** 一般来说,错误处理代码可用于解决: + + - 可恢复错误,你可以编写相应的错误恢复代码。例如,当 :cpp:func:`esp_wifi_start()` 返回 :c:macro:`ESP_ERR_NO_MEM` 时,调用可恢复错误处理代码 vTaskDelay 以获取微秒级的延迟后重新尝试。 + - 不可恢复非关键性错误,打印错误代码可以帮助你更好地处理该类错误。 + - 不可恢复关键性错误,可使用 "assert" 语句处理该类错误。例如,如果 :cpp:func:`esp_wifi_set_mode()` 返回 ``ESP_ERR_WIFI_NOT_INIT``,这意味着 Wi-Fi 驱动程序未通过 :cpp:func:`esp_wifi_init()` 成功初始化。这类错误可以在应用开发阶段被快速检测到。 + +在 :component_file:`esp_common/include/esp_err.h` 中, ``ESP_ERROR_CHECK`` 负责检查返回值。这是一个较为常见的错误处理代码,可在应用程序开发阶段作为默认的错误处理代码。但是,我们强烈建议 API 的使用者编写自己的错误处理代码。 + + +初始化 {IDF_TARGET_NAME} Wi-Fi API 参数 +---------------------------------------------------- + +在为 API 初始化结构体参数时,应遵循以下两种方式之一: + +- 显式设置参数的所有字段 +- 先使用 get API 获取当前配置,然后设置特定于应用程序的字段 + +初始化或获取整个结构体这一步至关重要,因为大多数情况下,值为 0 意味着程序使用了默认值。未来可能会向该结构体添加更多字段,而将这些字段初始化为 0 可以确保在 ESP-IDF 更新到新版本后,应用程序仍能正常运行。 + + +.. _wifi-programming-model: + +{IDF_TARGET_NAME} Wi-Fi 编程模型 +----------------------------------------- + +{IDF_TARGET_NAME} Wi-Fi 编程模型如下图所示: + +.. blockdiag:: + :caption: Wi-Fi 编程模型 + :align: center + + blockdiag wifi-programming-model { + + # global attributes + node_height = 60; + node_width = 100; + span_width = 100; + span_height = 60; + default_shape = roundedbox; + default_group_color = none; + + # node labels + TCP_STACK [label="TCP\n stack", fontsize=12]; + EVNT_TASK [label="Event\n task", fontsize=12]; + APPL_TASK [label="Application\n task", width = 120, fontsize=12]; + WIFI_DRV [label="Wi-Fi\n Driver", width = 120, fontsize=12]; + KNOT [shape=none]; + + # node connections + labels + TCP_STACK -> EVNT_TASK [label=event]; + EVNT_TASK -> APPL_TASK [label="callback\n or event"]; + + # arrange nodes vertically + group { + label = "default handler"; + orientation = portrait; + EVNT_TASK <- WIFI_DRV [label=event]; + } + + # intermediate node + group { + label = "user handler"; + orientation = portrait; + APPL_TASK -- KNOT; + } + WIFI_DRV <- KNOT [label="API\n call"]; + } + + +Wi-Fi 驱动程序可以看作是一个无法感知上层代码(如 TCP/IP 堆栈、应用程序任务、事件任务等)的黑匣子。通常,应用程序任务(代码)负责调用 :doc:`Wi-Fi 驱动程序 API <../../api-reference/network/esp_wifi>` 来初始化 Wi-Fi,并在必要时处理 Wi-Fi 事件。然后,Wi-Fi 驱动程序接收 API 调用,处理后将事件发送给应用程序。 + +Wi-Fi 事件处理是在 :doc:`esp_event 库 <../../api-reference/system/esp_event>` 的基础上进行的。Wi-Fi 驱动程序将事件发送至 :ref:`默认事件循环 `,应用程序便可以使用 :cpp:func:`esp_event_handler_register()` 中的回调函数处理这些事件。除此之外,:doc:`esp_netif 组件 <../../api-reference/network/esp_netif>` 也负责处理 Wi-Fi 事件,并产生一系列默认行为。例如,当 Wi-Fi station 连接至一个 AP 时,esp_netif 将自动开启 DHCP 客户端服务(系统默认)。 + + +.. _wifi-event-description: + +{IDF_TARGET_NAME} Wi-Fi 事件描述 +----------------------------------------- + +WIFI_EVENT_WIFI_READY +++++++++++++++++++++++++++++++++++++ + +Wi-Fi 驱动程序永远不会生成此事件,因此,应用程序的事件回调函数可忽略此事件。在未来的版本中,此事件可能会被移除。 + +.. _wifi-event-scan-done: + +WIFI_EVENT_SCAN_DONE +++++++++++++++++++++++++++++++++++++ + +扫描完成事件,由 :cpp:func:`esp_wifi_scan_start()` 函数触发,将在以下情况下产生: + + - 扫描已完成,例如:Wi-Fi 已成功找到目标 AP 或已扫描所有信道。 + - 当前扫描因函数 :cpp:func:`esp_wifi_scan_stop()` 而终止。 + - 在当前扫描完成之前调用了函数 :cpp:func:`esp_wifi_scan_start()`。此时,新的扫描将覆盖当前扫描过程,并生成一个扫描完成事件。 + +以下情况下将不会产生扫描完成事件: + + - 当前扫描为阻塞扫描。 + - 当前扫描是由函数 :cpp:func:`esp_wifi_connect()` 触发的。 + +接收到此事件后,事件任务暂不做任何响应。首先,应用程序的事件回调函数需调用 :cpp:func:`esp_wifi_scan_get_ap_num()` 和 :cpp:func:`esp_wifi_scan_get_ap_records()` 获取已扫描的 AP 列表,然后触发 Wi-Fi 驱动程序释放在扫描过程中占用的内存空间(**切记该步骤**)。 +更多详细信息,请参阅 :ref:`{IDF_TARGET_NAME} Wi-Fi 扫描 `。 + +.. _wifi-event-sta-start: + +WIFI_EVENT_STA_START +++++++++++++++++++++++++++++++++++++ + +如果调用函数 :cpp:func:`esp_wifi_start()` 后接收到返回值 :c:macro:`ESP_OK`,且当前 Wi-Fi 处于 station 或 station/AP 共存模式,则将产生此事件。接收到此事件后,事件任务将初始化 LwIP 网络接口 (netif)。通常,应用程序的事件回调函数需调用 :cpp:func:`esp_wifi_connect()` 来连接已配置的 AP。 + +WIFI_EVENT_STA_STOP +++++++++++++++++++++++++++++++++++++ + +如果调用函数 :cpp:func:`esp_wifi_stop()` 后接收到返回值 :c:macro:`ESP_OK`,且当前 Wi-Fi 处于 station 或 station/AP 共存模式,则将产生此事件。接收到此事件后,事件任务将进行释放 station IP 地址、终止 DHCP 客户端服务、移除 TCP/UDP 相关连接并清除 LwIP station netif 等动作。此时,应用程序的事件回调函数通常不需做任何响应。 + +.. _wifi-event-sta-connected: + +WIFI_EVENT_STA_CONNECTED +++++++++++++++++++++++++++++++++++++ + +如果调用函数 :cpp:func:`esp_wifi_connect()` 后接收到返回值 :c:macro:`ESP_OK`,且 station 已成功连接目标 AP,则将产生此连接事件。接收到此事件后,事件任务将启动 DHCP 客户端服务并开始获取 IP 地址。此时,Wi-Fi 驱动程序已准备就绪,可发送和接收数据。如果你的应用程序不依赖于 LwIP(即 IP 地址),则此刻便可以开始应用程序开发工作。但是,如果你的应用程序需基于 LwIP 进行,则还需等待 *got ip* 事件发生后才可开始。 + +.. _wifi-event-sta-disconnected: + +WIFI_EVENT_STA_DISCONNECTED +++++++++++++++++++++++++++++++++++++ + +此事件将在以下情况下产生: + + - 调用了函数 :cpp:func:`esp_wifi_disconnect()` 或 :cpp:func:`esp_wifi_stop()`,且 Wi-Fi station 已成功连接至 AP。 + - 调用了函数 :cpp:func:`esp_wifi_connect()`,但 Wi-Fi 驱动程序因为某些原因未能成功连接至 AP,例如:未扫描到目标 AP、验证超时等。或存在多个 SSID 相同的 AP,station 无法连接所有已找到的 AP,也将产生该事件。 + - Wi-Fi 连接因为某些原因而中断,例如:station 连续多次丢失 N beacon、AP 踢掉 station、AP 认证模式改变等。 + +接收到此事件后,事件任务的默认动作为: + + - 关闭 station 的 LwIP netif。 + - 通知 LwIP 任务清除导致所有套接字状态错误的 UDP/TCP 连接。针对基于套接字编写的应用程序,其回调函数可以在接收到此事件时(如有必要)关闭并重新创建所有套接字。 + +应用程序处理此事件最常用的方法为:调用函数 :cpp:func:`esp_wifi_connect()` 重新连接 Wi-Fi。但是,如果此事件是由函数 :cpp:func:`esp_wifi_disconnect()` 引发的,则应用程序不应调用 :cpp:func:`esp_wifi_connect()` 来重新连接。应用程序须明确区分此事件的引发原因,因为某些情况下应使用其它更好的方式进行重新连接。请参阅 :ref:`Wi-Fi 重新连接 ` 和 :ref:`连接 Wi-Fi 时扫描 `。 + +需要注意的另一点是:接收到此事件后,LwIP 的默认动作是终止所有 TCP 套接字连接。大多数情况下,该动作不会造成影响。但对某些特殊应用程序可能除外。例如: + +- 应用程序创建一个了 TCP 连接,以维护每 60 秒发送一次的应用程序级、保持活动状态的数据。 +- 由于某些原因,Wi-Fi 连接被切断并引发了 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件。根据当前实现,此时所有 TCP 连接都将被移除,且保持活动的套接字将处于错误的状态中。但是,由于应用程序设计者认为网络层 **不应** 考虑这个 Wi-Fi 层的错误,因此应用程序不会关闭套接字。 +- 5 秒后,因为在应用程序的事件回调函数中调用了 :cpp:func:`esp_wifi_connect()`,Wi-Fi 连接恢复。**同时,station 连接至同一个 AP 并获得与之前相同的 IPV4 地址。** +- 60 秒后,当应用程序发送具有保持活动状态的套接字的数据时,套接字将返回错误,应用程序将关闭套接字并在必要时重新创建。 + +在上述场景中,理想状态下应用程序套接字和网络层将不会受到影响,因为在此过程中 Wi-Fi 连接只是短暂地断开然后快速恢复。 + +.. _ip-event-sta-got-ip: + +IP_EVENT_STA_GOT_IP +++++++++++++++++++++++++++++++++++++ + +当 DHCP 客户端成功从 DHCP 服务器获取 IPV4 地址或 IPV4 地址发生改变时,将引发此事件。此事件意味着应用程序一切就绪,可以开始任务(如:创建套接字)。 + +IPV4 地址可能由于以下原因而发生改变: + + - DHCP 客户端无法重新获取/绑定 IPV4 地址,且 station 的 IPV4 重置为 0。 + - DHCP 客户端重新绑定了其它地址。 + - 静态配置的 IPV4 地址已发生改变。 + +函数 ``ip_event_got_ip_t`` 中的字段 ``ip_change`` 说明了 IPV4 地址是否发生改变。 + +套接字的状态是基于 IPV4 地址的,这意味着,如果 IPV4 地址发生改变,则所有与此 IPV4 相关的套接字都将变为异常。接收到此事件后,应用程序需关闭所有套接字,并在 IPV4 变为有效地址时重新创建应用程序。 + +IP_EVENT_GOT_IP6 +++++++++++++++++++++++++++++++++++++ + +当 IPV6 SLAAC 支持自动为 {IDF_TARGET_NAME} 配置一个地址,或 {IDF_TARGET_NAME} 地址发生改变时,将引发此事件。此事件意味着应用程序一切就绪,可以开始任务(如:创建套接字)。 + +IP_EVENT_STA_LOST_IP +++++++++++++++++++++++++++++++++++++ + +当 IPV4 地址失效时,将引发此事件。 + +此事件不会在 Wi-Fi 断连后立刻出现。Wi-Fi 连接断开后,首先将启动一个 IPV4 地址丢失计时器(可通过 :ref:`CONFIG_ESP_NETIF_LOST_IP_TIMER_ENABLE` 与 :ref:`CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL` 配置)。如果 station 在该计时器超时之前成功获取了 IPV4 地址,则不会发生此事件。否则,此事件将在计时器超时时发生。 + +一般来说,应用程序可忽略此事件。这只是一个调试事件,主要使应用程序获知 IPV4 地址已丢失。 + +WIFI_EVENT_AP_START +++++++++++++++++++++++++++++++++++++ + +与 `WIFI_EVENT_STA_START`_ 事件相似。 + +WIFI_EVENT_AP_STOP +++++++++++++++++++++++++++++++++++++ + +与 `WIFI_EVENT_STA_STOP`_ 事件相似。 + +WIFI_EVENT_AP_STACONNECTED +++++++++++++++++++++++++++++++++++++ + +每当有一个 station 成功连接 {IDF_TARGET_NAME} AP 时,将引发此事件。接收到此事件后,事件任务将不做任何响应,应用程序的回调函数也可忽略这一事件。但是,你可以在此时进行一些操作,例如:获取已连接 station 的信息等。 + +WIFI_EVENT_AP_STADISCONNECTED +++++++++++++++++++++++++++++++++++++ + +此事件将在以下情况下发生: + + - 应用程序通过调用函数 :cpp:func:`esp_wifi_disconnect()` 或 :cpp:func:`esp_wifi_deauth_sta()` 手动断开 station 连接。 + - Wi-Fi 驱动程序出于某些原因断开 station 连接,例如:AP 在过去 5 分钟(可通过函数 :cpp:func:`esp_wifi_set_inactive_time()` 修改该时间)内未接收到任何数据包等。 + - station 断开与 AP 之间的连接。 + +发生此事件时,事件任务将不做任何响应,但应用程序的事件回调函数需执行一些操作,例如:关闭与此 station 相关的套接字等。 + +WIFI_EVENT_AP_PROBEREQRECVED +++++++++++++++++++++++++++++++++++++ + +默认情况下,此事件处于禁用状态,应用程序可以通过调用 API :cpp:func:`esp_wifi_set_event_mask()` 启用。 +启用后,每当 AP 接收到 probe request 时都将引发此事件。 + +.. _wifi-event-sta-beacon-timeout: + +WIFI_EVENT_STA_BEACON_TIMEOUT +++++++++++++++++++++++++++++++++++++ + +如果 station 在 inactive 时间内未收到所连接 AP 的 beacon,将发生 beacon 超时,将引发此事件。inactive 时间通过调用函数 :cpp:func:`esp_wifi_set_inactive_time()` 设置。 + +.. _wifi-event-connectionless-module-wake-interval-start: + +WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +非连接模块在 `Interval` 开始时触发此事件。 请参考 :ref:`非连接模块功耗管理 ` 。 + + + +{IDF_TARGET_MAX_CONN_STA_NUM:default="15", esp32c2="4", esp32c3="10", esp32c6="10"} + +{IDF_TARGET_SUB_MAX_NUM_FROM_KEYS:default="2", esp32c3="7", esp32c6="7"} + +.. _wifi-configuration: + +{IDF_TARGET_NAME} Wi-Fi 配置 +------------------------------------- + +使能 Wi-Fi NVS 时,所有配置都将存储到 flash 中;反之,请参阅 :ref:`Wi-Fi NVS Flash `。 + +Wi-Fi 模式 ++++++++++++++++++++++++++ +调用函数 :cpp:func:`esp_wifi_set_mode()` 设置 Wi-Fi 模式。 + +.. list-table:: + :header-rows: 1 + :widths: 15 50 + + * - 模式 + - 描述 + * - ``WIFI_MODE_NULL`` + - NULL 模式:此模式下,内部数据结构不分配给 station 和 AP,同时,station 和 AP 接口不会为发送/接收 Wi-Fi 数据进行初始化。通常,此模式用于 Sniffer,或者你不想通过调用函数 :cpp:func:`esp_wifi_deinit()` 卸载整个 Wi-Fi 驱动程序来同时停止 station 和 AP。 + * - ``WIFI_MODE_STA`` + - station 模式:此模式下,:cpp:func:`esp_wifi_start()` 将初始化内部 station 数据,同时 station 接口准备发送/接收 Wi-Fi 数据。调用函数 :cpp:func:`esp_wifi_connect()` 后,station 将连接到目标 AP。 + * - ``WIFI_MODE_AP`` + - AP 模式:在此模式下,:cpp:func:`esp_wifi_start()` 将初始化内部 AP 数据,同时 AP 接口准备发送/接收 Wi-Fi 数据。随后,Wi-Fi 驱动程序开始广播 beacon,AP 即可与其它 station 连接。 + * - ``WIFI_MODE_APSTA`` + - station/AP 共存模式:在此模式下,函数 :cpp:func:`esp_wifi_start()` 将同时初始化 station 和 AP。该步骤在 station 模式和 AP 模式下完成。请注意 ESP station 所连外部 AP 的信道优先于 ESP AP 信道。 + + +.. only:: esp32c5 + + Wi-Fi 频段配置 + +++++++++++++++++++++++++ + + 可通过函数 :cpp:func:`esp_wifi_set_band_mode()` 设置 {IDF_TARGET_NAME} 所使用的 Wi-Fi 频段模式。 + + .. list-table:: + :header-rows: 1 + :widths: 15 50 + + * - 模式 + - 描述 + * - ``WIFI_BAND_MODE_2G_ONLY`` + - **2.4 GHz 频段模式**:设备仅可在 2.4 GHz 频段信道上工作。 + * - ``WIFI_BAND_MODE_5G_ONLY`` + - **5 GHz 频段模式**:设备仅可在 5 GHz 频段信道上工作。 + * - ``WIFI_BAND_MODE_AUTO`` + - **2.4 GHz + 5 GHz 自动模式**:设备可根据所连接的 AP 或 SoftAP 配置,自动选择 2.4 GHz 或 5 GHz 频段。 + + .. note:: + - ``WIFI_BAND_MODE_AUTO`` 并不表示同时支持双频段,而是允许自动选择频段。 + + 当工作在 ``WIFI_BAND_MODE_AUTO`` 模式下时,可以分别为 2.4 GHz 和 5 GHz 频段配置协议和带宽: + + - 使用函数 :cpp:func:`esp_wifi_set_protocols()` 设置每个频段支持的协议类型(例如 802.11b/g/n/ac/ax); + + - 使用函数 :cpp:func:`esp_wifi_set_bandwidths()` 设置每个频段的带宽(如 20MHz、40MHz等)。 + +.. only:: esp32c5 + + AP 选择 + +++++++++++++++++++++++++ + + 当设备扫描到多个 SSID 相同的 AP(接入点)时,{IDF_TARGET_NAME} 会根据信号强度(RSSI)以及频段等信息,选择最合适的 AP 进行连接。默认策略通常优先选择 RSSI 更高的 AP,但在 2.4 GHz 与 5 GHz 并存的环境下,这可能导致设备偏向连接 2.4 GHz 频段,忽略 5 GHz 频段的高性能优势。 + + 为此,ESP-IDF 提供了 :cpp:type:`wifi_scan_threshold_t` 结构体中的 :cpp:member:`rssi_5g_adjustment` 字段,用于优化 5G AP 的选择优先级。 + + .. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - 字段 + - 描述 + * - ``rssi_5g_adjustment`` + - 用于在 SSID 相同的 2.4 GHz 和 5 GHz AP 之间进行优先级调整。默认值为 ``10``,表示当 5 GHz AP 的 RSSI 至少比 2.4 GHz AP 低 ``10 dB`` 以内时,优先连接 5 GHz AP。通过合理设置该参数,可以在信号强度接近时优先连接具有更好带宽与干扰抵抗能力的 5 GHz 网络。 + + 示例: + + 若设备扫描到以下两个 AP,SSID 均为 "MyWiFi": + + - 2.4 GHz AP:RSSI = -60 dBm + - 5 GHz AP:RSSI = -68 dBm + + 则由于 ``rssi_5g_adjustment = 10``(默认值), 且满足 ``-68 > -60 - 10`` ,设备会优先连接 5 GHz AP。 + + .. note:: + + 该参数仅在扫描结果中存在相同 SSID 且分别处于 2.4 GHz 与 5 GHz 频段的 AP 时生效。其目的是避免设备总是连接信号强度略高但性能较差的 2.4 GHz 网络。 + + +.. _station-basic-configuration: + +Station 基本配置 ++++++++++++++++++++++++++++++++++++++ + +API :cpp:func:`esp_wifi_set_config()` 可用于配置 station。配置的参数信息会保存到 NVS 中。下表详细介绍了各个字段。 + +.. list-table:: + :header-rows: 1 + :widths: 15 45 + + * - 字段 + - 描述 + * - ssid + - station 想要连接的目标 AP 的 SSID。 + * - password + - 目标 AP 的密码。 + * - scan_method + - ``WIFI_FAST_SCAN`` 模式下,扫描到一个匹配的 AP 时即结束。 ``WIFI_ALL_CHANNEL_SCAN`` 模式下,在所有信道扫描所有匹配的 AP。默认扫描模式是 ``WIFI_FAST_SCAN``。 + * - bssid_set + - 如果 bssid_set 为 0,station 连接 SSID 与 “ssid” 字段相同的 AP,同时忽略字段 “bssid”。其他情况下,station 连接 SSID 与 “ssid” 字段相同、BSSID 与 “bssid” 字段也相同的 AP。 + * - bssid + - 只有当 bssid_set 为 1 时有效。见字段 “bssid_set”。 + * - channel + - 该字段为 0 时,station 扫描信道 1 ~ N 寻找目标 AP;否则,station 首先扫描值与 “channel” 字段相同的信道,再扫描其他信道。比如,当该字段设置为 3 时,扫描顺序为 3,1,2,...,N 。如果你不知道目标 AP 在哪个信道,请将该字段设置为 0。 + * - sort_method + - 该字段仅用于 ``WIFI_ALL_CHANNEL_SCAN`` 模式。 + + 如果设置为 ``WIFI_CONNECT_AP_BY_SIGNAL``,所有匹配的 AP 将会按照信号强度排序,信号最好的 AP 会被首先连接。比如,如果 station 想要连接 ssid 为 “apxx” 的 AP,且扫描到两个这样的 AP。第一个 AP 的信号为 -90 dBm,第二个 AP 的信号为 -30 dBm,station 首先连接第二个 AP。除非失败,才会连接第一个。 + + 如果设置为 ``WIFI_CONNECT_AP_BY_SECURITY``,所有匹配的 AP 将会按照安全性排序。比如,如果 station 想要连接 ssid 为 “apxx” 的 AP,并且扫描到两个这样的 AP。第一个 AP 为开放式,第二个 AP 为 WPA2 加密,station 首先连接第二个 AP。除非失败,才会连接第一个。 + * - threshold + - 该字段用来筛选找到的 AP,如果 AP 的 RSSI 或安全模式小于配置的阈值,则不会被连接。 + + 如果 RSSI 设置为 0,则表示默认阈值、默认 RSSI 阈值为 -127 dBm。如果 authmode 阈值设置为 0,则表示默认阈值,默认 authmode 阈值为开放模式。 + + +.. attention:: + + WEP/WPA 安全模式在 IEEE802.11-2016 协议中已弃用,建议不要使用。可使用 authmode 阈值代替,通过将 threshold.authmode 设置为 ``WIFI_AUTH_WPA2_PSK`` 使用 WPA2 模式。 + +AP 基本配置 ++++++++++++++++++++++++++++++++++++++ + +API :cpp:func:`esp_wifi_set_config()` 可用于配置 AP。配置的参数信息会保存到 NVS 中。下表详细介绍了各个字段。 + +.. only:: esp32 or esp32s2 or esp32s3 or esp32c3 or esp32c5 or esp32c6 + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - 字段 + - 描述 + * - ssid + - 指 AP 的 SSID。如果 ssid[0] 和 ssid[1] 均为 0xFF,AP 默认 SSID 为 ``ESP_aabbcc``,”aabbcc” 是 AP MAC 的最后三个字节。 + * - password + - AP 的密码。如果身份验证模式为 ``WIFI_AUTH_OPEN``,此字段将被忽略。 + * - ssid_len + - SSID 的长度。如果 ssid_len 为 0,则检查 SSID 直至出现终止字符。如果 ssid_len 大于 32,请更改为 32,或者根据 ssid_len 设置 SSID 长度。 + * - channel + - AP 的信道。如果信道超出范围,Wi-Fi 驱动程序将返回 error。所以,请确保信道在要求的范围内。有关详细信息,请参阅 `Wi-Fi 国家/地区代码`_。 + * - authmode + - ESP AP 的身份验证模式。目前,ESP AP 不支持 AUTH_WEP。如果 authmode 是一个无效值,AP 默认该值为 ``WIFI_AUTH_OPEN``。 + * - ssid_hidden + - 如果 ssid_hidden 为 1,AP 不广播 SSID。若为其他值,则广播。 + * - max_connection + - 允许连接 station 的最大数目,默认值是 10。ESP Wi-Fi 支持 {IDF_TARGET_MAX_CONN_STA_NUM} (``ESP_WIFI_MAX_CONN_NUM``) 个 Wi-Fi 连接。请注意, ESP AP 和 ESP-NOW 共享同一块加密硬件 keys,因此 max_connection 参数将受到 :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM` 的影响。加密硬件 keys 的总数是 17,如果 :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM` 小于等于 {IDF_TARGET_SUB_MAX_NUM_FROM_KEYS},那么 max_connection 最大可以设置为 {IDF_TARGET_MAX_CONN_STA_NUM},否则 max_connection 最大可以设置为 (17 - :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`)。 + * - beacon_interval + - beacon 间隔。值为 100 ~ 60000 ms,默认值为 100 ms。如果该值不在上述范围,AP 默认取 100 ms。 + + +.. only:: esp32c2 + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - 字段 + - 描述 + * - ssid + - 指 AP 的 SSID。如果 ssid[0] 和 ssid[1] 均为 0xFF,AP 默认 SSID 为 ``ESP_aabbcc``,”aabbcc” 是 AP MAC 的最后三个字节。 + * - password + - AP 的密码。如果身份验证模式为 ``WIFI_AUTH_OPEN``,此字段将被忽略。 + * - ssid_len + - SSID 的长度。如果 ssid_len 为 0,则检查 SSID 直至出现终止字符。如果 ssid_len 大于 32,请更改为 32,或者根据 ssid_len 设置 SSID 长度。 + * - channel + - AP 的信道。如果信道超出范围,Wi-Fi 驱动程序将默认为信道 1。所以,请确保信道在要求的范围内。有关详细信息,请参阅 `Wi-Fi 国家/地区代码`_。 + * - authmode + - ESP AP 的身份验证模式。目前,ESP AP 不支持 AUTH_WEP。如果 authmode 是一个无效值,AP 默认该值为 ``WIFI_AUTH_OPEN``。 + * - ssid_hidden + - 如果 ssid_hidden 为 1,AP 不广播 SSID。若为其他值,则广播。 + * - max_connection + - 允许连接 station 的最大数目,默认值是 2。ESP Wi-Fi 支持 {IDF_TARGET_MAX_CONN_STA_NUM} (``ESP_WIFI_MAX_CONN_NUM``) 个 Wi-Fi 连接。请注意, ESP AP 和 ESP-NOW 共享同一块加密硬件 keys,因此 max_connection 参数将受到 :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM` 的影响。加密硬件 keys 的总数是 {IDF_TARGET_MAX_CONN_STA_NUM}, max_connection 最大可以设置为 ({IDF_TARGET_MAX_CONN_STA_NUM} - :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`)。 + * - beacon_interval + - beacon 间隔。值为 100 ~ 60000 ms,默认值为 100 ms。如果该值不在上述范围,AP 默认取 100 ms。 + + +Wi-Fi 协议模式 ++++++++++++++++++++++++++ + +目前,IDF 支持以下协议模式: + +.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - 协议模式 + - 描述 + * - 802.11b + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B)``,将 station/AP 设置为仅 802.11b 模式。 + * - 802.11bg + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)``,将 station/AP 设置为 802.11bg 模式。 + * - 802.11g + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` 和 ``esp_wifi_config_11b_rate(ifx, true)``,将 station/AP 设置为 802.11g 模式。 + * - 802.11bgn + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)``,将 station/AP 设置为 802.11bgn 模式。 + * - 802.11gn + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` 和 ``esp_wifi_config_11b_rate(ifx, true)``,将 station/AP 设置为 802.11gn 模式。 + * - 802.11 BGNLR + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_LR)``,将 station/AP 设置为 802.11bgn 和 LR 模式。 + * - 802.11 LR + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_LR)``,将 station/AP 设置为 LR 模式。 + + **此模式是乐鑫的专利模式,可以达到 1 公里视线范围。请确保 station 和 AP 同时连接至 ESP 设备。** + +.. only:: esp32c6 + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - 协议模式 + - 描述 + * - 802.11b + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B)``,将 station/AP 设置为仅 802.11b 模式。 + * - 802.11bg + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)``,将 station/AP 设置为 802.11bg 模式。 + * - 802.11g + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` 和 ``esp_wifi_config_11b_rate(ifx, true)``,将 station/AP 设置为 802.11g 模式。 + * - 802.11bgn + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)``,将 station/AP 设置为 802.11bgn 模式。 + * - 802.11gn + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` 和 ``esp_wifi_config_11b_rate(ifx, true)``,将 station/AP 设置为 802.11gn 模式。 + * - 802.11 BGNLR + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_LR)``,将 station/AP 设置为 802.11bgn 和 LR 模式。 + * - 802.11bgnax + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_11AX)``,将 station/AP 设置为 802.11bgnax 模式。 + * - 802.11 BGNAXLR + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_11AX|WIFI_PROTOCOL_LR)``,将 station/AP 设置为 802.11bgnax 和 LR 模式。 + * - 802.11 LR + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_LR)``,将 station/AP 设置为 LR 模式。 + + **此模式是乐鑫的专利模式,可以达到 1 公里视线范围。请确保 station 和 AP 同时连接至 ESP 设备。** + + +.. only:: esp32c5 + + - **2.4 GHz 频段**:支持 802.11b、802.11bg、802.11bgn、802.11bgnax 以及乐鑫专有的 LR 模式。 + - **5 GHz 频段**:支持 802.11a、802.11an、802.11anac 和 802.11anacax。 + + {IDF_TARGET_NAME} 支持为 2.4 GHz 和 5 GHz 频段分别配置 Wi-Fi 协议模式。推荐使用 :cpp:func:`esp_wifi_set_protocols()` 进行配置,也兼容旧接口 :cpp:func:`esp_wifi_set_protocol()`。 + + **推荐用法** + + 使用新 API :cpp:func:`esp_wifi_set_protocols()`,分别设置两个频段的协议: + + .. code-block:: c + + // 设置 2.4 GHz 使用 802.11bgnax,5 GHz 使用 802.11anacax 协议 + wifi_protocols_t protocols = { + .ghz_2g = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX, + .ghz_5g = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AC | WIFI_PROTOCOL_11AX, + }; + esp_wifi_set_protocols(WIFI_IF_STA, &protocols); + + **兼容用法** + + 使用旧 API :cpp:func:`esp_wifi_set_protocol()`,配置 2.4 GHz 或者 5 GHz 频段的协议: + + .. code-block:: c + + // 设置频段为 2.4 GHz 频段 + esp_wifi_set_band_mode(WIFI_BAND_MODE_2G_ONLY); + + // 设置 STA 的协议为 802.11bgnax + uint8_t protocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX; + esp_wifi_set_protocol(WIFI_IF_STA, protocol); + + .. note:: + + - 新接口 `esp_wifi_set_protocols()` 可同时配置两个频段,建议在{IDF_TARGET_NAME}上优先使用。 + - ``esp_wifi_set_protocol()`` 适用于仅使用单一频段的场景,如 ``WIFI_BAND_MODE_2G_ONLY`` 或 ``WIFI_BAND_MODE_5G_ONLY`` 模式。仅对当前连接的频段生效,例如,当接口处于 5 GHz 频段时,该函数将忽略对 2.4 GHz 频段的配置。 + - 若配置包含不受支持的协议组合,函数调用将返回错误。 + - 如需启用乐鑫专有 LR 模式,请确保 2.4 GHz 配置中包含 `WIFI_PROTOCOL_LR`。 + + +.. only:: esp32c2 + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - 协议模式 + - 描述 + * - 802.11b + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B)``,将 station/AP 设置为仅 802.11b 模式。 + * - 802.11bg + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)``,将 station/AP 设置为 802.11bg 模式。 + * - 802.11g + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` 和 ``esp_wifi_config_11b_rate(ifx, true)``,将 station/AP 设置为 802.11g 模式。 + * - 802.11bgn + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)``,将 station/AP 设置为 802.11bgn 模式。 + * - 802.11gn + - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` 和 ``esp_wifi_config_11b_rate(ifx, true)``,将 station/AP 设置为 802.11gn 模式。 + + +Wi-Fi 带宽模式 +++++++++++++++++++++++ + +.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 + + {IDF_TARGET_NAME} 目前支持 20 MHz 和 40 MHz 两种带宽模式,并与协议模式组合使用,常见的组合包括: + + - **HT20**:802.11n,20 MHz 带宽 + - **HT40**:802.11n,40 MHz 带宽 + + .. note:: + + - 40 MHz 带宽模式仅在 802.11n 模式下支持。 + + 应用程序可以使用 :cpp:func:`esp_wifi_set_bandwidth()` API 来设置当前接口的带宽模式。 + + 示例: + + .. code-block:: c + + // 设置 STA 的协议为 802.11bgn + uint8_t protocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N; + esp_wifi_set_protocol(WIFI_IF_STA, protocol); + + // 设置 STA 的带宽为 40 MHz + esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40); + +.. only:: esp32c6 + + {IDF_TARGET_NAME} 目前支持 20 MHz 和 40 MHz 两种带宽模式,并与协议模式组合使用,常见的组合包括: + + - **HT20**:802.11n,20 MHz 带宽 + - **HT40**:802.11n,40 MHz 带宽 + - **HE20**:802.11ax,20 MHz 带宽 + + .. note:: + + - 40 MHz 带宽模式仅在 802.11n 模式下支持。 + + 应用程序可以使用 :cpp:func:`esp_wifi_set_bandwidth()` API 来设置当前接口的带宽模式。 + + 示例: + + .. code-block:: c + + // 设置 STA 的协议为 802.11bgn + uint8_t protocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N; + esp_wifi_set_protocol(WIFI_IF_STA, protocol); + + // 设置 STA 的带宽为 40 MHz + esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40); + +.. only:: esp32c5 + + {IDF_TARGET_NAME} 当前支持 20 MHz 和 40 MHz 两种带宽模式,可与不同协议模式组合使用,常见配置包括: + + - **HT20**:802.11n/11an,20 MHz 带宽 + - **HT40**:802.11n/11an,40 MHz 带宽 + - **HE20**:802.11ax,20 MHz 带宽 + + .. note:: + + - 40 MHz 模式仅适用于 802.11n(2.4 GHz)或 802.11an(5 GHz)协议。 + + 应用程序可使用 :cpp:func:`esp_wifi_set_bandwidths()` API,分别为 2.4 GHz 和 5 GHz 配置独立带宽。 + + 示例: + + .. code-block:: c + + // 设置 2.4 GHz 使用 802.11bgnax,5 GHz 使用 802.11an 协议 + wifi_protocols_t protocols = { + .ghz_2g = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX, + .ghz_5g = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N, + }; + esp_wifi_set_protocols(WIFI_IF_STA, &protocols); + + // 设置 2.4 GHz 带宽为 20 MHz,5 GHz 带宽为 40 MHz + wifi_bandwidths_t bw = { + .ghz_2g = WIFI_BW_HT20, + .ghz_5g = WIFI_BW_HT40 + }; + esp_wifi_set_bandwidths(WIFI_IF_STA, &bw); + + .. note:: + + - 若 `.ghz_2g` 设置为 0,仅配置 5 GHz 带宽,2.4 GHz 保持不变。 + - 若 `.ghz_5g` 设置为 0,仅配置 2.4 GHz 带宽,5 GHz 保持不变。 + + **兼容用法** + + 可使用旧版 API :cpp:func:`esp_wifi_set_bandwidth()` 配置 2.4 GHz 频段或者 5 GHz 频段的带宽: + + .. code-block:: c + + // 设置频段为 5 GHz 频段 + esp_wifi_set_band_mode(WIFI_BAND_MODE_5G_ONLY); + + // 设置 STA 的协议为 802.11an + uint8_t protocol = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N; + esp_wifi_set_protocol(WIFI_IF_STA, protocol); + + // 设置 STA 的带宽为 40 MHz + esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40); + + .. note:: + + - 新版 API :cpp:func:`esp_wifi_set_bandwidths()` 支持同时配置 2.4 GHz 与 5 GHz 带宽,推荐在 {IDF_TARGET_NAME} 上优先使用。 + - ``esp_wifi_set_bandwidth()`` 适用于单频段场景,如 ``WIFI_BAND_MODE_2G_ONLY`` 或 ``WIFI_BAND_MODE_5G_ONLY``,仅作用于当前连接频段。例如,若接口工作在 5 GHz,则 2.4 GHz 的配置将被忽略。 + - 若设置了当前频段不支持的带宽值,函数将返回错误。 + +.. only:: esp32c2 + + {IDF_TARGET_NAME} 目前仅支持 20 MHz 带宽模式。 + +.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 or esp32c5 or esp32c6 + + 长距离 (LR) + +++++++++++++++++++++++++ + + 长距离 (LR) 模式是乐鑫的一项专利 Wi-Fi 模式,可达到 1 公里视线范围。与传统 802.11b 模式相比,接收灵敏度更高,抗干扰能力更强,传输距离更长。 + + LR 兼容性 + ************************* + + 由于 LR 是乐鑫的独有 2.4 GHz 频段 Wi-Fi 模式,只有 ESP32 芯片系列设备(ESP32-C2 除外)才能传输和接收 LR 数据。也就是说,如果连接的设备不支持 LR,ESP32 芯片系列设备(ESP32-C2 除外)则不会以 LR 数据速率传输数据。可通过配置适当的 Wi-Fi 模式使你的应用程序实现这一功能。 + + - 如果协商的模式支持 LR,ESP32 芯片系列设备(ESP32-C2 除外)可能会以 LR 速率传输数据。 + - 否则,ESP32 芯片系列设备(ESP32-C2 除外)将以传统 Wi-Fi 数据速率传输所有数据。 + + 下表是 2.4 GHz 频段 Wi-Fi 模式协商: + + .. only:: esp32 or esp32s2 or esp32c3 or esp32s3 + + +-------+-----+----+---+-------+------+-----+----+ + |AP\STA | BGN | BG | B | BGNLR | BGLR | BLR | LR | + +=======+=====+====+===+=======+======+=====+====+ + | BGN | BGN | BG | B | BGN | BG | B | - | + +-------+-----+----+---+-------+------+-----+----+ + | BG | BG | BG | B | BG | BG | B | - | + +-------+-----+----+---+-------+------+-----+----+ + | B | B | B | B | B | B | B | - | + +-------+-----+----+---+-------+------+-----+----+ + | BGNLR | - | - | - | BGNLR | BGLR | BLR | LR | + +-------+-----+----+---+-------+------+-----+----+ + | BGLR | - | - | - | BGLR | BGLR | BLR | LR | + +-------+-----+----+---+-------+------+-----+----+ + | BLR | - | - | - | BLR | BLR | BLR | LR | + +-------+-----+----+---+-------+------+-----+----+ + | LR | - | - | - | LR | LR | LR | LR | + +-------+-----+----+---+-------+------+-----+----+ + + .. only:: esp32c5 or esp32c6 + + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | AP\STA | BGNAX | BGN | BG | B | BGNAXLR | BGNLR | BGLR | BLR | LR | + +=========+=======+=====+====+===+=========+=======+======+=====+====+ + | BGNAX | BGAX | BGN | BG | B | BGAX | BGN | BG | B | - | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | BGN | BGN | BGN | BG | B | BGN | BGN | BG | B | - | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | BG | BG | BG | BG | B | BG | BG | BG | B | - | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | B | B | B | B | B | B | B | B | B | - | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | BGNAXLR | - | - | - | - | BGAXLR | BGNLR | BGLR | BLR | LR | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | BGNLR | - | - | - | - | BGNLR | BGNLR | BGLR | BLR | LR | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | BGLR | - | - | - | - | BGLR | BGLR | BGLR | BLR | LR | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | BLR | - | - | - | - | BLR | BLR | BLR | BLR | LR | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + | LR | - | - | - | - | LR | LR | LR | LR | LR | + +---------+-------+-----+----+---+---------+-------+------+-----+----+ + + 上表中,行是 AP 的 Wi-Fi 模式,列是 station 的 Wi-Fi 模式。"-" 表示 AP 和 station 的 Wi-Fi 模式不兼容。 + + 根据上表,得出以下结论: + + - 对于已使能 LR 的 {IDF_TARGET_NAME} AP,由于以 LR 模式发送 beacon,因此与传统的 802.11 模式不兼容。 + - 对于已使能 LR 且并非仅 LR 模式的 {IDF_TARGET_NAME} station,与传统 802.11 模式兼容。 + - 如果 station 和 AP 都是 ESP32 芯片系列设备(ESP32-C2 除外),并且两者都使能 LR 模式,则协商的模式支持 LR。 + + 如果协商的 Wi-Fi 模式同时支持传统的 802.11 模式和 LR 模式,则 Wi-Fi 驱动程序会在不同的 Wi-Fi 模式下自动选择最佳数据速率,应用程序无需任何操作。 + + LR 对传统 Wi-Fi 设备的影响 + *************************************** + + 以 LR 速率进行的数据传输不会影响传统 Wi-Fi 设备,因为: + + - LR 模式下的 CCA 和回退过程符合 802.11 协议。 + - 传统的 Wi-Fi 设备可以通过 CCA 检测 LR 信号并进行回退。 + + 也就是说,LR 模式下传输效果与 802.11b 模式相似。 + + LR 传输距离 + ************************* + + LR 的接收灵敏度比传统的 802.11b 模式高 4 dB,理论上,传输距离约为 11B 的 2 至 2.5 倍。 + + LR 吞吐量 + ************************* + + 因为原始 PHY 数据传输速率为 1/2 Mbps 和 1/4 Mbps,LR 的吞吐量有限。 + + 何时使用 LR + ************************* + + 使用 LR 的一般条件如下: + + - AP 和 station 都是乐鑫设备。 + - 需要长距离 Wi-Fi 连接和数据传输。 + - 数据吞吐量要求非常小,例如远程设备控制等。 + + +.. only:: esp32c5 + + 动态频率选择(DFS) + +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + 在 5 GHz Wi-Fi 频段中,一些信道(如信道 52 ~ 144)与天气雷达等关键通信系统共享频谱。为避免 Wi-Fi 信号对这些系统产生干扰,Wi-Fi 设备在使用这些信道前,必须执行特定的侦测与切换机制,即 **动态频率选择(DFS)**。 + + 启用 DFS 的设备可以访问更多 5 GHz 信道,从而提高网络容量并减少干扰,尤其适用于高密度部署或需要大带宽的应用场景。不同国家和地区 DFS 信道范围可以参考 :component_file:`esp_wifi/regulatory/esp_wifi_regulatory.txt` + + {IDF_TARGET_NAME} 支持在 5 GHz 频段使用 DFS 信道,但仅支持 **被动雷达检测** 功能。 + + .. list-table:: + :header-rows: 1 + :widths: 20 60 + + * - 类型 + - 描述 + * - 被动雷达检测 支持 + - 设备在扫描过程中能够监听 DFS 信道,识别并连接工作在 DFS 信道上的接入点(AP)。当目标 AP 在 DFS 信道上检测到雷达并通过信道切换(CSA)切换信道时,{IDF_TARGET_NAME} 会跟随 AP 切换信道。 + * - 主动雷达检测 不支持 + - {IDF_TARGET_NAME} **不支持** 主动雷达检测功能,因此无法在 SoftAP 模式下作为 DFS AP 启动。 + + .. note:: + + - 在 STA 模式下,{IDF_TARGET_NAME} 可连接至位于 DFS 信道上的 AP,前提是该信道已在扫描中被识别。 + - 在 SoftAP 模式下,{IDF_TARGET_NAME} 不允许使用 DFS 信道作为工作信道,以避免违反无线电监管规定。 + - 在 STA+SoftAP 共存模式下: + + 1. 当 STA 连接到位于 DFS 信道的 AP 时,SoftAP 允许通过 CSA (Channel Switch Announcement) 切换至相同的 DFS 信道。 + 2. 当 STA 断开连接后,SoftAP 将通过 CSA 切换回非 DFS 信道,确保符合监管要求。 + +.. + +.. _wifi-country-code: + +Wi-Fi 国家/地区代码 ++++++++++++++++++++++++++++ + +.. only:: esp32 or esp32c2 or esp32s2 or esp32c3 or esp32s3 or esp32c6 + + 调用 :cpp:func:`esp_wifi_set_country()`,设置国家/地区信息。下表详细介绍了各个字段,请在配置这些字段之前参考当地的 2.4 GHz RF 操作规定。 + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - 字段 + - 描述 + * - cc[3] + - 国家/地区代码字符串,此属性标识 station/AP 位于的国家/地区或非国家/地区实体。如果是一个国家/地区,该字符串的前两个八位字节是 ISO/IEC3166-1 中规定的国家/地区两位字母代码。第三个八位字节应是下述之一: + + - ASCII 码空格字符,代表 station/AP 所处国家/地区的规定允许当前频段所需的所有环境。 + - ASCII 码 ‘O’ 字符,代表 station/AP 所处国家/地区的规定仅允许室外环境。 + - ASCII 码 ‘I’ 字符,代表 station/AP 所处国家/地区的规定仅允许室内环境。 + - ASCII 码 ‘X’ 字符,代表 station/AP 位于非国家/地区实体。非国家实体的前两个八位字节是两个 ASCII 码 ‘XX’ 字符。 + - 当前使用的操作类表编号的二进制形式。见 IEEE Std 802.11-2020 附件 E。 + + * - schan + - 起始信道,station/AP 所处国家/地区规定的最小信道值。 + * - nchan + - 规定的总信道数,比如,如果 schan=1,nchan=13,那么 station/AP 可以从信道 1 至 13 发送数据。 + * - policy + - 国家/地区策略,当配置的国家/地区信息与所连 AP 的国家/地区信息冲突时,该字段决定使用哪一信息。更多策略相关信息,可参见下文。 + + + 默认国家/地区信息为:: + + wifi_country_t config = { + .cc = "01", + .schan = 1, + .nchan = 11, + .policy = WIFI_COUNTRY_POLICY_AUTO, + }; + + 如果 Wi-Fi 模式为 station/AP 共存模式,则它们配置的国家/地区信息相同。有时,station 所连 AP 的国家/地区信息与配置的不同。例如,配置的 station 国家/地区信息为:: + + wifi_country_t config = { + .cc = "JP", + .schan = 1, + .nchan = 14, + .policy = WIFI_COUNTRY_POLICY_AUTO, + }; + + 但所连 AP 的国家/地区信息为:: + + wifi_country_t config = { + .cc = "CN", + .schan = 1, + .nchan = 13, + }; + + 此时,使用所连 AP 的国家/地区信息。 + + 下表描述了在不同 Wi-Fi 模式和不同国家/地区策略下使用的国家/地区信息,并描述了对主动扫描的影响。 + + .. list-table:: + :header-rows: 1 + :widths: 15 15 35 + + * - Wi-Fi 模式 + - 策略 + - 描述 + * - station 模式 + - WIFI_COUNTRY_POLICY_AUTO + - 如果所连 AP 的 beacon 中有国家/地区的 IE,使用的国家/地区信息为 beacon 中的信息,否则,使用默认信息。 + + 扫描时: + + 主动扫描信道 1 至信道 11,被动扫描信道 12 至 信道 14。 + + 请记住,如果带有隐藏 SSID 的 AP 和 station 被设置在被动扫描信道上,被动扫描将无法找到该 AP。也就是说,如果应用程序希望在每个信道中找到带有隐藏 SSID 的 AP,国家/地区信息应该配置为 WIFI_COUNTRY_POLICY_MANUAL。 + + * - station 模式 + - WIFI_COUNTRY_POLICY_MANUAL + - 总是使用配置的国家/地区信息。 + + 扫描时: + + 主动扫描信道 schan 至信道 schan+nchan-1。 + + * - AP 模式 + - WIFI_COUNTRY_POLICY_AUTO + - 总是使用配置的国家/地区信息。 + + * - AP 模式 + - WIFI_COUNTRY_POLICY_MANUAL + - 总是使用配置的国家/地区信息。 + + * - station/AP 共存模式 + - WIFI_COUNTRY_POLICY_AUTO + - 该 station 与 station 模式、WIFI_COUNTRY_POLICY_AUTO 策略下使用的国家/地区信息相同。 + 如果 station 不连接任何外部 AP,AP 使用配置的国家/地区信息。如果 station 连接一个外部 AP,该 AP 的国家/地区信息与该 station 相同。 + + * - station/AP 共存模式 + - WIFI_COUNTRY_POLICY_MANUAL + - 该 station 与 station 模式、WIFI_COUNTRY_POLICY_MANUAL 策略下使用的国家/地区信息相同。 + 该 AP 与 AP 模式、WIFI_COUNTRY_POLICY_MANUAL 策略下使用的国家/地区信息相同。 + +.. only:: esp32c5 + + 调用 :cpp:func:`esp_wifi_set_country()` 可设置国家/地区信息。下表详细介绍了各字段含义,请在配置这些字段前,参考本地 2.4 GHz 与 5 GHz 射频使用规定。 + + .. list-table:: + :header-rows: 1 + :widths: 15 55 + + * - 字段 + - 描述 + * - cc[3] + - 国家/地区代码字符串。用于标识 station/AP 所在的国家/地区,或非国家实体。如果为国家/地区,该字段的前两个字节为符合 ISO/IEC 3166-1 标准的两位国家代码,第三个字节含义如下: + + - 空格字符(ASCII),表示当前国家/地区在所有环境中允许使用相应频段。 + - 字符 `'O'`,表示仅允许在户外环境中使用。 + - 字符 `'I'`,表示仅允许在室内环境中使用。 + - 字符 `'X'`,表示非国家实体,此时前两个字符应为 `'X'`(即 `'XX'`)。 + - 二进制形式的操作类编号,参考 IEEE Std 802.11-2020 附录 E。 + + * - schan + - 起始信道值,即当前国家/地区在 2.4 GHz 频段中允许使用的最小信道。 + * - nchan + - 信道数量。定义在 2.4 GHz 频段中允许使用的总信道数。例如,若 schan = 1,nchan = 13,则 station/AP 可使用信道 1 至 13。 + * - policy + - 国家/地区策略。当配置的国家/地区与连接 AP 的信息冲突时,此字段决定应使用哪一方的信息。详情见下文说明。 + * - wifi_5g_channel_mask + - 表示 station/AP 在 5 GHz 频段中可使用的信道掩码。信道值与位的对应关系详见 :cpp:enum:`wifi_5g_channel_bit_t`。 + + 默认配置示例如下:: + + wifi_country_t config = { + .cc = "01", + .schan = 1, + .nchan = 11, + .wifi_5g_channel_mask = 0xfe, + .policy = WIFI_COUNTRY_POLICY_AUTO, + }; + + 若 Wi-Fi 处于 station/AP 共存模式,则两者使用相同的国家/地区信息。有时,连接的 AP 的国家/地区信息可能与 station 预设的不同。例如: + + 配置的 station 信息为:: + + wifi_country_t config = { + .cc = "JP", + .schan = 1, + .nchan = 14, + .wifi_5g_channel_mask = 0xfe, + .policy = WIFI_COUNTRY_POLICY_AUTO, + }; + + 而连接的 AP 信息为:: + + wifi_country_t config = { + .cc = "CN", + .schan = 1, + .nchan = 13, + }; + + 此时将使用连接的 AP 的国家/地区信息。 + + 下表说明了在不同 Wi-Fi 模式及策略下使用的国家/地区信息,并说明了扫描行为的差异: + + .. list-table:: + :header-rows: 1 + :widths: 15 15 35 + + * - Wi-Fi 模式 + - 策略 + - 描述 + * - station 模式 + - WIFI_COUNTRY_POLICY_AUTO + - 若连接的 AP 的 beacon 中包含国家/地区信息 IE,则使用该信息;否则使用默认配置。 + + 扫描行为: + + - 2.4 GHz 频段:主动扫描信道 1–11,被动扫描信道 12–14; + - 5 GHz 频段:主动扫描非 DFS 信道,被动扫描 DFS 信道。 + + 注意:若隐藏 SSID 的 AP 设在被动扫描信道上,扫描可能无法发现该 AP。若需在所有信道上发现隐藏 SSID,请使用 `WIFI_COUNTRY_POLICY_MANUAL`。 + + * - station 模式 + - WIFI_COUNTRY_POLICY_MANUAL + - 始终使用配置的国家/地区信息。 + + 扫描行为: + + - 2.4 GHz 频段:扫描从 `schan` 到 `schan + nchan - 1` 的信道; + - 5 GHz 频段:扫描 `wifi_5g_channel_mask` 中标记支持的信道。 + + * - AP 模式 + - WIFI_COUNTRY_POLICY_AUTO + - 始终使用配置的国家/地区信息。 + * - AP 模式 + - WIFI_COUNTRY_POLICY_MANUAL + - 始终使用配置的国家/地区信息。 + * - station/AP 共存模式 + - WIFI_COUNTRY_POLICY_AUTO + - 与 station 模式中的 `WIFI_COUNTRY_POLICY_AUTO` 相同。 + + 若 station 未连接任何 AP,则 AP 使用配置的国家/地区信息; + 若 station 连接了外部 AP,则 AP 使用该 station 获取的国家/地区信息。 + + * - station/AP 共存模式 + - WIFI_COUNTRY_POLICY_MANUAL + - 与 station 模式中 `WIFI_COUNTRY_POLICY_MANUAL` 相同,AP 也始终使用配置的国家/地区信息。 + + +主信道 +************************* + +AP 模式下,AP 的信道定义为主信道。station 模式下,station 所连 AP 的信道定义为主信道。station/AP 共存模式下,AP 和 station 的主信道必须相同。如果不同,station 的主信道始终优先。比如,初始时,AP 位于信道 6,但 station 连接信道 9 的 AP。因为 station 的主信道具有优先性,该 AP 需要将信道从 6 切换至 9,确保与 station 主信道相同。切换信道时,AP 模式下的 {IDF_TARGET_NAME} 将使用信道切换公告 (CSA) 通知连接的 station。支持信道切换的 station 将直接通过,无需与 AP 断连再重新连接。 + + +.. _wifi-menuconfig: + +Wi-Fi Menuconfig +----------------------- + +.. _wifi-buffer-configure: + +Wi-Fi 缓冲区配置 ++++++++++++++++++++++++ + +如果要修改默认的缓冲区数量或类型,最好也了解缓冲区在数据路径中如何分配或释放。下图显示了发送数据方向的过程。 + +.. blockdiag:: + :caption: TX Buffer Allocation + :align: center + + blockdiag buffer_allocation_tx { + + # global attributes + node_height = 60; + node_width = 100; + span_width = 50; + span_height = 20; + default_shape = roundedbox; + + # labels of diagram nodes + APPL_TASK [label="Application\n task", fontsize=12]; + LwIP_TASK [label="LwIP\n task", fontsize=12]; + WIFI_TASK [label="Wi-Fi\n task", fontsize=12]; + + # labels of description nodes + APPL_DESC [label="1> User data", width=120, height=25, shape=note, color=yellow]; + LwIP_DESC [label="2> Pbuf", width=120, height=25, shape=note, color=yellow]; + WIFI_DESC [label="3> Dynamic (Static)\n TX Buffer", width=150, height=40, shape=note, color=yellow]; + + # node connections + APPL_TASK -> LwIP_TASK -> WIFI_TASK + APPL_DESC -> LwIP_DESC -> WIFI_DESC [style=none] + } + + +描述: + + - 应用程序分配需要发送的数据。 + - 应用程序调用 TCPIP 或套接字相关的 API 发送用户数据。这些 API 会分配一个在 LwIP 中使用的 PBUF,并复制用户数据。 + - 当 LwIP 调用 Wi-Fi API 发送 PBUF 时,Wi-Fi API 会分配一个“动态发送数据缓冲区”或“静态发送数据缓冲区”,并复制 LwIP PBUF,最后发送数据。 + +下图展示了如何在接收数据方向分配或释放缓冲区: + +.. blockdiag:: + :caption: 接收数据缓冲区分配 + :align: center + + blockdiag buffer_allocation_rx { + + # global attributes + node_height = 60; + node_width = 100; + span_width = 40; + span_height = 20; + default_shape = roundedbox; + + # labels of diagram nodes + APPL_TASK [label="Application\n task", fontsize=12]; + LwIP_TASK [label="LwIP\n task", fontsize=12]; + WIFI_TASK [label="Wi-Fi\n task", fontsize=12]; + WIFI_INTR [label="Wi-Fi\n interrupt", fontsize=12]; + + # labels of description nodes + APPL_DESC [label="4> User\n Data Buffer", height=40, shape=note, color=yellow]; + LwIP_DESC [label="3> Pbuf", height=40, shape=note, color=yellow]; + WIFI_DESC [label="2> Dynamic\n RX Buffer", height=40, shape=note, color=yellow]; + INTR_DESC [label="1> Static\n RX Buffer", height=40, shape=note, color=yellow]; + + # node connections + APPL_TASK <- LwIP_TASK <- WIFI_TASK <- WIFI_INTR + APPL_DESC <- LwIP_DESC <- WIFI_DESC <- INTR_DESC [style=none] + } + +描述: + + - Wi-Fi 硬件在空中接收到数据包后,将数据包内容放到“静态接收数据缓冲区”,也就是“接收数据 DMA 缓冲区”。 + - Wi-Fi 驱动程序分配一个“动态接收数据缓冲区”、复制“静态接收数据缓冲区”,并将“静态接收数据缓冲区”返回给硬件。 + - Wi-Fi 驱动程序将数据包传送到上层 (LwIP),并分配一个 PBUF 用于存放“动态接收数据缓冲区”。 + - 应用程序从 LwIP 接收数据。 + +下表是 Wi-Fi 内部缓冲区的配置情况。 + +.. list-table:: + :header-rows: 1 + :widths: 10 10 10 10 25 + + * - 缓冲区类型 + - 分配类型 + - 默认 + - 是否可配置 + - 描述 + * - 静态接收数据缓冲区(硬件接收数据缓冲区) + - 静态 + - 10 * 1600 Bytes + - 是 + - 这是一种 DMA 内存,在函数 :cpp:func:`esp_wifi_init()` 中初始化,在函数 :cpp:func:`esp_wifi_deinit()` 中释放。 该缓冲区形成硬件接收列表。当通过空中接收到一个帧时,硬件将该帧写入缓冲区,并向 CPU 发起一个中断。然后,Wi-Fi 驱动程序从缓冲区中读取内容,并将缓冲区返回到列表中。 + + 如果应用程序希望减少 Wi-Fi 静态分配的内存,可以将该值从 10 减少到 6, 从而节省 6400 Bytes 的内存。除非禁用 AMPDU 功能,否则不建议将该值降低到 6 以下。 + * - 动态接收数据缓冲区 + - 动态 + - 32 + - 是 + - 缓冲区的长度可变,取决于所接收帧的长度。当 Wi-Fi 驱动程序 从“硬件接收数据缓冲区”接收到一帧时,需要从堆中分配“动态接收数据缓冲区”。在 Menuconfig 中配置的“动态接收数据缓冲区” 数量用来限制未释放的“动态接收数据缓冲区”总数量。 + * - 动态发送数据缓冲区 + - 动态 + - 32 + - 是 + - 这是一种 DMA 内存,位于堆内存中。当上层 (LwIP) 向 Wi-Fi 驱动程序发送数据包时,该缓冲区首先分配一个“动态发送数据缓 冲区”,并复制上层缓冲区。 + + 动态发送数据缓冲区和静态发送数据缓冲区相互排斥。 + * - 静态发送数据缓冲区 + - 静态 + - 16 * 1600 Bytes + - 是 + - 这是一种 DMA 内存,在函数 :cpp:func:`esp_wifi_init()` 中初始化,在函数 :cpp:func:`esp_wifi_deinit()` 中释放。 当上层 (LwIP) 向 Wi-Fi 驱动程序发送数据包时,该缓冲区首先 分配一个“静态发送数据缓冲区”,并复制上层缓冲区。 + + 动态发送数据缓冲区和静态发送数据缓冲区相互排斥。 + + 由于发送数据缓冲区必须是 DMA 缓冲区,所以当使能 PSRAM 时,发送数据缓冲区必须是静态的。 + * - 管理短缓冲区 + - 动态 + - 8 + - 否 + - Wi-Fi 驱动程序的内部缓冲区。 + * - 管理长缓冲区 + - 动态 + - 32 + - 否 + - Wi-Fi 驱动程序的内部缓冲区。 + * - 管理超长缓冲区 + - 动态 + - 32 + - 否 + - Wi-Fi 驱动程序的内部缓冲区。 + +.. _wifi-nvs-flash: + +Wi-Fi NVS Flash ++++++++++++++++++++++ + +如果使能 Wi-Fi NVS flash,所有通过 Wi-Fi API 设置的 Wi-Fi 配置都会被存储到 flash 中,Wi-Fi 驱动程序在下次开机或重启时将自动加载这些配置。但是,应用程序可视情况禁用 Wi-Fi NVS flash,例如:其配置信息不需要存储在非易失性内存中、其配置信息已安全备份,或仅出于某些调试原因等。 + + +故障排除 +--------------- + +请见 :doc:`../wireshark-user-guide`。 + +.. toctree:: + :hidden: + + ../wireshark-user-guide diff --git a/docs/zh_CN/api-guides/wifi-driver/security-and-roaming.rst b/docs/zh_CN/api-guides/wifi-driver/security-and-roaming.rst new file mode 100644 index 0000000000..ca67b3cd24 --- /dev/null +++ b/docs/zh_CN/api-guides/wifi-driver/security-and-roaming.rst @@ -0,0 +1,86 @@ +安全与漫游 +================= + +:link_to_translation:`en:[English]` + + +支持的 Wi-Fi 安全模式 +------------------------- + +{IDF_TARGET_NAME} 支持以下 Wi-Fi 安全模式。有关详细配置和使用说明,请参阅 :doc:`Wi-Fi 安全性 <../wifi-security>`。 + +- Open +- WEP +- 个人级 WPA +- 个人级 WPA2 +- 个人级 WPA3 +- 企业级 Wi-Fi + + +Wi-Fi Easy Connect™ (DPP) +-------------------------- + +Wi-Fi Easy Connect\ :sup:`TM` (也称为设备配置协议)是一个安全且标准化的配置协议,用于配置 Wi-Fi 设备。更多信息请参考 :doc:`esp_dpp <../../api-reference/network/esp_dpp>`。 + + +WPS 注册 +------------------------- + +在 Wi-Fi 模式 WIFI_MODE_STA 或 WIFI_MODE_APSTA 下,{IDF_TARGET_NAME} 支持 WPS 注册功能。目前,{IDF_TARGET_NAME} 支持的 WPS enrollee 类型有 PBC 和 PIN。 + + +无线网络管理 +---------------------------- + +无线网络管理让客户端设备能够交换有关网络拓扑结构的信息,包括与射频环境相关的信息。这使每个客户端都能感知网络状况,从而促进无线网络性能的整体改进。这是 802.11v 规范的一部分。它还使客户端能够支持网络辅助漫游。 +网络辅助漫游让 WLAN 能够向关联的客户端发送消息,从而使客户端与具有更好链路指标的 AP 关联。这对于促进负载平衡以及引导连接不良的客户端都很有用。 + +目前 802.11v 的实现支持 BSS 过渡管理帧。 + +无线资源管理 +--------------------------- + +无线电资源测量 (802.11k) 旨在改善网络内流量的分配方式。在无线局域网中,一般情况下,无线设备会连接发射信号最强的接入点 (AP)。根据用户的数量和地理位置,这种分配方式有时会导致某个接入点超负荷而其它接入点利用不足,从而导致整体网络性能下降。在符合 802.11k 规范的网络中,如果信号最强的 AP 已满负荷,无线设备则转移到其它未充分利用的 AP。尽管信号可能较弱,但由于更有效地利用了网络资源,总体吞吐量会更大。 + +目前 802.11k 的实现支持信标测量报告、链路测量报告和邻居请求。 + +请参考 IDF 示例程序 :idf_file:`examples/wifi/roaming/README.md` 来设置和使用这些 API。示例代码只演示了如何使用这些 API,应用程序应根据需要定义自己的算法和案例。 + +快速 BSS 切换 +--------------- + +快速 BSS 切换 (802.11r FT) 是一种标准,旨在允许移动中的无线设备保持连续连接,让客户端从一个 BSS(Basic Service Set,基站,口头也称 AP)快速安全地切换到另一个 BSS, 实现几乎无缝的连接, **避免 802.11i 的四次握手过程**。802.11r 重新定义了安全密钥协商协议,规定了 AP 之间的转换方式,允许以并行的方式协商和请求无线资源。服务器生成的密钥会缓存在无线网络中,未来可以基于此缓存的密钥建立一定数量的连接,避免了 802.11x 过程。 + + +{IDF_TARGET_NAME} station 模式支持 WPA2-PSK 网络 FT。注意,{IDF_TARGET_NAME} station 模式仅支持空中 FT 协议。 + +在 :cpp:type:`wifi_sta_config_t` 中提供了配置选项 :ref:`CONFIG_ESP_WIFI_11R_SUPPORT` 和配置参数 :cpp:type:`ft_enabled`,可启用 station 的 802.11r 支持。详细信息请参阅 ESP-IDF 示例 :idf_file:`examples/wifi/roaming/README.md`。 + +.. only:: SOC_WIFI_FTM_SUPPORT + + Wi-Fi Location + ------------------------------- + + Wi-Fi Location 将提高 AP 以外设备位置数据的准确性,这有助于创建新的、功能丰富的应用程序和服务,例如地理围栏、网络管理、导航等。用于确定设备相对于接入点的位置的协议之一是精细定时测量 (FTM),它会计算 Wi-Fi 帧的飞行时间。 + + 精细定时测量 (FTM) + +++++++++++++++++++++++++++++ + + FTM 用于测量 Wi-Fi 往返时间(Wi-Fi RTT),即 Wi-Fi 信号从一个设备到另一个设备并返回所需的时间。使用 Wi-Fi RTT,设备之间的距离可以用一个简单的公式 `RTT * c / 2` 来计算,其中 c 是光速。 + + 对于设备之间交换的帧,FTM 在帧到达或离开时使用时间戳,这个时间戳由 Wi-Fi 接口硬件提供。FTM 发起方(主要是 station 设备)发现 FTM 响应方(可以是 station 或 AP),并协商启动 FTM 程序。该程序以突发形式发送的多个动作帧及其 ACK 来收集时间戳数据。FTM 发起方最后收集数据以计算平均往返时间。 + + {IDF_TARGET_NAME} 在以下配置中支持 FTM: + + - {IDF_TARGET_NAME} 在 station 模式下为 FTM 发起方。 + - {IDF_TARGET_NAME} 在 AP 模式下为 FTM 响应方。 + +.. only:: esp32c6 + + {IDF_TARGET_NAME} ECO1 及更早的版本不支持 FTM 发起方模式。 + +.. attention:: + + 使用 RTT 的距离测量并不准确,RF 干扰、多径传播、天线方向和缺乏校准等因素会增加这些不准确度。为了获得更好的结果,建议在两个 ESP32 芯片系列设备(ESP32-C2 除外)之间执行 FTM,这两个设备可分别设置为 station 和 AP 模式。 + + 请参考 ESP-IDF 示例 :idf_file:`examples/wifi/ftm/README.md`,了解设置和执行 FTM 的详细步骤。 diff --git a/docs/zh_CN/api-guides/wifi-driver/station-scenarios.rst b/docs/zh_CN/api-guides/wifi-driver/station-scenarios.rst new file mode 100644 index 0000000000..15ff78bd83 --- /dev/null +++ b/docs/zh_CN/api-guides/wifi-driver/station-scenarios.rst @@ -0,0 +1,898 @@ +Station 场景 +============== + +:link_to_translation:`en:[English]` + +.. _wifi-station-general-scenario: + +{IDF_TARGET_NAME} Wi-Fi Station 通用场景 +------------------------------------------------ + +下图为 station 模式下的宏观场景,其中包含不同阶段的具体描述: + +.. seqdiag:: + :caption: station 模式下 Wi-Fi 事件场景示例 + :align: center + + seqdiag sample-scenarios-station-mode { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 140; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + MAIN_TASK [label = "Main\ntask"]; + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + LwIP_TASK [label = "LwIP\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + === 1. 初始化阶段 === + MAIN_TASK -> LwIP_TASK [label="1.1> 创建/初始化 LwIP"]; + MAIN_TASK -> EVENT_TASK [label="1.2> 创建/初始化事件"]; + MAIN_TASK -> WIFI_TASK [label="1.3> 创建/初始化 Wi-Fi"]; + MAIN_TASK -> APP_TASK [label="1.4> 创建应用程序任务"]; + === 2. 配置阶段 === + MAIN_TASK -> WIFI_TASK [label="2> 配置 Wi-Fi"]; + === 3. 启动阶段 === + MAIN_TASK -> WIFI_TASK [label="3.1> 启动 Wi-Fi"]; + EVENT_TASK <- WIFI_TASK [label="3.2> WIFI_EVENT_STA_START"]; + APP_TASK <- EVENT_TASK [label="3.3> WIFI_EVENT_STA_START"]; + === 4. 连接阶段 === + APP_TASK -> WIFI_TASK [label="4.1> 连接 Wi-Fi"]; + EVENT_TASK <- WIFI_TASK [label="4.2> WIFI_EVENT_STA_CONNECTED"]; + APP_TASK <- EVENT_TASK [label="4.3> WIFI_EVENT_STA_CONNECTED"]; + === 5. 获取 IP 阶段 === + EVENT_TASK -> LwIP_TASK [label="5.1> 启动 DHCP 客户端"]; + EVENT_TASK <- LwIP_TASK [label="5.2> IP_EVENT_STA_GOT_IP"]; + APP_TASK <- EVENT_TASK [label="5.3> IP_EVENT_STA_GOT_IP"]; + APP_TASK -> APP_TASK [label="5.4> 套接字相关初始化"]; + === 6. 断开阶段 === + EVENT_TASK <- WIFI_TASK [label="6.1> WIFI_EVENT_STA_DISCONNECTED"]; + APP_TASK <- EVENT_TASK [label="6.2> WIFI_EVENT_STA_DISCONNECTED"]; + APP_TASK -> APP_TASK [label="6.3> 断开处理"]; + === 7. IP 更改阶段 === + EVENT_TASK <- LwIP_TASK [label="7.1> IP_EVENT_STA_GOT_IP"]; + APP_TASK <- EVENT_TASK [label="7.2> IP_EVENT_STA_GOT_IP"]; + APP_TASK -> APP_TASK [label="7.3> 套接字错误处理"]; + === 8. 清理阶段 === + APP_TASK -> WIFI_TASK [label="8.1> 断开 Wi-Fi 连接"]; + APP_TASK -> WIFI_TASK [label="8.2> 终止 Wi-Fi"]; + APP_TASK -> WIFI_TASK [label="8.3> 清理 Wi-Fi"]; + } + + +1. Wi-Fi/LwIP 初始化阶段 +++++++++++++++++++++++++++++++ + + - s1.1:主任务通过调用函数 :cpp:func:`esp_netif_init()` 创建一个 LwIP 核心任务,并初始化 LwIP 相关工作。 + + - s1.2:主任务通过调用函数 :cpp:func:`esp_event_loop_create()` 创建一个系统事件任务,并初始化应用程序事件的回调函数。在此情况下,该回调函数唯一的动作就是将事件中继到应用程序任务中。 + + - s1.3:主任务通过调用函数 :cpp:func:`esp_netif_create_default_wifi_ap()` 或 :cpp:func:`esp_netif_create_default_wifi_sta()` 创建有 TCP/IP 堆栈的默认网络接口实例绑定 station 或 AP。 + + - s1.4:主任务通过调用函数 :cpp:func:`esp_wifi_init()` 创建 Wi-Fi 驱动程序任务,并初始化 Wi-Fi 驱动程序。 + + - s1.5:主任务通过调用 OS API 创建应用程序任务。 + +推荐按照 s1.1 ~ s1.5 的步骤顺序针对基于 Wi-Fi/LwIP 的应用程序进行初始化。但这一顺序 **并非** 强制,你可以在第 s1.1 步创建应用程序任务,然后在该应用程序任务中进行所有其它初始化操作。不过,如果你的应用程序任务依赖套接字,那么在初始化阶段创建应用程序任务可能并不适用。此时,你可以在接收到 IP 后再进行任务创建。 + +2. Wi-Fi 配置阶段 ++++++++++++++++++++++++++++++++ + +Wi-Fi 驱动程序初始化成功后,可以进入到配置阶段。该场景下,Wi-Fi 驱动程序处于 station 模式。因此,首先你需调用函数 :cpp:func:`esp_wifi_set_mode` (WIFI_MODE_STA) 将 Wi-Fi 模式配置为 station 模式。可通过调用其它 esp_wifi_set_xxx API 进行更多设置,例如:协议模式、国家代码、带宽等。请参阅 :ref:`{IDF_TARGET_NAME} Wi-Fi 配置 `。 + +一般情况下,我们会在建立 Wi-Fi 连接之前配置 Wi-Fi 驱动程序,但这 **并非** 强制要求。也就是说,只要 Wi-Fi 驱动程序已成功初始化,你可以在任意阶段进行配置。但是,如果你的 Wi-Fi 在建立连接后不需要更改配置,则应先在此阶段完成配置。因为调用配置 API(例如 :cpp:func:`esp_wifi_set_protocol()`)将会导致 Wi-Fi 连接断开,为操作带来不便。 + +如果 menuconfig 已使能 Wi-Fi NVS flash,则不论当前阶段还是后续的 Wi-Fi 配置信息都将被存储至该 flash 中。那么,当主板上电/重新启动时,就不需从头开始配置 Wi-Fi 驱动程序,只需调用函数 esp_wifi_get_xxx API 获取之前存储的配置信息。当然,如果不想使用之前的配置,你也可以重新配置 Wi-Fi 驱动程序。 + +3. Wi-Fi 启动阶段 +++++++++++++++++++++++++++++++++ + + - s3.1:调用函数 :cpp:func:`esp_wifi_start()` 启动 Wi-Fi 驱动程序。 + - s3.2:Wi-Fi 驱动程序将事件 :ref:`WIFI_EVENT_STA_START ` 发布到事件任务中,然后,事件任务将执行一些正常操作并调用应用程序的事件回调函数。 + - s3.3:应用程序的事件回调函数将事件 :ref:`WIFI_EVENT_STA_START ` 中继到应用程序任务中。此时,推荐调用函数 :cpp:func:`esp_wifi_connect()` 进行 Wi-Fi 连接。当然,你也可以等待在 :ref:`WIFI_EVENT_STA_START ` 事件发生后的其它阶段再调用此函数。 + +4. Wi-Fi 连接阶段 ++++++++++++++++++++++++++++++++++ + + - s4.1:调用函数 :cpp:func:`esp_wifi_connect()` 后,Wi-Fi 驱动程序将启动内部扫描/连接过程。 + + - s4.2:如果内部扫描/连接过程成功,将产生 :ref:`WIFI_EVENT_STA_CONNECTED ` 事件。然后,事件任务将启动 DHCP 客户端服务,最终触发 DHCP 程序。 + + - s4.3:在此情况下,应用程序的事件回调函数会将 :ref:`WIFI_EVENT_STA_CONNECTED ` 事件中继到应用程序任务中。通常,应用程序不需进行操作,而你可以执行任何动作,例如:打印日志等。 + +步骤 s4.2 中 Wi-Fi 连接可能会由于某些原因而失败,例如:密码错误、未找到 AP 等。这种情况下,将引发 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件并提示连接错误原因。有关如何处理中断 Wi-Fi 连接的事件,请参阅下文阶段 6 的描述。 + +5. Wi-Fi 获取 IP 阶段 ++++++++++++++++++++++++++++++++++ + + - s5.1:一旦步骤 4.2 中的 DHCP 客户端初始化完成,Wi-Fi 驱动程序将进入 *获取 IP* 阶段。 + - s5.2:如果 Wi-Fi 成功从 DHCP 服务器接收到 IP 地址,则将引发 :ref:`IP_EVENT_STA_GOT_IP ` 事件,事件任务将执行正常处理。 + - s5.3:应用程序的事件回调函数将事件 :ref:`IP_EVENT_STA_GOT_IP ` 中继到应用程序任务中。对于那些基于 LwIP 构建的应用程序,此事件较为特殊,因为它意味着应用程序已准备就绪,可以开始任务,例如:创建 TCP/UDP 套接字等。此时较为容易犯的一个错误就是在接收到 :ref:`IP_EVENT_STA_GOT_IP ` 事件之前就初始化套接字。**切忌在接收到 IP 之前启动任何套接字相关操作。** + +6. Wi-Fi 断开阶段 ++++++++++++++++++++++++++++++++++ + + - s6.1:当 Wi-Fi 因为某些原因(例如:AP 掉电、RSSI 较弱等)连接中断时,将产生 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件。此事件也可能在上文阶段 3 中发生。在这里,事件任务将通知 LwIP 任务清除/移除所有 UDP/TCP 连接。然后,所有应用程序套接字都将处于错误状态。也就是说,:ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件发生时,任何套接字都无法正常工作。 + - s6.2:上述情况下,应用程序的事件回调函数会将 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件中继到应用程序任务中。推荐调用函数 :cpp:func:`esp_wifi_connect()` 重新连接 Wi-Fi,关闭所有套接字,并在必要时重新创建套接字。请参阅 :ref:`WIFI_EVENT_STA_DISCONNECTED `。 + +7. Wi-Fi IP 更改阶段 +++++++++++++++++++++++++++++++++++ + + - s7.1:如果 IP 地址发生更改,将引发 :ref:`IP_EVENT_STA_GOT_IP ` 事件,其中 "ip_change" 被置为 "true"。 + - s7.2:**此事件对应用程序至关重要。这一事件发生时,适合关闭所有已创建的套接字并进行重新创建。** + + +8. Wi-Fi 清理阶段 +++++++++++++++++++++++++++++ + + - s8.1:调用函数 :cpp:func:`esp_wifi_disconnect()` 断开 Wi-Fi 连接。 + - s8.2:调用函数 :cpp:func:`esp_wifi_stop()` 终止 Wi-Fi 驱动程序。 + - s8.3:调用函数 :cpp:func:`esp_wifi_deinit()` 清理 Wi-Fi 驱动程序。 + + +.. _wifi-scan: + +{IDF_TARGET_NAME} Wi-Fi 扫描 +---------------------------------- + +目前,仅 station 或 station/AP 共存模式支持 :cpp:func:`esp_wifi_scan_start()` API。 + +扫描类型 ++++++++++++++++++++++++++ + +.. list-table:: + :header-rows: 1 + :widths: 15 50 + + * - 模式 + - 描述 + * - 主动扫描 + - 通过发送 probe request 进行扫描。该模式为默认的扫描模式。 + * - 被动扫描 + - 不发送 probe request。跳至某一特定信道并等待 beacon。应用程序可通过 :cpp:type:`wifi_scan_config_t` 中的 scan_type 字段使能被动扫描。 + * - 前端扫描 + - 在 station 模式下 Wi-Fi 未连接时,可进行前端扫描。Wi-Fi 驱动程序决定进行前端扫描还是后端扫描,应用程序无法配置这两种模式。 + * - 后端扫描 + - 在 station 模式或 station/AP 共存模式下 Wi-Fi 已连接时,可进行后端扫描。Wi-Fi 驱动程序决定进行前端扫描还是后端扫描,应用程序无法配置这两种模式。 + * - 全信道扫描 + - 扫描所有信道。:cpp:type:`wifi_scan_config_t` 中的 channel 字段为 0 时,当前模式为全信道扫描。 + * - 特定信道扫描 + - 仅扫描特定的信道。:cpp:type:`wifi_scan_config_t` 中的 channel 字段为 1-14 时,当前模式为特定信道扫描。 + +上表中的扫描模式可以任意组合,因此共有 8 种不同扫描方式: + + - 全信道后端主动扫描 + - 全信道后端被动扫描 + - 全信道前端主动扫描 + - 全信道后端被动扫描 + - 特定信道后端主动扫描 + - 特定信道后端被动扫描 + - 特定信道前端主动扫描 + - 特定信道前端被动扫描 + +扫描配置 ++++++++++++++++++ + +扫描类型与其他扫描属性通过函数 :cpp:func:`esp_wifi_scan_start()` 进行配置。下表详细描述了函数 :cpp:type:`wifi_scan_config_t` 各字段信息。 + +.. list-table:: + :header-rows: 1 + :widths: 15 50 + + * - 字段 + - 描述 + * - ssid + - 如果该字段的值不为 NULL,则仅可扫描到具有相同 SSID 值的 AP。 + * - bssid + - 如果该字段的值不为 NULL,则仅可扫描到具有相同 BSSID 值的 AP。 + * - channel + - 如果该字段值为 0,将进行全信道扫描;反之,将针对特定信道进行扫描。 + * - show_hidden + - 如果该字段值为 0,本次扫描将忽略具有隐藏 SSID 的 AP;反之,这些 AP 也会在扫描时被视为正常 AP。 + * - scan_type + - 如果该字段值为为 WIFI_SCAN_TYPE_ACTIVE,则本次扫描为主动扫描;反之,将被视为被动扫描。 + * - scan_time + - 该字段用于控制每个信道的扫描时间。 + + 被动扫描时,scan_time.passive 字段负责为每个信道指定扫描时间。 + + 主动扫描时,每个信道的扫描时间如下列表所示。其中,min 代表 scan_time_active_min,max 代表 scan_time_active_max。 + + - min=0, max=0:每个信道的扫描时间为 120 ms。 + - min>0, max=0:每个信道的扫描时间为 120 ms。 + - min=0, max>0:每个信道的扫描时间为 ``max`` ms。 + - min>0, max>0:每个信道扫描的最短时间为 ``min`` ms。 如果在这段时间内未找到 AP,将跳转至下一个信道。如这段时间内找到 AP,则该信道的扫描时间为 ``max`` ms。 + + 如希望提升 Wi-Fi 扫描性能,则可修改上述两个参数。 + + +调用 API :cpp:func:`esp_wifi_set_config()` 可全局配置一些扫描属性,请参阅 :ref:`Station 基本配置 `。 + +在所有信道中扫描全部 AP(前端) ++++++++++++++++++++++++++++++++++++++++++++ + +场景: + +.. seqdiag:: + :caption: 所有 Wi-Fi 信道的前端扫描 + :align: center + + seqdiag foreground-scan-all-channels { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 160; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + APP_TASK -> WIFI_TASK [label="1.1 > 配置国家代码"]; + APP_TASK -> WIFI_TASK [label="1.2 > 扫描配置"]; + WIFI_TASK -> WIFI_TASK [label="2.1 > 扫描信道 1"]; + WIFI_TASK -> WIFI_TASK [label="2.2 > 扫描信道 2"]; + WIFI_TASK -> WIFI_TASK [label="..."]; + WIFI_TASK -> WIFI_TASK [label="2.x > 扫描信道 N"]; + EVENT_TASK <- WIFI_TASK [label="3.1 > WIFI_EVENT_SCAN_DONE"]; + APP_TASK <- EVENT_TASK [label="3.2 > WIFI_EVENT_SCAN_DONE"]; + } + + +上述场景中描述了全信道前端扫描过程。仅 station 模式支持前端扫描,该模式下 station 未连接任何 AP。前端扫描还是后端扫描完全由 Wi-Fi 驱动程序决定,应用程序无法配置这一模式。 + +详细描述: + +扫描配置阶段 +************************** + + - s1.1:如果默认的国家信息有误,调用函数 :cpp:func:`esp_wifi_set_country()` 进行配置。请参阅 :ref:`Wi-Fi 国家/地区代码 `。 + - s1.2:调用函数 :cpp:func:`esp_wifi_scan_start()` 配置扫描信息,可参阅 `扫描配置`_。该场景为全信道扫描,将 SSID/BSSID/channel 设置为 0 即可。 + + +Wi-Fi 驱动程序内部扫描阶段 +************************************** + + - s2.1:Wi-Fi 驱动程序切换至信道 1,此时的扫描类型为 WIFI_SCAN_TYPE_ACTIVE,同时发送一个 probe request。反之,Wi-Fi 将等待接收 AP beacon。Wi-Fi 驱动程序将在信道 1 停留一段时间。min/max 扫描时间中定义了 Wi-Fi 在信道 1 中停留的时间长短,默认为 120 ms。 + - s2.2:Wi-Fi 驱动程序跳转至信道 2,并重复进行 s2.1 中的步骤。 + - s2.3:Wi-Fi 驱动程序扫描最后的信道 N,N 的具体数值由步骤 s1.1 中配置的国家代码决定。 + +扫描完成后事件处理阶段 +********************************* + + - s3.1:当所有信道扫描全部完成后,将产生 :ref:`WIFI_EVENT_SCAN_DONE ` 事件。 + - s3.2:应用程序的事件回调函数告知应用程序任务已接收到 :ref:`WIFI_EVENT_SCAN_DONE ` 事件。调用函数 :cpp:func:`esp_wifi_scan_get_ap_num()` 获取在本次扫描中找到的 AP 数量。然后,分配出足够的条目,并调用函数 :cpp:func:`esp_wifi_scan_get_ap_records()` 获取 AP 记录。请注意,一旦调用 :cpp:func:`esp_wifi_scan_get_ap_records()`,Wi-Fi 驱动程序中的 AP 记录将被释放。但是,请不要在单个扫描完成事件中重复调用两次 :cpp:func:`esp_wifi_scan_get_ap_records()`。反之,如果扫描完成事件发生后未调用 :cpp:func:`esp_wifi_scan_get_ap_records()`,则 Wi-Fi 驱动程序中的 AP 记录不会被释放。因此,请务必确保调用函数 :cpp:func:`esp_wifi_scan_get_ap_records()`,且仅调用一次。 + +在所有信道上扫描全部 AP(后端) +++++++++++++++++++++++++++++++++++++++++ + +场景: + +.. seqdiag:: + :caption: 所有 Wi-Fi 信道的后端扫描 + :align: center + + seqdiag background-scan-all-channels { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 160; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + APP_TASK -> WIFI_TASK [label="1.1 > 配置国家代码"]; + APP_TASK -> WIFI_TASK [label="1.2 > 扫描配置"]; + WIFI_TASK -> WIFI_TASK [label="2.1 > 扫描信道 1"]; + WIFI_TASK -> WIFI_TASK [label="2.2 > 返回主信道 H"]; + WIFI_TASK -> WIFI_TASK [label="2.3 > 扫描信道 2"]; + WIFI_TASK -> WIFI_TASK [label="2.4 > 返回主信道 H"]; + WIFI_TASK -> WIFI_TASK [label="..."]; + WIFI_TASK -> WIFI_TASK [label="2.x-1 > 扫描信道 N"]; + WIFI_TASK -> WIFI_TASK [label="2.x > 返回主信道 H"]; + EVENT_TASK <- WIFI_TASK [label="3.1 > WIFI_EVENT_SCAN_DONE"]; + APP_TASK <- EVENT_TASK [label="3.2 > WIFI_EVENT_SCAN_DONE"]; + } + +上述场景为一次全信道后端扫描。与 `在所有信道中扫描全部 AP(前端)`_ 相比,全信道后端扫描的不同之处在于:在跳至下一个信道之前,Wi-Fi 驱动程序会先返回主信道停留 30 ms,以便 Wi-Fi 连接有一定的时间发送/接收数据。 + +在所有信道中扫描特定 AP ++++++++++++++++++++++++++++++++++++++++ + +场景: + +.. seqdiag:: + :caption: 扫描特定的 Wi-Fi 信道 + :align: center + + seqdiag scan-specific-channels { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 160; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + APP_TASK -> WIFI_TASK [label="1.1 > 配置国家代码"]; + APP_TASK -> WIFI_TASK [label="1.2 > 扫描配置"]; + WIFI_TASK -> WIFI_TASK [label="2.1 > 扫描信道 C1"]; + WIFI_TASK -> WIFI_TASK [label="2.2 > 扫描信道 C2"]; + WIFI_TASK -> WIFI_TASK [label="..."]; + WIFI_TASK -> WIFI_TASK [label="2.x > 扫描信道 CN,或找到 AP"]; + EVENT_TASK <- WIFI_TASK [label="3.1 > WIFI_EVENT_SCAN_DONE"]; + APP_TASK <- EVENT_TASK [label="3.2 > WIFI_EVENT_SCAN_DONE"]; + } + +该扫描过程与 `在所有信道中扫描全部 AP(前端)`_ 相似。区别在于: + + - s1.1:在步骤 1.2 中,目标 AP 将配置为 SSID/BSSID。 + - s2.1 ~ s2.N:每当 Wi-Fi 驱动程序扫描某个 AP 时,它将检查该 AP 是否为目标 AP。如果本次扫描类型为 ``WIFI_FAST_SCAN``,且确认已找到目标 AP,则将产生扫描完成事件,同时结束本次扫描;反之,扫描将继续。请注意,第一个扫描的信道可能不是信道 1,因为 Wi-Fi 驱动程序会优化扫描顺序。 + +如果有多个匹配目标 AP 信息的 AP,例如:碰巧扫描到两个 SSID 为 "ap" 的 AP。如果本次扫描类型为 ``WIFI_FAST_SCAN``,则仅可找到第一个扫描到的 "ap";如果本次扫描类型为 ``WIFI_ALL_CHANNEL_SCAN``,则两个 "ap“ 都将被找到,且 station 将根据配置规则连接至其需要连接的 "ap",请参阅 :ref:`Station 基本配置 `。 + +你可以在任意信道中扫描某个特定的 AP,或扫描该信道中的所有 AP。这两种扫描过程也较为相似。 + +.. _scan-in-wifi-connect: + +在 Wi-Fi 连接模式下扫描 ++++++++++++++++++++++++++ + +调用函数 :cpp:func:`esp_wifi_connect()` 后,Wi-Fi 驱动程序将首先尝试扫描已配置的 AP。Wi-Fi 连接模式下的扫描过程与 `在所有信道中扫描特定 AP`_ 过程相同,但连接模式下扫描结束后将不会产生扫描完成事件。如果已找到目标 AP,则 Wi-Fi 驱动程序将开始 Wi-Fi 连接;反之,将产生 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件。请参阅 `在所有信道中扫描特定 AP`_。 + +在阻塞模式下扫描 +++++++++++++++++++++ + +如果函数 :cpp:func:`esp_wifi_scan_start()` 中的 block 参数为 "true",则扫描将以阻塞模式进行,应用任务会被阻塞,直到扫描完成。阻塞模式下的扫描和正常扫描相似,不同之处在于,阻塞模式下扫描完成之后将不会触发扫描完成事件。 + +并行扫描 ++++++++++++++ + +有时,可能会有两个应用程序任务同时调用函数 :cpp:func:`esp_wifi_scan_start()`,或者某个应用程序任务在获取扫描完成事件之前再次调用了函数 :cpp:func:`esp_wifi_scan_start()`。这两种情况都有可能会发生。**但是,Wi-Fi 驱动程序并不足以支持多个并行的扫描。因此,应避免上述并行扫描**。随着 {IDF_TARGET_NAME} 的 Wi-Fi 功能不断提升,未来的版本中可能会增加并行扫描支持。 + +.. _scan-when-wifi-is-connecting: + +连接 Wi-Fi 时扫描 ++++++++++++++++++++++++++++++++ + +如果 Wi-Fi 正在连接,则调用函数 :cpp:func:`esp_wifi_scan_start()` 后扫描将立即失败,因为 Wi-Fi 连接优先级高于扫描。如果扫描是因为 Wi-Fi 连接而失败的,此时推荐采取的策略为:等待一段时间后重试。因为一旦 Wi-Fi 连接完成后,扫描将立即成功。 + +但是,延时重试策略并非万无一失。试想以下场景: + +- 如果 station 正在连接一个不存在的 AP,或正在使用错误的密码连接一个 AP,此时将产生事件 :ref:`WIFI_EVENT_STA_DISCONNECTED `。 +- 接收到断开连接事件后,应用程序调用函数 :cpp:func:`esp_wifi_connect()` 进行重新连接。 +- 而另一个应用程序任务(如,控制任务)调用了函数 :cpp:func:`esp_wifi_scan_start()` 进行扫描。这种情况下,每一次扫描都会立即失败,因为 station 一直处于正在连接状态。 +- 扫描失败后,应用程序将等待一段时间后进行重新扫描。 + +上述场景中的扫描永远不会成功,因为 Wi-Fi 一直处于正在连接过程中。因此,如果你的应用程序也可能发生相似的场景,那么就需要为其配置一个更佳的重新连接策略。例如: + +- 应用程序可以定义一个连续重新连接次数的最大值,当重新连接的次数达到这个最大值时,立刻停止重新连接。 +- 应用程序可以选择在前 N 次连续重连时立即进行重连,然后延迟一段时间后再次尝试重连。 + +可以给应用程序定义其特殊的重新连接策略,以防止扫描无法成功。请参阅 :ref:`Wi-Fi 重新连接 `。 + +.. _wifi-station-connecting-scenario: + +{IDF_TARGET_NAME} Wi-Fi Station 连接场景 +------------------------------------------------------------ + +该场景仅针对在扫描阶段只找到一个目标 AP 的情况,对于多个相同 SSID AP 的情况,请参阅 :ref:`{IDF_TARGET_NAME} Wi-Fi Station 在发现多个 AP 时的连接策略 `。 + +通常,应用程序无需关心这一连接过程。如感兴趣,可参看下述简介。 + +场景: + +.. seqdiag:: + :caption: Wi-Fi station 连接过程 + :align: center + + seqdiag station-connecting-process { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 160; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + EVENT_TASK [label = "Event\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + AP [label = "AP"]; + + === 1. 扫描阶段 === + WIFI_TASK -> WIFI_TASK [label="1.1 > 扫描"]; + EVENT_TASK <- WIFI_TASK [label="1.2 > WIFI_EVENT_STA_DISCONNECTED"]; + === 2. 认证阶段 === + WIFI_TASK -> AP [label="2.1 > Auth request"]; + EVENT_TASK <- WIFI_TASK [label="2.2 > WIFI_EVENT_STA_DISCONNECTED"]; + WIFI_TASK <- AP [label="2.3 > Auth response"]; + EVENT_TASK <- WIFI_TASK [label="2.4 > WIFI_EVENT_STA_DISCONNECTED"]; + === 3. 关联阶段 === + WIFI_TASK -> AP [label="3.1 > Assoc request"]; + EVENT_TASK <- WIFI_TASK [label="3.2 > WIFI_EVENT_STA_DISCONNECTED"]; + WIFI_TASK <- AP [label="3.3 > Assoc response"]; + EVENT_TASK <- WIFI_TASK [label="3.4 > WIFI_EVENT_STA_DISCONNECTED"]; + === 4. 四次握手阶段 === + EVENT_TASK <- WIFI_TASK [label="4.1 > WIFI_EVENT_STA_DISCONNECTED"]; + WIFI_TASK <- AP [label="4.2 > 1/4 EAPOL"]; + WIFI_TASK -> AP [label="4.3 > 2/4 EAPOL"]; + EVENT_TASK <- WIFI_TASK [label="4.4 > WIFI_EVENT_STA_DISCONNECTED"]; + WIFI_TASK <- AP [label="4.5 > 3/4 EAPOL"]; + WIFI_TASK -> AP [label="4.6 > 4/4 EAPOL"]; + EVENT_TASK <- WIFI_TASK [label="4.7 > WIFI_EVENT_STA_CONNECTED"]; + } + + +扫描阶段 ++++++++++++++++++++++ + + - s1.1:Wi-Fi 驱动程序开始在“Wi-Fi 连接”模式下扫描。详细信息请参阅 :ref:`在 Wi-Fi 连接模式下扫描 `。 + - s1.2:如果未找到目标 AP,将产生 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件,原因代码可能为 ``WIFI_REASON_NO_AP_FOUND``、``WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY``、``WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD`` 或 ``WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD``, 具体取决于 station 的配置。请参阅 `Wi-Fi 原因代码`_。 + +认证阶段 ++++++++++++++++++++++ + + - s2.1:发送认证请求数据包并使能认证计时器。 + - s1.2:如果在认证计时器超时之前未接收到认证响应数据包,将产生 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件,且原因代码为 ``WIFI_REASON_AUTH_EXPIRE``。请参阅 `Wi-Fi 原因代码`_。 + - s2.3:接收到认证响应数据包,且认证计时器终止。 + - s2.4:AP 在响应中拒绝认证且产生 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件,原因代码为 ``WIFI_REASON_AUTH_FAIL`` 或为 AP 指定的其它原因。请参阅 `Wi-Fi 原因代码`_。 + +关联阶段 ++++++++++++++++++++++ + + - s3.1:发送关联请求并使能关联计时器。 + - s3.2:如果在关联计时器超时之前未接收到关联响应,将产生 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件,且原因代码为 ``WIFI_REASON_DISASSOC_DUE_TO_INACTIVITY``。请参阅 `Wi-Fi 原因代码`_。 + - s3.3:接收到关联响应,且关联计时器终止。 + - s3.4:AP 在响应中拒绝关联且产生 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件,原因代码将在关联响应中指定。请参阅 `Wi-Fi 原因代码`_。 + + +四次握手阶段 +++++++++++++++++++++++++++ + + - s4.1:使能握手定时器,定时器终止之前未接收到 1/4 EAPOL,此时将产生 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件,且原因代码为 ``WIFI_REASON_HANDSHAKE_TIMEOUT``。请参阅 `Wi-Fi 原因代码`_。 + - s4.2:接收到 1/4 EAPOL。 + - s4.3:station 回复 2/4 EAPOL。 + - s4.4:如果在握手定时器终止之前未接收到 3/4 EAPOL,将产生 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件,且原因代码为 ``WIFI_REASON_HANDSHAKE_TIMEOUT``。请参阅 `Wi-Fi 原因代码`_。 + - s4.5:接收到 3/4 EAPOL。 + - s4.6:station 回复 4/4 EAPOL。 + - s4.7:station 产生 :ref:`WIFI_EVENT_STA_CONNECTED ` 事件。 + + +.. _esp_wifi_reason_code: + +Wi-Fi 原因代码 ++++++++++++++++++++++ + +下表罗列了 {IDF_TARGET_NAME} 中定义的原因代码。其中,第一列为 :component_file:`esp_wifi/include/esp_wifi_types.h` 中定义的宏名称。名称中省去了前缀 ``WIFI_REASON``,也就是说,名称 ``UNSPECIFIED`` 实际应为 ``WIFI_REASON_UNSPECIFIED``,以此类推。第二列为原因代码的相应数值,该数值与 IEEE 802.11-2020 第 9.4.1.7 节中的定义一致 。(更多详细信息,请参阅前文描述。)最后一列为原因的描述。原因代码从 200 开始为乐鑫自定义的原因代码,这些代码不属于 IEEE 802.11-2020 标准的一部分。 + +另请注意,REASON_NO_AP_FOUND_XXX 代码按照重要性递增排列。因此,如果单个接入点(AP)因上述多种原因而导致连接失败,则会报告其中较为重要的原因代码。此外,如果有多个接入点满足标识条件,但它们因上述不同原因均连接失败,则报告的原因代码是因最不重要的原因代码而导致连接失败的接入点的代码,因为这是最接近成功连接的情况。 + +以下原因代码被重命名为较短的形式以适应表格页面宽度: + +- TRANSMISSION_LINK_ESTABLISHMENT_FAILED : TX_LINK_EST_FAILED +- NO_AP_FOUND_W_COMPATIBLE_SECURITY : NO_AP_FOUND_SECURITY +- NO_AP_FOUND_IN_AUTHMODE_THRESHOLD : NO_AP_FOUND_AUTHMODE +- NO_AP_FOUND_IN_RSSI_THRESHOLD : NO_AP_FOUND_RSSI + +.. list-table:: + :header-rows: 1 + :widths: 41 10 49 + :class: longtable + + * - 原因代码 + - 数值 + - 描述 + * - UNSPECIFIED + - 1 + - 出现内部错误,例如:内存已满,内部发送失败,或该原因已被远端接收等。 + * - AUTH_EXPIRE + - 2 + - 先前的 authentication 已失效。 + + 对于 ESP station,出现以下情况时将报告该代码: + + - authentication 超时; + - 从 AP 接收到该代码。 + + 对于 ESP AP,出现以下情况时将报告该代码: + + - 在过去五分钟之内,AP 未从 station 接收到任何数据包; + - 由于调用了函数 :cpp:func:`esp_wifi_stop()` 导致 AP 终止; + - 由于调用了函数 :cpp:func:`esp_wifi_deauth_sta()` 导致 station 的 authentication 取消。 + * - AUTH_LEAVE + - 3 + - authentication 取消,因为发送端 station 正在离开(或已经离开)。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + * - DISASSOC_DUE_TO_INACTIVITY + - 4 + - 因为 AP 不活跃,association 取消。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 关联超时。 + - 从 AP 接收到该代码。 + + * - ASSOC_TOOMANY + - 5 + - association 取消,因为 AP 无法同时处理所有当前已关联的 STA。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + + 对于 ESP AP,出现以下情况时将报告该代码: + + - 与 AP 相关联的 station 数量已到达 AP 可支持的最大值。 + * - CLASS2_FRAME_FROM_NONAUTH_STA + - 6 + - 从一个未认证 station 接收到 class-2 frame。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + + 对于 ESP AP,出现以下情况时将报告该代码: + + - AP 从一个未认证 station 接收到数据包。 + * - CLASS3_FRAME_FROM_NONASSOC_STA + - 7 + - 从一个未关联 station 接收到的 class-3 frame。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + + 对于 ESP AP,出现以下情况时将报告该代码: + + - AP 从未关联 station 接收到数据包。 + * - ASSOC_LEAVE + - 8 + - association 取消,因为发送端 station 正在离开(或已经离开)BSS。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + - 由于调用 :cpp:func:`esp_wifi_disconnect()` 和其它 API,station 断开连接。 + * - ASSOC_NOT_AUTHED + - 9 + - station 的 re(association) 请求未被响应 station 认证。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + + 对于 ESP AP,出现以下情况时将报告该代码: + + - AP 从一个已关联,但未认证的 station 接收到数据包。 + * - DISASSOC_PWRCAP_BAD + - 10 + - association 取消,因为无法接收功率能力 (Power Capability) 元素中的信息。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + * - DISASSOC_SUPCHAN_BAD + - 11 + - association 取消,因为无法接收支持的信道 (Supported Channels) 元素中的信息。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + * - BSS_TRANSITION_DISASSOC + - 12 + - AP 希望切换到另一个 AP,作为 BTM 过程的一部分发送。请注意,当 station 发送 BTM 请求并切换到另一个 AP 时,将报告 ROAMING 原因代码,而不是此代码。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + * - IE_INVALID + - 13 + - 无效元素,即内容不符合 Wi-Fi 协议中帧格式 (Frame formats) 章节所描述标准的元素。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + + 对于 ESP AP,出现以下情况时将报告该代码: + + - AP 解析了一个错误的 WPA 或 RSN IE。 + * - MIC_FAILURE + - 14 + - 消息完整性代码 (MIC) 出错。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + * - 4WAY_HANDSHAKE_TIMEOUT + - 15 + - 四次握手超时。由于某些历史原因,在 ESP 中该原因代码实为 ``WIFI_REASON_HANDSHAKE_TIMEOUT``。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 握手超时。 + - 从 AP 接收到该代码。 + * - GROUP_KEY_UPDATE_TIMEOUT + - 16 + - 组密钥 (Group-Key) 握手超时。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + * - IE_IN_4WAY_DIFFERS + - 17 + - 四次握手中产生的元素与 (re-)association 后的 request/probe 以及 response/beacon frame 中的信息不同。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + - station 发现四次握手的 IE 与 (re-)association 后的 request/probe 以及 response/beacon frame 中的 IE 不同。 + * - GROUP_CIPHER_INVALID + - 18 + - 无效组密文。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + * - PAIRWISE_CIPHER_INVALID + - 19 + - 无效成对密文。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + * - AKMP_INVALID + - 20 + - 无效 AKMP。 + + 对于 ESP station,出现以下情况时报告该代码: + - 从 AP 接收到该代码。 + * - UNSUPP_RSN_IE_VERSION + - 21 + - 不支持的 RSNE 版本。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + * - INVALID_RSN_IE_CAP + - 22 + - 无效的 RSNE 性能。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + * - 802_1X_AUTH_FAILED + - 23 + - IEEE 802.1X. authentication 失败。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + + 对于 ESP AP,出现以下情况时将报告该代码: + + - IEEE 802.1X. authentication 失败。 + * - CIPHER_SUITE_REJECTED + - 24 + - 因安全策略,安全密钥算法套件 (cipher suite) 被拒。 + + 对于 ESP station,出现以下情况时报告该代码: + + - 从 AP 接收到该代码。 + * - TDLS_PEER_UNREACHABLE + - 25 + - 通过 TDLS 直连无法到达 TDLS 对端 STA,导致 TDLS 直连中断。 + * - TDLS_UNSPECIFIED + - 26 + - 不明原因的 TDLS 直连中断。 + * - SSP_REQUESTED_DISASSOC + - 27 + - association 取消,由于会话被 SSP request 终止。 + * - NO_SSP_ROAMING_AGREEMENT + - 28 + - association 取消,由于缺乏 SSP 漫游认证。 + * - BAD_CIPHER_OR_AKM + - 29 + - 请求的服务被拒绝,由于 SSP 密码套件或者 AKM 的需求。 + * - NOT_AUTHORIZED_THIS_LO CATION + - 30 + - 请求的服务在此位置未得到授权。 + * - SERVICE_CHANGE_PRECLUDES_TS + - 31 + - TS 被删除,原因是:BSS 服务特性或者运行模式改变导致 Qos AP 缺少足够的带宽给 Qos STA 使用(例如:一个HT BSS 从 40 MHz 的信道切换到 20 MHz 的信道)。 + * - UNSPECIFIED_QOS + - 32 + - association 取消,由于不明确的 QoS 相关原因。 + * - NOT_ENOUGH_BANDWIDTH + - 33 + - association 取消,由于 QoS AP 缺少足够的带宽给该 QoS STA 使用。 + * - MISSING_ACKS + - 34 + - association 取消,原因是:大量的帧需要被确认,但由于 AP 传输或者糟糕的信道条件而没有被确认。 + * - EXCEEDED_TXOP + - 35 + - association 取消,由于 STA 的传输超过了 TXOPs 的限制。 + * - STA_LEAVING + - 36 + - 请求 STA 离开了 BSS 或者重置了。 + * - END_BA + - 37 + - 请求 STA 不再使用该流或者会话。 + * - UNKNOWN_BA + - 38 + - 请求 STA 使用一种尚未完成的机制接收帧。 + * - TIMEOUT + - 39 + - 对端 STA 的请求超时。 + * - Reserved + - 40 ~ 45 + - 根据 IEEE 802.11-2020 协议保留。 + * - PEER_INITIATED + - 46 + - 在 Disassociation 帧中:已达到授权访问限制。 + * - AP_INITIATED + - 47 + - 在 Disassociation 帧中:外部服务需求。 + * - INVALID_FT_ACTION_FRAME_COUNT + - 48 + - 无效的 FT Action 帧计数。 + * - INVALID_PMKID + - 49 + - 无效的成对主密钥标识符(PMKID)。 + * - INVALID_MDE + - 50 + - 无效的 MDE。 + * - INVALID_FTE + - 51 + - 无效的 FTE。 + * - TX_LINK_EST_FAILED + - 67 + - 在备用信道中建立传输链路失败。 + * - ALTERATIVE_CHANNEL_OCCUPIED + - 68 + - 备用信道被占用。 + * - BEACON_TIMEOUT + - 200 + - 乐鑫特有的 Wi-Fi 原因代码: 当 station 连续失去 N 个 beacon,将中断连接并报告该代码。 + * - NO_AP_FOUND + - 201 + - 乐鑫特有的 Wi-Fi 原因代码: 当 station 未扫描到目标 AP 时,将报告该代码。 + * - AUTH_FAIL + - 202 + - 乐鑫特有的 Wi-Fi 原因代码: authentication 失败,但并非由超时而引发。 + * - ASSOC_FAIL + - 203 + - 乐鑫特有的 Wi-Fi 原因代码: association 失败,但并非由 DISASSOC_DUE_TO_INACTIVITY 或 ASSOC_TOOMANY 引发。 + * - HANDSHAKE_TIMEOUT + - 204 + - 乐鑫特有的 Wi-Fi 原因代码: 握手失败,与 WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT 中失败原因相同。 + * - CONNECTION_FAIL + - 205 + - 乐鑫特有的 Wi-Fi 原因代码: AP 连接失败。 + * - AP_TSF_RESET + - 206 + - 乐鑫特有的 Wi-Fi 原因代码:由于 AP 的 TSF 重置导致断开连接。 + * - ROAMING + - 207 + - 乐鑫特有的 Wi-Fi 原因代码:station 正在漫游到另一个 AP,此原因代码仅供参考,station 将自动切换到另一个 AP。 + * - ASSOC_COMEBACK_TIME_TOO_LONG + - 208 + - 乐鑫特有的 Wi-Fi 原因代码:当关联响应中的 Assoc 回来时间过长时,将报告此原因代码。 + * - SA_QUERY_TIMEOUT + - 209 + - 乐鑫特有的 Wi-Fi 原因代码:当 ESP station 发送的 SA 查询未收到 AP 的回复时,将报告此原因代码。 + * - NO_AP_FOUND_SECURITY + - 210 + - 乐鑫特有的 Wi-Fi 原因代码:当找到符合标识条件(例如 SSID)的 AP,但由于安全配置不兼容导致连接被拒绝时,将报告 NO_AP_FOUND_W_COMPATIBLE_SECURITY。可能的情况包括: + + - 接入点提供 WEP 安全性,但 station 密码不符合 WEP 要求。 + - station 配置为开放模式,但接入点以安全模式广播。 + - 接入点使用企业安全性,但我们未设置相应的企业配置,反之亦然。 + - station 配置为 SAE-PK,但接入点不支持 SAE-PK。 + - station 配置为 SAE-H2E,但 AP 仅支持 WPA3-PSK 或 WPA3-WPA2-PSK。 + - station 配置为安全模式(密码或企业模式),但扫描中找到的 AP 是开放模式。 + - station 配置为 SAE HnP,但 AP 仅支持 H2E。 + - station 禁用 H2E,但 AP 是 WPA3-EXT-PSK,需支持 H2E。 + - 接入点需要 PMF,但 station 未配置为支持 PMF。 + - station 要求 PMF,但接入点未配置为支持 PMF。 + - 接入点使用不支持的组管理/对等加密算法。 + - station 未启用 OWE,但发现的 AP 使用 OWE 模式。 + - 接入点在信标中广播了无效的 RSNXE 信息。 + - 接入点处于独立 BSS 模式。 + + * - NO_AP_FOUND_AUTHMODE + - 211 + - 乐鑫特有的 Wi-Fi 原因代码:当找到符合标识条件(例如 SSID)的 AP,但未满足 wifi_config_t 中设置的身份验证模式阈值时,将报告 NO_AP_FOUND_IN_AUTHMODE_THRESHOLD。 + * - NO_AP_FOUND_RSSI + - 212 + - 乐鑫特有的 Wi-Fi 原因代码:当找到符合标识条件(例如 SSID)的 AP,但未满足 wifi_config_t 中设置的 RSSI 阈值时,将报告 NO_AP_FOUND_IN_RSSI_THRESHOLD。 + +与密码错误有关的 Wi-Fi 原因代码 ++++++++++++++++++++++++++++++++++ + +下表罗列了与密码错误相关的 Wi-Fi 原因代码。 + +.. list-table:: + :header-rows: 1 + :widths: 5 10 40 + + * - 原因代码 + - 数值 + - 描述 + * - 4WAY_HANDSHAKE_TIMEOUT + - 15 + - 四次握手超时。STA 在连接加密的 AP 的时候设置了错误的密码。 + * - NO_AP_FOUND + - 201 + - 这可能与以下两种场景中的密码错误有关: + + - STA 连接到未加密的 AP 时设置了密码。 + - STA 连接到加密的 AP 时未设置密码。 + * - HANDSHAKE_TIMEOUT + - 204 + - 四次握手失败。 + +与低 RSSI 有关的 Wi-Fi 原因代码 ++++++++++++++++++++++++++++++++++ + +下表罗列了与低 RSSI 相关的 Wi-Fi 原因代码。 + +.. list-table:: + :header-rows: 1 + :widths: 5 10 40 + + * - 原因代码 + - 数值 + - 描述 + * - NO_AP_FOUND_IN_RSSI_THRESHOLD + - 212 + - 低 RSSI 导致 station 无法扫描到目标 AP + * - HANDSHAKE_TIMEOUT + - 204 + - 四次握手失败。 + +.. _wifi-station-connecting-when-multiple-aps-are-found: + +{IDF_TARGET_NAME} Wi-Fi Station 在发现多个 AP 时的连接策略 +---------------------------------------------------------------------- + +该场景与 :ref:`{IDF_TARGET_NAME} Wi-Fi Station 连接场景 ` 相似,不同之处在于该场景中不会产生 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件,除非 station 无法连接所有找到的 AP。 + +.. _wifi-reconnect: + +Wi-Fi 重新连接 +--------------------------- + +出于多种原因,station 可能会断开连接,例如:连接的 AP 重新启动等。应用程序应负责重新连接。推荐使用的方法为:在接收到 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件后调用函数 :cpp:func:`esp_wifi_connect()`。 + +但有时,应用程序需要更复杂的方式进行重新连接: + +- 如果断开连接事件是由调用函数 :cpp:func:`esp_wifi_disconnect()` 引发的,那么应用程序可能不希望进行重新连接。 +- 如果 station 随时可能调用函数 :cpp:func:`esp_wifi_scan_start()` 开始扫描,此时就需要一个更佳的重新连接方法,请参阅 :ref:`连接 Wi-Fi 时扫描 `。 + +另一点需要注意的是,如果存在多个具有相同 SSID 的 AP,那么重新连接后可能不会连接到之前的同一个 AP。重新连接时,station 将永远选择最佳的 AP 进行连接。 + +Wi-Fi beacon 超时 +--------------------------- + +{IDF_TARGET_NAME} 使用 beacon 超时机制检测 AP 是否活跃。如果 station 在 inactive 时间内未收到所连接 AP 的 beacon,将发生 beacon 超时。inactive 时间通过调用函数 :cpp:func:`esp_wifi_set_inactive_time()` 设置。 + +beacon 超时发生后,station 将向 AP 发送 5 个 probe request,如果仍未从 AP 接收到 probe response 或 beacon,station 将与 AP 断开连接并产生 :ref:`WIFI_EVENT_STA_DISCONNECTED ` 事件。 + +需要注意的是,扫描过程中会重置 beacon 超时所使用的定时器,即扫描过程会影响 :ref:`WIFI_EVENT_STA_BEACON_TIMEOUT ` 事件的触发。 diff --git a/docs/zh_CN/api-guides/wifi-driver/wifi-mac-protocols.rst b/docs/zh_CN/api-guides/wifi-driver/wifi-mac-protocols.rst new file mode 100644 index 0000000000..950a0c4472 --- /dev/null +++ b/docs/zh_CN/api-guides/wifi-driver/wifi-mac-protocols.rst @@ -0,0 +1,94 @@ +Wi-Fi MAC 协议 +========================== + +:link_to_translation:`en:[English]` + +Wi-Fi HT20/40 +------------------------- + +.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 or esp32c6 or esp32c5 + + {IDF_TARGET_NAME} 支持 Wi-Fi 带宽 HT20 或 HT40,不支持 HT20/40 共存,调用函数 :cpp:func:`esp_wifi_set_bandwidth()` 可改变 station/AP 的默认带宽。{IDF_TARGET_NAME} station 和 AP 的默认带宽为 HT40。 + + station 模式下,实际带宽首先在 Wi-Fi 连接时协商。只有当 station 和所连 AP 都支持 HT40 时,带宽才为 HT40,否则为 HT20。如果所连的 AP 的带宽发生变化,则在不断开 Wi-Fi 连接的情况下再次协商实际带宽。 + + 同样,在 AP 模式下,在 AP 与所连 station 协商实际带宽。如果 AP 和其中一个 station 支持 HT40, 则为 HT40, 否则为 HT20。 + + 在 station/AP 共存模式下,station 和 AP 都可独立配置为 HT20/40。如果 station 和 AP 都协商为 HT40,由于 {IDF_TARGET_NAME} 中,station 的优先级总高于 AP,HT40 信道是 station 的信道。例如,AP 的配置带宽为 HT40,配置的主信道为 6,配置的辅助信道为 10。如果,station 所连路由器的主信道为 6、辅助信道为 2,AP 的实际信道将自动更改为主 6 和辅 2。 + + 理论上,HT40 可以获得更大的吞吐量,因为 HT40 的最大原始 PHY 数据速率为 150 Mbps,而 HT20 为 72 Mbps。但是,如果设备在某些特殊环境中使用,例如,{IDF_TARGET_NAME} 周围其他 Wi-Fi 设备过多,HT40 的性能可能会降低。因此,如果应用程序需要支持相同或类似的情况,建议始终将带宽配置为 HT20。 + +.. only:: esp32c5 + + .. note:: + + 当工作在 2.4 GHz + 5 GHz 频段模式(``WIFI_BAND_MODE_AUTO``)时,需要使用函数: :cpp:func:`esp_wifi_set_bandwidths()` 分别设置 2.4 GHz 频段 和 5 GHz 频段的带宽。 + + +.. only:: esp32c2 + + {IDF_TARGET_NAME} 仅支持 Wi-Fi 带宽 HT20,不支持 Wi-Fi 带宽 HT40 或 HT20/40 共存。 + +Wi-Fi QoS +------------------------- + +{IDF_TARGET_NAME} 支持 WFA Wi-Fi QoS 认证所要求的所有必备功能。 + +Wi-Fi 协议中定义了四个 AC(访问类别),每个 AC 有各自的优先级访问 Wi-Fi 信道。此外,还定义了映射规则以映射其他协议的 QoS 优先级,例如 802.11D 或 TCP/IP 到 Wi-Fi AC。 + +下表描述 {IDF_TARGET_NAME} 中 IP 优先级如何映射到 Wi-Fi AC,还指明此 AC 是否支持 AMPDU。该表按优先级降序排列,即 AC_VO 拥有最高优先级。 + ++-----------+---------------------+----------------+ +| IP 优先级 | Wi-Fi AC | 是否支持 AMPDU | ++===========+=====================+================+ +| 6, 7 | AC_VO (Voice) | 否 | ++-----------+---------------------+----------------+ +| 4, 5 | AC_VI (Video) | 是 | ++-----------+---------------------+----------------+ +| 3, 0 | AC_BE (Best Effort) | 是 | ++-----------+---------------------+----------------+ +| 1, 2 | AC_BK (Background) | 是 | ++-----------+---------------------+----------------+ + +应用程序可以通过套接字选项 IP_TOS 配置 IP 优先级使用 QoS 功能。下面是使套接字使用 VI 队列的示例:: + + const int ip_precedence_vi = 4; + const int ip_precedence_offset = 5; + int priority = (ip_precedence_vi << ip_precedence_offset); + setsockopt(socket_id, IPPROTO_IP, IP_TOS, &priority, sizeof(priority)); + +理论上,高优先级的 AC 比低优先级 AC 具有更好的性能,但并非总是如此,下面是一些关于如何使用 Wi-Fi QoS 的建议: + + - 可以把一些真正重要的应用程序流量放到 AC_VO 队列中。避免通过 AC_VO 队列发送大流量。一方面,AC_VO 队列不支持 AMPDU,如果流量很大,性能不会优于其他队列。另一方面,可能会影响同样使用 AC_VO 队列的管理帧。 + - 避免使用 AMPDU 支持的、两个以上的不同优先级,比如 socket A 使用优先级 0,socket B 使用优先级 1,socket C 使用优先级 2。因为可能需要更多的内存,不是好的设计。具体来说,Wi-Fi 驱动程序可能会为每个优先级生成一个 Block Ack 会话,如果设置了 Block Ack 会话,则需要更多内存。 + + +Wi-Fi AMPDU +-------------------- + +{IDF_TARGET_NAME} 同时支持接收和发送 AMPDU,AMPDU 可以大大提高 Wi-Fi 的吞吐量。 + +通常,应使能 AMPDU。禁用 AMPDU 通常用于调试目的。 + + +Wi-Fi AMSDU +------------------------- + +.. only:: not SOC_SPIRAM_SUPPORTED + + {IDF_TARGET_NAME} 支持接收 AMSDU。 + +.. only:: SOC_SPIRAM_SUPPORTED + + {IDF_TARGET_NAME} 支持接收和发送 AMSDU。开启 AMSDU 发送比较消耗内存,默认不开启 AMSDU 发送。可通过选项 :ref:`CONFIG_ESP_WIFI_AMSDU_TX_ENABLED` 使能 AMSDU 发送功能, 但是使能 AMSDU 发送依赖于 :ref:`CONFIG_SPIRAM` 。 + +Wi-Fi 分片 +------------------------- + +.. only:: not SOC_WIFI_TXOP_SUPPORT + + {IDF_TARGET_NAME} 支持 Wi-Fi 接收分片,但不支持 Wi-Fi 发送分片。 + +.. only:: SOC_WIFI_TXOP_SUPPORT + + {IDF_TARGET_NAME} 支持 Wi-Fi 接收和发送分片。 diff --git a/docs/zh_CN/api-guides/wifi-driver/wifi-modes.rst b/docs/zh_CN/api-guides/wifi-driver/wifi-modes.rst new file mode 100644 index 0000000000..01772db731 --- /dev/null +++ b/docs/zh_CN/api-guides/wifi-driver/wifi-modes.rst @@ -0,0 +1,100 @@ +Wi-Fi 模式 +=============== + +:link_to_translation:`en:[English]` + +.. _wifi-ap-general-scenario: + +{IDF_TARGET_NAME} Wi-Fi AP 通用场景 +--------------------------------------------- + +下图为 AP 模式下的宏观场景,其中包含不同阶段的具体描述: + + .. seqdiag:: + :caption: AP 模式下 Wi-Fi 事件场景示例 + :align: center + + seqdiag sample-scenarios-soft-ap-mode { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 140; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + MAIN_TASK [label = "Main\ntask"]; + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + LwIP_TASK [label = "LwIP\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + === 1. 初始化阶段 === + MAIN_TASK -> LwIP_TASK [label="1.1> 创建/初始化 LwIP"]; + MAIN_TASK -> EVENT_TASK [label="1.2> 创建/初始化事件"]; + MAIN_TASK -> WIFI_TASK [label="1.3> 创建/初始化 Wi-Fi"]; + MAIN_TASK -> APP_TASK [label="1.4> 创建应用程序任务"]; + === 2. 配置阶段 === + MAIN_TASK -> WIFI_TASK [label="2> 配置 Wi-Fi"]; + === 3. 启动阶段 === + MAIN_TASK -> WIFI_TASK [label="3.1> 启动 Wi-Fi"]; + EVENT_TASK <- WIFI_TASK [label="3.2> WIFI_EVENT_AP_START"]; + APP_TASK <- EVENT_TASK [label="3.3> WIFI_EVENT_AP_START"]; + === 4. 连接阶段 === + EVENT_TASK <- WIFI_TASK [label="4.1> WIFI_EVENT_AP_STACONNECTED"]; + APP_TASK <- EVENT_TASK [label="4.2> WIFI_EVENT_AP_STACONNECTED"]; + === 5. 断开阶段 === + EVENT_TASK <- WIFI_TASK [label="5.1> WIFI_EVENT_AP_STADISCONNECTED"]; + APP_TASK <- EVENT_TASK [label="5.2> WIFI_EVENT_AP_STADISCONNECTED"]; + APP_TASK -> APP_TASK [label="5.3> 断开处理"]; + === 6. 清理阶段 === + APP_TASK -> WIFI_TASK [label="6.1> 断开 Wi-Fi 连接"]; + APP_TASK -> WIFI_TASK [label="6.2> 终止 Wi-Fi"]; + APP_TASK -> WIFI_TASK [label="6.3> 清理 Wi-Fi"]; + } + + +Wi-Fi Sniffer 模式 +--------------------------- + +Wi-Fi Sniffer 模式可以通过 :cpp:func:`esp_wifi_set_promiscuous()` 使能。如果使能 Sniffer 模式, **可以** 向应用程序转储以下数据包。 + + - 802.11 管理帧 + - 802.11 数据帧,包括 MPDU、AMPDU、AMSDU 等 + - 802.11 MIMO 帧,Sniffer 模式仅转储 MIMO 帧的长度。 + - 802.11 控制帧 + - 802.11 CRC 错误帧 + +**不可以** 向应用程序转储以下数据包。 + + - 802.11 其它错误帧 + +对于 Sniffer 模式 **可以** 转储的帧,应用程序可以另外使用 :cpp:func:`esp_wifi_set_promiscuous_filter()` 和 :cpp:func:`esp_wifi_set_promiscuous_ctrl_filter()` 决定筛选哪些特定类型的数据包。应用程序默认筛选所有 802.11 数据和管理帧。如果你想要筛选 802.11 控制帧,:cpp:func:`esp_wifi_set_promiscuous_filter()` 中的 filter 参数需要包含 “WIFI_PROMIS_FILTER_MASK_CTRL” 类型, 如果你想进一步区分 802.11 控制帧,那么调用 :cpp:func:`esp_wifi_set_promiscuous_ctrl_filter()`。 + +可以在 WIFI_MODE_NULL、WIFI_MODE_STA、WIFI_MODE_AP、WIFI_MODE_APSTA 等 Wi-Fi 模式下使能 Wi-Fi Sniffer 模式。也就是说,当 station 连接到 AP,或者 AP 有 Wi-Fi 连接时,就可以使能。请注意,Sniffer 模式对 station/AP Wi-Fi 连接的吞吐量有 **很大影响**。通常,除非有特别原因,当 station/AP Wi-Fi 连接出现大量流量,不应使能。 + +该模式下还应注意回调函数 :cpp:type:`wifi_promiscuous_cb_t` 的使用。该回调将直接在 Wi-Fi 驱动程序任务中进行,所以如果应用程序需处理大量过滤的数据包,建议在回调中向应用程序任务发布一个事件,把真正的工作推迟到应用程序任务中完成。 + + +.. only:: SOC_WIFI_NAN_SUPPORT + + Wi-Fi Aware\ :sup:`TM` (NAN) + ---------------------------- + + Wi-Fi Aware\ :sup:`TM` 或 NAN,即 Neighbor Awareness Networking (邻居感知网络,下文简称 NAN) 协议可以让 Wi-Fi 设备发现附近的其他设备。NAN 使用设备间直接通信,无需通过互联网或 AP 连接。 + + 多个邻近的 NAN 设备组成一个 NAN 集群,集群中的设备可相互通信。同一集群中的 NAN 设备会同步时钟,并定期在信道 6 上互相监听。NAN 设备还可通过服务发现协议,在所处集群内提供(发布)或获取(订阅)服务。通过服务名称和匹配过滤器(可选),可以完成服务匹配。当订阅设备匹配到发布设备时,就可以发送信息(跟进)或与发布设备建立数据通路 (NDP)。NDP 建立后,订阅设备和发布设备都会获得一个 IPv6 地址用于通信。 + + 注意,数据包发送是不加密的,无法保证 NDP 的安全性。NAN 为发现 (Discovery) 和数据通路单独的接口,该接口与 STA 和 AP 所用的接口不同。NAN 以独立模式运行,不支持与 STA 或 AP 接口共存。 + + 要了解如何设置 NAN 发布设备和订阅设备,请参考 ESP-IDF 示例::idf_file:`examples/wifi/wifi_aware/nan_publisher/README.md` 和 :idf_file:`examples/wifi/wifi_aware/nan_subscriber/README.md`。 + + + 非同步服务发现 (USD) + --------------------------- + + 非同步服务发现 (USD) 是一种机制,可让设备在新的设备进入射频环境时发现其提供的可用服务,而无需设备之间进行同步。 + + USD 通过发布 (Publish) 及跟进消息 (Follow-up message) 中的 SDEA 的服务信息 (Service Info) 字段来传递服务相关信息。 + + 要了解如何设置 NAN-USD 发布设备和订阅设备,请参考 ESP-IDF 示例::idf_file:`examples/wifi/wifi_aware/usd_publisher/README.md` 和 :idf_file:`examples/wifi/wifi_aware/usd_subscriber/README.md`。 diff --git a/docs/zh_CN/api-guides/wifi-driver/wifi-performance-and-power-save.rst b/docs/zh_CN/api-guides/wifi-driver/wifi-performance-and-power-save.rst new file mode 100644 index 0000000000..c35e754d8c --- /dev/null +++ b/docs/zh_CN/api-guides/wifi-driver/wifi-performance-and-power-save.rst @@ -0,0 +1,1646 @@ +Wi-Fi 性能与节能 +===================== + +:link_to_translation:`en:[English]` + +.. _wifi-buffer-usage: + +Wi-Fi 缓冲区使用情况 +-------------------------- + +本节只介绍动态缓冲区配置。 + +缓冲区配置的重要性 ++++++++++++++++++++++++++++++++++++++++ + +为了获得一个具有强健、高性能的系统,我们需要非常谨慎地考虑内存的使用或配置情况,因为: + + - {IDF_TARGET_NAME} 的可用内存有限。 + - 目前,LwIP 和 Wi-Fi 驱动程序中默认的缓冲区类型是“动态”,**意味着 LwIP 和 Wi-Fi 都与应用程序共享内存**。程序员应该时刻牢记这一点,否则将面临如“堆内存耗尽”等的内存问题。 + - “堆耗尽”情况非常危险,会导致 {IDF_TARGET_NAME} 出现“未定义行为”。因此,应该为应用程序预留足够的堆内存,防止耗尽。 + - Wi-Fi 的吞吐量很大程度上取决于与内存相关的配置,如 TCP 窗口大小、Wi-Fi 接收/发送数据动态缓冲区数量等。 + - {IDF_TARGET_NAME} LwIP/Wi-Fi 可能使用的堆内存峰值取决于许多因素,例如应用程序可能拥有的最大 TCP/UDP 连接等。 + - 在考虑内存配置时,应用程序所需的总内存也是一个重要因素。 + +由于这些原因,不存在一个适合所有应用程序的配置。相反,我们必须为每个不同的应用程序考虑不同的内存配置。 + +动态与静态缓冲区 +++++++++++++++++++++++++++++++ + +Wi-Fi 驱动程序中默认的缓存类型是“动态”。大多数情况下,动态缓冲区可以极大地节省内存。但是因为应用程序需要考虑 Wi-Fi 的内存使用情况,会给应用程序编程造成一定的难度。 + +lwIP 还在 TCP/IP 层分配缓冲区,这种缓冲区分配也是动态的。具体内容,见 `lwIP 文档内存使用和性能部分 `_。 + +Wi-Fi 动态缓冲区峰值 +++++++++++++++++++++++++++++++ + +Wi-Fi 驱动程序支持多种类型的缓冲区(参考 :ref:`Wi-Fi 缓冲区配置 ` )。但本节只介绍 Wi-Fi 动态缓冲的使用方法 +Wi-Fi 使用的堆内存峰值是 Wi-Fi 驱动程序 **理论上消耗的最大内存**。通常,该内存峰值取决于: + +- :math:`b_{rx}` 配置的动态接收数据缓冲区数 +- :math:`b_{tx}` 配置的动态发送数据缓冲区数 +- :math:`m_{rx}` Wi-Fi 驱动程序可以接收的最大数据包 +- :math:`m_{tx}` Wi-Fi 驱动程序可以发送的最大数据包 + +因此,Wi-Fi 驱动程序消耗的内存峰值(:math:`p`)可以用下面的公式计算: + +.. math:: + + p = (b_{rx} * m_{rx}) + (b_{tx} * m_{tx}) + +一般情况下,不需要关心动态发送数据长缓冲区和超长缓冲区,因为它们是管理帧,对系统的影响很小。 + + +{IDF_TARGET_NAME} Wi-Fi 吞吐量 +----------------------------------- + +下表是我们在 Espressif 实验室和屏蔽箱中获得的最佳吞吐量结果。 + +.. only:: esp32 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - 类型/吞吐量 + - 实验室空气状况 + - 屏蔽箱 + - 测试工具 + - IDF 版本 (commit ID) + * - 原始 802.11 数据包接收数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - 原始 802.11 数据包发送数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - UDP 接收数据 + - 30 MBit/s + - 85 MBit/s + - iperf example + - 15575346 + * - UDP 发送数据 + - 30 MBit/s + - 75 MBit/s + - iperf example + - 15575346 + * - TCP 接收数据 + - 20 MBit/s + - 65 MBit/s + - iperf example + - 15575346 + * - TCP 发送数据 + - 20 MBit/s + - 75 MBit/s + - iperf example + - 15575346 + + 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32`。 + +.. only:: esp32s2 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - 类型/吞吐量 + - 实验室空气状况 + - 屏蔽箱 + - 测试工具 + - IDF 版本 (commit ID) + * - 原始 802.11 数据包接收数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - 原始 802.11 数据包发送数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - UDP 接收数据 + - 30 MBit/s + - 70 MBit/s + - iperf example + - 15575346 + * - UDP 发送数据 + - 30 MBit/s + - 50 MBit/s + - iperf example + - 15575346 + * - TCP 接收数据 + - 20 MBit/s + - 32 MBit/s + - iperf example + - 15575346 + * - TCP 发送数据 + - 20 MBit/s + - 37 MBit/s + - iperf example + - 15575346 + + 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32s2`。 + +.. only:: esp32c3 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - 类型/吞吐量 + - 实验室空气状况 + - 屏蔽箱 + - 测试工具 + - IDF 版本 (commit ID) + * - 原始 802.11 数据包接收数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - 原始 802.11 数据包发送数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - UDP 接收数据 + - 30 MBit/s + - 50 MBit/s + - iperf example + - 15575346 + * - UDP 发送数据 + - 30 MBit/s + - 40 MBit/s + - iperf example + - 15575346 + * - TCP 接收数据 + - 20 MBit/s + - 35 MBit/s + - iperf example + - 15575346 + * - TCP 发送数据 + - 20 MBit/s + - 37 MBit/s + - iperf example + - 15575346 + + 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c3`。 + +.. only:: esp32c5 + + - 2.4 GHz 频段 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - 类型/吞吐量 + - 实验室空气状况 + - 屏蔽箱 + - 测试工具 + - IDF 版本 (commit ID) + * - 原始 802.11 数据包接收数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - 原始 802.11 数据包发送数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - UDP 接收数据 + - 30 MBit/s + - 68 MBit/s + - iperf example + - 7ff0a07d + * - UDP 发送数据 + - 30 MBit/s + - 63 MBit/s + - iperf example + - 7ff0a07d + * - TCP 接收数据 + - 20 MBit/s + - 59 MBit/s + - iperf example + - 7ff0a07d + * - TCP 发送数据 + - 20 MBit/s + - 49 MBit/s + - iperf example + - 7ff0a07d + + - 5 GHz 频段 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - 类型/吞吐量 + - 实验室空气状况 + - 屏蔽箱 + - 测试工具 + - IDF 版本 (commit ID) + * - 原始 802.11 数据包接收数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - 原始 802.11 数据包发送数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - UDP 接收数据 + - 30 MBit/s + - 71 MBit/s + - iperf example + - 7ff0a07d + * - UDP 发送数据 + - 30 MBit/s + - 64 MBit/s + - iperf example + - 7ff0a07d + * - TCP 接收数据 + - 20 MBit/s + - 61 MBit/s + - iperf example + - 7ff0a07d + * - TCP 发送数据 + - 20 MBit/s + - 50 MBit/s + - iperf example + - 7ff0a07d + + 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c5`。 + +.. only:: esp32c6 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - 类型/吞吐量 + - 实验室空气状况 + - 屏蔽箱 + - 测试工具 + - IDF 版本 (commit ID) + * - 原始 802.11 数据包接收数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - 原始 802.11 数据包发送数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - UDP 接收数据 + - 30 MBit/s + - 63 MBit/s + - iperf example + - 7ff0a07d + * - UDP 发送数据 + - 30 MBit/s + - 51 MBit/s + - iperf example + - 7ff0a07d + * - TCP 接收数据 + - 20 MBit/s + - 46 MBit/s + - iperf example + - 7ff0a07d + * - TCP 发送数据 + - 20 MBit/s + - 43 MBit/s + - iperf example + - 7ff0a07d + + 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c6`。 + +.. only:: esp32c61 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - 类型/吞吐量 + - 实验室空气状况 + - 屏蔽箱 + - 测试工具 + - IDF 版本 (commit ID) + * - 原始 802.11 数据包接收数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - 原始 802.11 数据包发送数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - UDP 接收数据 + - 30 MBit/s + - 68 MBit/s + - iperf example + - 7ff0a07d + * - UDP 发送数据 + - 30 MBit/s + - 53 MBit/s + - iperf example + - 7ff0a07d + * - TCP 接收数据 + - 20 MBit/s + - 45 MBit/s + - iperf example + - 7ff0a07d + * - TCP 发送数据 + - 20 MBit/s + - 37 MBit/s + - iperf example + - 7ff0a07d + + 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c61`。 + +.. only:: esp32s3 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 20 + + * - 类型/吞吐量 + - 实验室空气状况 + - 屏蔽箱 + - 测试工具 + - IDF 版本 (commit ID) + * - 原始 802.11 数据包接收数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - 原始 802.11 数据包发送数据 + - N/A + - **130 MBit/s** + - 内部工具 + - N/A + * - UDP 接收数据 + - 30 MBit/s + - 88 MBit/s + - iperf example + - 15575346 + * - UDP 发送数据 + - 30 MBit/s + - 98 MBit/s + - iperf example + - 15575346 + * - TCP 接收数据 + - 20 MBit/s + - 73 MBit/s + - iperf example + - 15575346 + * - TCP 发送数据 + - 20 MBit/s + - 83 MBit/s + - iperf example + - 15575346 + + 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32s3`。 + +.. _How-to-improve-Wi-Fi-performance: + +如何提高 Wi-Fi 性能 +---------------------------------- + +{IDF_TARGET_NAME} Wi-Fi 的性能受许多参数的影响,各参数之间存在相互制约。如果配置地合理,不仅可以提高性能,还可以增加应用程序的可用内存,提高稳定性。 + +在本节中,我们将简单介绍 Wi-Fi/LWIP 协议栈的工作模式,并说明各个参数的作用。我们将推荐几种配置等级,你可以根据使用场景选择合适的等级。 + +协议栈工作模式 +++++++++++++++++++++++++++++++++++ + +.. figure:: ../../../_static/api-guides-WiFi-driver-how-to-improve-WiFi-performance.png + :align: center + + {IDF_TARGET_NAME} 数据路径 + +{IDF_TARGET_NAME} 协议栈分为四层,分别为应用层、LWIP 层、Wi-Fi 层和硬件层。 + + - 在接收过程中,硬件将接收到的数据包放入 DMA 缓冲区,然后依次传送到 Wi-Fi 的接收数据缓冲区、LWIP 的接收数据缓冲区进行相关协议处理,最后传送到应用层。Wi-Fi 的接收数据缓冲区和 LWIP 的接收数据缓冲区默认共享同一个缓冲区。也就是说,Wi-Fi 默认将数据包转发到 LWIP 作为参考。 + + - 在发送过程中,应用程序首先将要发送的消息复制到 LWIP 层的发送数据缓冲区,进行 TCP/IP 封装。然后将消息发送到 Wi-Fi 层的发送数据缓冲区进行 MAC 封装,最后等待发送。 + +参数 +++++++++++++++ + +适当增加上述缓冲区的大小或数量,可以提高 Wi-Fi 性能,但同时,会减少应用程序的可用内存。下面我们将介绍你需要配置的参数: + +**接收数据方向:** + + - :ref:`CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM` + 该参数表示硬件层的 DMA 缓冲区数量。提高该参数将增加发送方的一次性接收吞吐量,从而提高 Wi-Fi 协议栈处理突发流量的能力。 + + - :ref:`CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM` + 该参数表示 Wi-Fi 层中接收数据缓冲区的数量。提高该参数可以增强数据包的接收性能。该参数需要与 LWIP 层的接收数据缓冲区大小相匹配。 + + - :ref:`CONFIG_ESP_WIFI_RX_BA_WIN` + 该参数表示接收端 AMPDU BA 窗口的大小,应配置为 :ref:`CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM` 和 :ref:`CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM` 的二倍数值中较小的数值。 + + - :ref:`CONFIG_LWIP_TCP_WND_DEFAULT` + 该参数表示 LWIP 层用于每个 TCP 流的的接收数据缓冲区大小,应配置为 WIFI_DYNAMIC_RX_BUFFER_NUM (KB) 的值,从而实现高稳定性能。同时,在有多个流的情况下,应相应降低该参数值。 + +**发送数据方向:** + + - :ref:`CONFIG_ESP_WIFI_TX_BUFFER` + 该参数表示发送数据缓冲区的类型,建议配置为动态缓冲区,该配置可以充分利用内存。 + + - :ref:`CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM` + 该参数表示 Wi-Fi 层发送数据缓冲区数量。提高该参数可以增强数据包发送的性能。该参数值需要与 LWIP 层的发送数据缓冲区大小相匹配。 + + - :ref:`CONFIG_LWIP_TCP_SND_BUF_DEFAULT` + 该参数表示 LWIP 层用于每个 TCP 流的的发送数据缓冲区大小,应配置为 WIFI_DYNAMIC_TX_BUFFER_NUM (KB) 的值,从而实现高稳定性能。在有多个流的情况下,应相应降低该参数值。 + +**通过在 IRAM 中放置代码优化吞吐量:** + +.. only:: esp32 or esp32s2 + + - :ref:`CONFIG_ESP_WIFI_IRAM_OPT` + 如果使能该选项,一些 Wi-Fi 功能将被移至 IRAM,从而提高吞吐量,IRAM 使用量将增加 15 kB。 + + - :ref:`CONFIG_ESP_WIFI_RX_IRAM_OPT` + 如果使能该选项,一些 Wi-Fi 接收数据功能将被移至 IRAM,从而提高吞吐量,IRAM 使用量将增加 16 kB。 + + - :ref:`CONFIG_LWIP_IRAM_OPTIMIZATION` + 如果使能该选项,一些 LWIP 功能将被移至 IRAM,从而提高吞吐量,IRAM 使用量将增加 13 kB。 + +.. only:: esp32c6 + + - :ref:`CONFIG_ESP_WIFI_IRAM_OPT` + 如果使能该选项,一些 Wi-Fi 功能将被移至 IRAM,从而提高吞吐量,IRAM 使用量将增加 13 kB。 + + - :ref:`CONFIG_ESP_WIFI_RX_IRAM_OPT` + 如果使能该选项,一些 Wi-Fi 接收数据功能将被移至 IRAM,从而提高吞吐量,IRAM 使用量将增加 7 kB。 + + - :ref:`CONFIG_LWIP_IRAM_OPTIMIZATION` + 如果使能该选项,一些 LWIP 功能将被移至 IRAM,从而提高吞吐量,IRAM 使用量将增加 14 kB。 + +.. only:: esp32s2 + + **缓存:** + + - :ref:`CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE` + 配置指令缓存的大小。 + + - :ref:`CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_SIZE` + 配置指令缓存总线的宽度。 + +.. only:: esp32s3 + + **缓存:** + + - :ref:`CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE` + 配置指令缓存的大小。 + + - :ref:`CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE` + 配置指令缓存总线的宽度。 + + - :ref:`CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS` + 配置指令缓存相连方式. + + - :ref:`CONFIG_ESP32S3_DATA_CACHE_SIZE` + 配置数据缓存的大小. + + - :ref:`CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE` + 配置数据缓存行大小. + + - :ref:`CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS` + 配置数据缓存相连方式. + +.. note:: + 上述的缓冲区大小固定为 1.6 KB。 + +如何配置参数 +++++++++++++++++++++++++++++ + +{IDF_TARGET_NAME} 的内存由协议栈和应用程序共享。 + +在这里,我们给出了几种配置等级。在大多数情况下,应根据应用程序所占用内存的大小,选择合适的等级进行参数配置。 + +下表中未提及的参数应设置为默认值。 + +.. only:: esp32 + + .. list-table:: + :header-rows: 1 + :widths: 10 5 5 10 5 5 10 5 + + * - 等级 + - Iperf + - 发送数据优先 + - 高性能 + - 接收数据优先 + - 默认值 + - 节省内存 + - 最小 + * - 可用内存 (KB) + - 37.1 + - 113.8 + - 123.3 + - 145.5 + - 144.5 + - 170.2 + - 185.2 + * - WIFI_STATIC_RX_BUFFER_NUM + - 16 + - 6 + - 6 + - 6 + - 6 + - 6 + - 4 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 64 + - 16 + - 24 + - 34 + - 20 + - 12 + - 8 + * - WIFI_DYNAMIC_TX_BUFFER_NUM + - 64 + - 28 + - 24 + - 18 + - 20 + - 12 + - 8 + * - WIFI_RX_BA_WIN + - 32 + - 8 + - 12 + - 12 + - 10 + - 6 + - 禁用 + * - TCP_SND_BUF_DEFAULT (KB) + - 65 + - 28 + - 24 + - 18 + - 20 + - 12 + - 8 + * - TCP_WND_DEFAULT (KB) + - 65 + - 16 + - 24 + - 34 + - 20 + - 12 + - 8 + * - WIFI_IRAM_OPT + - 开启 + - 开启 + - 开启 + - 开启 + - 开启 + - 开启 + - 开启 + * - WIFI_RX_IRAM_OPT + - 开启 + - 开启 + - 开启 + - 开启 + - 开启 + - 开启 + - 开启 + * - LWIP_IRAM_OPTIMIZATION + - 开启 + - 开启 + - 开启 + - 开启 + - 开启 + - 开启 + - 开启 + * - TCP 发送数据吞吐量 (Mbit/s) + - 74.6 + - 50.8 + - 46.5 + - 39.9 + - 44.2 + - 33.8 + - 25.6 + * - TCP 接收数据吞吐量 (Mbit/s) + - 63.6 + - 35.5 + - 42.3 + - 48.5 + - 40.5 + - 30.1 + - 27.8 + * - UDP 发送数据吞吐量 (Mbit/s) + - 76.2 + - 75.1 + - 74.1 + - 72.4 + - 69.6 + - 64.1 + - 36.5 + * - UDP 接收数据吞吐量 (Mbit/s) + - 83.1 + - 66.3 + - 75.1 + - 75.6 + - 73.1 + - 65.3 + - 54.7 + + +.. only:: esp32s2 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 10 10 10 + + * - 等级 + - Iperf + - 高性能 + - 默认 + - 节省内存 + - 最小 + * - 可用内存 (KB) + - 4.1 + - 24.2 + - 78.4 + - 86.5 + - 116.4 + * - WIFI_STATIC_RX_BUFFER_NUM + - 8 + - 6 + - 6 + - 4 + - 3 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 24 + - 18 + - 12 + - 8 + - 6 + * - WIFI_DYNAMIC_TX_BUFFER_NUM + - 24 + - 18 + - 12 + - 8 + - 6 + * - WIFI_RX_BA_WIN + - 12 + - 9 + - 6 + - 4 + - 3 + * - TCP_SND_BUF_DEFAULT (KB) + - 24 + - 18 + - 12 + - 8 + - 6 + * - TCP_WND_DEFAULT (KB) + - 24 + - 18 + - 12 + - 8 + - 6 + * - WIFI_IRAM_OPT + - 开启 + - 开启 + - 开启 + - 开启 + - 关闭 + * - WIFI_RX_IRAM_OPT + - 开启 + - 开启 + - 开启 + - 关闭 + - 关闭 + * - LWIP_IRAM_OPTIMIZATION + - 开启 + - 开启 + - 关闭 + - 关闭 + - 关闭 + * - INSTRUCTION_CACHE + - 16 + - 16 + - 16 + - 16 + - 8 + * - INSTRUCTION_CACHE_LINE + - 16 + - 16 + - 16 + - 16 + - 16 + * - TCP 发送数据吞吐量 (Mbit/s) + - 37.6 + - 33.1 + - 22.5 + - 12.2 + - 5.5 + * - TCP 接收数据吞吐量 (Mbit/s) + - 31.5 + - 28.1 + - 20.1 + - 13.1 + - 7.2 + * - UDP 发送数据吞吐量 (Mbit/s) + - 58.1 + - 57.3 + - 28.1 + - 22.6 + - 8.7 + * - UDP 接收数据吞吐量 (Mbit/s) + - 78.1 + - 66.7 + - 65.3 + - 53.8 + - 28.5 + +.. only:: esp32c3 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 + + * - 等级 + - Iperf + - 默认 + - 最小 + * - 可用内存 (KB) + - 59 + - 160 + - 180 + * - WIFI_STATIC_RX_BUFFER_NUM + - 20 + - 8 + - 3 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 40 + - 16 + - 6 + * - WIFI_DYNAMIC_TX_BUFFER_NUM + - 40 + - 16 + - 6 + * - WIFI_RX_BA_WIN + - 32 + - 16 + - 6 + * - TCP_SND_BUF_DEFAULT (KB) + - 40 + - 16 + - 6 + * - TCP_WND_DEFAULT (KB) + - 40 + - 16 + - 6 + * - LWIP_IRAM_OPTIMIZATION + - 开启 + - 开启 + - 关闭 + * - TCP 发送数据吞吐量 (Mbit/s) + - 38.1 + - 27.2 + - 20.4 + * - TCP 接收数据吞吐量 (Mbit/s) + - 35.3 + - 24.2 + - 17.4 + * - UDP 发送数据吞吐量 (Mbit/s) + - 40.6 + - 38.9 + - 34.1 + * - UDP 接收数据吞吐量 (Mbit/s) + - 52.4 + - 44.5 + - 44.2 + +.. only:: esp32c6 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 + + * - 等级 + - Iperf + - 默认 + - 最小 + * - 可用内存 (KB) + - 223 + - 276 + - 299 + * - WIFI_STATIC_RX_BUFFER_NUM + - 20 + - 8 + - 3 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 40 + - 16 + - 6 + * - WIFI_DYNAMIC_TX_BUFFER_NUM + - 40 + - 16 + - 6 + * - WIFI_RX_BA_WIN + - 32 + - 16 + - 6 + * - TCP_SND_BUF_DEFAULT (KB) + - 40 + - 16 + - 6 + * - TCP_WND_DEFAULT (KB) + - 40 + - 16 + - 6 + * - LWIP_IRAM_OPTIMIZATION + - 开启 + - 开启 + - 关闭 + * - TCP 发送数据吞吐量 (Mbit/s) + - 30.5 + - 25.9 + - 16.4 + * - TCP 接收数据吞吐量 (Mbit/s) + - 27.8 + - 21.6 + - 14.3 + * - UDP 发送数据吞吐量 (Mbit/s) + - 37.8 + - 36.1 + - 34.6 + * - UDP 接收数据吞吐量 (Mbit/s) + - 41.5 + - 36.8 + - 36.7 + +.. only:: esp32c2 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 15 + + * - 等级 + - Iperf + - 默认 + - 最小 + * - 可用内存 (KB) + - 37 + - 56 + - 84 + * - WIFI_STATIC_RX_BUFFER_NUM + - 14 + - 7 + - 3 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 18 + - 14 + - 6 + * - WIFI_DYNAMIC_TX_BUFFER_NUM + - 18 + - 14 + - 6 + * - WIFI_RX_BA_WIN + - 16 + - 12 + - 6 + * - TCP_SND_BUF_DEFAULT (KB) + - 18 + - 14 + - 6 + * - TCP_WND_DEFAULT (KB) + - 18 + - 14 + - 6 + * - LWIP_IRAM_OPTIMIZATION + - 开启 + - 开启 + - 关闭 + * - TCP 发送数据吞吐量 (Mbit/s) + - 21.6 + - 21.4 + - 14.3 + * - TCP 接收数据吞吐量 (Mbit/s) + - 19.1 + - 17.9 + - 12.4 + * - UDP 发送数据吞吐量 (Mbit/s) + - 26.4 + - 26.3 + - 25.0 + * - UDP 接收数据吞吐量 (Mbit/s) + - 32.3 + - 31.5 + - 27.7 + +.. only:: esp32s3 + + .. list-table:: + :header-rows: 1 + :widths: 25 20 25 25 + + * - 等级 + - Iperf + - 默认 + - 最小 + * - 可用内存 (KB) + - 133.9 + - 183.9 + - 273.6 + * - WIFI_STATIC_RX_BUFFER_NUM + - 24 + - 8 + - 3 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 64 + - 32 + - 6 + * - WIFI_DYNAMIC_TX_BUFFER_NUM + - 64 + - 32 + - 6 + * - WIFI_RX_BA_WIN + - 32 + - 16 + - 6 + * - TCP_SND_BUF_DEFAULT (KB) + - 64 + - 32 + - 6 + * - TCP_WND_DEFAULT (KB) + - 64 + - 32 + - 6 + * - WIFI_IRAM_OPT + - 开启 + - 开启 + - 开启 + * - WIFI_RX_IRAM_OPT + - 开启 + - 开启 + - 开启 + * - LWIP_IRAM_OPTIMIZATION + - 开启 + - 开启 + - 关闭 + * - INSTRUCTION_CACHE + - 32 + - 32 + - 16 + * - INSTRUCTION_CACHE_LINE + - 32 + - 32 + - 32 + * - INSTRUCTION_CACHE_WAYS + - 8 + - 8 + - 4 + * - TCP 发送数据吞吐量 (Mbit/s) + - 83.93 + - 64.28 + - 23.17 + * - TCP 接收数据吞吐量 (Mbit/s) + - 73.98 + - 60.39 + - 18.11 + * - UDP 发送数据吞吐量 (Mbit/s) + - 98.69 + - 96.28 + - 48.78 + * - UDP 接收数据吞吐量 (Mbit/s) + - 88.58 + - 86.57 + - 59.45 + +.. only:: esp32 or esp32s3 + + .. note:: + 以上结果使用华硕 RT-N66U 路由器,在屏蔽箱中进行单流测试得出。 + {IDF_TARGET_NAME} 的 CPU 为双核,频率为 240 MHz,flash 为 QIO 模式,频率为 80 MHz。 + +.. only:: esp32s2 + + .. note:: + 以上结果使用华硕 RT-N66U 路由器,在屏蔽箱中进行单流测试得出。 + {IDF_TARGET_NAME} 的 CPU 为单核,频率为 240 MHz,flash 为 QIO 模式,频率为 80 MHz。 + +.. only:: esp32c3 + + .. note:: + 以上结果使用华硕 RT-N66U 路由器,在屏蔽箱中进行单流测试得出。 + {IDF_TARGET_NAME} 的 CPU 为单核,频率为 160 MHz,flash 为 QIO 模式,频率为 80 MHz。 + +.. only:: esp32c6 + + .. note:: + 以上结果使用小米 AX6000 路由器,在屏蔽箱中进行单流测试得出。 + {IDF_TARGET_NAME} 的 CPU 为单核,频率为 160 MHz,flash 为 QIO 模式,频率为 80 MHz。 + +.. only:: esp32c2 + + .. note:: + 以上结果使用红米 RM2100 路由器,在屏蔽箱中进行单流测试得出。 + {IDF_TARGET_NAME} 的 CPU 为单核,频率为 120 MHz,flash 为 QIO 模式,频率为 60 MHz。 + +.. only:: esp32 + + **等级:** + + - **Iperf 等级** + {IDF_TARGET_NAME} 的极端性能等级,用于测试极端性能。 + + - **高性能等级** + {IDF_TARGET_NAME} 的高性能配置等级,适用于应用程序占用内存较少且有高性能要求的场景。在该等级中,可以根据使用场景选择使用接收数据优先等级或发送数据优先等级。 + + - **默认等级** + {IDF_TARGET_NAME} 的默认配置等级、兼顾可用内存和性能。 + + - **节省内存等级** + 该等级适用于应用程序需要大量内存的场景,在这一等级下,收发器的性能会有所降低。 + + - **最小等级** + {IDF_TARGET_NAME} 的最小配置等级。协议栈只使用运行所需的内存。适用于对性能没有要求,而应用程序需要大量内存的场景。 + +.. only:: esp32s2 + + **等级:** + + - **Iperf 等级** + {IDF_TARGET_NAME} 极端性能等级,用于测试极端性能。 + + - **高性能等级** + {IDF_TARGET_NAME} 的高性能配置等级,适用于应用程序占用内存较少且有高性能要求的场景。 + + - **默认等级** + {IDF_TARGET_NAME} 的默认配置等级、兼顾可用内存和性能。 + + - **节省内存等级** + 该等级适用于应用程序需要大量内存的场景,在这一等级下,收发器的性能会有所降低。 + + - **最小等级** + {IDF_TARGET_NAME} 的最小配置等级。协议栈只使用运行所需的内存。适用于对性能没有要求,而应用程序需要大量内存的场景。 + +.. only:: esp32c3 or esp32s3 or esp32c6 + + **等级:** + + - **Iperf 等级** + {IDF_TARGET_NAME} 极端性能等级,用于测试极端性能。 + + - **默认等级** + {IDF_TARGET_NAME} 的默认配置等级、兼顾可用内存和性能。 + + - **最小等级** + {IDF_TARGET_NAME} 的最小配置等级。协议栈只使用运行所需的内存。适用于对性能没有要求,而应用程序需要大量内存的场景。 + +.. only:: SOC_SPIRAM_SUPPORTED + + 使用 PSRAM + ++++++++++++++++++++++++++++ + + PSRAM 一般在应用程序占用大量内存时使用。在该模式下,:ref:`CONFIG_ESP_WIFI_TX_BUFFER` 被强制为静态。:ref:`CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM` 表示硬件层 DMA 缓冲区数量,提高这一参数可以增强性能。 + 以下是使用 PSRAM 时的推荐等级。 + + .. only:: esp32 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 10 15 + + * - 等级 + - Iperf + - 默认 + - 节省内存 + - 最小 + * - 可用内存 (KB) + - 113.8 + - 152.4 + - 181.2 + - 202.6 + * - WIFI_STATIC_RX_BUFFER_NUM + - 16 + - 8 + - 4 + - 2 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 128 + - 128 + - 128 + - 128 + * - WIFI_STATIC_TX_BUFFER_NUM + - 16 + - 8 + - 4 + - 2 + * - WIFI_RX_BA_WIN + - 16 + - 16 + - 8 + - 禁用 + * - TCP_SND_BUF_DEFAULT (KB) + - 65 + - 65 + - 65 + - 65 + * - TCP_WND_DEFAULT (KB) + - 65 + - 65 + - 65 + - 65 + * - WIFI_IRAM_OPT + - 开启 + - 开启 + - 开启 + - 关闭 + * - WIFI_RX_IRAM_OPT + - 开启 + - 开启 + - 关闭 + - 关闭 + * - LWIP_IRAM_OPTIMIZATION + - 开启 + - 关闭 + - 关闭 + - 关闭 + * - TCP 发送数据吞吐量 (Mbit/s) + - 37.5 + - 31.7 + - 21.7 + - 14.6 + * - TCP 接收数据吞吐量 (Mbit/s) + - 31.5 + - 29.8 + - 26.5 + - 21.1 + * - UDP 发送数据吞吐量 (Mbit/s) + - 69.1 + - 31.5 + - 27.1 + - 24.1 + * - UDP 接收数据吞吐量 (Mbit/s) + - 40.1 + - 38.5 + - 37.5 + - 36.9 + + .. only:: esp32s2 + + .. list-table:: + :header-rows: 1 + :widths: 10 10 10 10 15 + + * - 等级 + - Iperf + - 默认 + - 节省内存 + - 最小 + * - 可用内存 (KB) + - 70.6 + - 96.4 + - 118.8 + - 148.2 + * - WIFI_STATIC_RX_BUFFER_NUM + - 8 + - 8 + - 6 + - 4 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 64 + - 64 + - 64 + - 64 + * - WIFI_STATIC_TX_BUFFER_NUM + - 16 + - 8 + - 6 + - 4 + * - WIFI_RX_BA_WIN + - 16 + - 6 + - 6 + - 禁用 + * - TCP_SND_BUF_DEFAULT (KB) + - 32 + - 32 + - 32 + - 32 + * - TCP_WND_DEFAULT (KB) + - 32 + - 32 + - 32 + - 32 + * - WIFI_IRAM_OPT + - 开启 + - 开启 + - 开启 + - 关闭 + * - WIFI_RX_IRAM_OPT + - 开启 + - 开启 + - 关闭 + - 关闭 + * - LWIP_IRAM_OPTIMIZATION + - 开启 + - 关闭 + - 关闭 + - 关闭 + * - INSTRUCTION_CACHE + - 16 + - 16 + - 16 + - 8 + * - INSTRUCTION_CACHE_LINE + - 16 + - 16 + - 16 + - 16 + * - DATA_CACHE + - 8 + - 8 + - 8 + - 8 + * - DATA_CACHE_LINE + - 32 + - 32 + - 32 + - 32 + * - TCP 发送数据吞吐量 (Mbit/s) + - 40.1 + - 29.2 + - 20.1 + - 8.9 + * - TCP 接收数据吞吐量 (Mbit/s) + - 21.9 + - 16.8 + - 14.8 + - 9.6 + * - UDP 发送数据吞吐量 (Mbit/s) + - 50.1 + - 25.7 + - 22.4 + - 10.2 + * - UDP 接收数据吞吐量 (Mbit/s) + - 45.3 + - 43.1 + - 28.5 + - 15.1 + + .. note:: + 达到性能的峰值可能会触发任务看门狗,由于 CPU 可能没有时间处理低优先级的任务,这是一个正常现象。 + + .. only:: esp32s3 + + **四线 PSRAM:** + + .. list-table:: + :header-rows: 1 + :widths: 25 20 25 25 25 + + * - 等级 + - Iperf + - 默认 + - 节省内存 + - 最小 + * - 可用内存 (KB) + - 50.3 + - 158.7 + - 198.2 + - 228.9 + * - WIFI_STATIC_RX_BUFFER_NUM + - 24 + - 8 + - 6 + - 4 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 85 + - 64 + - 32 + - 32 + * - WIFI_STATIC_TX_BUFFER_NUM + - 32 + - 32 + - 6 + - 4 + * - WIFI_RX_BA_WIN + - 32 + - 16 + - 12 + - 禁用 + * - TCP_SND_BUF_DEFAULT (KB) + - 85 + - 32 + - 32 + - 32 + * - TCP_WND_DEFAULT (KB) + - 85 + - 32 + - 32 + - 32 + * - WIFI_IRAM_OPT + - 开启 + - 开启 + - 开启 + - 关闭 + * - WIFI_RX_IRAM_OPT + - 开启 + - 开启 + - 关闭 + - 关闭 + * - LWIP_IRAM_OPTIMIZATION + - 开启 + - 关闭 + - 关闭 + - 关闭 + * - LWIP_UDP_RECVMBOX_SIZE + - 16 + - 16 + - 16 + - 16 + * - INSTRUCTION_CACHE + - 32 + - 16 + - 16 + - 16 + * - INSTRUCTION_CACHE_LINE + - 32 + - 16 + - 16 + - 16 + * - INSTRUCTION_CACHE_WAYS + - 8 + - 8 + - 8 + - 8 + * - DATA_CACHE + - 64 + - 16 + - 16 + - 16 + * - DATA_CACHE_LINE + - 32 + - 32 + - 32 + - 32 + * - DATA_CACHE_WAYS + - 8 + - 8 + - 8 + - 8 + * - TCP 发送数据吞吐量 (Mbit/s) + - 93.1 + - 62.5 + - 41.3 + - 42.7 + * - TCP 接收数据吞吐量 (Mbit/s) + - 88.9 + - 46.5 + - 46.2 + - 37.9 + * - UDP 发送数据吞吐量 (Mbit/s) + - 106.4 + - 106.2 + - 60.7 + - 50 + * - UDP 接收数据吞吐量 (Mbit/s) + - 99.8 + - 92.6 + - 94.3 + - 53.3 + + **八线 PSRAM:** + + .. list-table:: + :header-rows: 1 + :widths: 25 20 25 25 25 + + * - 等级 + - Iperf + - 默认 + - 节省内存 + - 最小 + * - 可用内存 (KB) + - 49.1 + - 151.3 + - 215.3 + - 243.6 + * - WIFI_STATIC_RX_BUFFER_NUM + - 24 + - 8 + - 6 + - 4 + * - WIFI_DYNAMIC_RX_BUFFER_NUM + - 85 + - 64 + - 32 + - 32 + * - WIFI_STATIC_TX_BUFFER_NUM + - 32 + - 32 + - 6 + - 4 + * - WIFI_RX_BA_WIN + - 32 + - 16 + - 12 + - 禁用 + * - TCP_SND_BUF_DEFAULT (KB) + - 85 + - 32 + - 32 + - 32 + * - TCP_WND_DEFAULT (KB) + - 85 + - 32 + - 32 + - 32 + * - WIFI_IRAM_OPT + - 开启 + - 开启 + - 开启 + - 关闭 + * - WIFI_RX_IRAM_OPT + - 开启 + - 开启 + - 关闭 + - 关闭 + * - LWIP_IRAM_OPTIMIZATION + - 开启 + - 关闭 + - 关闭 + - 关闭 + * - LWIP_UDP_RECVMBOX_SIZE + - 16 + - 16 + - 16 + - 16 + * - INSTRUCTION_CACHE + - 32 + - 16 + - 16 + - 16 + * - INSTRUCTION_CACHE_LINE + - 32 + - 16 + - 16 + - 16 + * - INSTRUCTION_CACHE_WAYS + - 8 + - 8 + - 8 + - 8 + * - DATA_CACHE + - 64 + - 16 + - 16 + - 16 + * - DATA_CACHE_LINE + - 32 + - 32 + - 32 + - 32 + * - DATA_CACHE_WAYS + - 8 + - 8 + - 8 + - 8 + * - TCP 发送数据吞吐量 (Mbit/s) + - 93.3 + - 58.4 + - 37.1 + - 35.6 + * - TCP 接收数据吞吐量 (Mbit/s) + - 86.1 + - 43.6 + - 42.5 + - 35 + * - UDP 发送数据吞吐量 (Mbit/s) + - 104.7 + - 82.2 + - 60.4 + - 47.9 + * - UDP 接收数据吞吐量 (Mbit/s) + - 104.6 + - 104.8 + - 104 + - 55.7 + + +{IDF_TARGET_NAME} Wi-Fi 节能模式 +----------------------------------------- + +本小节将简单介绍 Wi-Fi 节能模式相关的概念和使用方式,更加详细的介绍请参考 :doc:`低功耗模式使用指南 <../../api-guides/low-power-mode/index>`。 + +Station 睡眠 +++++++++++++++++++++++ + +目前, {IDF_TARGET_NAME} Wi-Fi 支持 Modem-sleep 模式,该模式是 IEEE 802.11 协议中的传统节能模式。仅 station 模式支持该模式,且 station 必须先连接到 AP。如果使能了 Modem-sleep 模式,station 将定期在活动状态和睡眠状态之间切换。在睡眠状态下,RF、PHY 和 BB 处于关闭状态,以减少功耗。Modem-sleep 模式下,station 可以与 AP 保持连接。 + +Modem-sleep 模式包括最小和最大节能模式。在最小节能模式下,每个 DTIM 间隔,station 都将唤醒以接收 beacon。广播数据在 DTIM 之后传输,因此不会丢失。但是,由于 DTIM 间隔长短由 AP 决定,如果该间隔时间设置较短,则省电效果不大。 + +在最大节能模式下,每个监听间隔,station 都将唤醒以接收 beacon。可以设置该监听间隔长于 AP 的 DTIM 周期。在 DTIM 期间内,station 可能处于睡眠状态,广播数据会丢失。如果监听间隔较长,则可以节省更多电量,但广播数据更容易丢失。连接 AP 前,可以通过调用 API :cpp:func:`esp_wifi_set_config()` 配置监听间隔。 + +调用 :cpp:func:`esp_wifi_init()` 后,调用 ``esp_wifi_set_ps(WIFI_PS_MIN_MODEM)`` 可使能 Modem-sleep 最小节能模式。调用 ``esp_wifi_set_ps(WIFI_PS_MAX_MODEM)`` 可使能 Modem-sleep 最大节能模式。station 连接到 AP 时,Modem-sleep 模式将启动。station 与 AP 断开连接时,Modem-sleep 模式将停止。 + +调用 ``esp_wifi_set_ps(WIFI_PS_NONE)`` 可以完全禁用 Modem-sleep 模式。禁用会增大功耗,但可以最大限度减少实时接收 Wi-Fi 数据的延迟。使能 Modem-sleep 模式时,接收 Wi-Fi 数据的延迟时间可能与 DTIM 周期(最小节能模式)或监听间隔(最大节能模式)相同。 + +.. only:: SOC_SUPPORT_COEXISTENCE + + 注意在共存模式下, 即使调用 ``esp_wifi_set_ps(WIFI_PS_NONE)``, Wi-Fi 也仅会在 Wi-Fi 时间片内保持活动状态, 非 Wi-Fi 时间片内仍然睡眠。请参照 :ref:`共存策略 `。 + +默认的 Modem-sleep 模式是 WIFI_PS_MIN_MODEM。 + +AP 睡眠 ++++++++++++++++++++++++++++++++ + +目前,{IDF_TARGET_NAME} AP 不支持 Wi-Fi 协议中定义的所有节能功能。具体来说,AP 只缓存所连 station 单播数据,不缓存组播数据。如果 {IDF_TARGET_NAME} AP 所连的 station 已使能节能功能,可能发生组播数据包丢失。 + +未来,{IDF_TARGET_NAME} AP 将支持所有节能功能。 + +非连接状态下的休眠 ++++++++++++++++++++++++++++++++ + +非连接状态指的是 :cpp:func:`esp_wifi_start` 至 :cpp:func:`esp_wifi_stop` 期间内,没有建立 Wi-Fi 连接的阶段。 + +目前, {IDF_TARGET_NAME} Wi-Fi 支持以 station 模式运行时,在非连接状态下休眠。可以通过选项 :ref:`CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE` 配置该功能。 + +如果打开配置选项 :ref:`CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE`,则在该阶段内,RF, PHY and BB 将在空闲时被关闭,电流将会等同于 Modem-sleep 模式下的休眠电流。 + +配置选项 :ref:`CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE` 默认情况下将会被打开,共存模式下被 Menuconfig 强制打开。 + +.. _connectionless-module-power-save-cn: + +非连接模块功耗管理 ++++++++++++++++++++++++++++++++ + +非连接模块指的是一些不依赖于 Wi-Fi 连接的 Wi-Fi 模块,例如 ESP-NOW,DPP,FTM。这些模块从 :cpp:func:`esp_wifi_start` 开始工作至 :cpp:func:`esp_wifi_stop` 结束。 + +目前,ESP-NOW 以 station 模式工作时,既支持在连接状态下休眠,也支持在非连接状态下休眠。 + +非连接模块发包 +******************************* + +对于任何非连接模块,在开启了休眠的任何时间点都可以发包,不需要进行任何额外的配置。 + +此外,:cpp:func:`esp_wifi_80211_tx` 也在休眠时被支持。 + +非连接模块收包 +******************************* + +对于非连接模块,在开启休眠时如果需要进行收包,需要配置两个参数,分别为 `Window` 和 `Interval`。 + +在每个 `Interval` 开始时,RF, PHY and BB 将会被打开并保持 `Window` 的时间。非连接模块可以在此时间内收包。 + +**Interval** + + - 全局只有一个 `Interval` 参数,所有非连接模块共享它。其数值由 API :cpp:func:`esp_wifi_set_connectionless_interval` 配置,单位为毫秒。 + + - `Interval` 的默认值为 `ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE` 。 + + - 在 `Interval` 开始时,将会给出 :ref:`WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START ` 事件,由于 `Window` 将在此时开始,可以在此事件内布置发包动作。 + + - 在连接状态下,`Interval` 开始的时间点将会与 TBTT 时间点对齐。可以通过将非连接模块的接收端和发送端连接在同一路由器下,并在 :ref:`WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START ` 事件内进行发包,以同步非连接模块的传输窗口,达到提高接收端收包成功率的效果。 + + .. only:: esp32 + + 在 ESP32 上,TBTT 时间点会受到 DFS (Dynamic Frequency Scaling) 的干扰,如果想要在 ESP32 上通过 TBTT 同步非连接模块的传输窗口,需要禁用 DFS。 + +**Window** + + - 每个非连接模块在启动后都有其自身的 `Window` 参数,休眠模块将取所有模块 `Window` 的最大值运作。 + + - 其数值由 API :cpp:func:`module_name_set_wake_window` 配置,单位为毫秒。 + + - 模块 `Window` 的默认值为最大值。 + +.. table:: 不同 Window 与 Interval 组合下的 RF, PHY and BB 使用情况 + + +----------------------+-----------------------------------------------------+---------------------------------------------------------------------------+ + | | Interval | + + +-----------------------------------------------------+---------------------------------------------------------------------------+ + | | ``ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE`` | 1 - maximum | + +--------+-------------+-----------------------------------------------------+---------------------------------------------------------------------------+ + | Window | 0 | not used | + + +-------------+-----------------------------------------------------+---------------------------------------------------------------------------+ + | | 1 - maximum | default mode | used periodically (Window < Interval) / used all time (Window ≥ Interval) | + +--------+-------------+-----------------------------------------------------+---------------------------------------------------------------------------+ + +默认模式 +******************************* + +当 `Interval` 参数被配置为 `ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE` ,且有非零的 `Window` 参数时,非连接模块功耗管理将会按默认模式运行。 + +在没有与非 Wi-Fi 协议共存时,RF、PHY 和 BB 将会在默认模式下被一直打开。 + +在与非 Wi-Fi 协议共存时,RF、PHY 和 BB 资源被共存模块分时划给 Wi-Fi 非连接模块和非 Wi-Fi 协议使用。在默认模式下,Wi-Fi 非连接模块被允许周期性使用 RF、PHY 和 BB,并且具有稳定性能。 + +推荐在与非 Wi-Fi 协议共存时将非连接模块功耗管理配置为默认模式。 diff --git a/docs/zh_CN/api-guides/wifi-driver/wifi-vendor-features.rst b/docs/zh_CN/api-guides/wifi-driver/wifi-vendor-features.rst new file mode 100644 index 0000000000..3f26148761 --- /dev/null +++ b/docs/zh_CN/api-guides/wifi-driver/wifi-vendor-features.rst @@ -0,0 +1,236 @@ +Wi-Fi Vendor 特性 +======================== + +:link_to_translation:`en:[English]` + +.. only:: SOC_WIFI_MESH_SUPPORT + + ESP-WIFI-MESH + ------------------------- + + 详细信息请参阅 :doc:`ESP-WIFI-MESH <../esp-wifi-mesh>`. + + +Wi-Fi 80211 数据包发送 +--------------------------- + +:cpp:func:`esp_wifi_80211_tx()` API 可用于: + + - 发送 beacon、probe request、probe response 和 action 帧。 + - 发送非 QoS 数据帧。 + +不能用于发送加密或 QoS 帧。 + +使用 :cpp:func:`esp_wifi_80211_tx()` 的前提条件 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + - Wi-Fi 模式为 station 模式,AP 模式,或 station/AP 共存模式。 + - API esp_wifi_set_promiscuous(true) 或 :cpp:func:`esp_wifi_start()`,或者二者都返回 :c:macro:`ESP_OK`。这是为确保在调用函数 :cpp:func:`esp_wifi_80211_tx()` 前,Wi-Fi 硬件已经初始化。对于 {IDF_TARGET_NAME},esp_wifi_set_promiscuous(true) 和 :cpp:func:`esp_wifi_start()` 都可以触发 Wi-Fi 硬件初始化。 + - 提供正确的 :cpp:func:`esp_wifi_80211_tx()` 参数。 + +传输速率 ++++++++++++++++++++++++++++++ + + - 默认传输速率为 1 Mbps。 + - 可以通过函数 :cpp:func:`esp_wifi_config_80211_tx_rate()` 设置任意速率。 + - 可以通过函数 :cpp:func:`esp_wifi_set_bandwidth()` 设置任意带宽。 + +在不同情况下需要避免的副作用 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +理论上,如果不考虑 API 对 Wi-Fi 驱动程序或其他 station 或 AP 的副作用,可以通过空中发送一个原始的 802.11 数据包,包括任何目的地址的 MAC、任何源地址的 MAC、任何 BSSID、或任何其他类型的数据包。但是,一个具有强健、有用的应用程序应该避免这种副作用。下表针对如何避免 :cpp:func:`esp_wifi_80211_tx()` 的副作用提供了一些提示或建议。 + +.. list-table:: + :header-rows: 1 + :widths: 10 55 + + * - 场景 + - 描述 + * - 无 Wi-Fi 连接 + - 在这种情况下,因为没有 Wi-Fi 连接,Wi-Fi 驱动程序不会受到副作用影响。如果 ``en_sys_seq==true``,则 Wi-Fi 驱动程序负责序列控制。如果 ``en_sys_seq==false``,应用程序需要确保缓冲区的序列正确。 + + 理论上,MAC 地址可以是任何地址。但是,这样可能会影响其他使用相同 MAC/BSSID 的 station/AP。 + + 例如,AP 模式下,应用程序调用函数 :cpp:func:`esp_wifi_80211_tx` 发送带有 BSSID == mac_x 的 beacon,但是 mac_x 并非 AP 接口的 MAC。而且,还有另一个 AP(我们称之为 “other-AP”)的 bssid 是 mac_x。因此,连接到 “other-AP” 的 station 无法分辨 beacon 来自 “other-AP” 还是 :cpp:func:`esp_wifi_80211_tx`,就会出现 “意外行为”。 + + 为了避免上述副作用,我们建议: + + - 如果在 station 模式下调用函数 :cpp:func:`esp_wifi_80211_tx`,第一个 MAC 应该是组播 MAC 或是目标设备的 MAC,第二个 MAC 应该是 station 接口的 MAC。 + + - 如果在 AP 模式下调用函数 :cpp:func:`esp_wifi_80211_tx`,第一个 MAC 应该是组播 MAC 或是目标设备的 MAC,第二个 MAC 应该是 AP 接口的 MAC。 + + 上述建议仅供避免副作用,在有充分理由的情况下可以忽略。 + + * - 有 Wi-Fi 连接 + - 当 Wi-Fi 已连接,且序列由应用程序控制,应用程序可能会影响整个 Wi-Fi 连接的序列控制。 因此,en_sys_seq 要为 true,否则将返回 ``ESP_ERR_INVALID_ARG``。 + + “无 Wi-Fi 连接”情况下的 MAC 地址建议也适用于此情况。 + + 如果 Wi-Fi 模式是 station 模式,MAC 的地址 1 是 station 所连 AP 的 MAC,地址 2 是 station 接口的 MAC,那么就称数据包是从 station 发送到 AP。另一方面,如果 Wi-Fi 模式是 AP 模式,且 MAC 地址 1 是该 AP 所连 station 的 MAC,地址 2 是 AP 接口的 MAC,那么就称数据包是从 AP 发送到 station。为避免与 Wi-Fi 连接冲突,可采用以下检查方法: + + - 如果数据包类型是数据,且是从 station 发送到 AP,IEEE 802.11 Frame control 字段中的 ToDS 位应该为 1,FromDS 位为 0,否则,Wi-Fi 驱动程序不接受该数据包。 + + - 如果数据包类型是数据,且是从 AP 发送到 station,IEEE 802.11 Frame control 字段中的 ToDS 位应该为 0,FromDS 位为 1,否则,Wi-Fi 驱动程序不接受该数据包。 + + - 如果数据包是从 station 发送到 AP,或从 AP 到 station,Power Management、More Data 和 Re-Transmission 位应该为 0,否则,Wi-Fi 驱动程序不接受该数据包。 + + 如果任何检查失败,将返回 ``ESP_ERR_INVALID_ARG``。 + + +Wi-Fi 供应商 IE 配置 +----------------------------- + +默认情况下,所有 Wi-Fi 管理帧都由 Wi-Fi 驱动程序处理,应用程序不需要任何操作。但是,某些应用程序可能需要处理 beacon、probe request、probe response 和其他管理帧。例如,如果在管理帧中插入一些只针对供应商的 IE,则只有包含此 IE 的管理帧才能得到处理。{IDF_TARGET_NAME} 中,:cpp:func:`esp_wifi_set_vendor_ie()` 和 :cpp:func:`esp_wifi_set_vendor_ie_cb()` 负责此类任务。 + + +.. only:: SOC_WIFI_CSI_SUPPORT + + Wi-Fi 信道状态信息 + ------------------------------------ + + .. only:: esp32 or esp32s2 or esp32c3 or esp32s3 + + 信道状态信息 (CSI) 是指 Wi-Fi 连接的信道信息。{IDF_TARGET_NAME} 中,CSI 由子载波的信道频率响应组成,CSI 从发送端接收数据包时开始估计。每个子载波信道频率响由两个字节的有符号字符记录,第一个字节是虚部,第二个字节是实部。根据接收数据包的类型,信道频率响应最多有三个字段。分别是 LLTF、HT-LTF 和 STBC-HT-LTF。对于在不同状态的信道上接收到的不同类型的数据包,CSI 的子载波索引和总字节数如下表所示。 + + +------------+-------------+-----------------------------------------+-----------------------------------------------------+--------------------------------------------------------+ + | 信道 | 辅助信道 | | 下 | 上 | + +------------+-------------+-------------+---------------------------+---------+-------------------------------------------+---------+----------------------------------------------+ + | 数据包信息 | 信号模式 | 非 HT | HT | 非 HT | HT | 非 HT | HT | + | +-------------+-------------+---------------------------+---------+---------------+---------------------------+---------+------------------+---------------------------+ + | | 信道带宽 | 20 MHz | 20 MHz | 20 MHz | 20 MHz | 40 MHz | 20 MHz | 20 MHz | 40 MHz | + | +-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+ + | | STBC | 非 STBC | 非 STBC | STBC | 非 STBC | 非 STBC| STBC | 非 STBC | STBC | 非 STBC | 非 STBC | STBC | 非 STBC | STBC | + +------------+-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+ + | 子载波索引 | LLTF | 0~31,-32~-1 | 0~31,-32~-1 | 0~31,-32~-1 | 0~63 | 0~63 | 0~63 | 0~63 | 0~63 | -64~-1 | -64~-1 | -64~-1 | -64~-1 | -64~-1 | + | +-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+ + | | HT-LTF | — | 0~31,-32~-1 | 0~31,-32~-1 | — | 0~63 | 0~62 | 0~63,-64~-1 | 0~60,-60~-1 | — | -64~-1 | -62~-1 | 0~63,-64~-1 | 0~60,-60~-1 | + | +-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+ + | | STBC-HT-LTF | — | — | 0~31,-32~-1 | — | — | 0~62 | — | 0~60,-60~-1 | — | — | -62~-1 | — | 0~60,-60~-1 | + +------------+-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+ + | 总字节数 | 128 | 256 | 384 | 128 | 256 | 380 | 384 | 612 | 128 | 256 | 376 | 384 | 612 | + +--------------------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+ + + 表中的所有信息可以在 wifi_csi_info_t 结构中找到。 + + - 辅助信道指 rx_ctrl 字段的 secondary_channel 字段。 + - 数据包的信号模式指 rx_ctrl 字段的 sig_mode 字段。 + - 信道带宽指 rx_ctrl 字段中的 cwb 字段。 + - STBC 指 rx_ctrl 字段的 stbc 字段。 + - 总字节数指 len 字段。 + - 每个长训练字段 (LTF) 类型对应的 CSI 数据存储在从 buf 字段开始的缓冲区中。每个元素以两个字节的形式存储:虚部和实部。每个元素的顺序与表中的子载波相同。LTF 的顺序是 LLTF、HT-LTF 和 STBC-HT-LTF。但是,根据信道和数据包的信息,3 个 LTF 可能都不存在(见上文)。 + - 如果 :cpp:type:`wifi_csi_info_t` 的 first_word_invalid 字段为 true,表示由于 {IDF_TARGET_NAME} 的硬件限制,CSI 数据的前四个字节无效。 + - 更多信息,如 RSSI,射频的噪声底,接收时间和天线 rx_ctrl 领域。 + + 子载波的虚部和实部的使用请参考下表。 + + +----------------+-------------------+------------------------------+------------------------------+ + | PHY 标准 | 子载波范围 | 导频子载波 | 子载波个数(总数/数据子载波)| + +================+===================+==============================+==============================+ + | 802.11a/g | -26 to +26 | -21, -7, +7, +21 | 52 total, 48 usable | + +----------------+-------------------+------------------------------+------------------------------+ + | 802.11n, 20 MHz| -28 to +28 | -21, -7, +7, +21 | 56 total, 52 usable | + +----------------+-------------------+------------------------------+------------------------------+ + | 802.11n, 40 MHz| -57 to +57 | -53, -25, -11, +11, +25, +53 | 114 total, 108 usable | + +----------------+-------------------+------------------------------+------------------------------+ + + .. note:: + + - 对于 STBC 数据包,每个空时流都提供了 CSI,不会出现 CSD(循环移位延迟)。由于附加链上的每一次循环移位为 -200 ns,因为子载波 0 中没有信道频率响应,在 HT-LTF 和 STBC-HT-LTF 中只记录第一空时流的 CSD 角度。CSD[10:0] 是 11 位,范围从 -pi 到 pi。 + + - 如果调用 API :cpp:func:`esp_wifi_set_csi_config()` 没有使能 LLTF、HT-LTF 或 STBC-HT-LTF,则 CSI 数据的总字节数会比表中的少。例如,如果没有使能 LLTF 和 HT-LTF,而使能 STBC-HT-LTF,当接收到上述条件、HT、40 MHz 或 STBC 的数据包时,CSI 数据的总字节数为 244((61+60)*2+2=244,结果对齐为四个字节,最后两个字节无效)。 + + .. only:: esp32c5 + + 信道状态信息 (CSI) 是指 Wi-Fi 连接的信道信息。{IDF_TARGET_NAME} 中,CSI 由子载波的信道频率响应组成,CSI 从发送端接收数据包时开始估计。每个子载波信道频率响由两个字节的有符号字符记录,第一个字节是虚部,第二个字节是实部。除了 IEEE 802.11g 模式外,其他模式均存在两段 LTF 序列(LLTF + HT/VHT/HE-LTF)。{IDF_TARGET_NAME}可以通过 :cpp:struct:`wifi_csi_acquire_config_t` 中 ``acquire_csi_force_lltf`` 字段决定包含 LLTF 或 HT/VHT/HE-LTF。对于在不同状态的信道上接收到的不同类型的数据包,CSI 的子载波索引和总字节数如下表所示。 + + +------------+------------------+-----------------------------------------+--------------------------------------------+----------------------------------------------------------------+----------------------------------------------------------------+ + | 信道 | 辅助信道 | | 下 | 上 | + +------------+------------------+-------------+---------------------------+--------------------------------------------+-------------+--------------------------------------------------+-------------+--------------------------------------------------+ + | 数据包信息 | 信号模式 | 非 HT | HT | HE | 非 HT | HT | 非 HT | HT | + | +------------------+-------------+---------------------------+--------------------------------------------+-------------+----------------------+---------------------------+-------------+----------------------+---------------------------+ + | | 信道带宽 | 20 MHz | 20 MHz | 20 MHz | 20 MHz | 20 MHz | 40 MHz | 20 MHz | 20 MHz | 40 MHz | + | +------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ + | | STBC | 非 STBC | 非 STBC | STBC | 非 STBC | STBC | 非 STBC | 非 STBC | STBC | 非 STBC | STBC | 非 STBC | 非 STBC | STBC | 非 STBC | STBC | + +------------+------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ + | 子载波索引 | LLTF | 0~26,-26~-1 | — | — | — | — | 0~52 | — | — | — | — | -53~-1| — | — | — | — | + | +------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ + | | HT-LTF (HT-LTF1) | — | 0~28,-28~-1 | 0~28,-28~-1 | — | — | — | 0~56| 0~56 | 0~58,-58~-1 | 0~58,-58~-1 | — | -57~-1| -57~-1 | 0~58,-58~-1 | 0~58,-58~-1 | + | +------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ + | | HT-LTF2 | — | — | 0~28,-28~-1 | — | — | — | — | 0~56 | — | 0~58,-58~-1 | — | — | -57~-1 | — | 0~58,-58~-1 | + | +------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ + | | HE-LTF (HE-LTF1) | — | — | — | 0~122,-122~1 | 由CSI配置决定 | — | — | — | — | — | — | — | — | — | — | + | +------------------+-------------+-------------+-------------+---------------+ +-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ + | | HE-LTF2 | — | — | — | — | | — | — | — | — | — | — | — | — | — | — | + +------------+------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ + | 总字节数 | 106 | 114| 228 | 490 | 490 | 106 | 114| 228 | 234 | 468 | 106 | 114| 228 | 234 | 468 | + +-------------------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ + + .. note:: + + - HT/VHT/HE 模式均存在两段 LTF 序列即:LLTF + HT/VHT/HE-LTF, 如果 :cpp:struct:`wifi_csi_acquire_config_t` 中 ``acquire_csi_force_lltf`` 为 false 时, CSI 数据中仅包含 HT/VHT/HE-LTF(如上表所示), 否则 CSI 数据中仅包含 LLTF。 HT/VHT/HE 模式 LLTF 的子载波索引和 CSI 总字节数同非 HT 模式 LLTF 子载波索引和 CSI 总字节数一致。 + - VHT 模式时子载波索引和 CSI 总字节数同 HT 模式的子载波索引和 CSI 总字节数一致。 + + 表中的信息可以在 :cpp:type:`wifi_csi_info_t` 结构体中找到。 + + - 辅助信道指 ``rx_ctrl`` 字段的 ``second`` 字段。 + - 数据包的信号模式指 ``rx_ctrl`` 字段的 ``cur_bb_format`` 字段。 + - 总字节数指 ``len`` 字段。 + - 每个长训练字段 (LTF) 类型对应的 CSI 数据存储在从 buf 字段开始的缓冲区中。每个元素以两个字节的形式存储:虚部和实部。每个元素的顺序与表中的子载波相同。LTF 的顺序是 LLTF、HT/VHT/HE-LTF。根据信道和数据包的信息,LTF 的存在情况见上文。 + - 如果 ``first_word_invalid`` 字段为 true,表示由于 {IDF_TARGET_NAME} 的硬件限制,CSI 数据的前四个字节无效。 + - 如果 ``rx_ctrl`` 字段中的 ``rx_channel_estimate_info_vld`` 为 1,表明CSI数据是有效的,否则,CSI数据是无效的。 + - 更多信息,如 RSSI、射频底噪声、接收时间及天线,请参见 ``rx_ctrl`` 字段。 + + 对于 STBC 数据包,HE-LTF 和 STBC-HE-LTF 的子载波索引由 :cpp:type:`wifi_csi_config_t` 中的 ``acquire_csi_he_stbc_mode`` 字段决定,具体请参见下表。 + + +---------------------+------------------+-------------------+ + | acquire_csi_he_stbc | HE-LTF1 | HE-LTF2 | + +---------------------+------------------+-------------------+ + | 0 | -122~-1, 0~122 | — | + +---------------------+------------------+-------------------+ + | 1 | — | -122~-1, 0~122 | + +---------------------+------------------+-------------------+ + | 2 | 在 HE-LTF1 和 HE-LTF2 中进行均匀采样 | + +---------------------+------------------+-------------------+ + + 有效子载波的虚部和实部的使用请参考下表。 + + +-----------------------+------------------+------------------------------------------+------------------------------+ + | PHY 标准 | 子载波范围 | 无效子载波 | 子载波个数(总数/数据子载波)| + +=======================+==================+==========================================+==============================+ + | 802.11a/g | -26 to +26 | 0 | 53 total, 52 usable | + +-----------------------+------------------+------------------------------------------+------------------------------+ + | 802.11n, 20 MHz | -28 to +28 | 0 | 57 total, 56 usable | + +-----------------------+------------------+------------------------------------------+------------------------------+ + | 802.11n, 40 MHz | -58 to +58 | -1, 0, 1 | 117 total, 114 usable | + +-----------------------+------------------+------------------------------------------+------------------------------+ + | 802.11ac, 20 MHz | -28 to +28 | 0 | 57 total, 56 usable | + +-----------------------+------------------+------------------------------------------+------------------------------+ + | 802.11ax, 20 MHz (SU) | -122 to + 122 | -1, 0, 1 | 245 total, 242 usable | + +-----------------------+------------------+------------------------------------------+------------------------------+ + + .. note:: + + - PHY 为 802.11ax时,MU 数据包的 CSI 子载波范围和无效子载波索引请参考协议。 + + .. note:: + + - 对于 STBC 数据包,每个空时流都提供了 CSI,不会出现 CSD(循环移位延迟)。由于附加链上的每一次循环移位为 -200 ns,因为子载波 0 中没有信道频率响应,在 HT-LTF1 和 HT-LTF2 中只记录第一空时流的 CSD 角度。CSD[10:0] 是 11 位,范围从 -pi 到 pi。 + + + Wi-Fi 信道状态信息配置 + ------------------------------------------- + + 要使用 Wi-Fi CSI,需要执行以下步骤。 + + - 在菜单配置中选择 Wi-Fi CSI。方法是 ``Menuconfig`` > ``Components config`` > ``Wi-Fi`` > ``Wi-Fi CSI (Channel State Information)``。 + - 调用 API :cpp:func:`esp_wifi_set_csi_rx_cb()` 设置 CSI 接收回调函数。 + - 调用 API :cpp:func:`esp_wifi_set_csi_config()` 配置 CSI。 + - 调用 API :cpp:func:`esp_wifi_set_csi()` 使能 CSI。 + + CSI 接收回调函数从 Wi-Fi 任务中运行。因此,不要在回调函数中进行冗长的操作。可以将需要的数据发布到队列中,并从一个较低优先级的任务中处理。由于 station 在断开连接时不会收到任何数据包,只有在连接时才会收到来自 AP 的数据包,因此建议通过调用函数 :cpp:func:`esp_wifi_set_promiscuous()` 使能 Sniffer 模式接收更多 CSI 数据。 + + +Wi-Fi 多根天线 +-------------------------- + +具体请参考 :doc:`PHY <../../api-guides/phy>`。 diff --git a/docs/zh_CN/api-guides/wifi-security.rst b/docs/zh_CN/api-guides/wifi-security.rst index f7c666a71c..e436d8082e 100644 --- a/docs/zh_CN/api-guides/wifi-security.rst +++ b/docs/zh_CN/api-guides/wifi-security.rst @@ -39,32 +39,78 @@ API 及用法 为最大限度地利用 PMF 的额外安全性优势,已弃用 ``pmf_cfg`` 中的 ``capable`` 标志,并在内部设置为 ``true``。 + 企业级 Wi-Fi ---------------------------------- +---------------------- 简介 -++++++++++++ +++++++++ -企业级安全是企业无线网的安全认证机制,采用 RADIUS 服务器在设备接入到接入点 (AP) 前认证网络用户。该机制基于 802.1X 标准完成认证,并采用多种扩展认证协议 (EAP) 方法,如 TLS、TTLS、PEAP 和 EAP-FAST。RADIUS 服务器根据用户凭证(用户名和密码)、数字证书或两者的组合进行用户认证。 +企业级 Wi-Fi (Wi-Fi Enterprise) 为企业无线网络提供安全认证机制。该机制基于 IEEE 802.1X 标准运作,并依赖 RADIUS 服务器在设备连接到接入点 (AP) 之前进行用户身份验证。根据所使用的可扩展认证协议 (EAP) 方法,认证可以基于用户凭证(用户名和密码)、数字证书,或两者结合。 + +当 {IDF_TARGET_NAME} 以 station 模式连接企业级 AP 时,会发起认证请求。AP 会将该请求转发给配置的 RADIUS 服务器,由其根据所选 EAP 方法和参数对设备进行验证。 .. note:: {IDF_TARGET_NAME} 仅在 station 模式下支持企业级 Wi-Fi。 -{IDF_TARGET_NAME} 支持 **企业级 WPA2** 和 **企业级 WPA3**。企业级 WPA3 构建在企业级 WPA2 的基础之上,并额外要求在所有 WPA3 连接中使用受保护的管理帧 (PMF) 和服务器证书验证。此外,**企业级 WPA3 还提供了一种更安全的模式,使用 192 位最低强度的安全协议和加密工具,更好地保护敏感数据**。企业级 WPA3 的 192 位模式可以确保用户正确使用密码工具组合,并在 WPA3 网络中设立了一致的安全基准。需要注意的是,只有支持 :c:macro:`SOC_WIFI_GCMP_SUPPORT` 的模组才支持企业级 WPA3 的 192 位模式。如需使用该模式,请启用 :ref:`CONFIG_ESP_WIFI_SUITE_B_192` 标志。 +企业级 WPA2 和企业级 WPA3 +++++++++++++++++++++++++++++++ -{IDF_TARGET_NAME} 支持以下 EAP 方法: - - EAP-TLS:该认证方法基于证书实现,仅需提供 SSID 和 EAP-IDF。 - - PEAP:该认证方法为受保护的 EAP 方法,必须提供用户名和密码。 - - EAP-TTLS:该认证方法基于凭证实现,必须提供服务器证书,用户证书为可选项。该方法支持多种第二阶段方法,如: - - PAP:密码认证协议 - - CHAP:挑战握手认证协议 - - MSCHAP 和 MSCHAP-V2 - - EAP-FAST:该认证方法基于受保护访问凭证 (PAC) 实现,同时也使用身份和密码。目前,需禁用 :ref:`CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT` 标志以使用此功能。 +{IDF_TARGET_NAME} 支持 **企业级 WPA2 (WPA2-Enterprise)** 和 **企业级 WPA3 (WPA3-Enterprise)**。 -- :example:`wifi/wifi_eap_fast` 演示如何使用 EAP-FAST 通过企业级 Wi-Fi 认证将 {IDF_TARGET_NAME} 连接到 AP,包括 CA 证书的安装、用户凭据的设置、启用 Wi-Fi 企业模式以及如何连接到 AP。 +**企业级 WPA2** 使用 802.1X/EAP 进行身份验证,并依赖安全的凭证或证书。为建立安全连接,AP 与 station 会协商并选定适当的加密套件。{IDF_TARGET_NAME} 支持以下内容: + +- 802.1X/EAP(WPA)AKM 方法 +- AES-CCM cipher suite +- 启用 `USE_MBEDTLS_CRYPTO` 后可使用 mbedtls 支持的其他 cipher suite + +**企业级 WPA3** 在企业级 WPA2 的基础上加强了安全性,并对所有 WPA3 连接增加两项强制要求:必须启用受保护管理帧 (PMF),并强制执行服务器证书验证。 + +此外,企业级 WPA3 还支持 **192 位最低强度安全模式 (Suite B)**,提供更高的加密强度。 + +- 企业级 WPA3 的 192 位模式仅适用于支持 :c:macro:`SOC_WIFI_GCMP_SUPPORT` 的芯片。 +- 若需启用该模式,请配置 :ref:`CONFIG_ESP_WIFI_SUITE_B_192`。 + +支持的 EAP 方法 ++++++++++++++++++++++ + +{IDF_TARGET_NAME} 支持多种企业级认证的 EAP 方法。不同方法可能需要不同的配置参数,如 SSID、身份标识、用户名/密码、CA 证书或客户端证书等。 + +支持以下 EAP 方法: + +- **EAP-TLS** + + 基于证书的认证方式,需要提供 SSID 和 EAP 身份;通过客户端证书进行设备认证。 + +- **PEAP** + + 一种受保护的 EAP 方法,需要提供用户名和密码。 + +- **EAP-TTLS** + + 一种基于凭证的认证方式。服务器认证为必选;用户认证取决于 Phase 2 方法。通常需要提供用户名和密码。支持的 Phase 2 方法包括: + + - PAP:密码认证协议 + - CHAP:挑战握手认证协议 + - MSCHAP + - MSCHAP-V2 + +- **EAP-FAST** + + 基于受保护访问凭证 (PAC) 的认证方法,需要身份标识和密码。使用 EAP-FAST 时需要 **禁用** :ref:`CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT`。 + +示例 +++++++++ + +- :example:`wifi/wifi_eap_fast` + + 演示如何使用 EAP-FAST 将 {IDF_TARGET_NAME} 连接到企业级 Wi-Fi,包括 CA 证书安装、凭证配置、启用企业级模式以及连接 AP。 + +- :example:`wifi/wifi_enterprise` + + 演示使用 EAP-TLS、EAP-PEAP 和 EAP-TTLS 连接企业级 Wi-Fi。有关使用 OpenSSL 生成证书及运行示例的说明,请参考 :example_file:`wifi/wifi_enterprise/README.md`。 -- :example:`wifi/wifi_enterprise` 演示如何使用除 ESP-FAST 之外的其他 EAP 方法(如 EAP-TLS、EAP-PEAP、EAP-TTLS)通过 Wi-Fi 企业认证将 {IDF_TARGET_NAME} 连接到 AP。有关使用 OpenSSL 命令生成证书和运行示例的详细信息,请参阅 :example_file:`wifi/wifi_enterprise/README.md`。 个人级 WPA3 ------------- diff --git a/docs/zh_CN/api-guides/wifi.rst b/docs/zh_CN/api-guides/wifi.rst deleted file mode 100644 index 9cef99805b..0000000000 --- a/docs/zh_CN/api-guides/wifi.rst +++ /dev/null @@ -1,4249 +0,0 @@ -Wi-Fi 驱动程序 -================== - -:link_to_translation:`en:[English]` - -{IDF_TARGET_MAX_CONN_STA_NUM:default="15", esp32c2="4", esp32c3="10", esp32c6="10"} - -{IDF_TARGET_SUB_MAX_NUM_FROM_KEYS:default="2", esp32c3="7", esp32c6="7"} - -{IDF_TARGET_NAME} Wi-Fi 功能列表 ------------------------------------- - -{IDF_TARGET_NAME} 支持以下 Wi-Fi 功能: - -.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 - - - 支持 4 个虚拟接口,即 STA、AP、Sniffer 和 reserved。 - - 支持仅 station 模式、仅 AP 模式、station/AP 共存模式 - - 支持使用 IEEE 802.11b、IEEE 802.11g、IEEE 802.11n 和 API 配置协议模式 - - 支持 WPA/WPA2/WPA3/WPA2-企业版/WPA3-企业版/WAPI/WPS 和 DPP - - 支持 AMSDU、AMPDU、HT40、QoS 以及其它主要功能 - - 支持 Modem-sleep - - 支持乐鑫专属协议,可实现 **1 km** 数据通信量 - - 空中数据传输最高可达 20 MBit/s TCP 吞吐量和 30 MBit/s UDP 吞吐量 - - 支持 Sniffer - - 支持快速扫描和全信道扫描 - - 支持多个天线 - - 支持获取信道状态信息 - -.. only:: esp32c2 - - - 支持 3 个虚拟接口,即 STA、AP 和 Sniffer。 - - 支持仅 station 模式、仅 AP 模式、station/AP 共存模式 - - 支持使用 IEEE 802.11b、IEEE 802.11g、IEEE 802.11n 和 API 配置协议模式 - - 支持 WPA/WPA2/WPA3/WPA2-企业版/WPA3-企业版/WPS 和 DPP - - 支持 AMPDU、QoS 以及其它主要功能 - - 支持 Modem-sleep - - 空中数据传输最高可达 20 MBit/s TCP 吞吐量和 30 MBit/s UDP 吞吐量 - - 支持 Sniffer - - 支持快速扫描和全信道扫描 - - 支持多个天线 - -.. only:: esp32c6 - - - 支持 4 个虚拟接口,即 STA、AP、Sniffer 和 reserved。 - - 支持仅 station 模式、仅 AP 模式、station/AP 共存模式 - - 支持使用 IEEE 802.11b、IEEE 802.11g、IEEE 802.11n、IEEE 802.11ax 和 API 配置协议模式 - - 支持 WPA/WPA2/WPA3/WPA2-企业版/WPA3-企业版/WAPI/WPS 和 DPP - - 支持 AMSDU、AMPDU、HT40、QoS 以及其它主要功能 - - 支持 Modem-sleep - - 支持乐鑫专属协议,可实现 **1 km** 数据通信量 - - 空中数据传输最高可达 20 MBit/s TCP 吞吐量和 30 MBit/s UDP 吞吐量 - - 支持 Sniffer - - 支持快速扫描和全信道扫描 - - 支持多个天线 - - 支持获取信道状态信息 - - 支持 Individual TWT 和 Broadcast TWT - - 支持下行 MU-MIMO - - 支持 OFDMA - - 支持 BSS Color - -.. only:: esp32c5 - - - 支持 4 个虚拟接口,即 STA、AP、Sniffer 和 reserved。 - - 支持仅 station 模式、仅 AP 模式、station/AP 共存模式 - - 支持使用 IEEE 802.11b、IEEE 802.11g、IEEE 802.11n、IEEE 802.11a、IEEE 802.11ac、IEEE 802.11ax 和 API 配置协议模式 - - 支持 WPA/WPA2/WPA3/WPA2-企业版/WPA3-企业版/WAPI/WPS 和 DPP - - 支持 AMSDU、AMPDU、HT40、QoS 以及其它主要功能 - - 支持 Modem-sleep - - 2.4 GHz 支持乐鑫专属协议,可实现 **1 km** 数据通信量 - - 空中数据传输最高可达 20 MBit/s TCP 吞吐量和 30 MBit/s UDP 吞吐量 - - 支持 Sniffer - - 支持快速扫描和全信道扫描 - - 支持多个天线 - - 支持获取信道状态信息 - - 支持 Individual TWT 和 Broadcast TWT - - 支持下行 MU-MIMO - - 支持 OFDMA - - 支持 BSS Color -.. only:: SOC_WIFI_NAN_SUPPORT - - - Wi-Fi Aware (NAN) - -如何编写 Wi-Fi 应用程序 ----------------------------------- - -准备工作 -+++++++++++ - -一般来说,要编写自己的 Wi-Fi 应用程序,最高效的方式是先选择一个相似的应用程序示例,然后将其中可用的部分移植到自己的项目中。如果你希望编写一个强健的 Wi-Fi 应用程序,强烈建议在开始之前先阅读本文。**非强制要求,请依个人情况而定。** - -本文将补充说明 Wi-Fi API 和 Wi-Fi 示例的相关信息,重点描述使用 Wi-Fi API 的原则、当前 Wi-Fi API 实现的限制以及使用 Wi-Fi 时的常见错误。同时,本文还介绍了 Wi-Fi 驱动程序的一些设计细节。建议选择一个示例 :example:`example ` 进行参考。 - -- :example:`wifi/getting_started/station` 演示如何使用 station 功能连接到 AP。 - -- :example:`wifi/getting_started/softAP` 演示如何使用 SoftAP 功能将 {IDF_TARGET_NAME} 配置为 AP。 - -- :example:`wifi/scan` 演示如何扫描可用的 AP,配置扫描设置,并显示扫描结果。 - -- :example:`wifi/fast_scan` 演示如何执行快速和全通道扫描,查找附近的 AP,设置信号强度的阈值和认证模式,并根据信号强度和认证模式连接到最合适的 AP。 - -- :example:`wifi/wps` 演示如何使用 WPS 入网功能,简化连接 Wi-Fi 路由器的过程,支持 PIN 或 PBC 模式。 - -- :example:`wifi/wps_softap_registrar` 演示如何在 SoftAP 模式下使用 WPS 注册器功能,从而简化从 station 连接到 Wi-Fi SoftAP 的过程。 - -- :example:`wifi/smart_config` 演示如何使用 smartconfig 功能通过 ESPTOUCH 应用连接到目标 AP。 - -- :example:`wifi/power_save` 演示如何使用 station 模式的省电模式。 - -- :example:`wifi/softap_sta` 演示如何配置 {IDF_TARGET_NAME} 同时用作 AP 和 station,从而可将其用作 Wi-Fi NAT 路由器。 - -- :example:`wifi/iperf` 演示如何实现 iPerf 性能测量工具所使用的协议,允许在两个芯片之间或在单个芯片和运行 iPerf 工具的计算机之间进行性能测量,并提供测试 station/SoftAP TCP/UDP RX/TX 吞吐量的具体说明。 - -- :example:`wifi/roaming/roaming_app` 演示如何使用 Wi-Fi Roaming App 功能,在兼容的 AP 之间高效漫游。 - -- :example:`wifi/roaming/roaming_11kvr` 演示如何使用 11k 和 11v API 实现漫游功能。 - -.. only:: SOC_WIFI_HE_SUPPORT - - - :example:`wifi/itwt` 演示如何使用 iTWT 功能,该功能仅在 station 模式下工作,并在不同的省电模式下提供设置、拆卸和挂起的命令,还展示了启用和禁用 iTWT 时的电流消耗差异。 - -设置 Wi-Fi 编译时选项 -++++++++++++++++++++++++++++++++++++ - -请参阅 `Wi-Fi menuconfig`_。 - -Wi-Fi 初始化 -+++++++++++++++ - -请参阅 `{IDF_TARGET_NAME} Wi-Fi station 一般情况`_、`{IDF_TARGET_NAME} Wi-Fi AP 一般情况`_。 - -启动/连接 Wi-Fi -++++++++++++++++++++ - -请参阅 `{IDF_TARGET_NAME} Wi-Fi station 一般情况`_、`{IDF_TARGET_NAME} Wi-Fi AP 一般情况`_。 - -事件处理 -++++++++++++++ - -通常,在理想环境下编写代码难度并不大,如 `WIFI_EVENT_STA_START`_、`WIFI_EVENT_STA_CONNECTED`_ 中所述。难度在于如何在现实的困难环境下编写代码,如 `WIFI_EVENT_STA_DISCONNECTED`_ 中所述。能否在后者情况下完美地解决各类事件冲突,是编写一个强健的 Wi-Fi 应用程序的根本。请参阅 `{IDF_TARGET_NAME} Wi-Fi 事件描述`_, `{IDF_TARGET_NAME} Wi-Fi station 一般情况`_, `{IDF_TARGET_NAME} Wi-Fi AP 一般情况`_。另可参阅 ESP-IDF 中的 :doc:`事件处理概述 <../api-reference/system/esp_event>`。 - -编写错误恢复程序 -++++++++++++++++++++++++++++++++++++++++++++++++++++ - -除了能在比较差的环境下工作,错误恢复能力也对一个强健的 Wi-Fi 应用程序至关重要。请参阅 `{IDF_TARGET_NAME} Wi-Fi API 错误代码`_。 - - -{IDF_TARGET_NAME} Wi-Fi API 错误代码 --------------------------------------- - -所有 {IDF_TARGET_NAME} Wi-Fi API 都有定义好的返回值,即错误代码。这些错误代码可分类为: - - - 无错误,例如:返回值 :c:macro:`ESP_OK` 代表 API 成功返回 - - 可恢复错误,例如::c:macro:`ESP_ERR_NO_MEM` - - 不可恢复的非关键性错误 - - 不可恢复的关键性错误 - -一个错误是否为关键性取决于其 API 和应用场景,并且由 API 用户定义。 - -**要使用 Wi-Fi API 编写一个强健的应用程序,根本原则便是要时刻检查错误代码并编写相应的错误处理代码。** 一般来说,错误处理代码可用于解决: - - - 可恢复错误,你可以编写一个可恢复错误处理代码解决该类错误。例如,当 :cpp:func:`esp_wifi_start()` 返回 :c:macro:`ESP_ERR_NO_MEM` 时,调用可恢复错误处理代码 vTaskDelay 可以获取几微秒的重试时间。 - - 不可恢复非关键性错误,打印错误代码可以帮助你更好地处理该类错误。 - - 不可恢复关键性错误,可使用 "assert" 语句处理该类错误。例如,如果 :cpp:func:`esp_wifi_set_mode()` 返回 ``ESP_ERR_WIFI_NOT_INIT`` :cpp:func:`esp_wifi_init()` 未成功初始化 Wi-Fi 驱动程序。你可以在应用程序开发阶段非常快速地检测到此类错误。 - -在 :component_file:`esp_common/include/esp_err.h` 中, ``ESP_ERROR_CHECK`` 负责检查返回值。这是一个较为常见的错误处理代码,可在应用程序开发阶段作为默认的错误处理代码。但是,我们强烈建议 API 的使用者编写自己的错误处理代码。 - -初始化 {IDF_TARGET_NAME} Wi-Fi API 参数 ----------------------------------------------------- - -初始化 API 的结构参数时,应遵循以下两种方式之一: - -- 设置该参数的所有字段 -- 先使用 get API 获取当前配置,然后只设置特定于应用程序的字段 - -初始化或获取整个结构这一步至关重要,因为大多数情况下,返回值 0 意味着程序使用了默认值。未来,我们将会在该结构中加入更多字段,并将这些字段初始化为 0,确保即使 ESP-IDF 版本升级后,你的应用程序依然能够正常运行。 - -.. _wifi-programming-model: - -{IDF_TARGET_NAME} Wi-Fi 编程模型 ------------------------------------------ - -{IDF_TARGET_NAME} Wi-Fi 编程模型如下图所示: - -.. blockdiag:: - :caption: Wi-Fi 编程模型 - :align: center - - blockdiag wifi-programming-model { - - # global attributes - node_height = 60; - node_width = 100; - span_width = 100; - span_height = 60; - default_shape = roundedbox; - default_group_color = none; - - # node labels - TCP_STACK [label="TCP\n stack", fontsize=12]; - EVNT_TASK [label="Event\n task", fontsize=12]; - APPL_TASK [label="Application\n task", width = 120, fontsize=12]; - WIFI_DRV [label="Wi-Fi\n Driver", width = 120, fontsize=12]; - KNOT [shape=none]; - - # node connections + labels - TCP_STACK -> EVNT_TASK [label=event]; - EVNT_TASK -> APPL_TASK [label="callback\n or event"]; - - # arrange nodes vertically - group { - label = "default handler"; - orientation = portrait; - EVNT_TASK <- WIFI_DRV [label=event]; - } - - # intermediate node - group { - label = "user handler"; - orientation = portrait; - APPL_TASK -- KNOT; - } - WIFI_DRV <- KNOT [label="API\n call"]; - } - - -Wi-Fi 驱动程序可以看作是一个无法感知上层代码(如 TCP/IP 堆栈、应用程序任务、事件任务等)的黑匣子。通常,应用程序任务(代码)负责调用 :doc:`Wi-Fi 驱动程序 APIs <../api-reference/network/esp_wifi>` 来初始化 Wi-Fi,并在必要时处理 Wi-Fi 事件。然后,Wi-Fi 驱动程序接收并处理 API 数据,并在应用程序中插入事件。 - -Wi-Fi 事件处理是在 :doc:`esp_event 库 <../api-reference/system/esp_event>` 的基础上进行的。Wi-Fi 驱动程序将事件发送至 :ref:`默认事件循环 `,应用程序便可以使用 :cpp:func:`esp_event_handler_register()` 中的回调函数处理这些事件。除此之外,:doc:`esp_netif 组件 <../api-reference/network/esp_netif>` 也负责处理 Wi-Fi 事件,并产生一系列默认行为。例如,当 Wi-Fi station 连接至一个 AP 时,esp_netif 将自动开启 DHCP 客户端服务(系统默认)。 - - -{IDF_TARGET_NAME} Wi-Fi 事件描述 ------------------------------------------ - -WIFI_EVENT_WIFI_READY -++++++++++++++++++++++++++++++++++++ - -Wi-Fi 驱动程序永远不会生成此事件,因此,应用程序的事件回调函数可忽略此事件。在未来的版本中,此事件可能会被移除。 - -WIFI_EVENT_SCAN_DONE -++++++++++++++++++++++++++++++++++++ - -扫描完成事件,由 :cpp:func:`esp_wifi_scan_start()` 函数触发,将在以下情况下产生: - - - 扫描已完成,例如:Wi-Fi 已成功找到目标 AP 或已扫描所有信道。 - - 当前扫描因函数 :cpp:func:`esp_wifi_scan_stop()` 而终止。 - - 在当前扫描完成之前调用了函数 :cpp:func:`esp_wifi_scan_start()`。此时,新的扫描将覆盖当前扫描过程,并生成一个扫描完成事件。 - -以下情况下将不会产生扫描完成事件: - - - 当前扫描被阻止。 - - 当前扫描是由函数 :cpp:func:`esp_wifi_connect()` 触发的。 - -接收到此事件后,事件任务暂不做任何响应。首先,应用程序的事件回调函数需调用 :cpp:func:`esp_wifi_scan_get_ap_num()` 和 :cpp:func:`esp_wifi_scan_get_ap_records()` 获取已扫描的 AP 列表,然后触发 Wi-Fi 驱动程序释放在扫描过程中占用的内存空间(**切记该步骤**)。 -更多详细信息,请参阅 `{IDF_TARGET_NAME} Wi-Fi 扫描`_。 - -WIFI_EVENT_STA_START -++++++++++++++++++++++++++++++++++++ - -如果调用函数 :cpp:func:`esp_wifi_start()` 后接收到返回值 :c:macro:`ESP_OK`,且当前 Wi-Fi 处于 station 或 station/AP 共存模式,则将产生此事件。接收到此事件后,事件任务将初始化 LwIP 网络接口 (netif)。通常,应用程序的事件回调函数需调用 :cpp:func:`esp_wifi_connect()` 来连接已配置的 AP。 - -WIFI_EVENT_STA_STOP -++++++++++++++++++++++++++++++++++++ - -如果调用函数 :cpp:func:`esp_wifi_stop()` 后接收到返回值 :c:macro:`ESP_OK`,且当前 Wi-Fi 处于 station 或 station/AP 共存模式,则将产生此事件。接收到此事件后,事件任务将进行释放 station IP 地址、终止 DHCP 客户端服务、移除 TCP/UDP 相关连接并清除 LwIP station netif 等动作。此时,应用程序的事件回调函数通常不需做任何响应。 - -WIFI_EVENT_STA_CONNECTED -++++++++++++++++++++++++++++++++++++ - -如果调用函数 :cpp:func:`esp_wifi_connect()` 后接收到返回值 :c:macro:`ESP_OK`,且 station 已成功连接目标 AP,则将产生此连接事件。接收到此事件后,事件任务将启动 DHCP 客户端服务并开始获取 IP 地址。此时,Wi-Fi 驱动程序已准备就绪,可发送和接收数据。如果你的应用程序不依赖于 LwIP(即 IP 地址),则此刻便可以开始应用程序开发工作。但是,如果你的应用程序需基于 LwIP 进行,则还需等待 *got ip* 事件发生后才可开始。 - -WIFI_EVENT_STA_DISCONNECTED -++++++++++++++++++++++++++++++++++++ - -此事件将在以下情况下产生: - - - 调用了函数 :cpp:func:`esp_wifi_disconnect()` 或 :cpp:func:`esp_wifi_stop()`,且 Wi-Fi station 已成功连接至 AP。 - - 调用了函数 :cpp:func:`esp_wifi_connect()`,但 Wi-Fi 驱动程序因为某些原因未能成功连接至 AP,例如:未扫描到目标 AP、验证超时等。或存在多个 SSID 相同的 AP,station 无法连接所有已找到的 AP,也将产生该事件。 - - Wi-Fi 连接因为某些原因而中断,例如:station 连续多次丢失 N beacon、AP 踢掉 station、AP 认证模式改变等。 - -接收到此事件后,事件任务的默认动作为: - - - 关闭 station 的 LwIP netif。 - - 通知 LwIP 任务清除导致所有套接字状态错误的 UDP/TCP 连接。针对基于套接字编写的应用程序,其回调函数可以在接收到此事件时(如有必要)关闭并重新创建所有套接字。 - -应用程序处理此事件最常用的方法为:调用函数 :cpp:func:`esp_wifi_connect()` 重新连接 Wi-Fi。但是,如果此事件是由函数 :cpp:func:`esp_wifi_disconnect()` 引发的,则应用程序不应调用 :cpp:func:`esp_wifi_connect()` 来重新连接。应用程序须明确区分此事件的引发原因,因为某些情况下应使用其它更好的方式进行重新连接。请参阅 `Wi-Fi 重新连接`_ 和 `连接 Wi-Fi 时扫描`_。 - -需要注意的另一点是:接收到此事件后,LwIP 的默认动作是终止所有 TCP 套接字连接。大多数情况下,该动作不会造成影响。但对某些特殊应用程序可能除外。例如: - -- 应用程序创建一个了 TCP 连接,以维护每 60 秒发送一次的应用程序级、保持活动状态的数据。 -- 由于某些原因,Wi-Fi 连接被切断并引发了 `WIFI_EVENT_STA_DISCONNECTED` 事件。根据当前实现,此时所有 TCP 连接都将被移除,且保持活动的套接字将处于错误的状态中。但是,由于应用程序设计者认为网络层 **不应** 考虑这个 Wi-Fi 层的错误,因此应用程序不会关闭套接字。 -- 5 秒后,因为在应用程序的事件回调函数中调用了 :cpp:func:`esp_wifi_connect()`,Wi-Fi 连接恢复。**同时,station 连接至同一个 AP 并获得与之前相同的 IPV4 地址。** -- 60 秒后,当应用程序发送具有保持活动状态的套接字的数据时,套接字将返回错误,应用程序将关闭套接字并在必要时重新创建。 - -在上述场景中,理想状态下应用程序套接字和网络层将不会受到影响,因为在此过程中 Wi-Fi 连接只是短暂地断开然后快速恢复。 - -IP_EVENT_STA_GOT_IP -++++++++++++++++++++++++++++++++++++ - -当 DHCP 客户端成功从 DHCP 服务器获取 IPV4 地址或 IPV4 地址发生改变时,将引发此事件。此事件意味着应用程序一切就绪,可以开始任务(如:创建套接字)。 - -IPV4 地址可能由于以下原因而发生改变: - - - DHCP 客户端无法重新获取/绑定 IPV4 地址,且 station 的 IPV4 重置为 0。 - - DHCP 客户端重新绑定了其它地址。 - - 静态配置的 IPV4 地址已发生改变。 - -函数 ``ip_event_got_ip_t`` 中的字段 ``ip_change`` 说明了 IPV4 地址是否发生改变。 - -套接字的状态是基于 IPV4 地址的,这意味着,如果 IPV4 地址发生改变,则所有与此 IPV4 相关的套接字都将变为异常。接收到此事件后,应用程序需关闭所有套接字,并在 IPV4 变为有效地址时重新创建应用程序。 - -IP_EVENT_GOT_IP6 -++++++++++++++++++++++++++++++++++++ - -当 IPV6 SLAAC 支持自动为 {IDF_TARGET_NAME} 配置一个地址,或 {IDF_TARGET_NAME} 地址发生改变时,将引发此事件。此事件意味着应用程序一切就绪,可以开始任务(如:创建套接字)。 - -IP_EVENT_STA_LOST_IP -++++++++++++++++++++++++++++++++++++ - -当 IPV4 地址失效时,将引发此事件。 - -此事件不会在 Wi-Fi 断连后立刻出现。Wi-Fi 连接断开后,首先将启动一个 IPV4 地址丢失计时器(可通过 :ref:`CONFIG_ESP_NETIF_LOST_IP_TIMER_ENABLE` 与 :ref:`CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL` 配置)。如果 station 在该计时器超时之前成功获取了 IPV4 地址,则不会发生此事件。否则,此事件将在计时器超时时发生。 - -一般来说,应用程序可忽略此事件。这只是一个调试事件,主要使应用程序获知 IPV4 地址已丢失。 - -WIFI_EVENT_AP_START -++++++++++++++++++++++++++++++++++++ - -与 `WIFI_EVENT_STA_START`_ 事件相似。 - -WIFI_EVENT_AP_STOP -++++++++++++++++++++++++++++++++++++ - -与 `WIFI_EVENT_STA_STOP`_ 事件相似。 - -WIFI_EVENT_AP_STACONNECTED -++++++++++++++++++++++++++++++++++++ - -每当有一个 station 成功连接 {IDF_TARGET_NAME} AP 时,将引发此事件。接收到此事件后,事件任务将不做任何响应,应用程序的回调函数也可忽略这一事件。但是,你可以在此时进行一些操作,例如:获取已连接 station 的信息等。 - -WIFI_EVENT_AP_STADISCONNECTED -++++++++++++++++++++++++++++++++++++ - -此事件将在以下情况下发生: - - - 应用程序通过调用函数 :cpp:func:`esp_wifi_disconnect()` 或 :cpp:func:`esp_wifi_deauth_sta()` 手动断开 station 连接。 - - Wi-Fi 驱动程序出于某些原因断开 station 连接,例如:AP 在过去 5 分钟(可通过函数 :cpp:func:`esp_wifi_set_inactive_time()` 修改该时间)内未接收到任何数据包等。 - - station 断开与 AP 之间的连接。 - -发生此事件时,事件任务将不做任何响应,但应用程序的事件回调函数需执行一些操作,例如:关闭与此 station 相关的套接字等。 - -WIFI_EVENT_AP_PROBEREQRECVED -++++++++++++++++++++++++++++++++++++ - -默认情况下,此事件处于禁用状态,应用程序可以通过调用 API :cpp:func:`esp_wifi_set_event_mask()` 启用。 -启用后,每当 AP 接收到 probe request 时都将引发此事件。 - -WIFI_EVENT_STA_BEACON_TIMEOUT -++++++++++++++++++++++++++++++++++++ - -如果 station 在 inactive 时间内未收到所连接 AP 的 beacon,将发生 beacon 超时,将引发此事件。inactive 时间通过调用函数 :cpp:func:`esp_wifi_set_inactive_time()` 设置。 - -WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -非连接模块在 `Interval` 开始时触发此事件。 请参考 :ref:`非连接模块功耗管理 ` 。 - -{IDF_TARGET_NAME} Wi-Fi station 一般情况 ------------------------------------------------- - -下图为 station 模式下的宏观场景,其中包含不同阶段的具体描述: - -.. seqdiag:: - :caption: station 模式下 Wi-Fi 事件场景示例 - :align: center - - seqdiag sample-scenarios-station-mode { - activation = none; - node_width = 80; - node_height = 60; - edge_length = 140; - span_height = 5; - default_shape = roundedbox; - default_fontsize = 12; - - MAIN_TASK [label = "Main\ntask"]; - APP_TASK [label = "App\ntask"]; - EVENT_TASK [label = "Event\ntask"]; - LwIP_TASK [label = "LwIP\ntask"]; - WIFI_TASK [label = "Wi-Fi\ntask"]; - - === 1. 初始化阶段 === - MAIN_TASK -> LwIP_TASK [label="1.1> 创建/初始化 LwIP"]; - MAIN_TASK -> EVENT_TASK [label="1.2> 创建/初始化事件"]; - MAIN_TASK -> WIFI_TASK [label="1.3> 创建/初始化 Wi-Fi"]; - MAIN_TASK -> APP_TASK [label="1.4> 创建应用程序任务"]; - === 2. 配置阶段 === - MAIN_TASK -> WIFI_TASK [label="2> 配置 Wi-Fi"]; - === 3. 启动阶段 === - MAIN_TASK -> WIFI_TASK [label="3.1> 启动 Wi-Fi"]; - EVENT_TASK <- WIFI_TASK [label="3.2> WIFI_EVENT_STA_START"]; - APP_TASK <- EVENT_TASK [label="3.3> WIFI_EVENT_STA_START"]; - === 4. 连接阶段 === - APP_TASK -> WIFI_TASK [label="4.1> 连接 Wi-Fi"]; - EVENT_TASK <- WIFI_TASK [label="4.2> WIFI_EVENT_STA_CONNECTED"]; - APP_TASK <- EVENT_TASK [label="4.3> WIFI_EVENT_STA_CONNECTED"]; - === 5. 获取 IP 阶段 === - EVENT_TASK -> LwIP_TASK [label="5.1> 启动 DHCP 客户端"]; - EVENT_TASK <- LwIP_TASK [label="5.2> IP_EVENT_STA_GOT_IP"]; - APP_TASK <- EVENT_TASK [label="5.3> IP_EVENT_STA_GOT_IP"]; - APP_TASK -> APP_TASK [label="5.4> 套接字相关初始化"]; - === 6. 断开阶段 === - EVENT_TASK <- WIFI_TASK [label="6.1> WIFI_EVENT_STA_DISCONNECTED"]; - APP_TASK <- EVENT_TASK [label="6.2> WIFI_EVENT_STA_DISCONNECTED"]; - APP_TASK -> APP_TASK [label="6.3> 断开处理"]; - === 7. IP 更改阶段 === - EVENT_TASK <- LwIP_TASK [label="7.1> IP_EVENT_STA_GOT_IP"]; - APP_TASK <- EVENT_TASK [label="7.2> IP_EVENT_STA_GOT_IP"]; - APP_TASK -> APP_TASK [label="7.3> 套接字错误处理"]; - === 8. 清理阶段 === - APP_TASK -> WIFI_TASK [label="8.1> 断开 Wi-Fi 连接"]; - APP_TASK -> WIFI_TASK [label="8.2> 终止 Wi-Fi"]; - APP_TASK -> WIFI_TASK [label="8.3> 清理 Wi-Fi"]; - } - - -1. Wi-Fi/LwIP 初始化阶段 -++++++++++++++++++++++++++++++ - - - s1.1:主任务通过调用函数 :cpp:func:`esp_netif_init()` 创建一个 LwIP 核心任务,并初始化 LwIP 相关工作。 - - - s1.2:主任务通过调用函数 :cpp:func:`esp_event_loop_create()` 创建一个系统事件任务,并初始化应用程序事件的回调函数。在此情况下,该回调函数唯一的动作就是将事件中继到应用程序任务中。 - - - s1.3:主任务通过调用函数 :cpp:func:`esp_netif_create_default_wifi_ap()` 或 :cpp:func:`esp_netif_create_default_wifi_sta()` 创建有 TCP/IP 堆栈的默认网络接口实例绑定 station 或 AP。 - - - s1.4:主任务通过调用函数 :cpp:func:`esp_wifi_init()` 创建 Wi-Fi 驱动程序任务,并初始化 Wi-Fi 驱动程序。 - - - s1.5:主任务通过调用 OS API 创建应用程序任务。 - -推荐按照 s1.1 ~ s1.5 的步骤顺序针对基于 Wi-Fi/LwIP 的应用程序进行初始化。但这一顺序 **并非** 强制,你可以在第 s1.1 步创建应用程序任务,然后在该应用程序任务中进行所有其它初始化操作。不过,如果你的应用程序任务依赖套接字,那么在初始化阶段创建应用程序任务可能并不适用。此时,你可以在接收到 IP 后再进行任务创建。 - -2. Wi-Fi 配置阶段 -+++++++++++++++++++++++++++++++ - -Wi-Fi 驱动程序初始化成功后,可以进入到配置阶段。该场景下,Wi-Fi 驱动程序处于 station 模式。因此,首先你需调用函数 :cpp:func:`esp_wifi_set_mode` (WIFI_MODE_STA) 将 Wi-Fi 模式配置为 station 模式。可通过调用其它 esp_wifi_set_xxx API 进行更多设置,例如:协议模式、国家代码、带宽等。请参阅 `{IDF_TARGET_NAME} Wi-Fi 配置`_。 - -一般情况下,我们会在建立 Wi-Fi 连接之前配置 Wi-Fi 驱动程序,但这 **并非** 强制要求。也就是说,只要 Wi-Fi 驱动程序已成功初始化,你可以在任意阶段进行配置。但是,如果你的 Wi-Fi 在建立连接后不需要更改配置,则应先在此阶段完成配置。因为调用配置 API(例如 :cpp:func:`esp_wifi_set_protocol()`)将会导致 Wi-Fi 连接断开,为操作带来不便。 - -如果 menuconfig 已使能 Wi-Fi NVS flash,则不论当前阶段还是后续的 Wi-Fi 配置信息都将被存储至该 flash 中。那么,当主板上电/重新启动时,就不需从头开始配置 Wi-Fi 驱动程序,只需调用函数 esp_wifi_get_xxx API 获取之前存储的配置信息。当然,如果不想使用之前的配置,你也可以重新配置 Wi-Fi 驱动程序。 - -3. Wi-Fi 启动阶段 -++++++++++++++++++++++++++++++++ - - - s3.1:调用函数 :cpp:func:`esp_wifi_start()` 启动 Wi-Fi 驱动程序。 - - s3.2:Wi-Fi 驱动程序将事件 `WIFI_EVENT_STA_START`_ 发布到事件任务中,然后,事件任务将执行一些正常操作并调用应用程序的事件回调函数。 - - s3.3:应用程序的事件回调函数将事件 `WIFI_EVENT_STA_START`_ 中继到应用程序任务中。此时,推荐调用函数 :cpp:func:`esp_wifi_connect()` 进行 Wi-Fi 连接。当然,你也可以等待在 `WIFI_EVENT_STA_START`_ 事件发生后的其它阶段再调用此函数。 - -4. Wi-Fi 连接阶段 -+++++++++++++++++++++++++++++++++ - - - s4.1:调用函数 :cpp:func:`esp_wifi_connect()` 后,Wi-Fi 驱动程序将启动内部扫描/连接过程。 - - - s4.2:如果内部扫描/连接过程成功,将产生 `WIFI_EVENT_STA_CONNECTED`_ 事件。然后,事件任务将启动 DHCP 客户端服务,最终触发 DHCP 程序。 - - - s4.3:在此情况下,应用程序的事件回调函数会将 `WIFI_EVENT_STA_CONNECTED`_ 事件中继到应用程序任务中。通常,应用程序不需进行操作,而你可以执行任何动作,例如:打印日志等。 - -步骤 s4.2 中 Wi-Fi 连接可能会由于某些原因而失败,例如:密码错误、未找到 AP 等。这种情况下,将引发 `WIFI_EVENT_STA_DISCONNECTED`_ 事件并提示连接错误原因。有关如何处理中断 Wi-Fi 连接的事件,请参阅下文阶段 6 的描述。 - -5. Wi-Fi 获取 IP 阶段 -+++++++++++++++++++++++++++++++++ - - - s5.1:一旦步骤 4.2 中的 DHCP 客户端初始化完成,Wi-Fi 驱动程序将进入 *获取 IP* 阶段。 - - s5.2:如果 Wi-Fi 成功从 DHCP 服务器接收到 IP 地址,则将引发 `IP_EVENT_STA_GOT_IP`_ 事件,事件任务将执行正常处理。 - - s5.3:应用程序的事件回调函数将事件 `IP_EVENT_STA_GOT_IP`_ 中继到应用程序任务中。对于那些基于 LwIP 构建的应用程序,此事件较为特殊,因为它意味着应用程序已准备就绪,可以开始任务,例如:创建 TCP/UDP 套接字等。此时较为容易犯的一个错误就是在接收到 `IP_EVENT_STA_GOT_IP`_ 事件之前就初始化套接字。**切忌在接收到 IP 之前启动任何套接字相关操作。** - -6. Wi-Fi 断开阶段 -+++++++++++++++++++++++++++++++++ - - - s6.1:当 Wi-Fi 因为某些原因(例如:AP 掉电、RSSI 较弱等)连接中断时,将产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件。此事件也可能在上文阶段 3 中发生。在这里,事件任务将通知 LwIP 任务清除/移除所有 UDP/TCP 连接。然后,所有应用程序套接字都将处于错误状态。也就是说,`WIFI_EVENT_STA_DISCONNECTED`_ 事件发生时,任何套接字都无法正常工作。 - - s6.2:上述情况下,应用程序的事件回调函数会将 `WIFI_EVENT_STA_DISCONNECTED`_ 事件中继到应用程序任务中。推荐调用函数 :cpp:func:`esp_wifi_connect()` 重新连接 Wi-Fi,关闭所有套接字,并在必要时重新创建套接字。请参阅 `WIFI_EVENT_STA_DISCONNECTED`_。 - -7. Wi-Fi IP 更改阶段 -++++++++++++++++++++++++++++++++++ - - - s7.1:如果 IP 地址发生更改,将引发 `IP_EVENT_STA_GOT_IP`_ 事件,其中 "ip_change" 被置为 "true"。 - - s7.2:**此事件对应用程序至关重要。这一事件发生时,适合关闭所有已创建的套接字并进行重新创建。** - - -8. Wi-Fi 清理阶段 -++++++++++++++++++++++++++++ - - - s8.1:调用函数 :cpp:func:`esp_wifi_disconnect()` 断开 Wi-Fi 连接。 - - s8.2:调用函数 :cpp:func:`esp_wifi_stop()` 终止 Wi-Fi 驱动程序。 - - s8.3:调用函数 :cpp:func:`esp_wifi_deinit()` 清理 Wi-Fi 驱动程序。 - - -{IDF_TARGET_NAME} Wi-Fi AP 一般情况 ---------------------------------------------- - -下图为 AP 模式下的宏观场景,其中包含不同阶段的具体描述: - - .. seqdiag:: - :caption: AP 模式下 Wi-Fi 事件场景示例 - :align: center - - seqdiag sample-scenarios-soft-ap-mode { - activation = none; - node_width = 80; - node_height = 60; - edge_length = 140; - span_height = 5; - default_shape = roundedbox; - default_fontsize = 12; - - MAIN_TASK [label = "Main\ntask"]; - APP_TASK [label = "App\ntask"]; - EVENT_TASK [label = "Event\ntask"]; - LwIP_TASK [label = "LwIP\ntask"]; - WIFI_TASK [label = "Wi-Fi\ntask"]; - - === 1. 初始化阶段 === - MAIN_TASK -> LwIP_TASK [label="1.1> 创建/初始化 LwIP"]; - MAIN_TASK -> EVENT_TASK [label="1.2> 创建/初始化事件"]; - MAIN_TASK -> WIFI_TASK [label="1.3> 创建/初始化 Wi-Fi"]; - MAIN_TASK -> APP_TASK [label="1.4> 创建应用程序任务"]; - === 2. 配置阶段 === - MAIN_TASK -> WIFI_TASK [label="2> 配置 Wi-Fi"]; - === 3. 启动阶段 === - MAIN_TASK -> WIFI_TASK [label="3.1> 启动 Wi-Fi"]; - EVENT_TASK <- WIFI_TASK [label="3.2> WIFI_EVENT_AP_START"]; - APP_TASK <- EVENT_TASK [label="3.3> WIFI_EVENT_AP_START"]; - === 4. 连接阶段 === - EVENT_TASK <- WIFI_TASK [label="4.1> WIFI_EVENT_AP_STACONNECTED"]; - APP_TASK <- EVENT_TASK [label="4.2> WIFI_EVENT_AP_STACONNECTED"]; - === 5. 断开阶段 === - EVENT_TASK <- WIFI_TASK [label="5.1> WIFI_EVENT_AP_STADISCONNECTED"]; - APP_TASK <- EVENT_TASK [label="5.2> WIFI_EVENT_AP_STADISCONNECTED"]; - APP_TASK -> APP_TASK [label="5.3> 断开处理"]; - === 6. 清理阶段 === - APP_TASK -> WIFI_TASK [label="6.1> 断开 Wi-Fi 连接"]; - APP_TASK -> WIFI_TASK [label="6.2> 终止 Wi-Fi"]; - APP_TASK -> WIFI_TASK [label="6.3> 清理 Wi-Fi"]; - } - - -{IDF_TARGET_NAME} Wi-Fi 扫描 ----------------------------------- - -目前,仅 station 或 station/AP 共存模式支持 :cpp:func:`esp_wifi_scan_start()` API。 - -扫描类型 -+++++++++++++++++++++++++ - -.. list-table:: - :header-rows: 1 - :widths: 15 50 - - * - 模式 - - 描述 - * - 主动扫描 - - 通过发送 probe request 进行扫描。该模式为默认的扫描模式。 - * - 被动扫描 - - 不发送 probe request。跳至某一特定信道并等待 beacon。应用程序可通过 :cpp:type:`wifi_scan_config_t` 中的 scan_type 字段使能被动扫描。 - * - 前端扫描 - - 在 station 模式下 Wi-Fi 未连接时,可进行前端扫描。Wi-Fi 驱动程序决定进行前端扫描还是后端扫描,应用程序无法配置这两种模式。 - * - 后端扫描 - - 在 station 模式或 station/AP 共存模式下 Wi-Fi 已连接时,可进行后端扫描。Wi-Fi 驱动程序决定进行前端扫描还是后端扫描,应用程序无法配置这两种模式。 - * - 全信道扫描 - - 扫描所有信道。:cpp:type:`wifi_scan_config_t` 中的 channel 字段为 0 时,当前模式为全信道扫描。 - * - 特定信道扫描 - - 仅扫描特定的信道。:cpp:type:`wifi_scan_config_t` 中的 channel 字段为 1-14 时,当前模式为特定信道扫描。 - -上表中的扫描模式可以任意组合,因此共有 8 种不同扫描方式: - - - 全信道后端主动扫描 - - 全信道后端被动扫描 - - 全信道前端主动扫描 - - 全信道后端被动扫描 - - 特定信道后端主动扫描 - - 特定信道后端被动扫描 - - 特定信道前端主动扫描 - - 特定信道前端被动扫描 - -扫描配置 -+++++++++++++++++ - -扫描类型与其他扫描属性通过函数 :cpp:func:`esp_wifi_scan_start()` 进行配置。下表详细描述了函数 :cpp:type:`wifi_scan_config_t` 各字段信息。 - -.. list-table:: - :header-rows: 1 - :widths: 15 50 - - * - 字段 - - 描述 - * - ssid - - 如果该字段的值不为 NULL,则仅可扫描到具有相同 SSID 值的 AP。 - * - bssid - - 如果该字段的值不为 NULL,则仅可扫描到具有相同 BSSID 值的 AP。 - * - channel - - 如果该字段值为 0,将进行全信道扫描;反之,将针对特定信道进行扫描。 - * - show_hidden - - 如果该字段值为 0,本次扫描将忽略具有隐藏 SSID 的 AP;反之,这些 AP 也会在扫描时被视为正常 AP。 - * - scan_type - - 如果该字段值为为 WIFI_SCAN_TYPE_ACTIVE,则本次扫描为主动扫描;反之,将被视为被动扫描。 - * - scan_time - - 该字段用于控制每个信道的扫描时间。 - - 被动扫描时,scan_time.passive 字段负责为每个信道指定扫描时间。 - - 主动扫描时,每个信道的扫描时间如下列表所示。其中,min 代表 scan_time_active_min,max 代表 scan_time_active_max。 - - - min=0, max=0:每个信道的扫描时间为 120 ms。 - - min>0, max=0:每个信道的扫描时间为 120 ms。 - - min=0, max>0:每个信道的扫描时间为 ``max`` ms。 - - min>0, max>0:每个信道扫描的最短时间为 ``min`` ms。 如果在这段时间内未找到 AP,将跳转至下一个信道。如这段时间内找到 AP,则该信道的扫描时间为 ``max`` ms。 - - 如希望提升 Wi-Fi 扫描性能,则可修改上述两个参数。 - - -调用 API :cpp:func:`esp_wifi_set_config()` 可全局配置一些扫描属性,请参阅 `station 基本配置`_。 - -在所有信道中扫描全部 AP(前端) -+++++++++++++++++++++++++++++++++++++++++++ - -场景: - -.. seqdiag:: - :caption: 所有 Wi-Fi 信道的前端扫描 - :align: center - - seqdiag foreground-scan-all-channels { - activation = none; - node_width = 80; - node_height = 60; - edge_length = 160; - span_height = 5; - default_shape = roundedbox; - default_fontsize = 12; - - APP_TASK [label = "App\ntask"]; - EVENT_TASK [label = "Event\ntask"]; - WIFI_TASK [label = "Wi-Fi\ntask"]; - - APP_TASK -> WIFI_TASK [label="1.1 > 配置国家代码"]; - APP_TASK -> WIFI_TASK [label="1.2 > 扫描配置"]; - WIFI_TASK -> WIFI_TASK [label="2.1 > 扫描信道 1"]; - WIFI_TASK -> WIFI_TASK [label="2.2 > 扫描信道 2"]; - WIFI_TASK -> WIFI_TASK [label="..."]; - WIFI_TASK -> WIFI_TASK [label="2.x > 扫描信道 N"]; - EVENT_TASK <- WIFI_TASK [label="3.1 > WIFI_EVENT_SCAN_DONE"]; - APP_TASK <- EVENT_TASK [label="3.2 > WIFI_EVENT_SCAN_DONE"]; - } - - -上述场景中描述了全信道前端扫描过程。仅 station 模式支持前端扫描,该模式下 station 未连接任何 AP。前端扫描还是后端扫描完全由 Wi-Fi 驱动程序决定,应用程序无法配置这一模式。 - -详细描述: - -扫描配置阶段 -************************** - - - s1.1:如果默认的国家信息有误,调用函数 :cpp:func:`esp_wifi_set_country()` 进行配置。请参阅 `Wi-Fi 国家/地区代码`_。 - - s1.2:调用函数 :cpp:func:`esp_wifi_scan_start()` 配置扫描信息,可参阅 `扫描配置`_。该场景为全信道扫描,将 SSID/BSSID/channel 设置为 0 即可。 - - -Wi-Fi 驱动程序内部扫描阶段 -************************************** - - - s2.1:Wi-Fi 驱动程序切换至信道 1,此时的扫描类型为 WIFI_SCAN_TYPE_ACTIVE,同时发送一个 probe request。反之,Wi-Fi 将等待接收 AP beacon。Wi-Fi 驱动程序将在信道 1 停留一段时间。min/max 扫描时间中定义了 Wi-Fi 在信道 1 中停留的时间长短,默认为 120 ms。 - - s2.2:Wi-Fi 驱动程序跳转至信道 2,并重复进行 s2.1 中的步骤。 - - s2.3:Wi-Fi 驱动程序扫描最后的信道 N,N 的具体数值由步骤 s1.1 中配置的国家代码决定。 - -扫描完成后事件处理阶段 -********************************* - - - s3.1:当所有信道扫描全部完成后,将产生 `WIFI_EVENT_SCAN_DONE`_ 事件。 - - s3.2:应用程序的事件回调函数告知应用程序任务已接收到 `WIFI_EVENT_SCAN_DONE`_ 事件。调用函数 :cpp:func:`esp_wifi_scan_get_ap_num()` 获取在本次扫描中找到的 AP 数量。然后,分配出足够的事物槽,并调用函数 :cpp:func:`esp_wifi_scan_get_ap_records()` 获取 AP 记录。请注意,一旦调用 :cpp:func:`esp_wifi_scan_get_ap_records()`,Wi-Fi 驱动程序中的 AP 记录将被释放。但是,请不要在单个扫描完成事件中重复调用两次 :cpp:func:`esp_wifi_scan_get_ap_records()`。反之,如果扫描完成事件发生后未调用 :cpp:func:`esp_wifi_scan_get_ap_records()`,则 Wi-Fi 驱动程序中的 AP 记录不会被释放。因此,请务必确保调用函数 :cpp:func:`esp_wifi_scan_get_ap_records()`,且仅调用一次。 - -在所有信道上扫描全部 AP(后端) -++++++++++++++++++++++++++++++++++++++++ - -场景: - -.. seqdiag:: - :caption: 所有 Wi-Fi 信道的后端扫描 - :align: center - - seqdiag background-scan-all-channels { - activation = none; - node_width = 80; - node_height = 60; - edge_length = 160; - span_height = 5; - default_shape = roundedbox; - default_fontsize = 12; - - APP_TASK [label = "App\ntask"]; - EVENT_TASK [label = "Event\ntask"]; - WIFI_TASK [label = "Wi-Fi\ntask"]; - - APP_TASK -> WIFI_TASK [label="1.1 > 配置国家代码"]; - APP_TASK -> WIFI_TASK [label="1.2 > 扫描配置"]; - WIFI_TASK -> WIFI_TASK [label="2.1 > 扫描信道 1"]; - WIFI_TASK -> WIFI_TASK [label="2.2 > 返回主信道 H"]; - WIFI_TASK -> WIFI_TASK [label="2.3 > 扫描信道 2"]; - WIFI_TASK -> WIFI_TASK [label="2.4 > 返回主信道 H"]; - WIFI_TASK -> WIFI_TASK [label="..."]; - WIFI_TASK -> WIFI_TASK [label="2.x-1 > 扫描信道 N"]; - WIFI_TASK -> WIFI_TASK [label="2.x > 返回主信道 H"]; - EVENT_TASK <- WIFI_TASK [label="3.1 > WIFI_EVENT_SCAN_DONE"]; - APP_TASK <- EVENT_TASK [label="3.2 > WIFI_EVENT_SCAN_DONE"]; - } - -上述场景为一次全信道后端扫描。与 `在所有信道中扫描全部 AP(前端)`_ 相比,全信道后端扫描的不同之处在于:在跳至下一个信道之前,Wi-Fi 驱动程序会先返回主信道停留 30 ms,以便 Wi-Fi 连接有一定的时间发送/接收数据。 - -在所有信道中扫描特定 AP -+++++++++++++++++++++++++++++++++++++++ - -场景: - -.. seqdiag:: - :caption: 扫描特定的 Wi-Fi 信道 - :align: center - - seqdiag scan-specific-channels { - activation = none; - node_width = 80; - node_height = 60; - edge_length = 160; - span_height = 5; - default_shape = roundedbox; - default_fontsize = 12; - - APP_TASK [label = "App\ntask"]; - EVENT_TASK [label = "Event\ntask"]; - WIFI_TASK [label = "Wi-Fi\ntask"]; - - APP_TASK -> WIFI_TASK [label="1.1 > 配置国家代码"]; - APP_TASK -> WIFI_TASK [label="1.2 > 扫描配置"]; - WIFI_TASK -> WIFI_TASK [label="2.1 > 扫描信道 C1"]; - WIFI_TASK -> WIFI_TASK [label="2.2 > 扫描信道 C2"]; - WIFI_TASK -> WIFI_TASK [label="..."]; - WIFI_TASK -> WIFI_TASK [label="2.x > 扫描信道 CN,或找到 AP"]; - EVENT_TASK <- WIFI_TASK [label="3.1 > WIFI_EVENT_SCAN_DONE"]; - APP_TASK <- EVENT_TASK [label="3.2 > WIFI_EVENT_SCAN_DONE"]; - } - -该扫描过程与 `在所有信道中扫描全部 AP(前端)`_ 相似。区别在于: - - - s1.1:在步骤 1.2 中,目标 AP 将配置为 SSID/BSSID。 - - s2.1 ~ s2.N:每当 Wi-Fi 驱动程序扫描某个 AP 时,它将检查该 AP 是否为目标 AP。如果本次扫描类型为 ``WIFI_FAST_SCAN``,且确认已找到目标 AP,则将产生扫描完成事件,同时结束本次扫描;反之,扫描将继续。请注意,第一个扫描的信道可能不是信道 1,因为 Wi-Fi 驱动程序会优化扫描顺序。 - -如果有多个匹配目标 AP 信息的 AP,例如:碰巧扫描到两个 SSID 为 "ap" 的 AP。如果本次扫描类型为 ``WIFI_FAST_SCAN``,则仅可找到第一个扫描到的 "ap";如果本次扫描类型为 ``WIFI_ALL_CHANNEL_SCAN``,则两个 "ap“ 都将被找到,且 station 将根据配置规则连接至其需要连接的 "ap",请参阅 `station 基本配置`_。 - -你可以在任意信道中扫描某个特定的 AP,或扫描该信道中的所有 AP。这两种扫描过程也较为相似。 - -在 Wi-Fi 连接模式下扫描 -+++++++++++++++++++++++++ - -调用函数 :cpp:func:`esp_wifi_connect()` 后,Wi-Fi 驱动程序将首先尝试扫描已配置的 AP。Wi-Fi 连接模式下的扫描过程与 `在所有信道中扫描特定 AP`_ 过程相同,但连接模式下扫描结束后将不会产生扫描完成事件。如果已找到目标 AP,则 Wi-Fi 驱动程序将开始 Wi-Fi 连接;反之,将产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件。请参阅 `在所有信道中扫描特定 AP`_。 - -在禁用模式下扫描 -++++++++++++++++++++ - -如果函数 :cpp:func:`esp_wifi_scan_start()` 中的禁用参数为 "true",则本次扫描为禁用模式下的扫描。在该次扫描完成之前,应用程序任务都将被禁用。禁用模式下的扫描和正常扫描相似,不同之处在于,禁用模式下扫描完成之后将不会出现扫描完成事件。 - -并行扫描 -+++++++++++++ - -有时,可能会有两个应用程序任务同时调用函数 :cpp:func:`esp_wifi_scan_start()`,或者某个应用程序任务在获取扫描完成事件之前再次调用了函数 :cpp:func:`esp_wifi_scan_start()`。这两种情况都有可能会发生。**但是,Wi-Fi 驱动程序并不足以支持多个并行的扫描。因此,应避免上述并行扫描**。随着 {IDF_TARGET_NAME} 的 Wi-Fi 功能不断提升,未来的版本中可能会增加并行扫描支持。 - -连接 Wi-Fi 时扫描 -+++++++++++++++++++++++++++++++ - -如果 Wi-Fi 正在连接,则调用函数 :cpp:func:`esp_wifi_scan_start()` 后扫描将立即失败,因为 Wi-Fi 连接优先级高于扫描。如果扫描是因为 Wi-Fi 连接而失败的,此时推荐采取的策略为:等待一段时间后重试。因为一旦 Wi-Fi 连接完成后,扫描将立即成功。 - -但是,延时重试策略并非万无一失。试想以下场景: - -- 如果 station 正在连接一个不存在的 AP,或正在使用错误的密码连接一个 AP,此时将产生事件 `WIFI_EVENT_STA_DISCONNECTED`_。 -- 接收到断开连接事件后,应用程序调用函数 :cpp:func:`esp_wifi_connect()` 进行重新连接。 -- 而另一个应用程序任务(如,控制任务)调用了函数 :cpp:func:`esp_wifi_scan_start()` 进行扫描。这种情况下,每一次扫描都会立即失败,因为 station 一直处于正在连接状态。 -- 扫描失败后,应用程序将等待一段时间后进行重新扫描。 - -上述场景中的扫描永远不会成功,因为 Wi-Fi 一直处于正在连接过程中。因此,如果你的应用程序也可能发生相似的场景,那么就需要为其配置一个更佳的重新连接策略。例如: - -- 应用程序可以定义一个连续重新连接次数的最大值,当重新连接的次数达到这个最大值时,立刻停止重新连接。 -- 应用程序可以在首轮连续重新连接 N 次后立即进行重新连接,然后延时一段时间后再进行下一次重新连接。 - -可以给应用程序定义其特殊的重新连接策略,以防止扫描无法成功。请参阅 `Wi-Fi 重新连接`_。 - -{IDF_TARGET_NAME} Wi-Fi station 连接场景 ------------------------------------------------------------- - -该场景仅针对在扫描阶段只找到一个目标 AP 的情况,对于多个相同 SSID AP 的情况,请参阅 `找到多个 AP 时的 {IDF_TARGET_NAME} Wi-Fi station 连接`_。 - -通常,应用程序无需关心这一连接过程。如感兴趣,可参看下述简介。 - -场景: - -.. seqdiag:: - :caption: Wi-Fi station 连接过程 - :align: center - - seqdiag station-connecting-process { - activation = none; - node_width = 80; - node_height = 60; - edge_length = 160; - span_height = 5; - default_shape = roundedbox; - default_fontsize = 12; - - EVENT_TASK [label = "Event\ntask"]; - WIFI_TASK [label = "Wi-Fi\ntask"]; - AP [label = "AP"]; - - === 1. 扫描阶段 === - WIFI_TASK -> WIFI_TASK [label="1.1 > 扫描"]; - EVENT_TASK <- WIFI_TASK [label="1.2 > WIFI_EVENT_STA_DISCONNECTED"]; - === 2. 认证阶段 === - WIFI_TASK -> AP [label="2.1 > Auth request"]; - EVENT_TASK <- WIFI_TASK [label="2.2 > WIFI_EVENT_STA_DISCONNECTED"]; - WIFI_TASK <- AP [label="2.3 > Auth response"]; - EVENT_TASK <- WIFI_TASK [label="2.4 > WIFI_EVENT_STA_DISCONNECTED"]; - === 3. 关联阶段 === - WIFI_TASK -> AP [label="3.1 > Assoc request"]; - EVENT_TASK <- WIFI_TASK [label="3.2 > WIFI_EVENT_STA_DISCONNECTED"]; - WIFI_TASK <- AP [label="3.3 > Assoc response"]; - EVENT_TASK <- WIFI_TASK [label="3.4 > WIFI_EVENT_STA_DISCONNECTED"]; - === 4. 四次握手阶段 === - EVENT_TASK <- WIFI_TASK [label="4.1 > WIFI_EVENT_STA_DISCONNECTED"]; - WIFI_TASK <- AP [label="4.2 > 1/4 EAPOL"]; - WIFI_TASK -> AP [label="4.3 > 2/4 EAPOL"]; - EVENT_TASK <- WIFI_TASK [label="4.4 > WIFI_EVENT_STA_DISCONNECTED"]; - WIFI_TASK <- AP [label="4.5 > 3/4 EAPOL"]; - WIFI_TASK -> AP [label="4.6 > 4/4 EAPOL"]; - EVENT_TASK <- WIFI_TASK [label="4.7 > WIFI_EVENT_STA_CONNECTED"]; - } - - -扫描阶段 -+++++++++++++++++++++ - - - s1.1:Wi-Fi 驱动程序开始在“Wi-Fi 连接”模式下扫描。详细信息请参阅 `在 Wi-Fi 连接模式下扫描`_。 - - s1.2:如果未找到目标 AP,将产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件,且原因代码为 ``WIFI_REASON_NO_AP_FOUND``。请参阅 `Wi-Fi 原因代码`_。 - -认证阶段 -+++++++++++++++++++++ - - - s2.1:发送认证请求数据包并使能认证计时器。 - - s1.2:如果在认证计时器超时之前未接收到认证响应数据包,将产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件,且原因代码为 ``WIFI_REASON_AUTH_EXPIRE``。请参阅 `Wi-Fi 原因代码`_。 - - s2.3:接收到认证响应数据包,且认证计时器终止。 - - s2.4:AP 在响应中拒绝认证且产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件,原因代码为 ``WIFI_REASON_AUTH_FAIL`` 或为 AP 指定的其它原因。请参阅 `Wi-Fi 原因代码`_。 - -关联阶段 -+++++++++++++++++++++ - - - s3.1:发送关联请求并使能关联计时器。 - - s3.2:如果在关联计时器超时之前未接收到关联响应,将产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件,且原因代码为 ``WIFI_REASON_DISASSOC_DUE_TO_INACTIVITY``。请参阅 `Wi-Fi 原因代码`_。 - - s3.3:接收到关联响应,且关联计时器终止。 - - s3.4:AP 在响应中拒绝关联且产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件,原因代码将在关联响应中指定。请参阅 `Wi-Fi 原因代码`_。 - - -四次握手阶段 -++++++++++++++++++++++++++ - - - s4.1:使能握手定时器,定时器终止之前未接收到 1/4 EAPOL,此时将产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件,且原因代码为 ``WIFI_REASON_HANDSHAKE_TIMEOUT``。请参阅 `Wi-Fi 原因代码`_。 - - s4.2:接收到 1/4 EAPOL。 - - s4.3:station 回复 2/4 EAPOL。 - - s4.4:如果在握手定时器终止之前未接收到 3/4 EAPOL,将产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件,且原因代码为 ``WIFI_REASON_HANDSHAKE_TIMEOUT``。请参阅 `Wi-Fi 原因代码`_。 - - s4.5:接收到 3/4 EAPOL。 - - s4.6:station 回复 4/4 EAPOL。 - - s4.7:station 产生 `WIFI_EVENT_STA_CONNECTED`_ 事件。 - - -Wi-Fi 原因代码 -+++++++++++++++++++++ - -下表罗列了 {IDF_TARGET_NAME} 中定义的原因代码。其中,第一列为 :component_file:`esp_wifi/include/esp_wifi_types.h` 中定义的宏名称。名称中省去了前缀 ``WIFI_REASON``,也就是说,名称 ``UNSPECIFIED`` 实际应为 ``WIFI_REASON_UNSPECIFIED``,以此类推。第二列为原因代码的相应数值。第三列为该原因映射到 IEEE 802.11-2020 中 9.4.1.7 段的标准值。(更多详细信息,请参阅前文描述。)最后一列为这一原因的描述。 - -.. list-table:: - :header-rows: 1 - :widths: 5 10 12 40 - - * - 原因代码 - - 数值 - - 映射值 - - 描述 - * - UNSPECIFIED - - 1 - - 1 - - 出现内部错误,例如:内存已满,内部发送失败,或该原因已被远端接收等。 - * - AUTH_EXPIRE - - 2 - - 2 - - 先前的 authentication 已失效。 - - 对于 ESP station,出现以下情况时将报告该代码: - - - authentication 超时; - - 从 AP 接收到该代码。 - - 对于 ESP AP,出现以下情况时将报告该代码: - - - 在过去五分钟之内,AP 未从 station 接收到任何数据包; - - 由于调用了函数 :cpp:func:`esp_wifi_stop()` 导致 AP 终止; - - 由于调用了函数 :cpp:func:`esp_wifi_deauth_sta()` 导致 station 的 authentication 取消。 - * - AUTH_LEAVE - - 3 - - 3 - - authentication 取消,因为发送 station 正在离开(或已经离开)。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - * - DISASSOC_DUE_TO_INACTIVITY - - 4 - - 4 - - 因为 AP 不活跃,association 取消。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - - 对于 ESP AP,出现以下情况时将报告该代码: - - - 在过去五分钟之内, AP 未从 station 接收到任何数据包; - - 由于调用了函数 :cpp:func:`esp_wifi_stop()` 导致 AP 终止; - - 由于调用了函数 :cpp:func:`esp_wifi_deauth_sta()` 导致 station 的 authentication 取消。 - * - ASSOC_TOOMANY - - 5 - - 5 - - association 取消,因为 AP 无法同时处理所有当前已关联的 STA。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - - 对于 ESP AP,出现以下情况时将报告该代码: - - - 与 AP 相关联的 station 数量已到达 AP 可支持的最大值。 - * - CLASS2_FRAME_FROM_NONAUTH_STA - - 6 - - 6 - - 从一个未认证 station 接收到 class-2 frame。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - - 对于 ESP AP,出现以下情况时将报告该代码: - - - AP 从一个未认证 station 接收到数据包。 - * - CLASS3_FRAME_FROM_NONASSOC_STA - - 7 - - 7 - - 从一个未关联 station 接收到的 class-3 frame。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - - 对于 ESP AP,出现以下情况时将报告该代码: - - - AP 从未关联 station 接收到数据包。 - * - ASSOC_LEAVE - - 8 - - 8 - - association 取消,因为发送 station 正在离开(或已经离开)BSS。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - - 由于调用 :cpp:func:`esp_wifi_disconnect()` 和其它 API,station 断开连接。 - * - ASSOC_NOT_AUTHED - - 9 - - 9 - - station 的 re(association) 请求未被响应 station 认证。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - - 对于 ESP AP,出现以下情况时将报告该代码: - - - AP 从一个已关联,但未认证的 station 接收到数据包。 - * - DISASSOC_PWRCAP_BAD - - 10 - - 10 - - association 取消,因为无法接收功率能力 (Power Capability) 元素中的信息。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - * - DISASSOC_SUPCHAN_BAD - - 11 - - 11 - - association 取消,因为无法接收支持的信道 (Supported Channels) 元素中的信息。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - * - IE_INVALID - - 13 - - 13 - - 无效元素,即内容不符合 Wi-Fi 协议中帧格式 (Frame formats) 章节所描述标准的元素。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - - 对于 ESP AP,出现以下情况时将报告该代码: - - - AP 解析了一个错误的 WPA 或 RSN IE。 - * - MIC_FAILURE - - 14 - - 14 - - 消息完整性代码 (MIC) 出错。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - * - 4WAY_HANDSHAKE_TIMEOUT - - 15 - - 15 - - 四次握手超时。由于某些历史原因,在 ESP 中该原因代码实为 ``WIFI_REASON_HANDSHAKE_TIMEOUT``。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 握手超时。 - - 从 AP 接收到该代码。 - * - GROUP_KEY_UPDATE_TIMEOUT - - 16 - - 16 - - 组密钥 (Group-Key) 握手超时。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - * - IE_IN_4WAY_DIFFERS - - 17 - - 17 - - 四次握手中产生的元素与 (re-)association 后的 request/probe 以及 response/beacon frame 中的信息不同。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - - station 发现四次握手的 IE 与 (re-)association 后的 request/probe 以及 response/beacon frame 中的 IE 不同。 - * - GROUP_CIPHER_INVALID - - 18 - - 18 - - 无效组密文。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - * - PAIRWISE_CIPHER_INVALID - - 19 - - 19 - - 无效成对密文。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - * - AKMP_INVALID - - 20 - - 20 - - 无效 AKMP。 - - 对于 ESP station,出现以下情况时报告该代码: - - 从 AP 接收到该代码。 - * - UNSUPP_RSN_IE_VERSION - - 21 - - 21 - - 不支持的 RSNE 版本。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - * - INVALID_RSN_IE_CAP - - 22 - - 22 - - 无效的 RSNE 性能。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - * - 802_1X_AUTH_FAILED - - 23 - - 23 - - IEEE 802.1X. authentication 失败。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - - 对于 ESP AP,出现以下情况时将报告该代码: - - - IEEE 802.1X. authentication 失败。 - * - CIPHER_SUITE_REJECTED - - 24 - - 24 - - 因安全策略,安全密钥算法套件 (cipher suite) 被拒。 - - 对于 ESP station,出现以下情况时报告该代码: - - - 从 AP 接收到该代码。 - * - TDLS_PEER_UNREACHABLE - - 25 - - 25 - - 通过 TDLS 直连无法到达TDLS 对端 STA,导致 TDLS 直连中断。 - * - TDLS_UNSPECIFIED - - 26 - - 26 - - 不明原因的 TDLS 直连中断。 - * - SSP_REQUESTED_DISASSOC - - 27 - - 27 - - association 取消,由于会话被 SSP request 终止。 - * - NO_SSP_ROAMING_AGREEMENT - - 28 - - 28 - - association 取消,由于缺乏 SSP 漫游认证。 - * - BAD_CIPHER_OR_AKM - - 29 - - 29 - - 请求的服务被拒绝,由于 SSP 密码套件或者 AKM 的需求。 - * - NOT_AUTHORIZED_THIS_LO CATION - - 30 - - 30 - - 请求的服务在此位置未得到授权。 - * - SERVICE_CHANGE_PRECLUDES_TS - - 31 - - 31 - - TS 被删除,原因是:BSS 服务特性或者运行模式改变导致 Qos AP 缺少足够的带宽给 Qos STA 使用(例如:一个HT BSS 从 40 MHz 的信道切换到 20 MHz 的信道)。 - * - UNSPECIFIED_QOS - - 32 - - 32 - - association 取消,由于不明确的 QoS 相关原因。 - * - NOT_ENOUGH_BANDWIDTH - - 33 - - 33 - - association 取消,由于QoS AP 缺少足够的带宽给该 QoS STA 使用。 - * - MISSING_ACKS - - 34 - - 34 - - association 取消,原因是:大量的帧需要被确认,但由于 AP 传输或者糟糕的信道条件而没有被确认。 - * - EXCEEDED_TXOP - - 35 - - 35 - - association 取消,由于 STA 的传输超过了 TXOPs 的限制。 - * - STA_LEAVING - - 36 - - 36 - - 请求 STA 离开了 BSS 或者重置了。 - * - END_BA - - 37 - - 37 - - 请求 STA 不再使用该流或者会话。 - * - UNKNOWN_BA - - 38 - - 38 - - 请求 STA 使用一种尚未完成的机制接收帧。 - * - TIMEOUT - - 39 - - 39 - - 对端 STA 的请求超时。 - * - Reserved - - 40 ~ 45 - - 40 ~ 45 - - 保留 - * - PEER_INITIATED - - 46 - - 46 - - 在 Disassociation 帧中:已达到授权访问限制。 - * - AP_INITIATED - - 47 - - 47 - - 在 Disassociation 帧中:外部服务需求。 - * - INVALID_FT_ACTION_FRAME_COUNT - - 48 - - 48 - - 无效的 FT Action 帧计数。 - * - INVALID_PMKID - - 49 - - 49 - - 无效的成对主密钥标识符(PMKID)。 - * - INVALID_MDE - - 50 - - 50 - - 无效的 MDE。 - * - INVALID_FTE - - 51 - - 51 - - 无效的 FTE。 - * - TRANSMISSION_LINK_ESTABLISHMENT_FAILED - - 67 - - 67 - - 在备用信道中建立传输链路失败。 - * - ALTERATIVE_CHANNEL_OCCUPIED - - 68 - - 68 - - 备用信道被占用。 - * - BEACON_TIMEOUT - - 200 - - 保留 - - 乐鑫特有的 Wi-Fi 原因代码: 当 station 连续失去 N 个 beacon,将中断连接并报告该代码。 - * - NO_AP_FOUND - - 201 - - 保留 - - 乐鑫特有的 Wi-Fi 原因代码: 当 station 未扫描到目标 AP 时,将报告该代码。 - * - AUTH_FAIL - - 202 - - 保留 - - 乐鑫特有的 Wi-Fi 原因代码: authentication 失败,但并非由超时而引发。 - * - ASSOC_FAIL - - 203 - - 保留 - - 乐鑫特有的 Wi-Fi 原因代码: association 失败,但并非由 DISASSOC_DUE_TO_INACTIVITY 或 ASSOC_TOOMANY 引发。 - * - HANDSHAKE_TIMEOUT - - 204 - - 保留 - - 乐鑫特有的 Wi-Fi 原因代码: 握手失败,与 WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT 中失败原因相同。 - * - CONNECTION_FAIL - - 205 - - 保留 - - 乐鑫特有的 Wi-Fi 原因代码: AP 连接失败。 - - -与密码错误有关的 Wi-Fi 原因代码 -+++++++++++++++++++++++++++++++++ - -下表罗列了与密码错误相关的 Wi-Fi 原因代码。 - -.. list-table:: - :header-rows: 1 - :widths: 5 10 40 - - * - 原因代码 - - 数值 - - 描述 - * - 4WAY_HANDSHAKE_TIMEOUT - - 15 - - 四次握手超时。STA 在连接加密的 AP 的时候输入了错误的密码 - * - NO_AP_FOUND - - 201 - - 密码错误会出现这个原因代码的场景有如下两个: - - - STA 在连接加密的 AP 的时候没有输入密码 - - STA 在连接非加密的 AP 的时候输入了密码 - * - HANDSHAKE_TIMEOUT - - 204 - - 握手超时。 - -与低 RSSI 有关的 Wi-Fi 原因代码 -+++++++++++++++++++++++++++++++++ - -下表罗列了与低 RSSI 相关的 Wi-Fi 原因代码。 - -.. list-table:: - :header-rows: 1 - :widths: 5 10 40 - - * - 原因代码 - - 数值 - - 描述 - * - NO_AP_FOUND - - 201 - - 低 RSSI 导致 station 无法扫描到目标 AP - * - HANDSHAKE_TIMEOUT - - 204 - - 握手超时。 - - -找到多个 AP 时的 {IDF_TARGET_NAME} Wi-Fi station 连接 ----------------------------------------------------------------------- - -该场景与 `{IDF_TARGET_NAME} Wi-Fi station 连接场景`_ 相似,不同之处在于该场景中不会产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件,除非 station 无法连接所有找到的 AP。 - -Wi-Fi 重新连接 ---------------------------- - -出于多种原因,station 可能会断开连接,例如:连接的 AP 重新启动等。应用程序应负责重新连接。推荐使用的方法为:在接收到 `WIFI_EVENT_STA_DISCONNECTED`_ 事件后调用函数 :cpp:func:`esp_wifi_connect()`。 - -但有时,应用程序需要更复杂的方式进行重新连接: - -- 如果断开连接事件是由调用函数 :cpp:func:`esp_wifi_disconnect()` 引发的,那么应用程序可能不希望进行重新连接。 -- 如果 station 随时可能调用函数 :cpp:func:`esp_wifi_scan_start()` 开始扫描,此时就需要一个更佳的重新连接方法,请参阅 `连接 Wi-Fi 时扫描`_。 - -另一点需要注意的是,如果存在多个具有相同 SSID 的 AP,那么重新连接后可能不会连接到之前的同一个 AP。重新连接时,station 将永远选择最佳的 AP 进行连接。 - -Wi-Fi beacon 超时 ---------------------------- - -{IDF_TARGET_NAME} 使用 beacon 超时机制检测 AP 是否活跃。如果 station 在 inactive 时间内未收到所连接 AP 的 beacon,将发生 beacon 超时。inactive 时间通过调用函数 :cpp:func:`esp_wifi_set_inactive_time()` 设置。 - -beacon 超时发生后,station 将向 AP 发送 5 个 probe request,如果仍未从 AP 接收到 probe response 或 beacon,station 将与 AP 断开连接并产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件。 - -需要注意的是,扫描过程中会重置 beacon 超时所使用的定时器,即扫描过程会影响 `WIFI_EVENT_STA_BEACON_TIMEOUT`_ 事件的触发。 - -{IDF_TARGET_NAME} Wi-Fi 配置 -------------------------------------- - -使能 Wi-Fi NVS 时,所有配置都将存储到 flash 中;反之,请参阅 `Wi-Fi NVS Flash`_。 - -Wi-Fi 模式 -+++++++++++++++++++++++++ -调用函数 :cpp:func:`esp_wifi_set_mode()` 设置 Wi-Fi 模式。 - -.. list-table:: - :header-rows: 1 - :widths: 15 50 - - * - 模式 - - 描述 - * - ``WIFI_MODE_NULL`` - - NULL 模式:此模式下,内部数据结构不分配给 station 和 AP,同时,station 和 AP 接口不会为发送/接收 Wi-Fi 数据进行初始化。通常,此模式用于 Sniffer,或者你不想通过调用函数 :cpp:func:`esp_wifi_deinit()` 卸载整个 Wi-Fi 驱动程序来同时停止 station 和 AP。 - * - ``WIFI_MODE_STA`` - - station 模式:此模式下,:cpp:func:`esp_wifi_start()` 将初始化内部 station 数据,同时 station 接口准备发送/接收 Wi-Fi 数据。调用函数 :cpp:func:`esp_wifi_connect()` 后,station 将连接到目标 AP。 - * - ``WIFI_MODE_AP`` - - AP 模式:在此模式下,:cpp:func:`esp_wifi_start()` 将初始化内部 AP 数据,同时 AP 接口准备发送/接收 Wi-Fi 数据。随后,Wi-Fi 驱动程序开始广播 beacon,AP 即可与其它 station 连接。 - * - ``WIFI_MODE_APSTA`` - - station/AP 共存模式:在此模式下,函数 :cpp:func:`esp_wifi_start()` 将同时初始化 station 和 AP。该步骤在 station 模式和 AP 模式下完成。请注意 ESP station 所连外部 AP 的信道优先于 ESP AP 信道。 - -.. only:: esp32c5 - - Wi-Fi 频段配置 - +++++++++++++++++++++++++ - - 可通过函数 :cpp:func:`esp_wifi_set_band_mode()` 设置 {IDF_TARGET_NAME} 所使用的 Wi-Fi 频段模式。 - - .. list-table:: - :header-rows: 1 - :widths: 15 50 - - * - 模式 - - 描述 - * - ``WIFI_BAND_MODE_2G_ONLY`` - - **2.4 GHz 频段模式**:设备仅可在 2.4 GHz 频段信道上工作。 - * - ``WIFI_BAND_MODE_5G_ONLY`` - - **5 GHz 频段模式**:设备仅可在 5 GHz 频段信道上工作。 - * - ``WIFI_BAND_MODE_AUTO`` - - **2.4 GHz + 5 GHz 自动模式**:设备可根据所连接的 AP 或 SoftAP 配置,自动选择 2.4 GHz 或 5 GHz 频段。 - - .. note:: - - ``WIFI_BAND_MODE_AUTO`` 并不表示同时支持双频段,而是允许自动选择频段。 - - 当工作在 ``WIFI_BAND_MODE_AUTO`` 模式下时,可以分别为 2.4 GHz 和 5 GHz 频段配置协议和带宽: - - - 使用函数 :cpp:func:`esp_wifi_set_protocols()` 设置每个频段支持的协议类型(例如 802.11b/g/n/ac/ax); - - - 使用函数 :cpp:func:`esp_wifi_set_bandwidths()` 设置每个频段的带宽(如 20MHz、40MHz等)。 - -.. only:: esp32c5 - - AP 选择 - +++++++++++++++++++++++++ - - 当设备扫描到多个 SSID 相同的 AP(接入点)时,{IDF_TARGET_NAME} 会根据信号强度(RSSI)以及频段等信息,选择最合适的 AP 进行连接。默认策略通常优先选择 RSSI 更高的 AP,但在 2.4 GHz 与 5 GHz 并存的环境下,这可能导致设备偏向连接 2.4 GHz 频段,忽略 5 GHz 频段的高性能优势。 - - 为此,ESP-IDF 提供了 :cpp:type:`wifi_scan_threshold_t` 结构体中的 :cpp:member:`rssi_5g_adjustment` 字段,用于优化 5G AP 的选择优先级。 - - .. list-table:: - :header-rows: 1 - :widths: 30 70 - - * - 字段 - - 描述 - * - ``rssi_5g_adjustment`` - - 用于在 SSID 相同的 2.4 GHz 和 5 GHz AP 之间进行优先级调整。默认值为 ``10``,表示当 5 GHz AP 的 RSSI 至少比 2.4 GHz AP 低 ``10 dB`` 以内时,优先连接 5 GHz AP。通过合理设置该参数,可以在信号强度接近时优先连接具有更好带宽与干扰抵抗能力的 5 GHz 网络。 - - 示例: - - 若设备扫描到以下两个 AP,SSID 均为 "MyWiFi": - - - 2.4 GHz AP:RSSI = -60 dBm - - 5 GHz AP:RSSI = -68 dBm - - 则由于 ``rssi_5g_adjustment = 10``(默认值), 且满足 ``-68 > -60 - 10`` ,设备会优先连接 5 GHz AP。 - - .. note:: - - 该参数仅在扫描结果中存在相同 SSID 且分别处于 2.4 GHz 与 5 GHz 频段的 AP 时生效。其目的是避免设备总是连接信号强度略高但性能较差的 2.4 GHz 网络。 - -station 基本配置 -+++++++++++++++++++++++++++++++++++++ - -API :cpp:func:`esp_wifi_set_config()` 可用于配置 station。配置的参数信息会保存到 NVS 中。下表详细介绍了各个字段。 - -.. list-table:: - :header-rows: 1 - :widths: 15 45 - - * - 字段 - - 描述 - * - ssid - - station 想要连接的目标 AP 的 SSID。 - * - password - - 目标 AP 的密码。 - * - scan_method - - ``WIFI_FAST_SCAN`` 模式下,扫描到一个匹配的 AP 时即结束。 ``WIFI_ALL_CHANNEL_SCAN`` 模式下,在所有信道扫描所有匹配的 AP。默认扫描模式是 ``WIFI_FAST_SCAN``。 - * - bssid_set - - 如果 bssid_set 为 0,station 连接 SSID 与 “ssid” 字段相同的 AP,同时忽略字段 “bssid”。其他情况下,station 连接 SSID 与 “ssid” 字段相同、BSSID 与 “bssid” 字段也相同的 AP。 - * - bssid - - 只有当 bssid_set 为 1 时有效。见字段 “bssid_set”。 - * - channel - - 该字段为 0 时,station 扫描信道 1 ~ N 寻找目标 AP;否则,station 首先扫描值与 “channel” 字段相同的信道,再扫描其他信道。比如,当该字段设置为 3 时,扫描顺序为 3,1,2,...,N 。如果你不知道目标 AP 在哪个信道,请将该字段设置为 0。 - * - sort_method - - 该字段仅用于 ``WIFI_ALL_CHANNEL_SCAN`` 模式。 - - 如果设置为 ``WIFI_CONNECT_AP_BY_SIGNAL``,所有匹配的 AP 将会按照信号强度排序,信号最好的 AP 会被首先连接。比如,如果 station 想要连接 ssid 为 “apxx” 的 AP,且扫描到两个这样的 AP。第一个 AP 的信号为 -90 dBm,第二个 AP 的信号为 -30 dBm,station 首先连接第二个 AP。除非失败,才会连接第一个。 - - 如果设置为 ``WIFI_CONNECT_AP_BY_SECURITY``,所有匹配的 AP 将会按照安全性排序。比如,如果 station 想要连接 ssid 为 “apxx” 的 AP,并且扫描到两个这样的 AP。第一个 AP 为开放式,第二个 AP 为 WPA2 加密,station 首先连接第二个 AP。除非失败,才会连接第一个。 - * - threshold - - 该字段用来筛选找到的 AP,如果 AP 的 RSSI 或安全模式小于配置的阈值,则不会被连接。 - - 如果 RSSI 设置为 0,则表示默认阈值、默认 RSSI 阈值为 -127 dBm。如果 authmode 阈值设置为 0,则表示默认阈值,默认 authmode 阈值无授权。 - - -.. attention:: - - WEP/WPA 安全模式在 IEEE802.11-2016 协议中已弃用,建议不要使用。可使用 authmode 阈值代替,通过将 threshold.authmode 设置为 ``WIFI_AUTH_WPA2_PSK`` 使用 WPA2 模式 - -AP 基本配置 -+++++++++++++++++++++++++++++++++++++ - -API :cpp:func:`esp_wifi_set_config()` 可用于配置 AP。配置的参数信息会保存到 NVS 中。下表详细介绍了各个字段。 - -.. only:: esp32 or esp32s2 or esp32s3 or esp32c3 or esp32c5 or esp32c6 - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - 字段 - - 描述 - * - ssid - - 指 AP 的 SSID。如果 ssid[0] 和 ssid[1] 均为 0xFF,AP 默认 SSID 为 ``ESP_aabbcc``,”aabbcc” 是 AP MAC 的最后三个字节。 - * - password - - AP 的密码。如果身份验证模式为 ``WIFI_AUTH_OPEN``,此字段将被忽略。 - * - ssid_len - - SSID 的长度。如果 ssid_len 为 0,则检查 SSID 直至出现终止字符。如果 ssid_len 大于 32,请更改为 32,或者根据 ssid_len 设置 SSID 长度。 - * - channel - - AP 的信道。如果信道超出范围,Wi-Fi 驱动程序将返回 error。所以,请确保信道在要求的范围内。有关详细信息,请参阅 `Wi-Fi 国家/地区代码`_。 - * - authmode - - ESP AP 的身份验证模式。目前,ESP AP 不支持 AUTH_WEP。如果 authmode 是一个无效值,AP 默认该值为 ``WIFI_AUTH_OPEN``。 - * - ssid_hidden - - 如果 ssid_hidden 为 1,AP 不广播 SSID。若为其他值,则广播。 - * - max_connection - - 允许连接 station 的最大数目,默认值是 10。ESP Wi-Fi 支持 {IDF_TARGET_MAX_CONN_STA_NUM} (``ESP_WIFI_MAX_CONN_NUM``) 个 Wi-Fi 连接。请注意, ESP AP 和 ESP-NOW 共享同一块加密硬件 keys,因此 max_connection 参数将受到 :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM` 的影响。加密硬件 keys 的总数是 17,如果 :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM` 小于等于 {IDF_TARGET_SUB_MAX_NUM_FROM_KEYS},那么 max_connection 最大可以设置为 {IDF_TARGET_MAX_CONN_STA_NUM},否则 max_connection 最大可以设置为 (17 - :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`)。 - * - beacon_interval - - beacon 间隔。值为 100 ~ 60000 ms,默认值为 100 ms。如果该值不在上述范围,AP 默认取 100 ms。 - - -.. only:: esp32c2 - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - 字段 - - 描述 - * - ssid - - 指 AP 的 SSID。如果 ssid[0] 和 ssid[1] 均为 0xFF,AP 默认 SSID 为 ``ESP_aabbcc``,”aabbcc” 是 AP MAC 的最后三个字节。 - * - password - - AP 的密码。如果身份验证模式为 ``WIFI_AUTH_OPEN``,此字段将被忽略。 - * - ssid_len - - SSID 的长度。如果 ssid_len 为 0,则检查 SSID 直至出现终止字符。如果 ssid_len 大于 32,请更改为 32,或者根据 ssid_len 设置 SSID 长度。 - * - channel - - AP 的信道。如果信道超出范围,Wi-Fi 驱动程序将默认为信道 1。所以,请确保信道在要求的范围内。有关详细信息,请参阅 `Wi-Fi 国家/地区代码`_。 - * - authmode - - ESP AP 的身份验证模式。目前,ESP AP 不支持 AUTH_WEP。如果 authmode 是一个无效值,AP 默认该值为 ``WIFI_AUTH_OPEN``。 - * - ssid_hidden - - 如果 ssid_hidden 为 1,AP 不广播 SSID。若为其他值,则广播。 - * - max_connection - - 允许连接 station 的最大数目,默认值是 2。ESP Wi-Fi 支持 {IDF_TARGET_MAX_CONN_STA_NUM} (``ESP_WIFI_MAX_CONN_NUM``) 个 Wi-Fi 连接。请注意, ESP AP 和 ESP-NOW 共享同一块加密硬件 keys,因此 max_connection 参数将受到 :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM` 的影响。加密硬件 keys 的总数是 {IDF_TARGET_MAX_CONN_STA_NUM}, max_connection 最大可以设置为 ({IDF_TARGET_MAX_CONN_STA_NUM} - :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`)。 - * - beacon_interval - - beacon 间隔。值为 100 ~ 60000 ms,默认值为 100 ms。如果该值不在上述范围,AP 默认取 100 ms。 - - -Wi-Fi 协议模式 -+++++++++++++++++++++++++ - -目前,IDF 支持以下协议模式: - -.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - 协议模式 - - 描述 - * - 802.11b - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B)``,将 station/AP 设置为仅 802.11b 模式。 - * - 802.11bg - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)``,将 station/AP 设置为 802.11bg 模式。 - * - 802.11g - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` 和 ``esp_wifi_config_11b_rate(ifx, true)``,将 station/AP 设置为 802.11g 模式。 - * - 802.11bgn - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)``,将 station/AP 设置为 802.11bgn 模式。 - * - 802.11gn - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` 和 ``esp_wifi_config_11b_rate(ifx, true)``,将 station/AP 设置为 802.11gn 模式。 - * - 802.11 BGNLR - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_LR)``,将 station/AP 设置为 802.11bgn 和 LR 模式。 - * - 802.11 LR - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_LR)``,将 station/AP 设置为 LR 模式。 - - **此模式是乐鑫的专利模式,可以达到 1 公里视线范围。请确保 station 和 AP 同时连接至 ESP 设备。** - -.. only:: esp32c6 - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - 协议模式 - - 描述 - * - 802.11b - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B)``,将 station/AP 设置为仅 802.11b 模式。 - * - 802.11bg - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)``,将 station/AP 设置为 802.11bg 模式。 - * - 802.11g - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` 和 ``esp_wifi_config_11b_rate(ifx, true)``,将 station/AP 设置为 802.11g 模式。 - * - 802.11bgn - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)``,将 station/AP 设置为 802.11bgn 模式。 - * - 802.11gn - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` 和 ``esp_wifi_config_11b_rate(ifx, true)``,将 station/AP 设置为 802.11gn 模式。 - * - 802.11 BGNLR - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_LR)``,将 station/AP 设置为 802.11bgn 和 LR 模式。 - * - 802.11bgnax - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_11AX)``,将 station/AP 设置为 802.11bgnax 模式。 - * - 802.11 BGNAXLR - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_11AX|WIFI_PROTOCOL_LR)``,将 station/AP 设置为 802.11bgnax 和 LR 模式。 - * - 802.11 LR - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_LR)``,将 station/AP 设置为 LR 模式。 - - **此模式是乐鑫的专利模式,可以达到 1 公里视线范围。请确保 station 和 AP 同时连接至 ESP 设备。** - -.. only:: esp32c5 - - - **2.4 GHz 频段**:支持 802.11b、802.11bg、802.11bgn、802.11bgnax 以及乐鑫专有的 LR 模式。 - - **5 GHz 频段**:支持 802.11a、802.11an、802.11anac 和 802.11anacax。 - - {IDF_TARGET_NAME} 支持为 2.4 GHz 和 5 GHz 频段分别配置 Wi-Fi 协议模式。推荐使用 :cpp:func:`esp_wifi_set_protocols()` 进行配置,也兼容旧接口 :cpp:func:`esp_wifi_set_protocol()`。 - - **推荐用法** - - 使用新 API :cpp:func:`esp_wifi_set_protocols()`,分别设置两个频段的协议: - - .. code-block:: c - - // 设置 2.4 GHz 使用 802.11bgnax,5 GHz 使用 802.11anacax 协议 - wifi_protocols_t protocols = { - .ghz_2g = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX, - .ghz_5g = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AC | WIFI_PROTOCOL_11AX, - }; - esp_wifi_set_protocols(WIFI_IF_STA, &protocols); - - **兼容用法** - - 使用旧 API :cpp:func:`esp_wifi_set_protocol()`,配置 2.4 GHz 或者 5 GHz 频段的协议: - - .. code-block:: c - - // 设置频段为 2.4 GHz 频段 - esp_wifi_set_band_mode(WIFI_BAND_MODE_2G_ONLY); - - // 设置 STA 的协议为 802.11bgnax - uint8_t protocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX; - esp_wifi_set_protocol(WIFI_IF_STA, protocol); - - .. note:: - - - 新接口 `esp_wifi_set_protocols()` 可同时配置两个频段,建议在{IDF_TARGET_NAME}上优先使用。 - - ``esp_wifi_set_protocol()`` 适用于仅使用单一频段的场景,如 ``WIFI_BAND_MODE_2G_ONLY`` 或 ``WIFI_BAND_MODE_5G_ONLY`` 模式。仅对当前连接的频段生效,例如,当接口处于 5 GHz 频段时,该函数将忽略对 2.4 GHz 频段的配置。 - - 若配置包含不受支持的协议组合,函数调用将返回错误。 - - 如需启用乐鑫专有 LR 模式,请确保 2.4 GHz 配置中包含 `WIFI_PROTOCOL_LR`。 - -.. only:: esp32c2 - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - 协议模式 - - 描述 - * - 802.11b - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B)``,将 station/AP 设置为仅 802.11b 模式。 - * - 802.11bg - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)``,将 station/AP 设置为 802.11bg 模式。 - * - 802.11g - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G)`` 和 ``esp_wifi_config_11b_rate(ifx, true)``,将 station/AP 设置为 802.11g 模式。 - * - 802.11bgn - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)``,将 station/AP 设置为 802.11bgn 模式。 - * - 802.11gn - - 调用函数 ``esp_wifi_set_protocol(ifx, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)`` 和 ``esp_wifi_config_11b_rate(ifx, true)``,将 station/AP 设置为 802.11gn 模式。 - -Wi-Fi 带宽模式 -++++++++++++++++++++++ - -.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 - - {IDF_TARGET_NAME} 目前支持 20 MHz 和 40 MHz 两种带宽模式,并与协议模式组合使用,常见的组合包括: - - - **HT20**:802.11n,20 MHz 带宽 - - **HT40**:802.11n,40 MHz 带宽 - - .. note:: - - - 40 MHz 带宽模式仅在 802.11n 模式下支持。 - - 应用程序可以使用 :cpp:func:`esp_wifi_set_bandwidth()` API 来设置当前接口的带宽模式。 - - 示例: - - .. code-block:: c - - // 设置 STA 的协议为 802.11bgn - uint8_t protocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N; - esp_wifi_set_protocol(WIFI_IF_STA, protocol); - - // 设置 STA 的带宽为 40 MHz - esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40); - -.. only:: esp32c6 - - {IDF_TARGET_NAME} 目前支持 20 MHz 和 40 MHz 两种带宽模式,并与协议模式组合使用,常见的组合包括: - - - **HT20**:802.11n,20 MHz 带宽 - - **HT40**:802.11n,40 MHz 带宽 - - **HE20**:802.11ax,20 MHz 带宽 - - .. note:: - - - 40 MHz 带宽模式仅在 802.11n 模式下支持。 - - 应用程序可以使用 :cpp:func:`esp_wifi_set_bandwidth()` API 来设置当前接口的带宽模式。 - - 示例: - - .. code-block:: c - - // 设置 STA 的协议为 802.11bgn - uint8_t protocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N; - esp_wifi_set_protocol(WIFI_IF_STA, protocol); - - // 设置 STA 的带宽为 40 MHz - esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40); - -.. only:: esp32c5 - - {IDF_TARGET_NAME} 当前支持 20 MHz 和 40 MHz 两种带宽模式,可与不同协议模式组合使用,常见配置包括: - - - **HT20**:802.11n/11an,20 MHz 带宽 - - **HT40**:802.11n/11an,40 MHz 带宽 - - **HE20**:802.11ax,20 MHz 带宽 - - .. note:: - - - 40 MHz 模式仅适用于 802.11n(2.4 GHz)或 802.11an(5 GHz)协议。 - - 应用程序可使用 :cpp:func:`esp_wifi_set_bandwidths()` API,分别为 2.4 GHz 和 5 GHz 配置独立带宽。 - - 示例: - - .. code-block:: c - - // 设置 2.4 GHz 使用 802.11bgnax,5 GHz 使用 802.11an 协议 - wifi_protocols_t protocols = { - .ghz_2g = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX, - .ghz_5g = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N, - }; - esp_wifi_set_protocols(WIFI_IF_STA, &protocols); - - // 设置 2.4 GHz 带宽为 20 MHz,5 GHz 带宽为 40 MHz - wifi_bandwidths_t bw = { - .ghz_2g = WIFI_BW_HT20, - .ghz_5g = WIFI_BW_HT40 - }; - esp_wifi_set_bandwidths(WIFI_IF_STA, &bw); - - .. note:: - - - 若 `.ghz_2g` 设置为 0,仅配置 5 GHz 带宽,2.4 GHz 保持不变。 - - 若 `.ghz_5g` 设置为 0,仅配置 2.4 GHz 带宽,5 GHz 保持不变。 - - **兼容用法** - - 可使用旧版 API :cpp:func:`esp_wifi_set_bandwidth()` 配置 2.4 GHz 频段或者 5 GHz 频段的带宽: - - .. code-block:: c - - // 设置频段为 5 GHz 频段 - esp_wifi_set_band_mode(WIFI_BAND_MODE_5G_ONLY); - - // 设置 STA 的协议为 802.11an - uint8_t protocol = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N; - esp_wifi_set_protocol(WIFI_IF_STA, protocol); - - // 设置 STA 的带宽为 40 MHz - esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40); - - .. note:: - - - 新版 API :cpp:func:`esp_wifi_set_bandwidths()` 支持同时配置 2.4 GHz 与 5 GHz 带宽,推荐在 {IDF_TARGET_NAME} 上优先使用。 - - ``esp_wifi_set_bandwidth()`` 适用于单频段场景,如 ``WIFI_BAND_MODE_2G_ONLY`` 或 ``WIFI_BAND_MODE_5G_ONLY``,仅作用于当前连接频段。例如,若接口工作在 5 GHz,则 2.4 GHz 的配置将被忽略。 - - 若设置了当前频段不支持的带宽值,函数将返回错误。 - -.. only:: esp32c2 - - {IDF_TARGET_NAME} 目前仅支持 20 MHz 带宽模式。 - -.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 or esp32c5 or esp32c6 - - 长距离 (LR) - +++++++++++++++++++++++++ - - 长距离 (LR) 模式是乐鑫的一项专利 Wi-Fi 模式,可达到 1 公里视线范围。与传统 802.11b 模式相比,接收灵敏度更高,抗干扰能力更强,传输距离更长。 - - LR 兼容性 - ************************* - - 由于 LR 是乐鑫的独有 2.4 GHz 频段 Wi-Fi 模式,只有 ESP32 芯片系列设备(ESP32-C2 除外)才能传输和接收 LR 数据。也就是说,如果连接的设备不支持 LR,ESP32 芯片系列设备(ESP32-C2 除外)则不会以 LR 数据速率传输数据。可通过配置适当的 Wi-Fi 模式使你的应用程序实现这一功能。 - - - 如果协商的模式支持 LR,ESP32 芯片系列设备(ESP32-C2 除外)可能会以 LR 速率传输数据。 - - 否则,ESP32 芯片系列设备(ESP32-C2 除外)将以传统 Wi-Fi 数据速率传输所有数据。 - - 下表是 2.4 GHz 频段 Wi-Fi 模式协商: - - .. only:: esp32 or esp32s2 or esp32c3 or esp32s3 - - +-------+-----+----+---+-------+------+-----+----+ - |AP\STA | BGN | BG | B | BGNLR | BGLR | BLR | LR | - +=======+=====+====+===+=======+======+=====+====+ - | BGN | BGN | BG | B | BGN | BG | B | - | - +-------+-----+----+---+-------+------+-----+----+ - | BG | BG | BG | B | BG | BG | B | - | - +-------+-----+----+---+-------+------+-----+----+ - | B | B | B | B | B | B | B | - | - +-------+-----+----+---+-------+------+-----+----+ - | BGNLR | - | - | - | BGNLR | BGLR | BLR | LR | - +-------+-----+----+---+-------+------+-----+----+ - | BGLR | - | - | - | BGLR | BGLR | BLR | LR | - +-------+-----+----+---+-------+------+-----+----+ - | BLR | - | - | - | BLR | BLR | BLR | LR | - +-------+-----+----+---+-------+------+-----+----+ - | LR | - | - | - | LR | LR | LR | LR | - +-------+-----+----+---+-------+------+-----+----+ - - .. only:: esp32c5 or esp32c6 - - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | AP\STA | BGNAX | BGN | BG | B | BGNAXLR | BGNLR | BGLR | BLR | LR | - +=========+=======+=====+====+===+=========+=======+======+=====+====+ - | BGNAX | BGAX | BGN | BG | B | BGAX | BGN | BG | B | - | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | BGN | BGN | BGN | BG | B | BGN | BGN | BG | B | - | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | BG | BG | BG | BG | B | BG | BG | BG | B | - | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | B | B | B | B | B | B | B | B | B | - | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | BGNAXLR | - | - | - | - | BGAXLR | BGNLR | BGLR | BLR | LR | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | BGNLR | - | - | - | - | BGNLR | BGNLR | BGLR | BLR | LR | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | BGLR | - | - | - | - | BGLR | BGLR | BGLR | BLR | LR | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | BLR | - | - | - | - | BLR | BLR | BLR | BLR | LR | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - | LR | - | - | - | - | LR | LR | LR | LR | LR | - +---------+-------+-----+----+---+---------+-------+------+-----+----+ - - 上表中,行是 AP 的 Wi-Fi 模式,列是 station 的 Wi-Fi 模式。"-" 表示 AP 和 station 的 Wi-Fi 模式不兼容。 - - 根据上表,得出以下结论: - - - 对于已使能 LR 的 {IDF_TARGET_NAME} AP,由于以 LR 模式发送 beacon,因此与传统的 802.11 模式不兼容。 - - 对于已使能 LR 且并非仅 LR 模式的 {IDF_TARGET_NAME} station,与传统 802.11 模式兼容。 - - 如果 station 和 AP 都是 ESP32 芯片系列设备(ESP32-C2 除外),并且两者都使能 LR 模式,则协商的模式支持 LR。 - - 如果协商的 Wi-Fi 模式同时支持传统的 802.11 模式和 LR 模式,则 Wi-Fi 驱动程序会在不同的 Wi-Fi 模式下自动选择最佳数据速率,应用程序无需任何操作。 - - LR 对传统 Wi-Fi 设备的影响 - *************************************** - - 以 LR 速率进行的数据传输不会影响传统 Wi-Fi 设备,因为: - - - LR 模式下的 CCA 和回退过程符合 802.11 协议。 - - 传统的 Wi-Fi 设备可以通过 CCA 检测 LR 信号并进行回退。 - - 也就是说,LR 模式下传输效果与 802.11b 模式相似。 - - LR 传输距离 - ************************* - - LR 的接收灵敏度比传统的 802.11b 模式高 4 dB,理论上,传输距离约为 802.11b 的 2 至 2.5 倍。 - - LR 吞吐量 - ************************* - - 因为原始 PHY 数据传输速率为 1/2 Mbps 和 1/4 Mbps,LR 的吞吐量有限。 - - 何时使用 LR - ************************* - - 通常使用 LR 的场景包括: - - - AP 和 station 都是乐鑫设备。 - - 需要长距离 Wi-Fi 连接和数据传输。 - - 数据吞吐量要求非常小,例如远程设备控制等。 - -.. only:: esp32c5 - - 动态频率选择(DFS) - +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - 在 5 GHz Wi-Fi 频段中,一些信道(如信道 52 ~ 144)与天气雷达等关键通信系统共享频谱。为避免 Wi-Fi 信号对这些系统产生干扰,Wi-Fi 设备在使用这些信道前,必须执行特定的侦测与切换机制,即 **动态频率选择(DFS)**。 - - 启用 DFS 的设备可以访问更多 5 GHz 信道,从而提高网络容量并减少干扰,尤其适用于高密度部署或需要大带宽的应用场景。不同国家和地区 DFS 信道范围可以参考 :component_file:`esp_wifi/regulatory/esp_wifi_regulatory.txt` - - {IDF_TARGET_NAME} 支持在 5 GHz 频段使用 DFS 信道,但仅支持 **被动雷达检测** 功能。 - - .. list-table:: - :header-rows: 1 - :widths: 20 60 - - * - 类型 - - 描述 - * - 被动雷达检测 支持 - - 设备在扫描过程中能够监听 DFS 信道,识别并连接工作在 DFS 信道上的接入点(AP)。当目标 AP 在 DFS 信道上检测到雷达并通过信道切换(CSA)切换信道时,{IDF_TARGET_NAME} 会跟随 AP 切换信道。 - * - 主动雷达检测 不支持 - - {IDF_TARGET_NAME} **不支持** 主动雷达检测功能,因此无法在 SoftAP 模式下作为 DFS AP 启动。 - - .. note:: - - 在 STA 模式下,{IDF_TARGET_NAME} 可连接至位于 DFS 信道上的 AP,前提是该信道已在扫描中被识别。 - - 在 SoftAP 模式下,{IDF_TARGET_NAME} 不允许使用 DFS 信道作为工作信道,以避免违反无线电监管规定。 - - 在 STA+SoftAP 共存模式下: - 1. 当 STA 连接到位于 DFS 信道的 AP 时,SoftAP 允许通过 CSA(Channel Switch Announcement)切换至相同的 DFS 信道。 - 2. 当 STA 断开连接后,SoftAP 将通过 CSA 切换回非 DFS 信道,确保符合监管要求。 - -Wi-Fi 国家/地区代码 -+++++++++++++++++++++++++ - -.. only:: esp32 or esp32c2 or esp32s2 or esp32c3 or esp32s3 or esp32c6 - - 调用 :cpp:func:`esp_wifi_set_country()`,设置国家/地区信息。下表详细介绍了各个字段,请在配置这些字段之前参考当地的 2.4 GHz RF 操作规定。 - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - 字段 - - 描述 - * - cc[3] - - 国家/地区代码字符串,此属性标识 station/AP 位于的国家/地区或非国家/地区实体。如果是一个国家/地区,该字符串的前两个八位字节是 ISO/IEC3166-1 中规定的国家/地区两位字母代码。第三个八位字节应是下述之一: - - - ASCII 码空格字符,代表 station/AP 所处国家/地区的规定允许当前频段所需的所有环境。 - - ASCII 码 ‘O’ 字符,代表 station/AP 所处国家/地区的规定仅允许室外环境。 - - ASCII 码 ‘I’ 字符,代表 station/AP 所处国家/地区的规定仅允许室内环境。 - - ASCII 码 ‘X’ 字符,代表 station/AP 位于非国家/地区实体。非国家实体的前两个八位字节是两个 ASCII 码 ‘XX’ 字符。 - - 当前使用的操作类表编号的二进制形式。见 IEEE Std 802.11-2020 附件 E。 - - * - schan - - 起始信道,station/AP 所处国家/地区规定的最小信道值。 - * - nchan - - 规定的总信道数,比如,如果 schan=1,nchan=13,那么 station/AP 可以从信道 1 至 13 发送数据。 - * - policy - - 国家/地区策略,当配置的国家/地区信息与所连 AP 的国家/地区信息冲突时,该字段决定使用哪一信息。更多策略相关信息,可参见下文。 - - - 默认国家/地区信息为:: - - wifi_country_t config = { - .cc = "01", - .schan = 1, - .nchan = 11, - .policy = WIFI_COUNTRY_POLICY_AUTO, - }; - - 如果 Wi-Fi 模式为 station/AP 共存模式,则它们配置的国家/地区信息相同。有时,station 所连 AP 的国家/地区信息与配置的不同。例如,配置的 station 国家/地区信息为:: - - wifi_country_t config = { - .cc = "JP", - .schan = 1, - .nchan = 14, - .policy = WIFI_COUNTRY_POLICY_AUTO, - }; - - 但所连 AP 的国家/地区信息为:: - - wifi_country_t config = { - .cc = "CN", - .schan = 1, - .nchan = 13, - }; - - 此时,使用所连 AP 的国家/地区信息。 - - 下表描述了在不同 Wi-Fi 模式和不同国家/地区策略下使用的国家/地区信息,并描述了对主动扫描的影响。 - - .. list-table:: - :header-rows: 1 - :widths: 15 15 35 - - * - Wi-Fi 模式 - - 策略 - - 描述 - * - station 模式 - - WIFI_COUNTRY_POLICY_AUTO - - 如果所连 AP 的 beacon 中有国家/地区的 IE,使用的国家/地区信息为 beacon 中的信息,否则,使用默认信息。 - - 扫描时: - - 主动扫描信道 1 至信道 11,被动扫描信道 12 至 信道 14。 - - 请记住,如果带有隐藏 SSID 的 AP 和 station 被设置在被动扫描信道上,被动扫描将无法找到该 AP。也就是说,如果应用程序希望在每个信道中找到带有隐藏 SSID 的 AP,国家/地区信息应该配置为 WIFI_COUNTRY_POLICY_MANUAL。 - - * - station 模式 - - WIFI_COUNTRY_POLICY_MANUAL - - 总是使用配置的国家/地区信息。 - - 扫描时: - - 主动扫描信道 schan 至信道 schan+nchan-1。 - - * - AP 模式 - - WIFI_COUNTRY_POLICY_AUTO - - 总是使用配置的国家/地区信息。 - - * - AP 模式 - - WIFI_COUNTRY_POLICY_MANUAL - - 总是使用配置的国家/地区信息。 - - * - station/AP 共存模式 - - WIFI_COUNTRY_POLICY_AUTO - - 该 station 与 station 模式、WIFI_COUNTRY_POLICY_AUTO 策略下使用的国家/地区信息相同。 - 如果 station 不连接任何外部 AP,AP 使用配置的国家/地区信息。如果 station 连接一个外部 AP,该 AP 的国家/地区信息与该 station 相同。 - - * - station/AP 共存模式 - - WIFI_COUNTRY_POLICY_MANUAL - - 该 station 与 station 模式、WIFI_COUNTRY_POLICY_MANUAL 策略下使用的国家/地区信息相同。 - 该 AP 与 AP 模式、WIFI_COUNTRY_POLICY_MANUAL 策略下使用的国家/地区信息相同。 - -.. only:: esp32c5 - - 调用 :cpp:func:`esp_wifi_set_country()` 可设置国家/地区信息。下表详细介绍了各字段含义,请在配置这些字段前,参考本地 2.4 GHz 与 5 GHz 射频使用规定。 - - .. list-table:: - :header-rows: 1 - :widths: 15 55 - - * - 字段 - - 描述 - * - cc[3] - - 国家/地区代码字符串。用于标识 station/AP 所在的国家/地区,或非国家实体。如果为国家/地区,该字段的前两个字节为符合 ISO/IEC 3166-1 标准的两位国家代码,第三个字节含义如下: - - - 空格字符(ASCII),表示当前国家/地区在所有环境中允许使用相应频段。 - - 字符 `'O'`,表示仅允许在户外环境中使用。 - - 字符 `'I'`,表示仅允许在室内环境中使用。 - - 字符 `'X'`,表示非国家实体,此时前两个字符应为 `'X'`(即 `'XX'`)。 - - 二进制形式的操作类编号,参考 IEEE Std 802.11-2020 附录 E。 - - * - schan - - 起始信道值,即当前国家/地区在 2.4 GHz 频段中允许使用的最小信道。 - * - nchan - - 信道数量。定义在 2.4 GHz 频段中允许使用的总信道数。例如,若 schan = 1,nchan = 13,则 station/AP 可使用信道 1 至 13。 - * - policy - - 国家/地区策略。当配置的国家/地区与连接 AP 的信息冲突时,此字段决定应使用哪一方的信息。详情见下文说明。 - * - wifi_5g_channel_mask - - 表示 station/AP 在 5 GHz 频段中可使用的信道掩码。信道值与位的对应关系详见 :cpp:enum:`wifi_5g_channel_bit_t`。 - - 默认配置示例如下:: - - wifi_country_t config = { - .cc = "01", - .schan = 1, - .nchan = 11, - .wifi_5g_channel_mask = 0xfe, - .policy = WIFI_COUNTRY_POLICY_AUTO, - }; - - 若 Wi-Fi 处于 station/AP 共存模式,则两者使用相同的国家/地区信息。有时,连接的 AP 的国家/地区信息可能与 station 预设的不同。例如: - - 配置的 station 信息为:: - - wifi_country_t config = { - .cc = "JP", - .schan = 1, - .nchan = 14, - .wifi_5g_channel_mask = 0xfe, - .policy = WIFI_COUNTRY_POLICY_AUTO, - }; - - 而连接的 AP 信息为:: - - wifi_country_t config = { - .cc = "CN", - .schan = 1, - .nchan = 13, - }; - - 此时将使用连接的 AP 的国家/地区信息。 - - 下表说明了在不同 Wi-Fi 模式及策略下使用的国家/地区信息,并说明了扫描行为的差异: - - .. list-table:: - :header-rows: 1 - :widths: 15 15 35 - - * - Wi-Fi 模式 - - 策略 - - 描述 - * - station 模式 - - WIFI_COUNTRY_POLICY_AUTO - - 若连接的 AP 的 beacon 中包含国家/地区信息 IE,则使用该信息;否则使用默认配置。 - - 扫描行为: - - - 2.4 GHz 频段:主动扫描信道 1–11,被动扫描信道 12–14; - - 5 GHz 频段:主动扫描非 DFS 信道,被动扫描 DFS 信道。 - - 注意:若隐藏 SSID 的 AP 设在被动扫描信道上,扫描可能无法发现该 AP。若需在所有信道上发现隐藏 SSID,请使用 `WIFI_COUNTRY_POLICY_MANUAL`。 - - * - station 模式 - - WIFI_COUNTRY_POLICY_MANUAL - - 始终使用配置的国家/地区信息。 - - 扫描行为: - - - 2.4 GHz 频段:扫描从 `schan` 到 `schan + nchan - 1` 的信道; - - 5 GHz 频段:扫描 `wifi_5g_channel_mask` 中标记支持的信道。 - - * - AP 模式 - - WIFI_COUNTRY_POLICY_AUTO - - 始终使用配置的国家/地区信息。 - * - AP 模式 - - WIFI_COUNTRY_POLICY_MANUAL - - 始终使用配置的国家/地区信息。 - * - station/AP 共存模式 - - WIFI_COUNTRY_POLICY_AUTO - - 与 station 模式中的 `WIFI_COUNTRY_POLICY_AUTO` 相同。 - - 若 station 未连接任何 AP,则 AP 使用配置的国家/地区信息; - 若 station 连接了外部 AP,则 AP 使用该 station 获取的国家/地区信息。 - - * - station/AP 共存模式 - - WIFI_COUNTRY_POLICY_MANUAL - - 与 station 模式中 `WIFI_COUNTRY_POLICY_MANUAL` 相同,AP 也始终使用配置的国家/地区信息。 - -主信道 -************************* - -AP 模式下,AP 的信道定义为主信道。station 模式下,station 所连 AP 的信道定义为主信道。station/AP 共存模式下,AP 和 station 的主信道必须相同。如果不同,station 的主信道始终优先。比如,初始时,AP 位于信道 6,但 station 连接信道 9 的 AP。因为 station 的主信道具有优先性,该 AP 需要将信道从 6 切换至 9,确保与 station 主信道相同。切换信道时,AP 模式下的 {IDF_TARGET_NAME} 将使用信道切换公告 (CSA) 通知连接的 station。支持信道切换的 station 将直接通过,无需与 AP 断连再重新连接。 - - -Wi-Fi 供应商 IE 配置 -+++++++++++++++++++++++++++++++++++ - -默认情况下,所有 Wi-Fi 管理帧都由 Wi-Fi 驱动程序处理,应用程序不需要任何操作。但是,某些应用程序可能需要处理 beacon、probe request、probe response 和其他管理帧。例如,如果在管理帧中插入一些只针对供应商的 IE,则只有包含此 IE 的管理帧才能得到处理。{IDF_TARGET_NAME} 中,:cpp:func:`esp_wifi_set_vendor_ie()` 和 :cpp:func:`esp_wifi_set_vendor_ie_cb()` 负责此类任务。 - - -Wi-Fi Easy Connect™ (DPP) --------------------------- - -Wi-Fi Easy Connect\ :sup:`TM` (也称为设备配置协议)是一个安全且标准化的配置协议,用于配置 Wi-Fi 设备。更多信息请参考 :doc:`esp_dpp <../api-reference/network/esp_dpp>`。 - -WPA2-Enterprise ---------------- - -WPA2-Enterprise 是企业无线网络的安全认证机制。在连接到接入点之前,它使用 RADIUS 服务器对网络用户进行身份验证。身份验证过程基于 802.1X 标准,并有不同的扩展身份验证协议 (EAP) 方法,如 TLS、TTLS、PEAP 等。RADIUS 服务器根据用户的凭据(用户名和密码)、数字证书或两者对用户进行身份验证。当处于 station 模式的 {IDF_TARGET_NAME} 尝试连接到企业模式的 AP 时,它会向 AP 发送身份验证请求,AP 会将该请求发送到 RADIUS 服务器以对 station 进行身份验证。根据不同的 EAP 方式,可以通过 ``idf.py menuconfig`` 打开配置,并在配置中设置参数。{IDF_TARGET_NAME} 仅在 station 模式下支持 WPA2_Enterprise。 - -为了建立安全连接,AP 和 station 协商并就要使用的最佳密码套件达成一致。{IDF_TARGET_NAME} 支持 AKM 的 802.1X/EAP (WPA) 方法和 AES-CCM(高级加密标准-带密码块链消息验证码协议的计数器模式)支持的密码套件。如果设置了 `USE_MBEDTLS_CRYPTO` 标志,{IDF_TARGET_NAME} 也支持 mbedtls 支持的密码套件。 - -目前,{IDF_TARGET_NAME} 支持以下 EAP 方法: - - EAP-TLS:这是基于证书的方法,只需要 SSID 和 EAP-IDF。 - - PEAP:这是受保护的 EAP 方法。用户名和密码是必填项。 - - EAP-TTLS:这是基于凭据的方法。只有服务器身份验证是强制性的,而用户身份验证是可选的。用户名和密码是必填项。 它支持不同的 Phase2 方法,例如: - - PAP:密码认证协议 - - CHAP:询问握手身份验证协议 - - MSCHAP 和 MSCHAP-V2 - - EAP-FAST:这是一种基于受保护的访问凭据 (PAC) 的认证方法,使用身份验证和密码。目前使用此功能时需要禁用 USE_MBEDTLS_CRYPTO 标志。 - -请查看 :example:`wifi/wifi_enterprise` 获取关于证书创建以及如何在 {IDF_TARGET_NAME} 上运行 wpa2_enterprise 示例的详细信息。 - -无线网络管理 ----------------------------- - -无线网络管理让客户端设备能够交换有关网络拓扑结构的信息,包括与射频环境相关的信息。这使每个客户端都能感知网络状况,从而促进无线网络性能的整体改进。这是 802.11v 规范的一部分。它还使客户端能够支持网络辅助漫游。 -网络辅助漫游让 WLAN 能够向关联的客户端发送消息,从而使客户端与具有更好链路指标的 AP 关联。这对于促进负载平衡以及引导连接不良的客户端都很有用。 - -目前 802.11v 的实现支持 BSS 过渡管理帧。 - -无线资源管理 ---------------------------- - -无线电资源测量 (802.11k) 旨在改善网络内流量的分配方式。在无线局域网中,一般情况下,无线设备会连接发射信号最强的接入点 (AP)。根据用户的数量和地理位置,这种分配方式有时会导致某个接入点超负荷而其它接入点利用不足,从而导致整体网络性能下降。在符合 802.11k 规范的网络中,如果信号最强的 AP 已满负荷加载,无线设备则转移到其它未充分利用的 AP。尽管信号可能较弱,但由于更有效地利用了网络资源,总体吞吐量会更大。 - -目前 802.11k 的实现支持信标测量报告、链路测量报告和邻居请求。 - -请参考 IDF 示例程序 :idf_file:`examples/wifi/roaming/README.md` 来设置和使用这些 API。示例代码只演示了如何使用这些 API,应用程序应根据需要定义自己的算法和案例。 - -.. only:: SOC_WIFI_FTM_SUPPORT - - Wi-Fi Location - ------------------------------- - - Wi-Fi Location 将提高 AP 以外设备位置数据的准确性,这有助于创建新的、功能丰富的应用程序和服务,例如地理围栏、网络管理、导航等。用于确定设备相对于接入点的位置的协议之一是精细定时测量 (FTM),它会计算 Wi-Fi 帧的飞行时间。 - - 精细定时测量 (FTM) - +++++++++++++++++++++++++++++ - - FTM 用于测量 Wi-Fi 往返时间(Wi-Fi RTT),即 Wi-Fi 信号从一个设备到另一个设备并返回所需的时间。使用 Wi-Fi RTT,设备之间的距离可以用一个简单的公式 `RTT * c / 2` 来计算,其中 c 是光速。 - - 对于设备之间交换的帧,FTM 在帧到达或离开时使用时间戳,这个时间戳由 Wi-Fi 接口硬件提供。FTM 发起方(主要是 station 设备)发现 FTM 响应方(可以是 station 或 AP),并协商启动 FTM 程序。该程序以突发形式发送的多个动作帧及其 ACK 来收集时间戳数据。FTM 发起方最后收集数据以计算平均往返时间。 - - {IDF_TARGET_NAME} 在以下配置中支持 FTM: - - - {IDF_TARGET_NAME} 在 station 模式下为 FTM 发起方。 - - {IDF_TARGET_NAME} 在 AP 模式下为 FTM 响应方。 - - 使用 RTT 的距离测量并不准确,RF 干扰、多径传播、天线方向和缺乏校准等因素会增加这些不准确度。为了获得更好的结果,建议在两个 ESP32 芯片系列设备(ESP32-C2 除外)之间执行 FTM,这两个设备可分别设置为 station 和 AP 模式。 - - 请参考 ESP-IDF 示例 :idf_file:`examples/wifi/ftm/README.md`,了解设置和执行 FTM 的详细步骤。 - -{IDF_TARGET_NAME} Wi-Fi 节能模式 ------------------------------------------ - -本小节将简单介绍Wi-Fi节能模式相关的概念和使用方式,更加详细的介绍请参考 :doc:`低功耗模式使用指南 <../api-guides/low-power-mode/index>`。 - -station 睡眠 -++++++++++++++++++++++ - -目前, {IDF_TARGET_NAME} Wi-Fi 支持 Modem-sleep 模式,该模式是 IEEE 802.11 协议中的传统节能模式。仅 station 模式支持该模式,station 必须先连接到 AP。如果使能了 Modem-sleep 模式,station 将定期在活动状态和睡眠状态之间切换。在睡眠状态下,RF、PHY 和 BB 处于关闭状态,以减少功耗。Modem-sleep 模式下,station 可以与 AP 保持连接。 - -Modem-sleep 模式包括最小和最大节能模式。在最小节能模式下,每个 DTIM 间隔,station 都将唤醒以接收 beacon。广播数据在 DTIM 之后传输,因此不会丢失。但是,由于 DTIM 间隔长短由 AP 决定,如果该间隔时间设置较短,则省电效果不大。 - -在最大节能模式下,每个监听间隔,station 都将唤醒以接收 beacon。可以设置该监听间隔长于 AP 的 DTIM 周期。在 DTIM 期间内,station 可能处于睡眠状态,广播数据会丢失。如果监听间隔较长,则可以节省更多电量,但广播数据更容易丢失。连接 AP 前,可以通过调用 API :cpp:func:`esp_wifi_set_config()` 配置监听间隔。 - -调用 :cpp:func:`esp_wifi_init()` 后,调用 ``esp_wifi_set_ps(WIFI_PS_MIN_MODEM)`` 可使能 Modem-sleep 最小节能模式。调用 ``esp_wifi_set_ps(WIFI_PS_MAX_MODEM)`` 可使能 Modem-sleep 最大节能模式。station 连接到 AP 时,Modem-sleep 模式将启动。station 与 AP 断开连接时,Modem-sleep 模式将停止。 - -调用 ``esp_wifi_set_ps(WIFI_PS_NONE)`` 可以完全禁用 Modem-sleep 模式。禁用会增大功耗,但可以最大限度减少实时接收 Wi-Fi 数据的延迟。使能 Modem-sleep 模式时,接收 Wi-Fi 数据的延迟时间可能与 DTIM 周期(最小节能模式)或监听间隔(最大节能模式)相同。 - -.. only:: SOC_SUPPORT_COEXISTENCE - - 注意在共存模式下, 即使调用 ``esp_wifi_set_ps(WIFI_PS_NONE)``, Wi-Fi 也仅会在 Wi-Fi 时间片内保持活动状态, 非 Wi-Fi 时间片内仍然睡眠。请参照 :ref:`共存策略 `。 - -默认的 Modem-sleep 模式是 WIFI_PS_MIN_MODEM。 - -AP 睡眠 -+++++++++++++++++++++++++++++++ - -目前,{IDF_TARGET_NAME} AP 不支持 Wi-Fi 协议中定义的所有节能功能。具体来说,AP 只缓存所连 station 单播数据,不缓存组播数据。如果 {IDF_TARGET_NAME} AP 所连的 station 已使能节能功能,可能发生组播数据包丢失。 - -未来,{IDF_TARGET_NAME} AP 将支持所有节能功能。 - -非连接状态下的休眠 -+++++++++++++++++++++++++++++++ - -非连接状态指的是 :cpp:func:`esp_wifi_start` 至 :cpp:func:`esp_wifi_stop` 期间内,没有建立 Wi-Fi 连接的阶段。 - -目前, {IDF_TARGET_NAME} Wi-Fi 支持以 station 模式运行时,在非连接状态下休眠。可以通过选项 :ref:`CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE` 配置该功能。 - -如果打开配置选项 :ref:`CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE`,则在该阶段内,RF, PHY and BB 将在空闲时被关闭,电流将会等同于 Modem-sleep 模式下的休眠电流。 - -配置选项 :ref:`CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE` 默认情况下将会被打开,共存模式下被 Menuconfig 强制打开。 - -.. _connectionless-module-power-save-cn: - -非连接模块功耗管理 -+++++++++++++++++++++++++++++++ - -非连接模块指的是一些不依赖于 Wi-Fi 连接的 Wi-Fi 模块,例如 ESP-NOW,DPP,FTM。这些模块从 :cpp:func:`esp_wifi_start` 开始工作至 :cpp:func:`esp_wifi_stop` 结束。 - -目前,ESP-NOW 以 station 模式工作时,既支持在连接状态下休眠,也支持在非连接状态下休眠。 - -非连接模块发包 -******************************* - -对于任何非连接模块,在开启了休眠的任何时间点都可以发包,不需要进行任何额外的配置。 - -此外,:cpp:func:`esp_wifi_80211_tx` 也在休眠时被支持。 - -非连接模块收包 -******************************* - -对于非连接模块,在开启休眠时如果需要进行收包,需要配置两个参数,分别为 `Window` 和 `Interval`。 - -在每个 `Interval` 开始时,RF, PHY and BB 将会被打开并保持 `Window` 的时间。非连接模块可以在此时间内收包。 - -**Interval** - - - 全局只有一个 `Interval` 参数,所有非连接模块共享它。其数值由 API :cpp:func:`esp_wifi_set_connectionless_interval` 配置,单位为毫秒。 - - - `Interval` 的默认值为 `ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE` 。 - - - 在 `Interval` 开始时,将会给出 `WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START`_ 事件,由于 `Window` 将在此时开始,可以在此事件内布置发包动作。 - - - 在连接状态下,`Interval` 开始的时间点将会与 TBTT 时间点对齐。可以通过将非连接模块的接收端和发送端连接在同一路由器下,并在 `WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START`_ 事件内进行发包,以同步非连接模块的传输窗口,达到提高接收端收包成功率的效果。 - - .. only:: esp32 - - 在 ESP32 上,TBTT 时间点会受到 DFS(Dynamic Frequency Scaling) 的干扰,如果想要在 ESP32 上通过 TBTT 同步非连接模块的传输窗口,需要禁用 DFS。 - -**Window** - - - 每个非连接模块在启动后都有其自身的 `Window` 参数,休眠模块将取所有模块 `Window` 的最大值运作。 - - - 其数值由 API :cpp:func:`module_name_set_wake_window` 配置,单位为毫秒。 - - - 模块 `Window` 的默认值为最大值。 - -.. table:: 不同 Window 与 Interval 组合下的 RF, PHY and BB 使用情况 - - +----------------------+-----------------------------------------------------+---------------------------------------------------------------------------+ - | | Interval | - + +-----------------------------------------------------+---------------------------------------------------------------------------+ - | | ``ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE`` | 1 - maximum | - +--------+-------------+-----------------------------------------------------+---------------------------------------------------------------------------+ - | Window | 0 | not used | - + +-------------+-----------------------------------------------------+---------------------------------------------------------------------------+ - | | 1 - maximum | default mode | used periodically (Window < Interval) / used all time (Window ≥ Interval) | - +--------+-------------+-----------------------------------------------------+---------------------------------------------------------------------------+ - -默认模式 -******************************* - -当 `Interval` 参数被配置为 `ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE` ,且有非零的 `Window` 参数时,非连接模块功耗管理将会按默认模式运行。 - -在没有与非 Wi-Fi 协议共存时,RF、PHY 和 BB 将会在默认模式下被一直打开。 - -在与非 Wi-Fi 协议共存时,RF、PHY 和 BB 资源被共存模块分时划给 Wi-Fi 非连接模块和非 Wi-Fi 协议使用。在默认模式下,Wi-Fi 非连接模块被允许周期性使用 RF、PHY 和 BB,并且具有稳定性能。 - -推荐在与非 Wi-Fi 协议共存时将非连接模块功耗管理配置为默认模式。 - -{IDF_TARGET_NAME} Wi-Fi 吞吐量 ------------------------------------ - -下表是我们在 Espressif 实验室和屏蔽箱中获得的最佳吞吐量结果。 - -.. only:: esp32 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - 类型/吞吐量 - - 实验室空气状况 - - 屏蔽箱 - - 测试工具 - - IDF 版本 (commit ID) - * - 原始 802.11 数据包接收数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - 原始 802.11 数据包发送数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - UDP 接收数据 - - 30 MBit/s - - 85 MBit/s - - iperf example - - 15575346 - * - UDP 发送数据 - - 30 MBit/s - - 75 MBit/s - - iperf example - - 15575346 - * - TCP 接收数据 - - 20 MBit/s - - 65 MBit/s - - iperf example - - 15575346 - * - TCP 发送数据 - - 20 MBit/s - - 75 MBit/s - - iperf example - - 15575346 - - 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32`。 - -.. only:: esp32s2 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - 类型/吞吐量 - - 实验室空气状况 - - 屏蔽箱 - - 测试工具 - - IDF 版本 (commit ID) - * - 原始 802.11 数据包接收数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - 原始 802.11 数据包发送数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - UDP 接收数据 - - 30 MBit/s - - 70 MBit/s - - iperf example - - 15575346 - * - UDP 发送数据 - - 30 MBit/s - - 50 MBit/s - - iperf example - - 15575346 - * - TCP 接收数据 - - 20 MBit/s - - 32 MBit/s - - iperf example - - 15575346 - * - TCP 发送数据 - - 20 MBit/s - - 37 MBit/s - - iperf example - - 15575346 - - 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32s2`。 - -.. only:: esp32c3 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - 类型/吞吐量 - - 实验室空气状况 - - 屏蔽箱 - - 测试工具 - - IDF 版本 (commit ID) - * - 原始 802.11 数据包接收数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - 原始 802.11 数据包发送数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - UDP 接收数据 - - 30 MBit/s - - 50 MBit/s - - iperf example - - 15575346 - * - UDP 发送数据 - - 30 MBit/s - - 40 MBit/s - - iperf example - - 15575346 - * - TCP 接收数据 - - 20 MBit/s - - 35 MBit/s - - iperf example - - 15575346 - * - TCP 发送数据 - - 20 MBit/s - - 37 MBit/s - - iperf example - - 15575346 - - 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c3`。 - -.. only:: esp32c5 - - - 2.4 GHz 频段 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - 类型/吞吐量 - - 实验室空气状况 - - 屏蔽箱 - - 测试工具 - - IDF 版本 (commit ID) - * - 原始 802.11 数据包接收数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - 原始 802.11 数据包发送数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - UDP 接收数据 - - 30 MBit/s - - 68 MBit/s - - iperf example - - 7ff0a07d - * - UDP 发送数据 - - 30 MBit/s - - 63 MBit/s - - iperf example - - 7ff0a07d - * - TCP 接收数据 - - 20 MBit/s - - 59 MBit/s - - iperf example - - 7ff0a07d - * - TCP 发送数据 - - 20 MBit/s - - 49 MBit/s - - iperf example - - 7ff0a07d - - - 5 GHz 频段 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - 类型/吞吐量 - - 实验室空气状况 - - 屏蔽箱 - - 测试工具 - - IDF 版本 (commit ID) - * - 原始 802.11 数据包接收数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - 原始 802.11 数据包发送数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - UDP 接收数据 - - 30 MBit/s - - 71 MBit/s - - iperf example - - 7ff0a07d - * - UDP 发送数据 - - 30 MBit/s - - 64 MBit/s - - iperf example - - 7ff0a07d - * - TCP 接收数据 - - 20 MBit/s - - 61 MBit/s - - iperf example - - 7ff0a07d - * - TCP 发送数据 - - 20 MBit/s - - 50 MBit/s - - iperf example - - 7ff0a07d - - 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c5`。 - -.. only:: esp32c6 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - 类型/吞吐量 - - 实验室空气状况 - - 屏蔽箱 - - 测试工具 - - IDF 版本 (commit ID) - * - 原始 802.11 数据包接收数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - 原始 802.11 数据包发送数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - UDP 接收数据 - - 30 MBit/s - - 63 MBit/s - - iperf example - - 7ff0a07d - * - UDP 发送数据 - - 30 MBit/s - - 51 MBit/s - - iperf example - - 7ff0a07d - * - TCP 接收数据 - - 20 MBit/s - - 46 MBit/s - - iperf example - - 7ff0a07d - * - TCP 发送数据 - - 20 MBit/s - - 43 MBit/s - - iperf example - - 7ff0a07d - - 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c6`。 - -.. only:: esp32c61 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - 类型/吞吐量 - - 实验室空气状况 - - 屏蔽箱 - - 测试工具 - - IDF 版本 (commit ID) - * - 原始 802.11 数据包接收数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - 原始 802.11 数据包发送数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - UDP 接收数据 - - 30 MBit/s - - 68 MBit/s - - iperf example - - 7ff0a07d - * - UDP 发送数据 - - 30 MBit/s - - 53 MBit/s - - iperf example - - 7ff0a07d - * - TCP 接收数据 - - 20 MBit/s - - 45 MBit/s - - iperf example - - 7ff0a07d - * - TCP 发送数据 - - 20 MBit/s - - 37 MBit/s - - iperf example - - 7ff0a07d - - 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32c61`。 - -.. only:: esp32s3 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 20 - - * - 类型/吞吐量 - - 实验室空气状况 - - 屏蔽箱 - - 测试工具 - - IDF 版本 (commit ID) - * - 原始 802.11 数据包接收数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - 原始 802.11 数据包发送数据 - - N/A - - **130 MBit/s** - - 内部工具 - - N/A - * - UDP 接收数据 - - 30 MBit/s - - 88 MBit/s - - iperf example - - 15575346 - * - UDP 发送数据 - - 30 MBit/s - - 98 MBit/s - - iperf example - - 15575346 - * - TCP 接收数据 - - 20 MBit/s - - 73 MBit/s - - iperf example - - 15575346 - * - TCP 发送数据 - - 20 MBit/s - - 83 MBit/s - - iperf example - - 15575346 - - 使用 iperf example 测试吞吐量时,sdkconfig 是 :idf_file:`examples/wifi/iperf/sdkconfig.defaults.esp32s3`。 - -Wi-Fi 80211 数据包发送 ---------------------------- - -:cpp:func:`esp_wifi_80211_tx()` API 可用于: - - - 发送 beacon、probe request、probe response 和 action 帧。 - - 发送非 QoS 数据帧。 - -不能用于发送加密或 QoS 帧。 - -使用 :cpp:func:`esp_wifi_80211_tx()` 的前提条件 -+++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - - Wi-Fi 模式为 station 模式,AP 模式,或 station/AP 共存模式。 - - API esp_wifi_set_promiscuous(true) 或 :cpp:func:`esp_wifi_start()`,或者二者都返回 :c:macro:`ESP_OK`。这是为确保在调用函数 :cpp:func:`esp_wifi_80211_tx()` 前,Wi-Fi 硬件已经初始化。对于 {IDF_TARGET_NAME},esp_wifi_set_promiscuous(true) 和 :cpp:func:`esp_wifi_start()` 都可以触发 Wi-Fi 硬件初始化。 - - 提供正确的 :cpp:func:`esp_wifi_80211_tx()` 参数。 - -传输速率 -+++++++++++++++++++++++++++++ - - - 默认传输速率为 1 Mbps。 - - 可以通过函数 :cpp:func:`esp_wifi_config_80211_tx_rate()` 设置任意速率。 - - 可以通过函数 :cpp:func:`esp_wifi_set_bandwidth()` 设置任意带宽。 - -在不同情况下需要避免的副作用 -+++++++++++++++++++++++++++++++++++++++++++++++++++++ - -理论上,如果不考虑 API 对 Wi-Fi 驱动程序或其他 station 或 AP 的副作用,可以通过空中发送一个原始的 802.11 数据包,包括任何目的地址的 MAC、任何源地址的 MAC、任何 BSSID、或任何其他类型的数据包。但是,一个具有强健、有用的应用程序应该避免这种副作用。下表针对如何避免 :cpp:func:`esp_wifi_80211_tx()` 的副作用提供了一些提示或建议。 - -.. list-table:: - :header-rows: 1 - :widths: 10 55 - - * - 场景 - - 描述 - * - 无 Wi-Fi 连接 - - 在这种情况下,因为没有 Wi-Fi 连接,Wi-Fi 驱动程序不会受到副作用影响。如果 ``en_sys_seq==true``,则 Wi-Fi 驱动程序负责序列控制。如果 ``en_sys_seq==false``,应用程序需要确保缓冲区的序列正确。 - - 理论上,MAC 地址可以是任何地址。但是,这样可能会影响其他使用相同 MAC/BSSID 的 station/AP。 - - 例如,AP 模式下,应用程序调用函数 :cpp:func:`esp_wifi_80211_tx` 发送带有 BSSID == mac_x 的 beacon,但是 mac_x 并非 AP 接口的 MAC。而且,还有另一个 AP(我们称之为 “other-AP”)的 bssid 是 mac_x。因此,连接到 “other-AP” 的 station 无法分辨 beacon 来自 “other-AP” 还是 :cpp:func:`esp_wifi_80211_tx`,就会出现 “意外行为”。 - - 为了避免上述副作用,我们建议: - - - 如果在 station 模式下调用函数 :cpp:func:`esp_wifi_80211_tx`,第一个 MAC 应该是组播 MAC 或是目标设备的 MAC,第二个 MAC 应该是 station 接口的 MAC。 - - - 如果在 AP 模式下调用函数 :cpp:func:`esp_wifi_80211_tx`,第一个 MAC 应该是组播 MAC 或是目标设备的 MAC,第二个 MAC 应该是 AP 接口的 MAC。 - - 上述建议仅供避免副作用,在有充分理由的情况下可以忽略。 - - * - 有 Wi-Fi 连接 - - 当 Wi-Fi 已连接,且序列由应用程序控制,应用程序可能会影响整个 Wi-Fi 连接的序列控制。 因此,en_sys_seq 要为 true,否则将返回 ``ESP_ERR_INVALID_ARG``。 - - “无 Wi-Fi 连接”情况下的 MAC 地址建议也适用于此情况。 - - 如果 Wi-Fi 模式是 station 模式,MAC 的地址 1 是 station 所连 AP 的 MAC,地址 2 是 station 接口的 MAC,那么就称数据包是从 station 发送到 AP。另一方面,如果 Wi-Fi 模式是 AP 模式,且 MAC 地址 1 是该 AP 所连 station 的 MAC,地址 2 是 AP 接口的 MAC,那么就称数据包是从 AP 发送到 station。为避免与 Wi-Fi 连接冲突,可采用以下检查方法: - - - 如果数据包类型是数据,且是从 station 发送到 AP,IEEE 802.11 Frame control 字段中的 ToDS 位应该为 1,FromDS 位为 0,否则,Wi-Fi 驱动程序不接受该数据包。 - - - 如果数据包类型是数据,且是从 AP 发送到 station,IEEE 802.11 Frame control 字段中的 ToDS 位应该为 0,FromDS 位为 1,否则,Wi-Fi 驱动程序不接受该数据包。 - - - 如果数据包是从 station 发送到 AP,或从 AP 到 station,Power Management、More Data 和 Re-Transmission 位应该为 0,否则,Wi-Fi 驱动程序不接受该数据包。 - - 如果任何检查失败,将返回 ``ESP_ERR_INVALID_ARG``。 - - -Wi-Fi Sniffer 模式 ---------------------------- - -Wi-Fi Sniffer 模式可以通过 :cpp:func:`esp_wifi_set_promiscuous()` 使能。如果使能 Sniffer 模式, **可以** 向应用程序转储以下数据包。 - - - 802.11 管理帧 - - 802.11 数据帧,包括 MPDU、AMPDU、AMSDU 等 - - 802.11 MIMO 帧,Sniffer 模式仅转储 MIMO 帧的长度。 - - 802.11 控制帧 - - 802.11 CRC 错误帧 - -**不可以** 向应用程序转储以下数据包。 - - - 802.11 其它错误帧 - -对于 Sniffer 模式 **可以** 转储的帧,应用程序可以另外使用 :cpp:func:`esp_wifi_set_promiscuous_filter()` 和 :cpp:func:`esp_wifi_set_promiscuous_ctrl_filter()` 决定筛选哪些特定类型的数据包。应用程序默认筛选所有 802.11 数据和管理帧。如果你想要筛选 802.11 控制帧,:cpp:func:`esp_wifi_set_promiscuous_filter()` 中的 filter 参数需要包含 “WIFI_PROMIS_FILTER_MASK_CTRL” 类型, 如果你想进一步区分 802.11 控制帧,那么调用 :cpp:func:`esp_wifi_set_promiscuous_ctrl_filter()`。 - -可以在 WIFI_MODE_NULL、WIFI_MODE_STA、WIFI_MODE_AP、WIFI_MODE_APSTA 等 Wi-Fi 模式下使能 Wi-Fi Sniffer 模式。也就是说,当 station 连接到 AP,或者 AP 有 Wi-Fi 连接时,就可以使能。请注意,Sniffer 模式对 station/AP Wi-Fi 连接的吞吐量有 **很大影响**。通常,除非有特别原因,当 station/AP Wi-Fi 连接出现大量流量,不应使能。 - -该模式下还应注意回调函数 :cpp:type:`wifi_promiscuous_cb_t` 的使用。该回调将直接在 Wi-Fi 驱动程序任务中进行,所以如果应用程序需处理大量过滤的数据包,建议在回调中向应用程序任务发布一个事件,把真正的工作推迟到应用程序任务中完成。 - -Wi-Fi 多根天线 --------------------------- -具体请参考 :doc:`PHY <../api-guides/phy>`。 - -.. only:: SOC_WIFI_CSI_SUPPORT - - Wi-Fi 信道状态信息 - ------------------------------------ - - .. only:: esp32 or esp32s2 or esp32c3 or esp32s3 - - 信道状态信息 (CSI) 是指 Wi-Fi 连接的信道信息。{IDF_TARGET_NAME} 中,CSI 由子载波的信道频率响应组成,CSI 从发送端接收数据包时开始估计。每个子载波信道频率响由两个字节的有符号字符记录,第一个字节是虚部,第二个字节是实部。根据接收数据包的类型,信道频率响应最多有三个字段。分别是 LLTF、HT-LTF 和 STBC-HT-LTF。对于在不同状态的信道上接收到的不同类型的数据包,CSI 的子载波索引和总字节数如下表所示。 - - +------------+-------------+-----------------------------------------+-----------------------------------------------------+--------------------------------------------------------+ - | 信道 | 辅助信道 | | 下 | 上 | - +------------+-------------+-------------+---------------------------+---------+-------------------------------------------+---------+----------------------------------------------+ - | 数据包信息 | 信号模式 | 非 HT | HT | 非 HT | HT | 非 HT | HT | - | +-------------+-------------+---------------------------+---------+---------------+---------------------------+---------+------------------+---------------------------+ - | | 信道带宽 | 20 MHz | 20 MHz | 20 MHz | 20 MHz | 40 MHz | 20 MHz | 20 MHz | 40 MHz | - | +-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+ - | | STBC | 非 STBC | 非 STBC | STBC | 非 STBC | 非 STBC| STBC | 非 STBC | STBC | 非 STBC | 非 STBC | STBC | 非 STBC | STBC | - +------------+-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+ - | 子载波索引 | LLTF | 0~31,-32~-1 | 0~31,-32~-1 | 0~31,-32~-1 | 0~63 | 0~63 | 0~63 | 0~63 | 0~63 | -64~-1 | -64~-1 | -64~-1 | -64~-1 | -64~-1 | - | +-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+ - | | HT-LTF | — | 0~31,-32~-1 | 0~31,-32~-1 | — | 0~63 | 0~62 | 0~63,-64~-1 | 0~60,-60~-1 | — | -64~-1 | -62~-1 | 0~63,-64~-1 | 0~60,-60~-1 | - | +-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+ - | | STBC-HT-LTF | — | — | 0~31,-32~-1 | — | — | 0~62 | — | 0~60,-60~-1 | — | — | -62~-1 | — | 0~60,-60~-1 | - +------------+-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+ - | 总字节数 | 128 | 256 | 384 | 128 | 256 | 380 | 384 | 612 | 128 | 256 | 376 | 384 | 612 | - +--------------------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+ - - 表中的所有信息可以在 wifi_csi_info_t 结构中找到。 - - - 辅助信道指 rx_ctrl 字段的 secondary_channel 字段。 - - 数据包的信号模式指 rx_ctrl 字段的 sig_mode 字段。 - - 信道带宽指 rx_ctrl 字段中的 cwb 字段。 - - STBC 指 rx_ctrl 字段的 stbc 字段。 - - 总字节数指 len 字段。 - - 每个长训练字段 (LTF) 类型对应的 CSI 数据存储在从 buf 字段开始的缓冲区中。每个元素以两个字节的形式存储:虚部和实部。每个元素的顺序与表中的子载波相同。LTF 的顺序是 LLTF、HT-LTF 和 STBC-HT-LTF。但是,根据信道和数据包的信息,3 个 LTF 可能都不存在(见上文)。 - - 如果 :cpp:type:`wifi_csi_info_t` 的 first_word_invalid 字段为 true,表示由于 {IDF_TARGET_NAME} 的硬件限制,CSI 数据的前四个字节无效。 - - 更多信息,如 RSSI,射频的噪声底,接收时间和天线 rx_ctrl 领域。 - - 子载波的虚部和实部的使用请参考下表。 - - +----------------+-------------------+------------------------------+------------------------------+ - | PHY 标准 | 子载波范围 | 导频子载波 | 子载波个数(总数/数据子载波)| - +================+===================+==============================+==============================+ - | 802.11a/g | -26 to +26 | -21, -7, +7, +21 | 52 total, 48 usable | - +----------------+-------------------+------------------------------+------------------------------+ - | 802.11n, 20 MHz| -28 to +28 | -21, -7, +7, +21 | 56 total, 52 usable | - +----------------+-------------------+------------------------------+------------------------------+ - | 802.11n, 40 MHz| -57 to +57 | -53, -25, -11, +11, +25, +53 | 114 total, 108 usable | - +----------------+-------------------+------------------------------+------------------------------+ - - .. note :: - - - 对于 STBC 数据包,每个空时流都提供了 CSI,不会出现 CSD(循环移位延迟)。由于附加链上的每一次循环移位为 -200 ns,因为子载波 0 中没有信道频率响应,在 HT-LTF 和 STBC-HT-LTF 中只记录第一空时流的 CSD 角度。CSD[10:0] 是 11 位,范围从 -pi 到 pi。 - - - 如果调用 API :cpp:func:`esp_wifi_set_csi_config()` 没有使能 LLTF、HT-LTF 或 STBC-HT-LTF,则 CSI 数据的总字节数会比表中的少。例如,如果没有使能 LLTF 和 HT-LTF,而使能 STBC-HT-LTF,当接收到上述条件、HT、40 MHz 或 STBC 的数据包时,CSI 数据的总字节数为 244((61+60)*2+2=244,结果对齐为四个字节,最后两个字节无效)。 - - .. only:: esp32c5 - - 信道状态信息 (CSI) 是指 Wi-Fi 连接的信道信息。{IDF_TARGET_NAME} 中,CSI 由子载波的信道频率响应组成,CSI 从发送端接收数据包时开始估计。每个子载波信道频率响由两个字节的有符号字符记录,第一个字节是虚部,第二个字节是实部。除了 IEEE 802.11g 模式外,其他模式均存在两段 LTF 序列(LLTF + HT/VHT/HE-LTF)。{IDF_TARGET_NAME}可以通过 :cpp:struct:`wifi_csi_acquire_config_t` 中 ``acquire_csi_force_lltf`` 字段决定包含 LLTF 或 HT/VHT/HE-LTF。对于在不同状态的信道上接收到的不同类型的数据包,CSI 的子载波索引和总字节数如下表所示。 - - +------------+------------------+-----------------------------------------+--------------------------------------------+----------------------------------------------------------------+----------------------------------------------------------------+ - | 信道 | 辅助信道 | | 下 | 上 | - +------------+------------------+-------------+---------------------------+--------------------------------------------+-------------+--------------------------------------------------+-------------+--------------------------------------------------+ - | 数据包信息 | 信号模式 | 非 HT | HT | HE | 非 HT | HT | 非 HT | HT | - | +------------------+-------------+---------------------------+--------------------------------------------+-------------+----------------------+---------------------------+-------------+----------------------+---------------------------+ - | | 信道带宽 | 20 MHz | 20 MHz | 20 MHz | 20 MHz | 20 MHz | 40 MHz | 20 MHz | 20 MHz | 40 MHz | - | +------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ - | | STBC | 非 STBC | 非 STBC | STBC | 非 STBC | STBC | 非 STBC | 非 STBC | STBC | 非 STBC | STBC | 非 STBC | 非 STBC | STBC | 非 STBC | STBC | - +------------+------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ - | 子载波索引 | LLTF | 0~26,-26~-1 | — | — | — | — | 0~52 | — | — | — | — | -53~-1| — | — | — | — | - | +------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ - | | HT-LTF (HT-LTF1) | — | 0~28,-28~-1 | 0~28,-28~-1 | — | — | — | 0~56| 0~56 | 0~58,-58~-1 | 0~58,-58~-1 | — | -57~-1| -57~-1 | 0~58,-58~-1 | 0~58,-58~-1 | - | +------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ - | | HT-LTF2 | — | — | 0~28,-28~-1 | — | — | — | — | 0~56 | — | 0~58,-58~-1 | — | — | -57~-1 | — | 0~58,-58~-1 | - | +------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ - | | HE-LTF (HE-LTF1) | — | — | — | 0~122,-122~1 | 由CSI配置决定 | — | — | — | — | — | — | — | — | — | — | - | +------------------+-------------+-------------+-------------+---------------+ +-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ - | | HE-LTF2 | — | — | — | — | | — | — | — | — | — | — | — | — | — | — | - +------------+------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ - | 总字节数 | 106 | 114| 228 | 490 | 490 | 106 | 114| 228 | 234 | 468 | 106 | 114| 228 | 234 | 468 | - +-------------------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+ - - .. note :: - - - HT/VHT/HE 模式均存在两段 LTF 序列即:LLTF + HT/VHT/HE-LTF, 如果 :cpp:struct:`wifi_csi_acquire_config_t` 中 ``acquire_csi_force_lltf`` 为 false 时, CSI 数据中仅包含 HT/VHT/HE-LTF(如上表所示), 否则 CSI 数据中仅包含 LLTF。 HT/VHT/HE 模式 LLTF 的子载波索引和 CSI 总字节数同非 HT 模式 LLTF 子载波索引和 CSI 总字节数一致。 - - VHT 模式时子载波索引和 CSI 总字节数同 HT 模式的子载波索引和 CSI 总字节数一致。 - - 表中的信息可以在 :cpp:type:`wifi_csi_info_t` 结构体中找到。 - - - 辅助信道指 ``rx_ctrl`` 字段的 ``second`` 字段。 - - 数据包的信号模式指 ``rx_ctrl`` 字段的 ``cur_bb_format`` 字段。 - - 总字节数指 ``len`` 字段。 - - 每个长训练字段 (LTF) 类型对应的 CSI 数据存储在从 buf 字段开始的缓冲区中。每个元素以两个字节的形式存储:虚部和实部。每个元素的顺序与表中的子载波相同。LTF 的顺序是 LLTF、HT/VHT/HE-LTF。根据信道和数据包的信息,LTF 的存在情况见上文。 - - 如果 ``first_word_invalid`` 字段为 true,表示由于 {IDF_TARGET_NAME} 的硬件限制,CSI 数据的前四个字节无效。 - - 如果 ``rx_ctrl`` 字段中的 ``rx_channel_estimate_info_vld`` 为 1,表明CSI数据是有效的,否则,CSI数据是无效的。 - - 更多信息,如 RSSI、射频底噪声、接收时间及天线,请参见 ``rx_ctrl`` 字段。 - - 对于 STBC 数据包,HE-LTF 和 STBC-HE-LTF 的子载波索引由 :cpp:type:`wifi_csi_config_t` 中的 ``acquire_csi_he_stbc_mode`` 字段决定,具体请参见下表。 - - +---------------------+------------------+-------------------+ - | acquire_csi_he_stbc | HE-LTF1 | HE-LTF2 | - +---------------------+------------------+-------------------+ - | 0 | -122~-1, 0~122 | — | - +---------------------+------------------+-------------------+ - | 1 | — | -122~-1, 0~122 | - +---------------------+------------------+-------------------+ - | 2 | 在 HE-LTF1 和 HE-LTF2 中进行均匀采样 | - +---------------------+------------------+-------------------+ - - 有效子载波的虚部和实部的使用请参考下表。 - - +-----------------------+------------------+------------------------------------------+------------------------------+ - | PHY 标准 | 子载波范围 | 无效子载波 | 子载波个数(总数/数据子载波)| - +=======================+==================+==========================================+==============================+ - | 802.11a/g | -26 to +26 | 0 | 53 total, 52 usable | - +-----------------------+------------------+------------------------------------------+------------------------------+ - | 802.11n, 20 MHz | -28 to +28 | 0 | 57 total, 56 usable | - +-----------------------+------------------+------------------------------------------+------------------------------+ - | 802.11n, 40 MHz | -58 to +58 | -1, 0, 1 | 117 total, 114 usable | - +-----------------------+------------------+------------------------------------------+------------------------------+ - | 802.11ac, 20 MHz | -28 to +28 | 0 | 57 total, 56 usable | - +-----------------------+------------------+------------------------------------------+------------------------------+ - | 802.11ax, 20 MHz (SU) | -122 to + 122 | -1, 0, 1 | 245 total, 242 usable | - +-----------------------+------------------+------------------------------------------+------------------------------+ - - - .. note :: - - - PHY 为 802.11ax时,MU 数据包的 CSI 子载波范围和无效子载波索引请参考协议。 - - .. note :: - - - 对于 STBC 数据包,每个空时流都提供了 CSI,不会出现 CSD(循环移位延迟)。由于附加链上的每一次循环移位为 -200 ns,因为子载波 0 中没有信道频率响应,在 HT-LTF1 和 HT-LTF2 中只记录第一空时流的 CSD 角度。CSD[10:0] 是 11 位,范围从 -pi 到 pi。 - - Wi-Fi 信道状态信息配置 - ------------------------------------------- - - 要使用 Wi-Fi CSI,需要执行以下步骤。 - - - 在菜单配置中选择 Wi-Fi CSI。方法是 ``Menuconfig`` > ``Components config`` > ``Wi-Fi`` > ``Wi-Fi CSI (Channel State Information)``。 - - 调用 API :cpp:func:`esp_wifi_set_csi_rx_cb()` 设置 CSI 接收回调函数。 - - 调用 API :cpp:func:`esp_wifi_set_csi_config()` 配置 CSI。 - - 调用 API :cpp:func:`esp_wifi_set_csi()` 使能 CSI。 - - CSI 接收回调函数从 Wi-Fi 任务中运行。因此,不要在回调函数中进行冗长的操作。可以将需要的数据发布到队列中,并从一个较低优先级的任务中处理。由于 station 在断开连接时不会收到任何数据包,只有在连接时才会收到来自 AP 的数据包,因此建议通过调用函数 :cpp:func:`esp_wifi_set_promiscuous()` 使能 Sniffer 模式接收更多 CSI 数据。 - -Wi-Fi HT20/40 -------------------------- - -.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 or esp32c6 or esp32c5 - - {IDF_TARGET_NAME} 支持 Wi-Fi 带宽 HT20 或 HT40,不支持 HT20/40 共存,调用函数 :cpp:func:`esp_wifi_set_bandwidth()` 可改变 station/AP 的默认带宽。{IDF_TARGET_NAME} station 和 AP 的默认带宽为 HT40。 - - station 模式下,实际带宽首先在 Wi-Fi 连接时协商。只有当 station 和所连 AP 都支持 HT40 时,带宽才为 HT40,否则为 HT20。如果所连的 AP 的带宽发生变化,则在不断开 Wi-Fi 连接的情况下再次协商实际带宽。 - - 同样,在 AP 模式下,在 AP 与所连 station 协商实际带宽。如果 AP 和其中一个 station 支持 HT40, 则为 HT40, 否则为 HT20。 - - 在 station/AP 共存模式下,station 和 AP 都可独立配置为 HT20/40。如果 station 和 AP 都协商为 HT40,由于 {IDF_TARGET_NAME} 中,station 的优先级总高于 AP,HT40 信道是 station 的信道。例如,AP 的配置带宽为 HT40,配置的主信道为 6,配置的辅助信道为 10。如果,station 所连路由器的主信道为 6、辅助信道为 2,AP 的实际信道将自动更改为主 6 和辅 2。 - - 理论上,HT40 可以获得更大的吞吐量,因为 HT40 的最大原始 PHY 数据速率为 150 Mbps,而 HT20 为 72 Mbps。但是,如果设备在某些特殊环境中使用,例如,{IDF_TARGET_NAME} 周围其他 Wi-Fi 设备过多,HT40 的性能可能会降低。因此,如果应用程序需要支持相同或类似的情况,建议始终将带宽配置为 HT20。 - -.. only:: esp32c5 - - .. note:: - - 当工作在 2.4 GHz + 5 GHz 频段模式(``WIFI_BAND_MODE_AUTO``)时,需要使用函数: :cpp:func:`esp_wifi_set_bandwidths()` 分别设置 2.4 GHz 频段 和 5 GHz 频段的带宽。 - -.. only:: esp32c2 - - {IDF_TARGET_NAME} 仅支持 Wi-Fi 带宽 HT20,不支持 Wi-Fi 带宽 HT40 或 HT20/40 共存。 - -Wi-Fi QoS -------------------------- - -{IDF_TARGET_NAME} 支持 WFA Wi-Fi QoS 认证所要求的所有必备功能。 - -Wi-Fi 协议中定义了四个 AC(访问类别),每个 AC 有各自的优先级访问 Wi-Fi 信道。此外,还定义了映射规则以映射其他协议的 QoS 优先级,例如 802.11D 或 TCP/IP 到 Wi-Fi AC。 - -下表描述 {IDF_TARGET_NAME} 中 IP 优先级如何映射到 Wi-Fi AC,还指明此 AC 是否支持 AMPDU。该表按优先级降序排列,即 AC_VO 拥有最高优先级。 - -+-----------+---------------------+----------------+ -| IP 优先级 | Wi-Fi AC | 是否支持 AMPDU | -+===========+=====================+================+ -| 6, 7 | AC_VO (Voice) | 否 | -+-----------+---------------------+----------------+ -| 4, 5 | AC_VI (Video) | 是 | -+-----------+---------------------+----------------+ -| 3, 0 | AC_BE (Best Effort) | 是 | -+-----------+---------------------+----------------+ -| 1, 2 | AC_BK (Background) | 是 | -+-----------+---------------------+----------------+ - -应用程序可以通过套接字选项 IP_TOS 配置 IP 优先级使用 QoS 功能。下面是使套接字使用 VI 队列的示例:: - - const int ip_precedence_vi = 4; - const int ip_precedence_offset = 5; - int priority = (ip_precedence_vi << ip_precedence_offset); - setsockopt(socket_id, IPPROTO_IP, IP_TOS, &priority, sizeof(priority)); - -理论上,高优先级的 AC 比低优先级 AC 具有更好的性能,但并非总是如此,下面是一些关于如何使用 Wi-Fi QoS 的建议: - - - 可以把一些真正重要的应用程序流量放到 AC_VO 队列中。避免通过 AC_VO 队列发送大流量。一方面,AC_VO 队列不支持 AMPDU,如果流量很大,性能不会优于其他队列。另一方面,可能会影响同样使用 AC_VO 队列的管理帧。 - - 避免使用 AMPDU 支持的、两个以上的不同优先级,比如 socket A 使用优先级 0,socket B 使用优先级 1,socket C 使用优先级 2。因为可能需要更多的内存,不是好的设计。具体来说,Wi-Fi 驱动程序可能会为每个优先级生成一个 Block Ack 会话,如果设置了 Block Ack 会话,则需要更多内存。 - - -Wi-Fi AMSDU -------------------------- - -.. only:: not SOC_SPIRAM_SUPPORTED - - {IDF_TARGET_NAME} 支持接收 AMSDU。 - -.. only:: SOC_SPIRAM_SUPPORTED - - {IDF_TARGET_NAME} 支持接收和发送 AMSDU。开启 AMSDU 发送比较消耗内存,默认不开启 AMSDU 发送。可通过选项 :ref:`CONFIG_ESP_WIFI_AMSDU_TX_ENABLED` 使能 AMSDU 发送功能, 但是使能 AMSDU 发送依赖于 :ref:`CONFIG_SPIRAM` 。 - -Wi-Fi 分片 -------------------------- - -.. only:: not SOC_WIFI_TXOP_SUPPORT - - 支持 Wi-Fi 接收分片,但不支持 Wi-Fi 发送分片。 - -.. only:: SOC_WIFI_TXOP_SUPPORT - - {IDF_TARGET_NAME} 支持 Wi-Fi 接收和发送分片。 - -WPS 注册 -------------------------- - -在 Wi-Fi 模式 WIFI_MODE_STA 或 WIFI_MODE_APSTA 下,{IDF_TARGET_NAME} 支持 WPS 注册功能。目前,{IDF_TARGET_NAME} 支持的 WPS enrollee 类型有 PBC 和 PIN。 - -.. _wifi-buffer-usage: - -Wi-Fi 缓冲区使用情况 --------------------------- - -本节只介绍动态缓冲区配置。 - -缓冲区配置的重要性 -+++++++++++++++++++++++++++++++++++++++ - -为了获得一个具有强健、高性能的系统,我们需要非常谨慎地考虑内存的使用或配置情况,因为: - - - {IDF_TARGET_NAME} 的可用内存有限。 - - 目前,LwIP 和 Wi-Fi 驱动程序中默认的缓冲区类型是“动态”,**意味着 LwIP 和 Wi-Fi 都与应用程序共享内存**。程序员应该时刻牢记这一点,否则将面临如“堆内存耗尽”等的内存问题。 - - “堆耗尽”情况非常危险,会导致 {IDF_TARGET_NAME} 出现“未定义行为”。因此,应该为应用程序预留足够的堆内存,防止耗尽。 - - Wi-Fi 的吞吐量很大程度上取决于与内存相关的配置,如 TCP 窗口大小、Wi-Fi 接收/发送数据动态缓冲区数量等。 - - {IDF_TARGET_NAME} LwIP/Wi-Fi 可能使用的堆内存峰值取决于许多因素,例如应用程序可能拥有的最大 TCP/UDP 连接等。 - - 在考虑内存配置时,应用程序所需的总内存也是一个重要因素。 - -由于这些原因,不存在一个适合所有应用程序的配置。相反,我们必须为每个不同的应用程序考虑不同的内存配置。 - -动态与静态缓冲区 -++++++++++++++++++++++++++++++ - -Wi-Fi 驱动程序中默认的缓存类型是“动态”。大多数情况下,动态缓冲区可以极大地节省内存。但是因为应用程序需要考虑 Wi-Fi 的内存使用情况,会给应用程序编程造成一定的难度。 - -lwIP 还在 TCP/IP 层分配缓冲区,这种缓冲区分配也是动态的。具体内容,见 `lwIP 文档内存使用和性能部分 `_。 - -Wi-Fi 动态缓冲区峰值 -++++++++++++++++++++++++++++++ - -Wi-Fi 驱动程序支持多种类型的缓冲区(参考 `Wi-Fi 缓冲区配置`_ )。但本节只介绍 Wi-Fi 动态缓冲的使用方法 -Wi-Fi 使用的堆内存峰值是 Wi-Fi 驱动程序 **理论上消耗的最大内存**。通常,该内存峰值取决于: - -- :math:`b_{rx}` 配置的动态接收数据缓冲区数 -- :math:`b_{tx}` 配置的动态发送数据缓冲区数 -- :math:`m_{rx}` Wi-Fi 驱动程序可以接收的最大数据包 -- :math:`m_{tx}` Wi-Fi 驱动程序可以发送的最大数据包 - -因此,Wi-Fi 驱动程序消耗的内存峰值(:math:`p`)可以用下面的公式计算: - -.. math:: - - p = (b_{rx} * m_{rx}) + (b_{tx} * m_{tx}) - -一般情况下,不需要关心动态发送数据长缓冲区和超长缓冲区,因为它们是管理帧,对系统的影响很小。 - -.. _How-to-improve-Wi-Fi-performance: - -如何提高 Wi-Fi 性能 ----------------------------------- - -{IDF_TARGET_NAME} Wi-Fi 的性能受许多参数的影响,各参数之间存在相互制约。如果配置地合理,不仅可以提高性能,还可以增加应用程序的可用内存,提高稳定性。 - -在本节中,我们将简单介绍 Wi-Fi/LWIP 协议栈的工作模式,并说明各个参数的作用。我们将推荐几种配置等级,你可以根据使用场景选择合适的等级。 - -协议栈工作模式 -++++++++++++++++++++++++++++++++++ - -.. figure:: ../../_static/api-guides-WiFi-driver-how-to-improve-WiFi-performance.png - :align: center - - {IDF_TARGET_NAME} 数据路径 - -{IDF_TARGET_NAME} 协议栈分为四层,分别为应用层、LWIP 层、Wi-Fi 层和硬件层。 - - - 在接收过程中,硬件将接收到的数据包放入 DMA 缓冲区,然后依次传送到 Wi-Fi 的接收数据缓冲区、LWIP 的接收数据缓冲区进行相关协议处理,最后传送到应用层。Wi-Fi 的接收数据缓冲区和 LWIP 的接收数据缓冲区默认共享同一个缓冲区。也就是说,Wi-Fi 默认将数据包转发到 LWIP 作为参考。 - - - 在发送过程中,应用程序首先将要发送的消息复制到 LWIP 层的发送数据缓冲区,进行 TCP/IP 封装。然后将消息发送到 Wi-Fi 层的发送数据缓冲区进行 MAC 封装,最后等待发送。 - -参数 -++++++++++++++ - -适当增加上述缓冲区的大小或数量,可以提高 Wi-Fi 性能,但同时,会减少应用程序的可用内存。下面我们将介绍你需要配置的参数: - -**接收数据方向:** - - - :ref:`CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM` - 该参数表示硬件层的 DMA 缓冲区数量。提高该参数将增加发送方的一次性接收吞吐量,从而提高 Wi-Fi 协议栈处理突发流量的能力。 - - - :ref:`CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM` - 该参数表示 Wi-Fi 层中接收数据缓冲区的数量。提高该参数可以增强数据包的接收性能。该参数需要与 LWIP 层的接收数据缓冲区大小相匹配。 - - - :ref:`CONFIG_ESP_WIFI_RX_BA_WIN` - 该参数表示接收端 AMPDU BA 窗口的大小,应配置为 :ref:`CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM` 和 :ref:`CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM` 的二倍数值中较小的数值。 - - - :ref:`CONFIG_LWIP_TCP_WND_DEFAULT` - 该参数表示 LWIP 层用于每个 TCP 流的的接收数据缓冲区大小,应配置为 WIFI_DYNAMIC_RX_BUFFER_NUM (KB) 的值,从而实现高稳定性能。同时,在有多个流的情况下,应相应降低该参数值。 - -**发送数据方向:** - - - :ref:`CONFIG_ESP_WIFI_TX_BUFFER` - 该参数表示发送数据缓冲区的类型,建议配置为动态缓冲区,该配置可以充分利用内存。 - - - :ref:`CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM` - 该参数表示 Wi-Fi 层发送数据缓冲区数量。提高该参数可以增强数据包发送的性能。该参数值需要与 LWIP 层的发送数据缓冲区大小相匹配。 - - - :ref:`CONFIG_LWIP_TCP_SND_BUF_DEFAULT` - 该参数表示 LWIP 层用于每个 TCP 流的的发送数据缓冲区大小,应配置为 WIFI_DYNAMIC_TX_BUFFER_NUM (KB) 的值,从而实现高稳定性能。在有多个流的情况下,应相应降低该参数值。 - -**通过在 IRAM 中放置代码优化吞吐量:** - -.. only:: esp32 or esp32s2 - - - :ref:`CONFIG_ESP_WIFI_IRAM_OPT` - 如果使能该选项,一些 Wi-Fi 功能将被移至 IRAM,从而提高吞吐量,IRAM 使用量将增加 15 kB。 - - - :ref:`CONFIG_ESP_WIFI_RX_IRAM_OPT` - 如果使能该选项,一些 Wi-Fi 接收数据功能将被移至 IRAM,从而提高吞吐量,IRAM 使用量将增加 16 kB。 - - - :ref:`CONFIG_LWIP_IRAM_OPTIMIZATION` - 如果使能该选项,一些 LWIP 功能将被移至 IRAM,从而提高吞吐量,IRAM 使用量将增加 13 kB。 - -.. only:: esp32c6 - - - :ref:`CONFIG_ESP_WIFI_IRAM_OPT` - 如果使能该选项,一些 Wi-Fi 功能将被移至 IRAM,从而提高吞吐量,IRAM 使用量将增加 13 kB。 - - - :ref:`CONFIG_ESP_WIFI_RX_IRAM_OPT` - 如果使能该选项,一些 Wi-Fi 接收数据功能将被移至 IRAM,从而提高吞吐量,IRAM 使用量将增加 7 kB。 - - - :ref:`CONFIG_LWIP_IRAM_OPTIMIZATION` - 如果使能该选项,一些 LWIP 功能将被移至 IRAM,从而提高吞吐量,IRAM 使用量将增加 14 kB。 - -.. only:: esp32s2 - - **缓存:** - - - :ref:`CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE` - 配置指令缓存的大小。 - - - :ref:`CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_SIZE` - 配置指令缓存总线的宽度。 - -.. only:: esp32s3 - - **缓存:** - - - :ref:`CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE` - 配置指令缓存的大小。 - - - :ref:`CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE` - 配置指令缓存总线的宽度。 - - - :ref:`CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS` - 配置指令缓存相连方式. - - - :ref:`CONFIG_ESP32S3_DATA_CACHE_SIZE` - 配置数据缓存的大小. - - - :ref:`CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE` - 配置数据缓存行大小. - - - :ref:`CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS` - 配置数据缓存相连方式. - -.. note:: - 上述的缓冲区大小固定为 1.6 KB。 - -如何配置参数 -++++++++++++++++++++++++++++ - -{IDF_TARGET_NAME} 的内存由协议栈和应用程序共享。 - -在这里,我们给出了几种配置等级。在大多数情况下,应根据应用程序所占用内存的大小,选择合适的等级进行参数配置。 - -下表中未提及的参数应设置为默认值。 - -.. only:: esp32 - - .. list-table:: - :header-rows: 1 - :widths: 10 5 5 10 5 5 10 5 - - * - 等级 - - Iperf - - 发送数据优先 - - 高性能 - - 接收数据优先 - - 默认值 - - 节省内存 - - 最小 - * - 可用内存 (KB) - - 37.1 - - 113.8 - - 123.3 - - 145.5 - - 144.5 - - 170.2 - - 185.2 - * - WIFI_STATIC_RX_BUFFER_NUM - - 16 - - 6 - - 6 - - 6 - - 6 - - 6 - - 4 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 64 - - 16 - - 24 - - 34 - - 20 - - 12 - - 8 - * - WIFI_DYNAMIC_TX_BUFFER_NUM - - 64 - - 28 - - 24 - - 18 - - 20 - - 12 - - 8 - * - WIFI_RX_BA_WIN - - 32 - - 8 - - 12 - - 12 - - 10 - - 6 - - 禁用 - * - TCP_SND_BUF_DEFAULT (KB) - - 65 - - 28 - - 24 - - 18 - - 20 - - 12 - - 8 - * - TCP_WND_DEFAULT (KB) - - 65 - - 16 - - 24 - - 34 - - 20 - - 12 - - 8 - * - WIFI_IRAM_OPT - - 开启 - - 开启 - - 开启 - - 开启 - - 开启 - - 开启 - - 开启 - * - WIFI_RX_IRAM_OPT - - 开启 - - 开启 - - 开启 - - 开启 - - 开启 - - 开启 - - 开启 - * - LWIP_IRAM_OPTIMIZATION - - 开启 - - 开启 - - 开启 - - 开启 - - 开启 - - 开启 - - 开启 - * - TCP 发送数据吞吐量 (Mbit/s) - - 74.6 - - 50.8 - - 46.5 - - 39.9 - - 44.2 - - 33.8 - - 25.6 - * - TCP 接收数据吞吐量 (Mbit/s) - - 63.6 - - 35.5 - - 42.3 - - 48.5 - - 40.5 - - 30.1 - - 27.8 - * - UDP 发送数据吞吐量 (Mbit/s) - - 76.2 - - 75.1 - - 74.1 - - 72.4 - - 69.6 - - 64.1 - - 36.5 - * - UDP 接收数据吞吐量 (Mbit/s) - - 83.1 - - 66.3 - - 75.1 - - 75.6 - - 73.1 - - 65.3 - - 54.7 - - -.. only:: esp32s2 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 10 10 10 - - * - 等级 - - Iperf - - 高性能 - - 默认 - - 节省内存 - - 最小 - * - 可用内存 (KB) - - 4.1 - - 24.2 - - 78.4 - - 86.5 - - 116.4 - * - WIFI_STATIC_RX_BUFFER_NUM - - 8 - - 6 - - 6 - - 4 - - 3 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 24 - - 18 - - 12 - - 8 - - 6 - * - WIFI_DYNAMIC_TX_BUFFER_NUM - - 24 - - 18 - - 12 - - 8 - - 6 - * - WIFI_RX_BA_WIN - - 12 - - 9 - - 6 - - 4 - - 3 - * - TCP_SND_BUF_DEFAULT (KB) - - 24 - - 18 - - 12 - - 8 - - 6 - * - TCP_WND_DEFAULT (KB) - - 24 - - 18 - - 12 - - 8 - - 6 - * - WIFI_IRAM_OPT - - 开启 - - 开启 - - 开启 - - 开启 - - 关闭 - * - WIFI_RX_IRAM_OPT - - 开启 - - 开启 - - 开启 - - 关闭 - - 关闭 - * - LWIP_IRAM_OPTIMIZATION - - 开启 - - 开启 - - 关闭 - - 关闭 - - 关闭 - * - INSTRUCTION_CACHE - - 16 - - 16 - - 16 - - 16 - - 8 - * - INSTRUCTION_CACHE_LINE - - 16 - - 16 - - 16 - - 16 - - 16 - * - TCP 发送数据吞吐量 (Mbit/s) - - 37.6 - - 33.1 - - 22.5 - - 12.2 - - 5.5 - * - TCP 接收数据吞吐量 (Mbit/s) - - 31.5 - - 28.1 - - 20.1 - - 13.1 - - 7.2 - * - UDP 发送数据吞吐量 (Mbit/s) - - 58.1 - - 57.3 - - 28.1 - - 22.6 - - 8.7 - * - UDP 接收数据吞吐量 (Mbit/s) - - 78.1 - - 66.7 - - 65.3 - - 53.8 - - 28.5 - -.. only:: esp32c3 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 - - * - 等级 - - Iperf - - 默认 - - 最小 - * - 可用内存 (KB) - - 59 - - 160 - - 180 - * - WIFI_STATIC_RX_BUFFER_NUM - - 20 - - 8 - - 3 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 40 - - 16 - - 6 - * - WIFI_DYNAMIC_TX_BUFFER_NUM - - 40 - - 16 - - 6 - * - WIFI_RX_BA_WIN - - 32 - - 16 - - 6 - * - TCP_SND_BUF_DEFAULT (KB) - - 40 - - 16 - - 6 - * - TCP_WND_DEFAULT (KB) - - 40 - - 16 - - 6 - * - LWIP_IRAM_OPTIMIZATION - - 开启 - - 开启 - - 关闭 - * - TCP 发送数据吞吐量 (Mbit/s) - - 38.1 - - 27.2 - - 20.4 - * - TCP 接收数据吞吐量 (Mbit/s) - - 35.3 - - 24.2 - - 17.4 - * - UDP 发送数据吞吐量 (Mbit/s) - - 40.6 - - 38.9 - - 34.1 - * - UDP 接收数据吞吐量 (Mbit/s) - - 52.4 - - 44.5 - - 44.2 - -.. only:: esp32c6 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 - - * - 等级 - - Iperf - - 默认 - - 最小 - * - 可用内存 (KB) - - 223 - - 276 - - 299 - * - WIFI_STATIC_RX_BUFFER_NUM - - 20 - - 8 - - 3 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 40 - - 16 - - 6 - * - WIFI_DYNAMIC_TX_BUFFER_NUM - - 40 - - 16 - - 6 - * - WIFI_RX_BA_WIN - - 32 - - 16 - - 6 - * - TCP_SND_BUF_DEFAULT (KB) - - 40 - - 16 - - 6 - * - TCP_WND_DEFAULT (KB) - - 40 - - 16 - - 6 - * - LWIP_IRAM_OPTIMIZATION - - 开启 - - 开启 - - 关闭 - * - TCP 发送数据吞吐量 (Mbit/s) - - 30.5 - - 25.9 - - 16.4 - * - TCP 接收数据吞吐量 (Mbit/s) - - 27.8 - - 21.6 - - 14.3 - * - UDP 发送数据吞吐量 (Mbit/s) - - 37.8 - - 36.1 - - 34.6 - * - UDP 接收数据吞吐量 (Mbit/s) - - 41.5 - - 36.8 - - 36.7 - -.. only:: esp32c2 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 15 - - * - 等级 - - Iperf - - 默认 - - 最小 - * - 可用内存 (KB) - - 37 - - 56 - - 84 - * - WIFI_STATIC_RX_BUFFER_NUM - - 14 - - 7 - - 3 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 18 - - 14 - - 6 - * - WIFI_DYNAMIC_TX_BUFFER_NUM - - 18 - - 14 - - 6 - * - WIFI_RX_BA_WIN - - 16 - - 12 - - 6 - * - TCP_SND_BUF_DEFAULT (KB) - - 18 - - 14 - - 6 - * - TCP_WND_DEFAULT (KB) - - 18 - - 14 - - 6 - * - LWIP_IRAM_OPTIMIZATION - - 开启 - - 开启 - - 关闭 - * - TCP 发送数据吞吐量 (Mbit/s) - - 21.6 - - 21.4 - - 14.3 - * - TCP 接收数据吞吐量 (Mbit/s) - - 19.1 - - 17.9 - - 12.4 - * - UDP 发送数据吞吐量 (Mbit/s) - - 26.4 - - 26.3 - - 25.0 - * - UDP 接收数据吞吐量 (Mbit/s) - - 32.3 - - 31.5 - - 27.7 - -.. only:: esp32s3 - - .. list-table:: - :header-rows: 1 - :widths: 25 20 25 25 - - * - 等级 - - Iperf - - 默认 - - 最小 - * - 可用内存 (KB) - - 133.9 - - 183.9 - - 273.6 - * - WIFI_STATIC_RX_BUFFER_NUM - - 24 - - 8 - - 3 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 64 - - 32 - - 6 - * - WIFI_DYNAMIC_TX_BUFFER_NUM - - 64 - - 32 - - 6 - * - WIFI_RX_BA_WIN - - 32 - - 16 - - 6 - * - TCP_SND_BUF_DEFAULT (KB) - - 64 - - 32 - - 6 - * - TCP_WND_DEFAULT (KB) - - 64 - - 32 - - 6 - * - WIFI_IRAM_OPT - - 开启 - - 开启 - - 开启 - * - WIFI_RX_IRAM_OPT - - 开启 - - 开启 - - 开启 - * - LWIP_IRAM_OPTIMIZATION - - 开启 - - 开启 - - 关闭 - * - INSTRUCTION_CACHE - - 32 - - 32 - - 16 - * - INSTRUCTION_CACHE_LINE - - 32 - - 32 - - 32 - * - INSTRUCTION_CACHE_WAYS - - 8 - - 8 - - 4 - * - TCP 发送数据吞吐量 (Mbit/s) - - 83.93 - - 64.28 - - 23.17 - * - TCP 接收数据吞吐量 (Mbit/s) - - 73.98 - - 60.39 - - 18.11 - * - UDP 发送数据吞吐量 (Mbit/s) - - 98.69 - - 96.28 - - 48.78 - * - UDP 接收数据吞吐量 (Mbit/s) - - 88.58 - - 86.57 - - 59.45 - -.. only:: esp32 or esp32s3 - - .. note:: - 以上结果使用华硕 RT-N66U 路由器,在屏蔽箱中进行单流测试得出。 - {IDF_TARGET_NAME} 的 CPU 为双核,频率为 240 MHz,flash 为 QIO 模式,频率为 80 MHz。 - -.. only:: esp32s2 - - .. note:: - 以上结果使用华硕 RT-N66U 路由器,在屏蔽箱中进行单流测试得出。 - {IDF_TARGET_NAME} 的 CPU 为单核,频率为 240 MHz,flash 为 QIO 模式,频率为 80 MHz。 - -.. only:: esp32c3 - - .. note:: - 以上结果使用华硕 RT-N66U 路由器,在屏蔽箱中进行单流测试得出。 - {IDF_TARGET_NAME} 的 CPU 为单核,频率为 160 MHz,flash 为 QIO 模式,频率为 80 MHz。 - -.. only:: esp32c6 - - .. note:: - 以上结果使用小米 AX6000 路由器,在屏蔽箱中进行单流测试得出。 - {IDF_TARGET_NAME} 的 CPU 为单核,频率为 160 MHz,flash 为 QIO 模式,频率为 80 MHz。 - -.. only:: esp32c2 - - .. note:: - 以上结果使用红米 RM2100 路由器,在屏蔽箱中进行单流测试得出。 - {IDF_TARGET_NAME} 的 CPU 为单核,频率为 120 MHz,flash 为 QIO 模式,频率为 60 MHz。 - -.. only:: esp32 - - **等级:** - - - **Iperf 等级** - {IDF_TARGET_NAME} 的极端性能等级,用于测试极端性能。 - - - **高性能等级** - {IDF_TARGET_NAME} 的高性能配置等级,适用于应用程序占用内存较少且有高性能要求的场景。在该等级中,可以根据使用场景选择使用接收数据优先等级或发送数据优先等级。 - - - **默认等级** - {IDF_TARGET_NAME} 的默认配置等级、兼顾可用内存和性能。 - - - **节省内存等级** - 该等级适用于应用程序需要大量内存的场景,在这一等级下,收发器的性能会有所降低。 - - - **最小等级** - {IDF_TARGET_NAME} 的最小配置等级。协议栈只使用运行所需的内存。适用于对性能没有要求,而应用程序需要大量内存的场景。 - -.. only:: esp32s2 - - **等级:** - - - **Iperf 等级** - {IDF_TARGET_NAME} 极端性能等级,用于测试极端性能。 - - - **高性能等级** - {IDF_TARGET_NAME} 的高性能配置等级,适用于应用程序占用内存较少且有高性能要求的场景。 - - - **默认等级** - {IDF_TARGET_NAME} 的默认配置等级、兼顾可用内存和性能。 - - - **节省内存等级** - 该等级适用于应用程序需要大量内存的场景,在这一等级下,收发器的性能会有所降低。 - - - **最小等级** - {IDF_TARGET_NAME} 的最小配置等级。协议栈只使用运行所需的内存。适用于对性能没有要求,而应用程序需要大量内存的场景。 - -.. only:: esp32c3 or esp32s3 or esp32c6 - - **等级:** - - - **Iperf 等级** - {IDF_TARGET_NAME} 极端性能等级,用于测试极端性能。 - - - **默认等级** - {IDF_TARGET_NAME} 的默认配置等级、兼顾可用内存和性能。 - - - **最小等级** - {IDF_TARGET_NAME} 的最小配置等级。协议栈只使用运行所需的内存。适用于对性能没有要求,而应用程序需要大量内存的场景。 - -.. only:: SOC_SPIRAM_SUPPORTED - - 使用 PSRAM - ++++++++++++++++++++++++++++ - - PSRAM 一般在应用程序占用大量内存时使用。在该模式下,:ref:`CONFIG_ESP_WIFI_TX_BUFFER` 被强制为静态。:ref:`CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM` 表示硬件层 DMA 缓冲区数量,提高这一参数可以增强性能。 - 以下是使用 PSRAM 时的推荐等级。 - - .. only:: esp32 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 10 15 - - * - 等级 - - Iperf - - 默认 - - 节省内存 - - 最小 - * - 可用内存 (KB) - - 113.8 - - 152.4 - - 181.2 - - 202.6 - * - WIFI_STATIC_RX_BUFFER_NUM - - 16 - - 8 - - 4 - - 2 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 128 - - 128 - - 128 - - 128 - * - WIFI_STATIC_TX_BUFFER_NUM - - 16 - - 8 - - 4 - - 2 - * - WIFI_RX_BA_WIN - - 16 - - 16 - - 8 - - 禁用 - * - TCP_SND_BUF_DEFAULT (KB) - - 65 - - 65 - - 65 - - 65 - * - TCP_WND_DEFAULT (KB) - - 65 - - 65 - - 65 - - 65 - * - WIFI_IRAM_OPT - - 开启 - - 开启 - - 开启 - - 关闭 - * - WIFI_RX_IRAM_OPT - - 开启 - - 开启 - - 关闭 - - 关闭 - * - LWIP_IRAM_OPTIMIZATION - - 开启 - - 关闭 - - 关闭 - - 关闭 - * - TCP 发送数据吞吐量 (Mbit/s) - - 37.5 - - 31.7 - - 21.7 - - 14.6 - * - TCP 接收数据吞吐量 (Mbit/s) - - 31.5 - - 29.8 - - 26.5 - - 21.1 - * - UDP 发送数据吞吐量 (Mbit/s) - - 69.1 - - 31.5 - - 27.1 - - 24.1 - * - UDP 接收数据吞吐量 (Mbit/s) - - 40.1 - - 38.5 - - 37.5 - - 36.9 - - .. only:: esp32s2 - - .. list-table:: - :header-rows: 1 - :widths: 10 10 10 10 15 - - * - 等级 - - Iperf - - 默认 - - 节省内存 - - 最小 - * - 可用内存 (KB) - - 70.6 - - 96.4 - - 118.8 - - 148.2 - * - WIFI_STATIC_RX_BUFFER_NUM - - 8 - - 8 - - 6 - - 4 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 64 - - 64 - - 64 - - 64 - * - WIFI_STATIC_TX_BUFFER_NUM - - 16 - - 8 - - 6 - - 4 - * - WIFI_RX_BA_WIN - - 16 - - 6 - - 6 - - 禁用 - * - TCP_SND_BUF_DEFAULT (KB) - - 32 - - 32 - - 32 - - 32 - * - TCP_WND_DEFAULT (KB) - - 32 - - 32 - - 32 - - 32 - * - WIFI_IRAM_OPT - - 开启 - - 开启 - - 开启 - - 关闭 - * - WIFI_RX_IRAM_OPT - - 开启 - - 开启 - - 关闭 - - 关闭 - * - LWIP_IRAM_OPTIMIZATION - - 开启 - - 关闭 - - 关闭 - - 关闭 - * - INSTRUCTION_CACHE - - 16 - - 16 - - 16 - - 8 - * - INSTRUCTION_CACHE_LINE - - 16 - - 16 - - 16 - - 16 - * - DATA_CACHE - - 8 - - 8 - - 8 - - 8 - * - DATA_CACHE_LINE - - 32 - - 32 - - 32 - - 32 - * - TCP 发送数据吞吐量 (Mbit/s) - - 40.1 - - 29.2 - - 20.1 - - 8.9 - * - TCP 接收数据吞吐量 (Mbit/s) - - 21.9 - - 16.8 - - 14.8 - - 9.6 - * - UDP 发送数据吞吐量 (Mbit/s) - - 50.1 - - 25.7 - - 22.4 - - 10.2 - * - UDP 接收数据吞吐量 (Mbit/s) - - 45.3 - - 43.1 - - 28.5 - - 15.1 - - .. note:: - 达到性能的峰值可能会触发任务看门狗,由于 CPU 可能没有时间处理低优先级的任务,这是一个正常现象。 - - .. only:: esp32s3 - - **四线 PSRAM:** - - .. list-table:: - :header-rows: 1 - :widths: 25 20 25 25 25 - - * - 等级 - - Iperf - - 默认 - - 节省内存 - - 最小 - * - 可用内存 (KB) - - 50.3 - - 158.7 - - 198.2 - - 228.9 - * - WIFI_STATIC_RX_BUFFER_NUM - - 24 - - 8 - - 6 - - 4 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 85 - - 64 - - 32 - - 32 - * - WIFI_STATIC_TX_BUFFER_NUM - - 32 - - 32 - - 6 - - 4 - * - WIFI_RX_BA_WIN - - 32 - - 16 - - 12 - - 禁用 - * - TCP_SND_BUF_DEFAULT (KB) - - 85 - - 32 - - 32 - - 32 - * - TCP_WND_DEFAULT (KB) - - 85 - - 32 - - 32 - - 32 - * - WIFI_IRAM_OPT - - 开启 - - 开启 - - 开启 - - 关闭 - * - WIFI_RX_IRAM_OPT - - 开启 - - 开启 - - 关闭 - - 关闭 - * - LWIP_IRAM_OPTIMIZATION - - 开启 - - 关闭 - - 关闭 - - 关闭 - * - LWIP_UDP_RECVMBOX_SIZE - - 16 - - 16 - - 16 - - 16 - * - INSTRUCTION_CACHE - - 32 - - 16 - - 16 - - 16 - * - INSTRUCTION_CACHE_LINE - - 32 - - 16 - - 16 - - 16 - * - INSTRUCTION_CACHE_WAYS - - 8 - - 8 - - 8 - - 8 - * - DATA_CACHE - - 64 - - 16 - - 16 - - 16 - * - DATA_CACHE_LINE - - 32 - - 32 - - 32 - - 32 - * - DATA_CACHE_WAYS - - 8 - - 8 - - 8 - - 8 - * - TCP 发送数据吞吐量 (Mbit/s) - - 93.1 - - 62.5 - - 41.3 - - 42.7 - * - TCP 接收数据吞吐量 (Mbit/s) - - 88.9 - - 46.5 - - 46.2 - - 37.9 - * - UDP 发送数据吞吐量 (Mbit/s) - - 106.4 - - 106.2 - - 60.7 - - 50 - * - UDP 接收数据吞吐量 (Mbit/s) - - 99.8 - - 92.6 - - 94.3 - - 53.3 - - **八线 PSRAM:** - - .. list-table:: - :header-rows: 1 - :widths: 25 20 25 25 25 - - * - 等级 - - Iperf - - 默认 - - 节省内存 - - 最小 - * - 可用内存 (KB) - - 49.1 - - 151.3 - - 215.3 - - 243.6 - * - WIFI_STATIC_RX_BUFFER_NUM - - 24 - - 8 - - 6 - - 4 - * - WIFI_DYNAMIC_RX_BUFFER_NUM - - 85 - - 64 - - 32 - - 32 - * - WIFI_STATIC_TX_BUFFER_NUM - - 32 - - 32 - - 6 - - 4 - * - WIFI_RX_BA_WIN - - 32 - - 16 - - 12 - - 禁用 - * - TCP_SND_BUF_DEFAULT (KB) - - 85 - - 32 - - 32 - - 32 - * - TCP_WND_DEFAULT (KB) - - 85 - - 32 - - 32 - - 32 - * - WIFI_IRAM_OPT - - 开启 - - 开启 - - 开启 - - 关闭 - * - WIFI_RX_IRAM_OPT - - 开启 - - 开启 - - 关闭 - - 关闭 - * - LWIP_IRAM_OPTIMIZATION - - 开启 - - 关闭 - - 关闭 - - 关闭 - * - LWIP_UDP_RECVMBOX_SIZE - - 16 - - 16 - - 16 - - 16 - * - INSTRUCTION_CACHE - - 32 - - 16 - - 16 - - 16 - * - INSTRUCTION_CACHE_LINE - - 32 - - 16 - - 16 - - 16 - * - INSTRUCTION_CACHE_WAYS - - 8 - - 8 - - 8 - - 8 - * - DATA_CACHE - - 64 - - 16 - - 16 - - 16 - * - DATA_CACHE_LINE - - 32 - - 32 - - 32 - - 32 - * - DATA_CACHE_WAYS - - 8 - - 8 - - 8 - - 8 - * - TCP 发送数据吞吐量 (Mbit/s) - - 93.3 - - 58.4 - - 37.1 - - 35.6 - * - TCP 接收数据吞吐量 (Mbit/s) - - 86.1 - - 43.6 - - 42.5 - - 35 - * - UDP 发送数据吞吐量 (Mbit/s) - - 104.7 - - 82.2 - - 60.4 - - 47.9 - * - UDP 接收数据吞吐量 (Mbit/s) - - 104.6 - - 104.8 - - 104 - - 55.7 - - -Wi-Fi Menuconfig ------------------------ - -Wi-Fi 缓冲区配置 -+++++++++++++++++++++++ - -如果要修改默认的缓冲区数量或类型,最好也了解缓冲区在数据路径中如何分配或释放。下图显示了发送数据方向的过程。 - -.. blockdiag:: - :caption: TX Buffer Allocation - :align: center - - blockdiag buffer_allocation_tx { - - # global attributes - node_height = 60; - node_width = 100; - span_width = 50; - span_height = 20; - default_shape = roundedbox; - - # labels of diagram nodes - APPL_TASK [label="Application\n task", fontsize=12]; - LwIP_TASK [label="LwIP\n task", fontsize=12]; - WIFI_TASK [label="Wi-Fi\n task", fontsize=12]; - - # labels of description nodes - APPL_DESC [label="1> User data", width=120, height=25, shape=note, color=yellow]; - LwIP_DESC [label="2> Pbuf", width=120, height=25, shape=note, color=yellow]; - WIFI_DESC [label="3> Dynamic (Static)\n TX Buffer", width=150, height=40, shape=note, color=yellow]; - - # node connections - APPL_TASK -> LwIP_TASK -> WIFI_TASK - APPL_DESC -> LwIP_DESC -> WIFI_DESC [style=none] - } - - -描述: - - - 应用程序分配需要发送的数据。 - - 应用程序调用 TCPIP 或套接字相关的 API 发送用户数据。这些 API 会分配一个在 LwIP 中使用的 PBUF,并复制用户数据。 - - 当 LwIP 调用 Wi-Fi API 发送 PBUF 时,Wi-Fi API 会分配一个“动态发送数据缓冲区”或“静态发送数据缓冲区”,并复制 LwIP PBUF,最后发送数据。 - -下图展示了如何在接收数据方向分配或释放缓冲区: - -.. blockdiag:: - :caption: 接收数据缓冲区分配 - :align: center - - blockdiag buffer_allocation_rx { - - # global attributes - node_height = 60; - node_width = 100; - span_width = 40; - span_height = 20; - default_shape = roundedbox; - - # labels of diagram nodes - APPL_TASK [label="Application\n task", fontsize=12]; - LwIP_TASK [label="LwIP\n task", fontsize=12]; - WIFI_TASK [label="Wi-Fi\n task", fontsize=12]; - WIFI_INTR [label="Wi-Fi\n interrupt", fontsize=12]; - - # labels of description nodes - APPL_DESC [label="4> User\n Data Buffer", height=40, shape=note, color=yellow]; - LwIP_DESC [label="3> Pbuf", height=40, shape=note, color=yellow]; - WIFI_DESC [label="2> Dynamic\n RX Buffer", height=40, shape=note, color=yellow]; - INTR_DESC [label="1> Static\n RX Buffer", height=40, shape=note, color=yellow]; - - # node connections - APPL_TASK <- LwIP_TASK <- WIFI_TASK <- WIFI_INTR - APPL_DESC <- LwIP_DESC <- WIFI_DESC <- INTR_DESC [style=none] - } - -描述: - - - Wi-Fi 硬件在空中接收到数据包后,将数据包内容放到“静态接收数据缓冲区”,也就是“接收数据 DMA 缓冲区”。 - - Wi-Fi 驱动程序分配一个“动态接收数据缓冲区”、复制“静态接收数据缓冲区”,并将“静态接收数据缓冲区”返回给硬件。 - - Wi-Fi 驱动程序将数据包传送到上层 (LwIP),并分配一个 PBUF 用于存放“动态接收数据缓冲区”。 - - 应用程序从 LwIP 接收数据。 - -下表是 Wi-Fi 内部缓冲区的配置情况。 - -.. list-table:: - :header-rows: 1 - :widths: 10 10 10 10 25 - - * - 缓冲区类型 - - 分配类型 - - 默认 - - 是否可配置 - - 描述 - * - 静态接收数据缓冲区(硬件接收数据缓冲区) - - 静态 - - 10 * 1600 Bytes - - 是 - - 这是一种 DMA 内存,在函数 :cpp:func:`esp_wifi_init()` 中初始化,在函数 :cpp:func:`esp_wifi_deinit()` 中释放。 该缓冲区形成硬件接收列表。当通过空中接收到一个帧时,硬件将该帧写入缓冲区,并向 CPU 发起一个中断。然后,Wi-Fi 驱动程序从缓冲区中读取内容,并将缓冲区返回到列表中。 - - 如果应用程序希望减少 Wi-Fi 静态分配的内存,可以将该值从 10 减少到 6, 从而节省 6400 Bytes 的内存。除非禁用 AMPDU 功能,否则不建议将该值降低到 6 以下。 - * - 动态接收数据缓冲区 - - 动态 - - 32 - - 是 - - 缓冲区的长度可变,取决于所接收帧的长度。当 Wi-Fi 驱动程序 从“硬件接收数据缓冲区”接收到一帧时,需要从堆中分配“动态接收数据缓冲区”。在 Menuconfig 中配置的“动态接收数据缓冲区” 数量用来限制未释放的“动态接收数据缓冲区”总数量。 - * - 动态发送数据缓冲区 - - 动态 - - 32 - - 是 - - 这是一种 DMA 内存,位于堆内存中。当上层 (LwIP) 向 Wi-Fi 驱动程序发送数据包时,该缓冲区首先分配一个“动态发送数据缓 冲区”,并复制上层缓冲区。 - - 动态发送数据缓冲区和静态发送数据缓冲区相互排斥。 - * - 静态发送数据缓冲区 - - 静态 - - 16 * 1600 Bytes - - 是 - - 这是一种 DMA 内存,在函数 :cpp:func:`esp_wifi_init()` 中初始化,在函数 :cpp:func:`esp_wifi_deinit()` 中释放。 当上层 (LwIP) 向 Wi-Fi 驱动程序发送数据包时,该缓冲区首先 分配一个“静态发送数据缓冲区”,并复制上层缓冲区。 - - 动态发送数据缓冲区和静态发送数据缓冲区相互排斥。 - - 由于发送数据缓冲区必须是 DMA 缓冲区,所以当使能 PSRAM 时,发送数据缓冲区必须是静态的。 - * - 管理短缓冲区 - - 动态 - - 8 - - 否 - - Wi-Fi 驱动程序的内部缓冲区。 - * - 管理长缓冲区 - - 动态 - - 32 - - 否 - - Wi-Fi 驱动程序的内部缓冲区。 - * - 管理超长缓冲区 - - 动态 - - 32 - - 否 - - Wi-Fi 驱动程序的内部缓冲区。 - -Wi-Fi NVS Flash -+++++++++++++++++++++ -如果使能 Wi-Fi NVS flash,所有通过 Wi-Fi API 设置的 Wi-Fi 配置都会被存储到 flash 中,Wi-Fi 驱动程序在下次开机或重启时将自动加载这些配置。但是,应用程序可视情况禁用 Wi-Fi NVS flash,例如:其配置信息不需要存储在非易失性内存中、其配置信息已安全备份,或仅出于某些调试原因等。 - -Wi-Fi AMPDU -+++++++++++++++++++++++++++ - -{IDF_TARGET_NAME} 同时支持接收和发送 AMPDU,AMPDU 可以大大提高 Wi-Fi 的吞吐量。 - -通常,应使能 AMPDU。禁用 AMPDU 通常用于调试目的。 - - -故障排除 ---------------- - -请见 :doc:`wireshark-user-guide`。 - -.. toctree:: - :hidden: - - wireshark-user-guide -