esp_wifi: optimize WiFi TX performance

This commit is contained in:
xiehang 2020-12-07 15:40:14 +08:00 committed by bot
parent 42061dded1
commit 7b245e59c4
7 changed files with 138 additions and 27 deletions

View File

@ -1177,6 +1177,19 @@ menu Wi-Fi
layer can deliver frames faster than WiFi layer can transmit. In these cases, we may run out layer can deliver frames faster than WiFi layer can transmit. In these cases, we may run out
of TX buffers. of TX buffers.
config ESP32_WIFI_CACHE_TX_BUFFER_NUM
int "Max number of WiFi cache TX buffers"
depends on (ESP32_SPIRAM_SUPPORT || ESP32S2_SPIRAM_SUPPORT)
range 16 128
default 32
help
Set the number of WiFi cache TX buffer number.
For each TX packet from uplayer, such as LWIP etc, WiFi driver needs to allocate a static TX
buffer and makes a copy of uplayer packet. If WiFi driver fails to allocate the static TX buffer,
it caches the uplayer packets to a dedicated buffer queue, this option is used to configure the
size of the cached TX queue.
config ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM config ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM
int "Max number of WiFi dynamic TX buffers" int "Max number of WiFi dynamic TX buffers"
depends on ESP32_WIFI_DYNAMIC_TX_BUFFER depends on ESP32_WIFI_DYNAMIC_TX_BUFFER
@ -1226,8 +1239,7 @@ menu Wi-Fi
config ESP32_WIFI_RX_BA_WIN config ESP32_WIFI_RX_BA_WIN
int "WiFi AMPDU RX BA window size" int "WiFi AMPDU RX BA window size"
depends on ESP32_WIFI_AMPDU_RX_ENABLED depends on ESP32_WIFI_AMPDU_RX_ENABLED
range 2 32 if !WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST range 2 32
range 16 32 if WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST
default 6 if !WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST default 6 if !WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST
default 16 if WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST default 16 if WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST
help help

View File

@ -210,6 +210,7 @@ esp_err_t system_event_ap_start_handle_default(system_event_t *event)
uint8_t ap_mac[6]; uint8_t ap_mac[6];
WIFI_API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, (wifi_rxcb_t)tcpip_adapter_ap_input), ESP_OK); WIFI_API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, (wifi_rxcb_t)tcpip_adapter_ap_input), ESP_OK);
API_CALL_CHECK("esp_wifi_internal_reg_netstack_buf_cb",esp_wifi_internal_reg_netstack_buf_cb(esp_netif_netstack_buf_ref, esp_netif_netstack_buf_free), ESP_OK);
WIFI_API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_AP, ap_mac), ESP_OK); WIFI_API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_AP, ap_mac), ESP_OK);
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ap_ip); tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ap_ip);
@ -232,6 +233,7 @@ esp_err_t system_event_sta_start_handle_default(system_event_t *event)
tcpip_adapter_ip_info_t sta_ip; tcpip_adapter_ip_info_t sta_ip;
uint8_t sta_mac[6]; uint8_t sta_mac[6];
API_CALL_CHECK("esp_wifi_internal_reg_netstack_buf_cb",esp_wifi_internal_reg_netstack_buf_cb(esp_netif_netstack_buf_ref, esp_netif_netstack_buf_free), ESP_OK);
WIFI_API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_STA, sta_mac), ESP_OK); WIFI_API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_STA, sta_mac), ESP_OK);
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip);
tcpip_adapter_sta_start(sta_mac, &sta_ip); tcpip_adapter_sta_start(sta_mac, &sta_ip);

View File

@ -87,6 +87,8 @@ extern "C" {
#define ESP_ERR_WIFI_POST (ESP_ERR_WIFI_BASE + 18) /*!< Failed to post the event to WiFi task */ #define ESP_ERR_WIFI_POST (ESP_ERR_WIFI_BASE + 18) /*!< Failed to post the event to WiFi task */
#define ESP_ERR_WIFI_INIT_STATE (ESP_ERR_WIFI_BASE + 19) /*!< Invalid WiFi state when init/deinit is called */ #define ESP_ERR_WIFI_INIT_STATE (ESP_ERR_WIFI_BASE + 19) /*!< Invalid WiFi state when init/deinit is called */
#define ESP_ERR_WIFI_STOP_STATE (ESP_ERR_WIFI_BASE + 20) /*!< Returned when WiFi is stopping */ #define ESP_ERR_WIFI_STOP_STATE (ESP_ERR_WIFI_BASE + 20) /*!< Returned when WiFi is stopping */
#define ESP_ERR_WIFI_NOT_ASSOC (ESP_ERR_WIFI_BASE + 21) /*!< The WiFi connection is not associated */
#define ESP_ERR_WIFI_TX_DISALLOW (ESP_ERR_WIFI_BASE + 22) /*!< The WiFi TX is disallowed */
/** /**
* @brief WiFi stack configuration parameters passed to esp_wifi_init call. * @brief WiFi stack configuration parameters passed to esp_wifi_init call.
@ -100,12 +102,12 @@ typedef struct {
int tx_buf_type; /**< WiFi TX buffer type */ int tx_buf_type; /**< WiFi TX buffer type */
int static_tx_buf_num; /**< WiFi static TX buffer number */ int static_tx_buf_num; /**< WiFi static TX buffer number */
int dynamic_tx_buf_num; /**< WiFi dynamic TX buffer number */ int dynamic_tx_buf_num; /**< WiFi dynamic TX buffer number */
int cache_tx_buf_num; /**< WiFi TX cache buffer number */
int csi_enable; /**< WiFi channel state information enable flag */ int csi_enable; /**< WiFi channel state information enable flag */
int ampdu_rx_enable; /**< WiFi AMPDU RX feature enable flag */ int ampdu_rx_enable; /**< WiFi AMPDU RX feature enable flag */
int ampdu_tx_enable; /**< WiFi AMPDU TX feature enable flag */ int ampdu_tx_enable; /**< WiFi AMPDU TX feature enable flag */
int nvs_enable; /**< WiFi NVS flash enable flag */ int nvs_enable; /**< WiFi NVS flash enable flag */
int nano_enable; /**< Nano option for printf/scan family enable flag */ int nano_enable; /**< Nano option for printf/scan family enable flag */
int tx_ba_win; /**< WiFi Block Ack TX window size */
int rx_ba_win; /**< WiFi Block Ack RX window size */ int rx_ba_win; /**< WiFi Block Ack RX window size */
int wifi_task_core_id; /**< WiFi Task Core ID */ int wifi_task_core_id; /**< WiFi Task Core ID */
int beacon_max_len; /**< WiFi softAP maximum length of the beacon */ int beacon_max_len; /**< WiFi softAP maximum length of the beacon */
@ -119,6 +121,12 @@ typedef struct {
#define WIFI_STATIC_TX_BUFFER_NUM 0 #define WIFI_STATIC_TX_BUFFER_NUM 0
#endif #endif
#if (CONFIG_ESP32_SPIRAM_SUPPORT | CONFIG_ESP32S2_SPIRAM_SUPPORT)
#define WIFI_CACHE_TX_BUFFER_NUM CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM
#else
#define WIFI_CACHE_TX_BUFFER_NUM 0
#endif
#ifdef CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM #ifdef CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM
#define WIFI_DYNAMIC_TX_BUFFER_NUM CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM #define WIFI_DYNAMIC_TX_BUFFER_NUM CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM
#else #else
@ -159,12 +167,6 @@ extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs;
#define WIFI_INIT_CONFIG_MAGIC 0x1F2F3F4F #define WIFI_INIT_CONFIG_MAGIC 0x1F2F3F4F
#ifdef CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED
#define WIFI_DEFAULT_TX_BA_WIN CONFIG_ESP32_WIFI_TX_BA_WIN
#else
#define WIFI_DEFAULT_TX_BA_WIN 0 /* unused if ampdu_tx_enable == false */
#endif
#ifdef CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED #ifdef CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED
#define WIFI_DEFAULT_RX_BA_WIN CONFIG_ESP32_WIFI_RX_BA_WIN #define WIFI_DEFAULT_RX_BA_WIN CONFIG_ESP32_WIFI_RX_BA_WIN
#else #else
@ -189,6 +191,8 @@ extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs;
#define WIFI_MGMT_SBUF_NUM 32 #define WIFI_MGMT_SBUF_NUM 32
#endif #endif
#define CONFIG_FEATURE_CACHE_TX_BUF_BIT (1<<1)
#define WIFI_INIT_CONFIG_DEFAULT() { \ #define WIFI_INIT_CONFIG_DEFAULT() { \
.event_handler = &esp_event_send, \ .event_handler = &esp_event_send, \
.osi_funcs = &g_wifi_osi_funcs, \ .osi_funcs = &g_wifi_osi_funcs, \
@ -198,12 +202,12 @@ extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs;
.tx_buf_type = CONFIG_ESP32_WIFI_TX_BUFFER_TYPE,\ .tx_buf_type = CONFIG_ESP32_WIFI_TX_BUFFER_TYPE,\
.static_tx_buf_num = WIFI_STATIC_TX_BUFFER_NUM,\ .static_tx_buf_num = WIFI_STATIC_TX_BUFFER_NUM,\
.dynamic_tx_buf_num = WIFI_DYNAMIC_TX_BUFFER_NUM,\ .dynamic_tx_buf_num = WIFI_DYNAMIC_TX_BUFFER_NUM,\
.cache_tx_buf_num = WIFI_CACHE_TX_BUFFER_NUM,\
.csi_enable = WIFI_CSI_ENABLED,\ .csi_enable = WIFI_CSI_ENABLED,\
.ampdu_rx_enable = WIFI_AMPDU_RX_ENABLED,\ .ampdu_rx_enable = WIFI_AMPDU_RX_ENABLED,\
.ampdu_tx_enable = WIFI_AMPDU_TX_ENABLED,\ .ampdu_tx_enable = WIFI_AMPDU_TX_ENABLED,\
.nvs_enable = WIFI_NVS_ENABLED,\ .nvs_enable = WIFI_NVS_ENABLED,\
.nano_enable = WIFI_NANO_FORMAT_ENABLED,\ .nano_enable = WIFI_NANO_FORMAT_ENABLED,\
.tx_ba_win = WIFI_DEFAULT_TX_BA_WIN,\
.rx_ba_win = WIFI_DEFAULT_RX_BA_WIN,\ .rx_ba_win = WIFI_DEFAULT_RX_BA_WIN,\
.wifi_task_core_id = WIFI_TASK_CORE_ID,\ .wifi_task_core_id = WIFI_TASK_CORE_ID,\
.beacon_max_len = WIFI_SOFTAP_BEACON_MAX_LEN, \ .beacon_max_len = WIFI_SOFTAP_BEACON_MAX_LEN, \

View File

@ -100,15 +100,6 @@ typedef enum {
*/ */
esp_err_t esp_wifi_init_internal(const wifi_init_config_t *config); esp_err_t esp_wifi_init_internal(const wifi_init_config_t *config);
/**
* @brief get whether the wifi driver is allowed to transmit data or not
*
* @return
* - true : upper layer should stop to transmit data to wifi driver
* - false : upper layer can transmit data to wifi driver
*/
bool esp_wifi_internal_tx_is_stop(void);
/** /**
* @brief free the rx buffer which allocated by wifi driver * @brief free the rx buffer which allocated by wifi driver
* *
@ -119,18 +110,77 @@ void esp_wifi_internal_free_rx_buffer(void* buffer);
/** /**
* @brief transmit the buffer via wifi driver * @brief transmit the buffer via wifi driver
* *
* This API makes a copy of the input buffer and then forwards the buffer
* copy to WiFi driver.
* @param wifi_interface_t wifi_if : wifi interface id * @param wifi_interface_t wifi_if : wifi interface id
* @param void *buffer : the buffer to be tansmit * @param void *buffer : the buffer to be tansmit
* @param uint16_t len : the length of buffer * @param uint16_t len : the length of buffer
* *
* @return * @return
* - ERR_OK : Successfully transmit the buffer to wifi driver * - ESP_OK : Successfully transmit the buffer to wifi driver
* - ERR_MEM : Out of memory * - ESP_ERR_NO_MEM: out of memory
* - ERR_IF : WiFi driver error * - ESP_ERR_WIFI_ARG: invalid argument
* - ERR_ARG : Invalid argument * - ESP_ERR_WIFI_IF : WiFi interface is invalid
* - ESP_ERR_WIFI_CONN : WiFi interface is not created, e.g. send the data to STA while WiFi mode is AP mode
* - ESP_ERR_WIFI_NOT_STARTED : WiFi is not started
* - ESP_ERR_WIFI_STATE : WiFi internal state is not ready, e.g. WiFi is not started
* - ESP_ERR_WIFI_NOT_ASSOC : WiFi is not associated
* - ESP_ERR_WIFI_TX_DISALLOW : WiFi TX is disallowed, e.g. WiFi hasn't pass the authentication
* - ESP_ERR_WIFI_POST : caller fails to post event to WiFi task
*/ */
int esp_wifi_internal_tx(wifi_interface_t wifi_if, void *buffer, uint16_t len); int esp_wifi_internal_tx(wifi_interface_t wifi_if, void *buffer, uint16_t len);
/**
* @brief The net stack buffer reference counter callback function
*
*/
typedef void (*wifi_netstack_buf_ref_cb_t)(void *netstack_buf);
/**
* @brief The net stack buffer free callback function
*
*/
typedef void (*wifi_netstack_buf_free_cb_t)(void *netstack_buf);
/**
* @brief transmit the buffer by reference via wifi driver
*
* This API firstly increases the reference counter of the input buffer and
* then forwards the buffer to WiFi driver. The WiFi driver will free the buffer
* after processing it. Use esp_wifi_internal_tx() if the uplayer buffer doesn't
* supports reference counter.
*
* @param wifi_if : wifi interface id
* @param buffer : the buffer to be tansmit
* @param len : the length of buffer
* @param netstack_buf : the netstack buffer related to bufffer
*
* @return
* - ESP_OK : Successfully transmit the buffer to wifi driver
* - ESP_ERR_NO_MEM: out of memory
* - ESP_ERR_WIFI_ARG: invalid argument
* - ESP_ERR_WIFI_IF : WiFi interface is invalid
* - ESP_ERR_WIFI_CONN : WiFi interface is not created, e.g. send the data to STA while WiFi mode is AP mode
* - ESP_ERR_WIFI_NOT_STARTED : WiFi is not started
* - ESP_ERR_WIFI_STATE : WiFi internal state is not ready, e.g. WiFi is not started
* - ESP_ERR_WIFI_NOT_ASSOC : WiFi is not associated
* - ESP_ERR_WIFI_TX_DISALLOW : WiFi TX is disallowed, e.g. WiFi hasn't pass the authentication
* - ESP_ERR_WIFI_POST : caller fails to post event to WiFi task
*/
esp_err_t esp_wifi_internal_tx_by_ref(wifi_interface_t ifx, void *buffer, size_t len, void *netstack_buf);
/**
* @brief register the net stack buffer reference increasing and free callback
*
* @param ref : net stack buffer reference callback
* @param free: net stack buffer free callback
*
* @return
* - ESP_OK : Successfully transmit the buffer to wifi driver
* - others : failed to register the callback
*/
esp_err_t esp_wifi_internal_reg_netstack_buf_cb(wifi_netstack_buf_ref_cb_t ref, wifi_netstack_buf_free_cb_t free);
/** /**
* @brief The WiFi RX callback function * @brief The WiFi RX callback function
* *

View File

@ -92,6 +92,15 @@ low_level_init(struct netif *netif)
#endif #endif
} }
static esp_err_t wifi_transmit_wrap(wifi_interface_t wifi_if, void *buffer, size_t len, void *netstack_buf)
{
#if (CONFIG_ESP32_SPIRAM_SUPPORT)
return esp_wifi_internal_tx_by_ref(wifi_if, buffer, len, netstack_buf);
#else
return esp_wifi_internal_tx(wifi_if, buffer, len);
#endif
}
/** /**
* This function should do the actual transmission of the packet. The packet is * This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf * contained in the pbuf that is passed to the function. This pbuf
@ -112,14 +121,14 @@ low_level_output(struct netif *netif, struct pbuf *p)
{ {
wifi_interface_t wifi_if = tcpip_adapter_get_esp_if(netif); wifi_interface_t wifi_if = tcpip_adapter_get_esp_if(netif);
struct pbuf *q = p; struct pbuf *q = p;
err_t ret; esp_err_t ret;
if (wifi_if >= ESP_IF_MAX) { if (wifi_if >= ESP_IF_MAX) {
return ERR_IF; return ERR_IF;
} }
if(q->next == NULL) { if(q->next == NULL) {
ret = esp_wifi_internal_tx(wifi_if, q->payload, q->len); ret = wifi_transmit_wrap(wifi_if, q->payload, q->len, q);
} else { } else {
LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug")); LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug"));
q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM); q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM);
@ -129,11 +138,19 @@ low_level_output(struct netif *netif, struct pbuf *p)
} else { } else {
return ERR_MEM; return ERR_MEM;
} }
ret = esp_wifi_internal_tx(wifi_if, q->payload, q->len); ret = wifi_transmit_wrap(wifi_if, q->payload, q->len, q);
pbuf_free(q); pbuf_free(q);
} }
return ret; if (ret == ESP_OK) {
return ERR_OK;
} else if (ret == ESP_ERR_NO_MEM) {
return ERR_MEM;
} else if (ret == ESP_ERR_INVALID_ARG) {
return ERR_ARG;
} else {
return ERR_IF;
}
} }
/** /**

View File

@ -676,6 +676,22 @@ esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void ** netif);
*/ */
bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if); bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if);
/**
* @brief increase the reference counter of net stack buffer
*
* @param[in] netstack_buf the net stack buffer
*
*/
void esp_netif_netstack_buf_ref(void *netstack_buf);
/**
* @brief free the netstack buffer
*
* @param[in] netstack_buf the net stack buffer
*
*/
void esp_netif_netstack_buf_free(void *netstack_buf);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1285,4 +1285,14 @@ bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if)
} }
} }
void esp_netif_netstack_buf_ref(void *pbuf)
{
pbuf_ref(pbuf);
}
void esp_netif_netstack_buf_free(void *pbuf)
{
pbuf_free(pbuf);
}
#endif /* CONFIG_TCPIP_LWIP */ #endif /* CONFIG_TCPIP_LWIP */