From 3bb9a42c6b9d8cd09fb6cb7f014df0ccfbd5197b Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Thu, 12 Nov 2020 15:55:38 +0800 Subject: [PATCH] xtensa/esp32: Refactor ESP32 Wi-Fi driver --- arch/xtensa/src/esp32/Kconfig | 28 + arch/xtensa/src/esp32/Make.defs | 2 +- arch/xtensa/src/esp32/esp32_rt_timer.c | 24 + arch/xtensa/src/esp32/esp32_rt_timer.h | 16 + arch/xtensa/src/esp32/esp32_wifi_adapter.c | 1177 +++++++++------- arch/xtensa/src/esp32/esp32_wifi_adapter.h | 19 + arch/xtensa/src/esp32/esp32_wlan.c | 1198 +++++++++-------- arch/xtensa/src/esp32/esp32_wlan.h | 8 +- arch/xtensa/src/esp32/hardware/esp32_dport.h | 1 + .../esp32/esp32-core/src/esp32_bringup.c | 2 +- 10 files changed, 1441 insertions(+), 1034 deletions(-) diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig index 2cc2f39cb0..7b8b8494e7 100644 --- a/arch/xtensa/src/esp32/Kconfig +++ b/arch/xtensa/src/esp32/Kconfig @@ -661,6 +661,34 @@ endmenu # ESP32_EMAC menu "WiFi configuration" depends on ESP32_WIRELESS +config ESP32_WIFI_STATIC_RXBUF_NUM + int "WiFi static RX buffer number" + default 10 + +config ESP32_WIFI_DYNAMIC_RXBUF_NUM + int "WiFi dynamic RX buffer number" + default 32 + +config ESP32_WIFI_DYNAMIC_TXBUF_NUM + int "WiFi dynamic TX buffer number" + default 32 + +config ESP32_WIFI_TX_AMPDU + bool "WiFi TX AMPDU" + default y + +config ESP32_WIFI_RX_AMPDU + bool "WiFi RX AMPDU" + default y + +config ESP32_WIFI_RXBA_AMPDU_WZ + int "WiFi RX BA AMPDU windown size" + default 6 + +config ESP32_WLAN_RXBUF_NUM + int "WLAN netcard RX buffer number" + default 16 + config ESP32_WIFI_CONNECT_TIMEOUT int "Connect timeout by second" default 10 diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index c53ce20fee..b986485dd0 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -180,7 +180,7 @@ endif ifeq ($(CONFIG_ESP32_WIRELESS),y) WIRELESS_DRV_UNPACK = esp-wireless-drivers-3rdparty -WIRELESS_DRV_ID = 5cb6561 +WIRELESS_DRV_ID = 4a352be WIRELESS_DRV_ZIP = $(WIRELESS_DRV_ID).zip WIRELESS_DRV_URL = https://github.com/espressif/esp-wireless-drivers-3rdparty/archive diff --git a/arch/xtensa/src/esp32/esp32_rt_timer.c b/arch/xtensa/src/esp32/esp32_rt_timer.c index da36d5ad29..51a476b803 100644 --- a/arch/xtensa/src/esp32/esp32_rt_timer.c +++ b/arch/xtensa/src/esp32/esp32_rt_timer.c @@ -553,6 +553,30 @@ void rt_timer_delete(FAR struct rt_timer_s *timer) delete_rt_timer(timer); } +/**************************************************************************** + * Name: rt_timer_time_us + * + * Description: + * Get time of RT timer by micro second. + * + * Input Parameters: + * None + * + * Returned Value: + * Time of RT timer by micro second. + * + ****************************************************************************/ + +uint64_t rt_timer_time_us(void) +{ + uint64_t counter; + struct esp32_tim_dev_s *tim = s_esp32_tim_dev; + + ESP32_TIM_GETCTR(tim, &counter); + + return counter; +} + /**************************************************************************** * Name: esp32_rt_timer_init * diff --git a/arch/xtensa/src/esp32/esp32_rt_timer.h b/arch/xtensa/src/esp32/esp32_rt_timer.h index 3b9a222760..b540b9ea4f 100644 --- a/arch/xtensa/src/esp32/esp32_rt_timer.h +++ b/arch/xtensa/src/esp32/esp32_rt_timer.h @@ -150,6 +150,22 @@ void rt_timer_stop(FAR struct rt_timer_s *timer); void rt_timer_delete(FAR struct rt_timer_s *timer); +/**************************************************************************** + * Name: rt_timer_time_us + * + * Description: + * Get time of RT timer by micro second. + * + * Input Parameters: + * None + * + * Returned Value: + * Time of RT timer by micro second. + * + ****************************************************************************/ + +uint64_t rt_timer_time_us(void); + /**************************************************************************** * Name: esp32_rt_timer_init * diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.c b/arch/xtensa/src/esp32/esp32_wifi_adapter.c index a0e7bfd625..4aeeefc115 100644 --- a/arch/xtensa/src/esp32/esp32_wifi_adapter.c +++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.c @@ -145,14 +145,19 @@ struct nvs_adpt * Private Function Prototypes ****************************************************************************/ +static bool wifi_env_is_chip(void); +static void wifi_set_intr(int32_t cpu_no, uint32_t intr_source, + uint32_t intr_num, int32_t intr_prio); +static void wifi_clear_intr(uint32_t intr_source, uint32_t intr_num); static void esp_set_isr(int32_t n, void *f, void *arg); static void esp32_ints_on(uint32_t mask); static void esp32_ints_off(uint32_t mask); +static bool wifi_is_from_isr(void); static void *esp_spin_lock_create(void); static void esp_spin_lock_delete(void *lock); static uint32_t esp_wifi_int_disable(void *wifi_int_mux); static void esp_wifi_int_restore(void *wifi_int_mux, uint32_t tmp); -static void IRAM_ATTR esp_task_yield_from_isr(void); +static void esp_task_yield_from_isr(void); static void *esp_semphr_create(uint32_t max, uint32_t init); static void esp_semphr_delete(void *semphr); static int32_t esp_semphr_take(void *semphr, uint32_t block_time_tick); @@ -203,18 +208,24 @@ static void *esp_malloc(uint32_t size); static uint32_t esp_rand(void); static void esp_dport_access_stall_other_cpu_start(void); static void esp_dport_access_stall_other_cpu_end(void); -static int32_t esp_phy_deinit_rf(uint32_t module); -static void esp_phy_init(uint32_t module); +static void wifi_apb80m_request(void); +static void wifi_apb80m_release(void); +static void wifi_phy_disable(void); +static void wifi_phy_enable(void); static void esp_phy_enable_clock(void); static void esp_phy_disable_clock(void); +static int32_t wifi_phy_update_country_info(const char *country); static int32_t esp_wifi_read_mac(uint8_t *mac, uint32_t type); static void esp_timer_arm(void *timer, uint32_t tmout, bool repeat); static void esp_timer_disarm(void *timer); static void esp32_timer_done(void *timer); static void esp_timer_setfn(void *timer, void *pfunction, void *parg); static void esp_timer_arm_us(void *timer, uint32_t us, bool repeat); -static void esp_periph_module_enable(uint32_t periph); -static void esp_periph_module_disable(uint32_t periph); +static void wifi_reset_mac(void); +static void wifi_clock_enable(void); +static void wifi_clock_disable(void); +static void wifi_rtc_enable_iso(void); +static void wifi_rtc_disable_iso(void); static int32_t esp_nvs_set_i8(uint32_t handle, const char *key, int8_t value); static int32_t esp_nvs_get_i8(uint32_t handle, const char *key, @@ -248,18 +259,32 @@ static void *esp_wifi_malloc(size_t size); static void *esp_wifi_realloc(void *ptr, size_t size); static void *esp_wifi_calloc(size_t n, size_t size); static void *esp_wifi_zalloc(size_t size); -static int32_t esp_modem_enter_sleep(uint32_t module); -static int32_t esp_modem_exit_sleep(uint32_t module); -static int32_t esp_modem_register_sleep(uint32_t module); -static int32_t esp_modem_deregister_sleep(uint32_t module); static void *esp_wifi_create_queue(int32_t queue_len, int32_t item_size); static void esp_wifi_delete_queue(void *queue); +static int wifi_coex_init(void); +static void wifi_coex_deinit(void); +static int wifi_coex_enable(void); +static void wifi_coex_disable(void); static uint32_t esp_coex_status_get(void); static void esp_coex_condition_set(uint32_t type, bool dissatisfy); static int32_t esp_coex_wifi_request(uint32_t event, uint32_t latency, uint32_t duration); static int32_t esp_coex_wifi_release(uint32_t event); static unsigned long esp_random_ulong(void); +static int wifi_coex_wifi_set_channel(uint8_t primary, uint8_t secondary); +static int wifi_coex_get_event_duration(uint32_t event, + uint32_t *duration); +static int wifi_coex_get_pti(uint32_t event, uint8_t *pti); +static void wifi_coex_clear_schm_status_bit(uint32_t type, + uint32_t status); +static void wifi_coex_set_schm_status_bit(uint32_t type, + uint32_t status); +static int wifi_coex_set_schm_interval(uint32_t interval); +static uint32_t wifi_coex_get_schm_interval(void); +static uint8_t wifi_coex_get_schm_curr_period(void); +static void *wifi_coex_get_schm_curr_phase(void); +static int wifi_coex_set_schm_curr_phase_idx(int idx); +static int wifi_coex_get_schm_curr_phase_idx(void); /**************************************************************************** * Public Functions declaration @@ -277,35 +302,44 @@ uint8_t esp_crc8(const uint8_t *p, uint32_t len); /* WiFi interrupt private data */ -static int s_wifi_irq; +static int g_wifi_irq = -1; /* WiFi thread private data */ -static pthread_key_t s_wifi_thread_key; -static bool s_wifi_tkey_init; +static pthread_key_t g_wifi_thread_key; +static bool g_wifi_tkey_init; /* WiFi sleep private data */ -static uint32_t s_esp32_module_mask; -static uint32_t s_esp32_module_sleep; -static bool s_esp32_sleep; -static uint32_t s_phy_clk_en_cnt = 0; -static bool s_esp23_phy_en; -static uint32_t s_esp32_phy_init_mask; -static int64_t s_esp32_phy_rf_stop_tm; +static uint32_t g_phy_clk_en_cnt; + +/* Reference count of enabling PHY */ + +static uint8_t g_phy_access_ref; + +/* time stamp updated when the PHY/RF is turned on */ + +static int64_t g_phy_rf_en_ts; + +static uint32_t g_common_clock_disable_time; /* WiFi event private data */ -static struct work_s s_wifi_evt_work; -static sq_queue_t s_wifi_evt_queue; -static struct wifi_notify s_wifi_notify[WIFI_ADPT_EVT_MAX]; -static sem_t s_connect_sem; -static bool s_connected; +static struct work_s g_wifi_evt_work; +static sq_queue_t g_wifi_evt_queue; +static struct wifi_notify g_wifi_notify[WIFI_ADPT_EVT_MAX]; +static sem_t g_evtexcl_sem = SEM_INITIALIZER(1); +static sem_t g_connect_sem = SEM_INITIALIZER(0); +static bool g_connected; -static uint8_t s_ssid[32]; -static uint8_t s_password[64]; -static uint8_t s_ssid_len; -static uint8_t s_password_len; +static uint8_t g_ssid[32]; +static uint8_t g_password[64]; +static uint8_t g_ssid_len; +static uint8_t g_password_len; + +/* Callback function to update WiFi MAC time */ + +wifi_mac_time_update_cb_t g_wifi_mac_time_update_cb; /**************************************************************************** * Public Data @@ -316,9 +350,13 @@ static uint8_t s_password_len; wifi_osi_funcs_t g_wifi_osi_funcs = { ._version = ESP_WIFI_OS_ADAPTER_VERSION, + ._env_is_chip = wifi_env_is_chip, + ._set_intr = wifi_set_intr, + ._clear_intr = wifi_clear_intr, ._set_isr = esp_set_isr, ._ints_on = esp32_ints_on, ._ints_off = esp32_ints_off, + ._is_from_isr = wifi_is_from_isr, ._spin_lock_create = esp_spin_lock_create, ._spin_lock_delete = esp_spin_lock_delete, ._wifi_int_disable = esp_wifi_int_disable, @@ -363,18 +401,24 @@ wifi_osi_funcs_t g_wifi_osi_funcs = esp_dport_access_stall_other_cpu_start, ._dport_access_stall_other_cpu_end_wrap = esp_dport_access_stall_other_cpu_end, - ._phy_rf_deinit = esp_phy_deinit_rf, - ._phy_load_cal_and_init = esp_phy_init, + ._wifi_apb80m_request = wifi_apb80m_request, + ._wifi_apb80m_release = wifi_apb80m_release, + ._phy_disable = wifi_phy_disable, + ._phy_enable = wifi_phy_enable, ._phy_common_clock_enable = esp_phy_enable_clock, ._phy_common_clock_disable = esp_phy_disable_clock, + ._phy_update_country_info = wifi_phy_update_country_info, ._read_mac = esp_wifi_read_mac, ._timer_arm = esp_timer_arm, ._timer_disarm = esp_timer_disarm, ._timer_done = esp32_timer_done, ._timer_setfn = esp_timer_setfn, ._timer_arm_us = esp_timer_arm_us, - ._periph_module_enable = esp_periph_module_enable, - ._periph_module_disable = esp_periph_module_disable, + ._wifi_reset_mac = wifi_reset_mac, + ._wifi_clock_enable = wifi_clock_enable, + ._wifi_clock_disable = wifi_clock_disable, + ._wifi_rtc_enable_iso = wifi_rtc_enable_iso, + ._wifi_rtc_disable_iso = wifi_rtc_disable_iso, ._esp_timer_get_time = esp_timer_get_time, ._nvs_set_i8 = esp_nvs_set_i8, ._nvs_get_i8 = esp_nvs_get_i8, @@ -404,14 +448,25 @@ wifi_osi_funcs_t g_wifi_osi_funcs = ._wifi_zalloc = esp_wifi_zalloc, ._wifi_create_queue = esp_wifi_create_queue, ._wifi_delete_queue = esp_wifi_delete_queue, - ._modem_sleep_enter = esp_modem_enter_sleep, - ._modem_sleep_exit = esp_modem_exit_sleep, - ._modem_sleep_register = esp_modem_register_sleep, - ._modem_sleep_deregister = esp_modem_deregister_sleep, + ._coex_init = wifi_coex_init, + ._coex_deinit = wifi_coex_deinit, + ._coex_enable = wifi_coex_enable, + ._coex_disable = wifi_coex_disable, ._coex_status_get = esp_coex_status_get, ._coex_condition_set = esp_coex_condition_set, ._coex_wifi_request = esp_coex_wifi_request, ._coex_wifi_release = esp_coex_wifi_release, + ._coex_wifi_channel_set = wifi_coex_wifi_set_channel, + ._coex_event_duration_get = wifi_coex_get_event_duration, + ._coex_pti_get = wifi_coex_get_pti, + ._coex_schm_status_bit_clear = wifi_coex_clear_schm_status_bit, + ._coex_schm_status_bit_set = wifi_coex_set_schm_status_bit, + ._coex_schm_interval_set = wifi_coex_set_schm_interval, + ._coex_schm_interval_get = wifi_coex_get_schm_interval, + ._coex_schm_curr_period_get = wifi_coex_get_schm_curr_period, + ._coex_schm_curr_phase_get = wifi_coex_get_schm_curr_phase, + ._coex_schm_curr_phase_idx_set = wifi_coex_set_schm_curr_phase_idx, + ._coex_schm_curr_phase_idx_get = wifi_coex_get_schm_curr_phase_idx, ._magic = ESP_WIFI_OS_ADAPTER_MAGIC, }; @@ -526,6 +581,36 @@ static void esp_update_time(struct timespec *timespec, uint32_t ticks) timespec->tv_nsec += tmp; } +/**************************************************************************** + * Name: esp_event_lock + * + * Description: + * Lock or unlock the event process + * + * Input Parameters: + * lock - true: Lock event process, false: unlock event process + * + * Returned Value: + * The result of lock or unlock the event process + * + ****************************************************************************/ + +static int esp_event_lock(bool lock) +{ + int ret; + + if (lock) + { + ret = nxsem_wait_uninterruptible(&g_evtexcl_sem); + } + else + { + ret = nxsem_post(&g_evtexcl_sem); + } + + return ret; +} + /**************************************************************************** * Name: esp_set_isr * @@ -550,6 +635,11 @@ static void esp_set_isr(int32_t n, void *f, void *arg) int cpu = 0; int tmp; + if (g_wifi_irq >= 0) + { + return ; + } + irq = esp32_alloc_levelint(1); if (irq < 0) { @@ -583,7 +673,7 @@ static void esp_set_isr(int32_t n, void *f, void *arg) esp32_attach_peripheral(cpu, n, irq); - s_wifi_irq = irq; + g_wifi_irq = irq; } /**************************************************************************** @@ -602,7 +692,7 @@ static void esp_set_isr(int32_t n, void *f, void *arg) static void esp32_ints_on(uint32_t mask) { - up_enable_irq(s_wifi_irq); + up_enable_irq(g_wifi_irq); } /**************************************************************************** @@ -621,7 +711,26 @@ static void esp32_ints_on(uint32_t mask) static void esp32_ints_off(uint32_t mask) { - up_disable_irq(s_wifi_irq); + up_disable_irq(g_wifi_irq); +} + +/**************************************************************************** + * Name: wifi_is_from_isr + * + * Description: + * Check current is in interrupt + * + * Input Parameters: + * None + * + * Returned Value: + * true if in interrupt or false if not + * + ****************************************************************************/ + +static bool IRAM_ATTR wifi_is_from_isr(void) +{ + return up_interrupt_context(); } /**************************************************************************** @@ -921,19 +1030,19 @@ static void *esp_thread_semphr_get(void) int ret; void *sem; - if (s_wifi_tkey_init) + if (g_wifi_tkey_init) { - ret = pthread_key_create(&s_wifi_thread_key, esp_thread_semphr_free); + ret = pthread_key_create(&g_wifi_thread_key, esp_thread_semphr_free); if (ret) { wlerr("ERROR: Failed to create pthread key\n"); return NULL; } - s_wifi_tkey_init = true; + g_wifi_tkey_init = true; } - sem = pthread_getspecific(s_wifi_thread_key); + sem = pthread_getspecific(g_wifi_thread_key); if (!sem) { sem = esp_semphr_create(1, 0); @@ -943,7 +1052,7 @@ static void *esp_thread_semphr_get(void) return NULL; } - ret = pthread_setspecific(s_wifi_thread_key, sem); + ret = pthread_setspecific(g_wifi_thread_key, sem); if (ret) { wlerr("ERROR: Failed to set specific\n"); @@ -1800,7 +1909,7 @@ static void esp_evt_work_cb(FAR void *arg) while (1) { flags = enter_critical_section(); - evt_adpt = (struct evt_adpt *)sq_remfirst(&s_wifi_evt_queue); + evt_adpt = (struct evt_adpt *)sq_remfirst(&g_wifi_evt_queue); leave_critical_section(flags); if (!evt_adpt) { @@ -1810,6 +1919,11 @@ static void esp_evt_work_cb(FAR void *arg) switch (evt_adpt->id) { case WIFI_ADPT_EVT_STA_START: + ret = esp_wifi_set_ps(WIFI_PS_NONE); + if (ret) + { + wlerr("ERROR: Failed to close PS\n"); + } ret = esp_wifi_connect(); if (ret) { @@ -1817,15 +1931,15 @@ static void esp_evt_work_cb(FAR void *arg) } break; case WIFI_ADPT_EVT_STA_CONNECT: - s_connected = true; - ret = sem_post(&s_connect_sem); + g_connected = true; + ret = sem_post(&g_connect_sem); if (ret) { wlerr("ERROR: Failed to post sem error=%d\n", errno); } break; case WIFI_ADPT_EVT_STA_DISCONNECT: - s_connected = false; + g_connected = false; ret = esp_wifi_connect(); if (ret) { @@ -1836,7 +1950,9 @@ static void esp_evt_work_cb(FAR void *arg) break; } - notify = &s_wifi_notify[evt_adpt->id]; + esp_event_lock(true); + + notify = &g_wifi_notify[evt_adpt->id]; if (notify->assigned) { notify->event.sigev_value.sival_ptr = evt_adpt->buf; @@ -1850,10 +1966,64 @@ static void esp_evt_work_cb(FAR void *arg) } } + esp_event_lock(false); + free(evt_adpt); } } +/**************************************************************************** + * Name: wifi_env_is_chip + * + * Description: + * Config chip environment + * + * Returned Value: + * True if on chip or false if on FPGA. + * + ****************************************************************************/ + +static bool wifi_env_is_chip(void) +{ + return true; +} + +/**************************************************************************** + * Name: wifi_set_intr + * + * Description: + * Do nothing + * + * Input Parameters: + * cpu_no - The CPU which the interrupt number belongs. + * intr_source - The interrupt hardware source number. + * intr_num - The interrupt number CPU. + * intr_prio - The interrupt priority. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wifi_set_intr(int32_t cpu_no, uint32_t intr_source, + uint32_t intr_num, int32_t intr_prio) +{ + wlinfo("cpu_no=%d, intr_source=%u, intr_num=%u, intr_prio=%d"); +} + +/**************************************************************************** + * Name: wifi_clear_intr + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void IRAM_ATTR wifi_clear_intr(uint32_t intr_source, + uint32_t intr_num) +{ +} + /**************************************************************************** * Name: esp_event_post * @@ -1905,10 +2075,10 @@ int32_t esp_event_post(esp_event_base_t event_base, memcpy(evt_adpt->buf, event_data, event_data_size); flags = enter_critical_section(); - sq_addlast(&evt_adpt->entry, &s_wifi_evt_queue); + sq_addlast(&evt_adpt->entry, &g_wifi_evt_queue); leave_critical_section(flags); - work_queue(LPWORK, &s_wifi_evt_work, esp_evt_work_cb, NULL, 0); + work_queue(LPWORK, &g_wifi_evt_work, esp_evt_work_cb, NULL, 0); return 0; } @@ -1973,160 +2143,125 @@ static void esp_dport_access_stall_other_cpu_end(void) } /**************************************************************************** - * Name: esp_phy_rf_init + * Name: wifi_apb80m_request * * Description: - * Initialize PHY hardware with given parameters - * - * Input Parameters: - * init_data - PHY hardware initialization parameters - * mode - PHY RF calculation mode - * calibration_data - PHY RF calculation parameters - * module - PHY mode which is to be initialized - * - * Returned Value: - * 0 if success or -1 if fail + * Don't support * ****************************************************************************/ -int32_t esp_phy_rf_init(const esp_phy_init_data_t *init_data, - esp_phy_calibration_mode_t mode, - esp_phy_calibration_data_t *calibration_data, - phy_rf_module_t module) +static void wifi_apb80m_request(void) { - irqstate_t flags; - int64_t time; - bool enable = false; - - if (module >= PHY_MODULE_COUNT) - { - return -1; - } - - flags = enter_critical_section(); - - s_esp32_phy_init_mask |= 1 << module; - - if (s_esp23_phy_en) - { - leave_critical_section(flags); - return 0; - } - - if (module == PHY_MODEM_MODULE) - { - if (s_esp32_phy_init_mask & PHY_RF_MASK) - { - enable = true; - } - } - else if (module == PHY_WIFI_MODULE || module == PHY_BT_MODULE) - { - enable = true; - } - - if (enable) - { - if (s_esp32_phy_rf_stop_tm) - { - time = esp_timer_get_time() - s_esp32_phy_rf_stop_tm; - esp_wifi_internal_update_mac_time((uint32_t)time); - s_esp32_phy_rf_stop_tm = 0; - } - - esp_phy_enable_clock(); - - phy_set_wifi_mode_only(0); - - register_chipv7_phy(init_data, calibration_data, mode); - - s_esp23_phy_en = true; - } - - leave_critical_section(flags); - - return 0; } /**************************************************************************** - * Name: esp_phy_deinit_rf + * Name: wifi_apb80m_release + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void wifi_apb80m_release(void) +{ +} + +/**************************************************************************** + * Name: phy_update_wifi_mac_time + * + * Description: + * Update WiFi mac timer. + * + * Input Parameters: + * en_clock_stopped - Check if clock is stoppped + * now - time now + * + * Returned Value: + * NOne + * + ****************************************************************************/ + +static void phy_update_wifi_mac_time(bool en_clock_stopped, int64_t now) +{ + uint32_t diff; + + if (en_clock_stopped) + { + g_common_clock_disable_time = (uint32_t)now; + } + else + { + if (g_common_clock_disable_time) + { + diff = (uint64_t)now - g_common_clock_disable_time; + + esp_wifi_internal_update_mac_time(diff); + + g_common_clock_disable_time = 0; + } + } +} + +/**************************************************************************** + * Name: wifi_phy_disable * * Description: * Deinitialize PHY hardware * * Input Parameters: - * module - PHY mode which is to be deinitialized - * - * Returned Value: - * 0 if success or -1 if fail - * - ****************************************************************************/ - -static int32_t esp_phy_deinit_rf(uint32_t module) -{ - irqstate_t flags; - bool disable = false; - - if (module >= PHY_MODULE_COUNT) - { - return -1; - } - - flags = enter_critical_section(); - - s_esp32_phy_init_mask |= ~(1 << module); - - if (!s_esp23_phy_en) - { - leave_critical_section(flags); - return 0; - } - - if (module == PHY_MODEM_MODULE) - { - disable = true; - } - else if (module == PHY_WIFI_MODULE || module == PHY_BT_MODULE) - { - if (!(s_esp32_phy_init_mask & PHY_RF_MASK)) - { - disable = true; - } - } - - if (disable) - { - phy_close_rf(); - - s_esp32_phy_rf_stop_tm = esp_timer_get_time(); - - esp_phy_disable_clock(); - - s_esp23_phy_en = false; - } - - leave_critical_section(flags); - - return 0; -} - -/**************************************************************************** - * Name: esp_phy_init - * - * Description: - * Initialize PHY hardware - * - * Input Parameters: - * module - PHY mode which is to be initialized + * None * * Returned Value: * None * ****************************************************************************/ -static void esp_phy_init(uint32_t module) +static void wifi_phy_disable(void) { - int ret; + irqstate_t flags; + flags = enter_critical_section(); + + g_phy_access_ref--; + + if (g_phy_access_ref == 0) + { + /* Disable PHY and RF. */ + + phy_close_rf(); + + /* Update WiFi MAC time before disalbe + * WiFi/BT common peripheral clock. + */ + + phy_update_wifi_mac_time(true, esp_timer_get_time()); + + /* Disable WiFi/BT common peripheral clock. + * Do not disable clock for hardware RNG. + */ + + esp_phy_disable_clock(); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: wifi_phy_enable + * + * Description: + * Initialize PHY hardware + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wifi_phy_enable(void) +{ + irqstate_t flags; esp_phy_calibration_data_t *cal_data; cal_data = kmm_zalloc(sizeof(esp_phy_calibration_data_t)); @@ -2136,13 +2271,24 @@ static void esp_phy_init(uint32_t module) DEBUGASSERT(0); } - ret = esp_phy_rf_init(&phy_init_data, PHY_RF_CAL_FULL, cal_data, module); - if (ret) + flags = enter_critical_section(); + + if (g_phy_access_ref == 0) { - wlerr("ERROR: Failed to initialize RF"); - DEBUGASSERT(0); + /* Update time stamp */ + + g_phy_rf_en_ts = esp_timer_get_time(); + + /* Update WiFi MAC time before WiFi/BT common clock is enabled */ + + phy_update_wifi_mac_time(false, g_phy_rf_en_ts); + esp_phy_enable_clock(); + phy_set_wifi_mode_only(0); + register_chipv7_phy(&phy_init_data, cal_data, PHY_RF_CAL_NONE); } + g_phy_access_ref++; + leave_critical_section(flags); kmm_free(cal_data); } @@ -2166,13 +2312,13 @@ void esp_phy_enable_clock(void) flags = enter_critical_section(); - if (s_phy_clk_en_cnt == 0) + if (g_phy_clk_en_cnt == 0) { modifyreg32(DPORT_WIFI_CLK_EN_REG, 0, DPORT_WIFI_CLK_WIFI_BT_COMMON_M); } - s_phy_clk_en_cnt++; + g_phy_clk_en_cnt++; leave_critical_section(flags); } @@ -2197,10 +2343,10 @@ void esp_phy_disable_clock(void) flags = enter_critical_section(); - if (s_phy_clk_en_cnt) + if (g_phy_clk_en_cnt) { - s_phy_clk_en_cnt--; - if (!s_phy_clk_en_cnt) + g_phy_clk_en_cnt--; + if (!g_phy_clk_en_cnt) { modifyreg32(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_BT_COMMON_M, @@ -2211,6 +2357,19 @@ void esp_phy_disable_clock(void) leave_critical_section(flags); } +/**************************************************************************** + * Name: wifi_phy_update_country_info + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int32_t wifi_phy_update_country_info(const char *country) +{ + return -1; +} + /**************************************************************************** * Name: esp_read_mac * @@ -2466,43 +2625,87 @@ static void esp_timer_arm_us(void *ptimer, uint32_t us, bool repeat) } /**************************************************************************** - * Name: esp_periph_module_enable + * Name: wifi_reset_mac * * Description: - * Enable WiFi module clock + * Reset WiFi hardware MAC * * Input Parameters: - * periph - No mean + * None * * Returned Value: * None * ****************************************************************************/ -static void esp_periph_module_enable(uint32_t periph) +static void wifi_reset_mac(void) +{ + modifyreg32(DPORT_WIFI_RST_EN_REG, 0, DPORT_MAC_RST_EN); + modifyreg32(DPORT_WIFI_RST_EN_REG, DPORT_MAC_RST_EN, 0); +} + +/**************************************************************************** + * Name: wifi_clock_enable + * + * Description: + * Enable Wi-Fi clock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wifi_clock_enable(void) { modifyreg32(DPORT_WIFI_CLK_EN_REG, 0, DPORT_WIFI_CLK_WIFI_EN_M); } /**************************************************************************** - * Name: esp_periph_module_enable + * Name: wifi_clock_disable * * Description: - * Disable WiFi module clock + * Disable Wi-Fi clock * * Input Parameters: - * periph - No mean + * None * * Returned Value: * None * ****************************************************************************/ -static void esp_periph_module_disable(uint32_t periph) +static void wifi_clock_disable(void) { modifyreg32(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN_M, 0); } +/**************************************************************************** + * Name: wifi_rtc_enable_iso + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void wifi_rtc_enable_iso(void) +{ +} + +/**************************************************************************** + * Name: wifi_rtc_disable_iso + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void wifi_rtc_disable_iso(void) +{ +} + /**************************************************************************** * Name: esp_timer_get_time * @@ -2519,22 +2722,7 @@ static void esp_periph_module_disable(uint32_t periph) int64_t esp_timer_get_time(void) { - int64_t us; - struct timeval tv; - int ret; - - ret = gettimeofday(&tv, NULL); - if (!ret) - { - us = tv.tv_sec * (1000 * 1000) + tv.tv_usec; - } - else - { - us = 0; - wlerr("ERROR: Failed to get time of day\n"); - } - - return us; + return (int64_t)rt_timer_time_us(); } /**************************************************************************** @@ -3173,10 +3361,10 @@ void esp_log_write(uint32_t level, const char *tag, const char *format, ...) { - va_list list; - va_start(list, format); - esp_log_writev(level, tag, format, list); - va_end(list); + va_list list; + va_start(list, format); + esp_log_writev(level, tag, format, list); + va_end(list); } /**************************************************************************** @@ -3414,213 +3602,55 @@ static void esp_wifi_delete_queue(void *queue) } /**************************************************************************** - * Name: esp_modem_enter_sleep + * Name: wifi_coex_init * * Description: - * Let given module to enter sleep mode - * - * Input Parameters: - * module - hardware module ID - * - * Returned Value: - * 0 if success or -1 if fail + * Don't support * ****************************************************************************/ -static int32_t esp_modem_enter_sleep(uint32_t module) +static int wifi_coex_init(void) { - int ret = 0; - irqstate_t flags; - uint32_t bit; - - if (module >= (uint32_t)MODEM_MODULE_COUNT) - { - return -1; - } - - bit = 1 << module; - - if (!(s_esp32_module_mask & bit)) - { - return -1; - } - - flags = enter_critical_section(); - - s_esp32_module_sleep |= bit; - if (!s_esp32_sleep && (s_esp32_module_sleep == s_esp32_module_mask)) - { - ret = esp_phy_deinit_rf(PHY_MODEM_MODULE); - if (ret) - { - wlerr("ERROR: Failed to close RF\n"); - } - else - { - s_esp32_sleep = true; - } - } - - leave_critical_section(flags); - - return ret; -} - -/**************************************************************************** - * Name: esp_modem_enter_sleep - * - * Description: - * Let given module to exit from sleep mode - * - * Input Parameters: - * module - hardware module ID - * - * Returned Value: - * 0 if success or -1 if fail - * - ****************************************************************************/ - -static int32_t esp_modem_exit_sleep(uint32_t module) -{ - int ret = 0; - irqstate_t flags; - uint32_t bit; - - if (module >= (uint32_t)MODEM_MODULE_COUNT) - { - return -1; - } - - bit = 1 << module; - - if (!(s_esp32_module_mask & bit)) - { - return -1; - } - - flags = enter_critical_section(); - - s_esp32_module_sleep &= ~bit; - if (s_esp32_sleep) - { - ret = esp_phy_rf_init(NULL, PHY_RF_CAL_NONE, - NULL, PHY_MODEM_MODULE); - if (ret) - { - wlerr("ERROR: Failed to open RF\n"); - } - else - { - s_esp32_sleep = false; - } - } - - leave_critical_section(flags); - - return ret; -} - -/**************************************************************************** - * Name: esp_modem_register_sleep - * - * Description: - * Regitser given module so that it can enter sleep mode - * - * Input Parameters: - * module - hardware module ID - * - * Returned Value: - * 0 if success or -1 if fail - * - ****************************************************************************/ - -static int32_t esp_modem_register_sleep(uint32_t module) -{ - irqstate_t flags; - uint32_t bit; - - if (module >= (uint32_t)MODEM_MODULE_COUNT) - { - return -1; - } - - bit = 1 << module; - - flags = enter_critical_section(); - - if (s_esp32_module_mask & bit) - { - /* Has registered and return success */ - - return 0; - } - - s_esp32_module_mask |= bit; - s_esp32_module_sleep |= bit; - - leave_critical_section(flags); - return 0; } /**************************************************************************** - * Name: esp_modem_deregister_sleep + * Name: wifi_coex_deinit * * Description: - * Deregitser given module so that it can't enter sleep mode - * - * Input Parameters: - * module - hardware module ID - * - * Returned Value: - * 0 if success or -1 if fail + * Don't support * ****************************************************************************/ -static int32_t esp_modem_deregister_sleep(uint32_t module) +static void wifi_coex_deinit(void) { - int ret; - irqstate_t flags; - uint32_t bit; +} - if (module >= (uint32_t)MODEM_MODULE_COUNT) - { - return -1; - } - - bit = 1 << module; - - flags = enter_critical_section(); - - if (!(s_esp32_module_mask & bit)) - { - /* Has deregistered and return success */ - - return 0; - } - - s_esp32_module_mask &= ~bit; - s_esp32_module_sleep &= ~bit; - if (!s_esp32_module_mask) - { - s_esp32_module_mask = 0; - if (s_esp32_sleep) - { - s_esp32_sleep = false; - ret = esp_phy_rf_init(NULL, PHY_RF_CAL_NONE, - NULL, PHY_MODEM_MODULE); - if (ret) - { - wlerr("ERROR: Failed to open RF\n"); - } - } - } - - leave_critical_section(flags); +/**************************************************************************** + * Name: wifi_coex_enable + * + * Description: + * Don't support + * + ****************************************************************************/ +static int wifi_coex_enable(void) +{ return 0; } +/**************************************************************************** + * Name: wifi_coex_disable + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void wifi_coex_disable(void) +{ +} + /**************************************************************************** * Name: esp_coex_status_get * @@ -3673,6 +3703,147 @@ static int32_t esp_coex_wifi_release(uint32_t event) return 0; } +/**************************************************************************** + * Name: wifi_coex_wifi_set_channel + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_wifi_set_channel(uint8_t primary, uint8_t secondary) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_get_event_duration + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_get_event_duration(uint32_t event, uint32_t *duration) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_get_pti + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_get_pti(uint32_t event, uint8_t *pti) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_clear_schm_status_bit + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void wifi_coex_clear_schm_status_bit(uint32_t type, uint32_t status) +{ +} + +/**************************************************************************** + * Name: wifi_coex_set_schm_status_bit + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void wifi_coex_set_schm_status_bit(uint32_t type, uint32_t status) +{ +} + +/**************************************************************************** + * Name: wifi_coex_set_schm_interval + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_set_schm_interval(uint32_t interval) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_get_schm_interval + * + * Description: + * Don't support + * + ****************************************************************************/ + +static uint32_t wifi_coex_get_schm_interval(void) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_get_schm_curr_period + * + * Description: + * Don't support + * + ****************************************************************************/ + +static uint8_t wifi_coex_get_schm_curr_period(void) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_get_schm_curr_phase + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void *wifi_coex_get_schm_curr_phase(void) +{ + return NULL; +} + +/**************************************************************************** + * Name: wifi_coex_set_schm_curr_phase_idx + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_set_schm_curr_phase_idx(int idx) +{ + return -1; +} + +/**************************************************************************** + * Name: wifi_coex_get_schm_curr_phase_idx + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_get_schm_curr_phase_idx(void) +{ + return 0; +} + /**************************************************************************** * Name: esp_random_ulong * @@ -3810,6 +3981,38 @@ int net80211_printf(const char *format, ...) return 0; } +/**************************************************************************** + * Functions needed by libnet80211.a + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_mesh_send_event_internal + * + * Description: + * Don't support + * + ****************************************************************************/ + +int esp_mesh_send_event_internal(int32_t event_id, + void *event_data, + size_t event_data_size) +{ + return -1; +} + +/**************************************************************************** + * Name: esp_mesh_get_topology + * + * Description: + * Don't support + * + ****************************************************************************/ + +void *esp_mesh_get_topology(void) +{ + return NULL; +} + /**************************************************************************** * Functions needed by libwpa_supplicant.a ****************************************************************************/ @@ -3969,9 +4172,9 @@ int32_t esp_timer_delete(esp_timer_handle_t timer) void __assert_func(const char *file, int line, const char *func, const char *expr) { - wlerr("ERROR: Assert failed in %s, %s:%d (%s)", - func, file, line, expr); - abort(); + wlerr("ERROR: Assert failed in %s, %s:%d (%s)", + func, file, line, expr); + abort(); } /**************************************************************************** @@ -4191,41 +4394,70 @@ int esp_wifi_notify_subscribe(pid_t pid, FAR struct sigevent *event) wlinfo("PID=%d event=%p\n", pid, event); - if (event->sigev_notify != SIGEV_SIGNAL) - { - wlerr("ERROR: sigev_notify %d is invalid\n", event->sigev_signo); - return -1; - } + esp_event_lock(true); - id = esp_event_id_map(event->sigev_signo); - if (id < 0) + if (event->sigev_notify == SIGEV_SIGNAL) { - wlerr("ERROR: No process event %d\n", event->sigev_signo); - } - else - { - notify = &s_wifi_notify[id]; - - if (notify->assigned) + id = esp_event_id_map(event->sigev_signo); + if (id < 0) { - wlerr("ERROR: sigev_signo %d has subscribed\n", - event->sigev_signo); + wlerr("ERROR: No process event %d\n", event->sigev_signo); } else { - if (pid == 0) + notify = &g_wifi_notify[id]; + + if (notify->assigned) { - pid = getpid(); - wlinfo("Actual PID=%d\n", pid); + wlerr("ERROR: sigev_signo %d has subscribed\n", + event->sigev_signo); } + else + { + if (pid == 0) + { + pid = getpid(); + wlinfo("Actual PID=%d\n", pid); + } - notify->pid = pid; - notify->event = *event; - notify->assigned = true; + notify->pid = pid; + notify->event = *event; + notify->assigned = true; - ret = 0; + ret = 0; + } } } + else if (event->sigev_notify == SIGEV_NONE) + { + id = esp_event_id_map(event->sigev_signo); + if (id < 0) + { + wlerr("ERROR: No process event %d\n", event->sigev_signo); + } + else + { + notify = &g_wifi_notify[id]; + + if (!notify->assigned) + { + wlerr("ERROR: sigev_signo %d has not subscribed\n", + event->sigev_signo); + } + else + { + notify->assigned = false; + + ret = 0; + } + } + } + else + { + wlerr("ERROR: sigev_notify %d is invalid\n", event->sigev_signo); + } + + esp_event_lock(false); return ret; } @@ -4247,37 +4479,47 @@ int esp_wifi_notify_subscribe(pid_t pid, FAR struct sigevent *event) int esp_wifi_adapter_init(void) { int ret; - wifi_init_config_t init_cfg = WIFI_INIT_CONFIG_DEFAULT(); - - ret = sem_init(&s_connect_sem, 0, 0); - if (ret) - { - wlerr("ERROR: Failed to initialize sem error=%d\n", errno); - return -1; - } - -#ifndef CONFIG_ESP32_WIFI_SAVE_PARAM - init_cfg.nvs_enable = 0; -#endif + wifi_init_config_t wifi_cfg = WIFI_INIT_CONFIG_DEFAULT(); ret = esp32_rt_timer_init(); if (ret < 0) { wlerr("ERROR: Failed to initialize RT timer error=%d\n", ret); - sem_destroy(&s_connect_sem); return -1; } - ret = esp_wifi_init(&init_cfg); +#ifdef CONFIG_ESP32_WIFI_SAVE_PARAM + wifi_cfg.nvs_enable = 1; +#else + wifi_cfg.nvs_enable = 0; +#endif + +#ifdef CONFIG_ESP32_WIFI_TX_AMPDU + wifi_cfg.ampdu_tx_enable = 1; +#else + wifi_cfg.ampdu_tx_enable = 0; +#endif + +#ifdef CONFIG_ESP32_WIFI_RX_AMPDU + wifi_cfg.ampdu_rx_enable = 1; +#else + wifi_cfg.ampdu_rx_enable = 0; +#endif + + wifi_cfg.rx_ba_win = CONFIG_ESP32_WIFI_RXBA_AMPDU_WZ; + wifi_cfg.static_rx_buf_num = CONFIG_ESP32_WIFI_STATIC_RXBUF_NUM; + wifi_cfg.dynamic_rx_buf_num = CONFIG_ESP32_WIFI_DYNAMIC_RXBUF_NUM; + wifi_cfg.dynamic_tx_buf_num = CONFIG_ESP32_WIFI_DYNAMIC_TXBUF_NUM; + + ret = esp_wifi_init(&wifi_cfg); if (ret) { wlerr("ERROR: Failed to initialize WiFi error=%d\n", ret); - sem_destroy(&s_connect_sem); esp32_rt_timer_deinit(); return -1; } - sq_init(&s_wifi_evt_queue); + sq_init(&g_wifi_evt_queue); return 0; } @@ -4299,8 +4541,8 @@ int esp_wifi_adapter_init(void) int esp_wifi_set_password(const uint8_t *pdata, uint8_t len) { - memcpy(s_password, pdata, len); - s_password_len = len; + memcpy(g_password, pdata, len); + g_password_len = len; return 0; } @@ -4322,8 +4564,8 @@ int esp_wifi_set_password(const uint8_t *pdata, uint8_t len) int esp_wifi_set_ssid(const uint8_t *pdata, uint8_t len) { - memcpy(s_ssid, pdata, len); - s_ssid_len = len; + memcpy(g_ssid, pdata, len); + g_ssid_len = len; return 0; } @@ -4348,7 +4590,7 @@ int esp_wifi_connect_internal(void) wifi_config_t wifi_cfg; struct timespec timeout; - if (s_connected) + if (g_connected) { wlinfo("INFO: WiFi has connected AP\n"); return 0; @@ -4363,8 +4605,8 @@ int esp_wifi_connect_internal(void) } memset(&wifi_cfg, 0, sizeof(wifi_config_t)); - memcpy((char *)wifi_cfg.sta.ssid, s_ssid, s_ssid_len); - memcpy((char *)wifi_cfg.sta.password, s_password, s_password_len); + memcpy((char *)wifi_cfg.sta.ssid, g_ssid, g_ssid_len); + memcpy((char *)wifi_cfg.sta.password, g_password, g_password_len); ret = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_cfg); if (ret) @@ -4383,7 +4625,7 @@ int esp_wifi_connect_internal(void) clock_gettime(CLOCK_REALTIME, &timeout); timeout.tv_sec += WIFI_CONNECT_TIMEOUT; - ret = sem_timedwait(&s_connect_sem, &timeout); + ret = sem_timedwait(&g_connect_sem, &timeout); if (ret) { wlerr("ERROR: Failed to wait sem error=%d\n", errno); @@ -4391,7 +4633,7 @@ int esp_wifi_connect_internal(void) return -1; } - if (!s_connected) + if (!g_connected) { wlerr("ERROR: Process connection error\n"); esp_wifi_stop(); @@ -4400,3 +4642,22 @@ int esp_wifi_connect_internal(void) return 0; } + +/**************************************************************************** + * Name: esp_wifi_sta_register_txdone_cb + * + * Description: + * Register the txDone callback function of type wifi_tx_done_cb_t + * + * Input Parameters: + * callback - The callback function + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_sta_register_txdone_cb(void *callback) +{ + return esp_wifi_set_tx_done_cb((wifi_tx_done_cb_t)callback); +} diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.h b/arch/xtensa/src/esp32/esp32_wifi_adapter.h index 33ccbfeabb..5a66d2c002 100644 --- a/arch/xtensa/src/esp32/esp32_wifi_adapter.h +++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.h @@ -60,6 +60,9 @@ enum wifi_adpt_evt_e typedef void (*wifi_evt_cb_t)(void *p); +typedef void (* wifi_tx_done_cb_t)(uint8_t ifidx, uint8_t *data, + uint16_t *len, bool txstatus); + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -214,6 +217,22 @@ int esp_wifi_set_ssid(const uint8_t *pdata, uint8_t len); int esp_wifi_connect_internal(void); +/**************************************************************************** + * Name: esp_wifi_sta_register_txdone_cb + * + * Description: + * Register the txDone callback function of type wifi_tx_done_cb_t + * + * Input Parameters: + * callback - The callback function + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_sta_register_txdone_cb(void *callback); + #ifdef __cplusplus } #endif diff --git a/arch/xtensa/src/esp32/esp32_wlan.c b/arch/xtensa/src/esp32/esp32_wlan.c index 1a7ab34dfe..d5cf9df86b 100644 --- a/arch/xtensa/src/esp32/esp32_wlan.c +++ b/arch/xtensa/src/esp32/esp32_wlan.c @@ -23,161 +23,186 @@ ****************************************************************************/ #include -#include + +#ifdef CONFIG_ESP32_WIRELESS + #include #include +#include +#include #include +#include #include #include #include #include -#include #include #include -#include - #if defined(CONFIG_NET_PKT) # include #endif -#include -#include -#include - #include "esp32_wifi_adapter.h" -#include - -#ifdef CONFIG_ESP32_WIRELESS - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -#define STA_DEVNO 0 +/* WLAN station device ID */ -/* TX poll delay = 1 seconds. +#define WLAN_STA_DEVNO (0) + +/** + * TX poll delay = 1 seconds. * CLK_TCK is the number of clock ticks per second */ -#define ESP_WDDELAY (1*CLK_TCK) -#define ESPWORK LPWORK +#define WLAN_WDDELAY (1 * CLK_TCK) /* TX timeout = 1 minute */ -#define ESP_TXTIMEOUT (60*CLK_TCK) -#define DEFAULT_SCAN_LIST_SIZE 2 +#define WLAN_TXTOUT (60 * CLK_TCK) -/* Add 4 to the configured buffer size to account for the 2 byte checksum - * memory needed at the end of the maximum size packet. Buffer sizes must - * be an even multiple of 4, 8, or 16 bytes (depending on buswidth). We - * will use the 16-byte alignment in all cases. +/* Low-priority workqueue processes RX/TX */ + +#define WLAN_WORK LPWORK + +/** + * Ethernet frame: + * Resource address : 6 bytes + * Destination address: 6 bytes + * Type : 2 bytes + * Payload : MAX 1500 + * Checksum : Ignore + * + * Total size : 1514 */ -#define OPTIMAL_ETH_BUFSIZE ((CONFIG_NET_ETH_PKTSIZE + 4 + 15) & ~15) +#define WLAN_BUF_SIZE (CONFIG_NET_ETH_PKTSIZE) -#ifndef CONFIG_ESP_ETH_BUFSIZE -# define CONFIG_ESP_ETH_BUFSIZE OPTIMAL_ETH_BUFSIZE +/* WiFi receive buffer number */ + +#define WLAN_RXBUF_NUM (CONFIG_ESP32_WLAN_RXBUF_NUM) + +/** + * Receive threshold which let the receive function to trigger a sheduler + * to active application if possible. + */ + +#ifdef CONFIG_MM_IOB +# define IOBBUF_SIZE (CONFIG_IOB_NBUFFERS * CONFIG_IOB_BUFSIZE) +# if (IOBBUF_SIZE) > (WLAN_BUF_SIZE + 1) +# define WLAN_RX_THRESHOLD (IOBBUF_SIZE - WLAN_BUF_SIZE + 1) +# endif #endif -#ifndef CONFIG_ESP_ETH_NTXDESC -# define CONFIG_ESP_ETH_NTXDESC 4 -#endif - -/* We need at least one more free buffer than transmit buffers */ - -#define ESP_ETH_NFREEBUFFERS (CONFIG_ESP_ETH_NTXDESC+1) -#define ETH_MAX_LEN 1518 - -/* This is a helper pointer for accessing the contents of wlan header */ - -#define BUF ((struct eth_hdr_s *)priv->esp_dev.d_buf) - /**************************************************************************** * Private Types ****************************************************************************/ -/* The esp_dev_s encapsulates all state information for a single +/* Receive buffer */ + +struct wlan_rxbuf +{ + sq_entry_t entry; /* Queue entry */ + + /* Packet data buffer */ + + uint8_t buffer[WLAN_BUF_SIZE]; + uint16_t len; /* Packet data length */ +}; + +/* The wlan_priv_s encapsulates all state information for a single * hardware interface */ -struct esp_dev_s +struct wlan_priv_s { bool ifup; /* true:ifup false:ifdown */ - struct wdog_s esp_txpoll; /* TX poll timer */ - struct wdog_s esp_txtimeout; /* TX timeout timer */ - struct work_s esp_irqwork; /* For deferring interrupt work to the work queue */ - struct work_s esp_pollwork; /* For deferring poll work to the work queue */ + + struct wdog_s txpoll; /* TX poll timer */ + struct wdog_s txtimeout; /* TX timeout timer */ + + struct work_s rxwork; /* Send packet work */ + struct work_s txwork; /* Receive packet work */ + struct work_s pollwork; /* Poll work */ + struct work_s toutwork; /* Send packet timeout work */ /* This holds the information visible to the NuttX network */ - struct net_driver_s esp_dev; - sq_queue_t freeb; /* The free buffer list */ + struct net_driver_s dev; - /* Buffer allocations */ + /* TX buffer */ - uint8_t alloc[CONFIG_ESP_ETH_NTXDESC*CONFIG_ESP_ETH_BUFSIZE]; - uint8_t rxbuf[ETH_MAX_LEN]; - uint32_t rx_len; + uint8_t txbuf[WLAN_BUF_SIZE]; + + /* Rest data in TX buffer which needs being sent */ + + uint8_t txrst; + + /* RX buffer cache */ + + struct wlan_rxbuf rxbuf[WLAN_RXBUF_NUM]; + + /* RX buffer queue */ + + sq_queue_t rxb; + + /* Free buffer queue */ + + sq_queue_t freeb; }; /**************************************************************************** * Private Data ****************************************************************************/ -static struct esp_dev_s s_esp32_dev; -static bool g_tx_ready = false; +static struct wlan_priv_s g_wlan_priv; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -/* Free buffer management */ - -static void esp_initbuffer(FAR struct esp_dev_s *priv); -static inline uint8_t *esp_allocbuffer(FAR struct esp_dev_s *priv); -static inline void esp_freebuffer(FAR struct esp_dev_s *priv, - uint8_t *buffer); -static inline bool esp_isfreebuffer(FAR struct esp_dev_s *priv); - /* Common TX logic */ -static int esp_transmit(FAR struct esp_dev_s *priv); -static void esp_receive(FAR struct esp_dev_s *priv); -static int esp_txpoll(FAR struct net_driver_s *dev); -static void esp_rxpoll(FAR void *arg); -static void esp_dopoll(FAR struct esp_dev_s *priv); -static void esp_netdev_notify_rx(FAR struct esp_dev_s *priv, - void *buffer, uint16_t len); -static int esp_sta_input(void *buffer, uint16_t len, void *eb); +static int wlan_transmit(FAR struct wlan_priv_s *priv); +static void wlan_rxpoll(FAR void *arg); +static int wlan_txpoll(FAR struct net_driver_s *dev); +static void wlan_dopoll(FAR struct wlan_priv_s *priv); /* Watchdog timer expirations */ -static void esp_txtimeout_work(FAR void *arg); -static void esp_txtimeout_expiry(wdparm_t arg); +static void wlan_txtimeout_work(FAR void *arg); +static void wlan_txtimeout_expiry(wdparm_t arg); -static void esp_poll_work(FAR void *arg); -static void esp_poll_expiry(wdparm_t arg); +static void wlan_poll_work(FAR void *arg); +static void wlan_poll_expiry(wdparm_t arg); /* NuttX callback functions */ -static int esp_ifup(struct net_driver_s *dev); -static int esp_ifdown(struct net_driver_s *dev); +static int wlan_ifup(struct net_driver_s *dev); +static int wlan_ifdown(struct net_driver_s *dev); -static void esp_txavail_work(FAR void *arg); -static int esp_txavail(struct net_driver_s *dev); +static void wlan_txavail_work(FAR void *arg); +static int wlan_txavail(struct net_driver_s *dev); #if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6) -static int esp_addmac(struct net_driver_s *dev, FAR const uint8_t *mac); +static int wlan_addmac(struct net_driver_s *dev, FAR const uint8_t *mac); #endif + #ifdef CONFIG_NET_MCASTGROUP -static int esp_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac); +static int wlan_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac); #endif + #ifdef CONFIG_NETDEV_IOCTL -static int esp_ioctl(struct net_driver_s *dev, int cmd, - unsigned long arg); +static int wlan_ioctl(struct net_driver_s *dev, int cmd, + unsigned long arg); #endif + +static void wlan_tx_done(uint8_t ifidx, uint8_t *data, + uint16_t *len, bool txstatus); +static int wlan_rx_done(void *buffer, uint16_t len, void *eb); static int esp32_net_initialize(unsigned int devno); /**************************************************************************** @@ -188,73 +213,91 @@ static int esp32_net_initialize(unsigned int devno); * Note: * All TX done/RX done/Error trigger functions are not called from * interrupts, this is much different from ethernet driver, including: - * * esp_sta_input + * * wlan_rx_done + * * wlan_tx_done * * These functions are called in a WiFi private thread. So we just use * mutex/semaphore instead of disable interrupt, if necessary. */ /**************************************************************************** - * Function: esp_initbuffer + * Function: wlan_init_buffer * * Description: - * Initialize the free buffer list. + * Initialize the free buffer list * * Input Parameters: - * priv - Reference to the driver state structure + * priv - Reference to the driver state structure * * Returned Value: * None * ****************************************************************************/ -static void esp_initbuffer(FAR struct esp_dev_s *priv) +static inline void wlan_init_buffer(struct wlan_priv_s *priv) { - uint8_t *buffer; int i; + irqstate_t flags; - /* Initialize the head of the free buffer list */ + flags = enter_critical_section(); + + priv->txrst = 0; + + priv->dev.d_buf = NULL; + priv->dev.d_len = 0; sq_init(&priv->freeb); + sq_init(&priv->rxb); - /* Add all of the pre-allocated buffers to the free buffer list */ - - for (i = 0, buffer = priv->alloc; i < ESP_ETH_NFREEBUFFERS; - i++, buffer += CONFIG_ESP_ETH_BUFSIZE) + for (i = 0; i < WLAN_RXBUF_NUM; i++) { - sq_addlast((FAR sq_entry_t *)buffer, &priv->freeb); + sq_addlast(&priv->rxbuf[i].entry, &priv->freeb); } + + leave_critical_section(flags); } /**************************************************************************** - * Function: esp_allocbuffer + * Function: wlan_alloc_buffer * * Description: - * Allocate one buffer from the free buffer list. + * Allocate one buffer from the free buffer queue * * Input Parameters: - * priv - Reference to the driver state structure + * priv - Reference to the driver state structure * * Returned Value: * Pointer to the allocated buffer on success; NULL on failure * ****************************************************************************/ -static inline uint8_t *esp_allocbuffer(FAR struct esp_dev_s *priv) +static inline struct wlan_rxbuf *wlan_alloc_buffer(struct wlan_priv_s *priv) { - /* Allocate a buffer by returning the head of the free buffer list */ + sq_entry_t *entry; + irqstate_t flags; + struct wlan_rxbuf *rxbuf = NULL; - return (uint8_t *)sq_remfirst(&priv->freeb); + flags = enter_critical_section(); + + entry = sq_remfirst(&priv->freeb); + if (entry) + { + rxbuf = container_of(entry, struct wlan_rxbuf, entry); + } + + leave_critical_section(flags); + + return rxbuf; } /**************************************************************************** - * Function: esp_freebuffer + * Function: wlan_free_buffer * * Description: - * Return a buffer to the free buffer list. + * Insert a free Rx buffer into free queue * * Input Parameters: - * priv - Reference to the driver state structure + * priv - Reference to the driver state structure * buffer - A pointer to the buffer to be freed * * Returned Value: @@ -262,42 +305,62 @@ static inline uint8_t *esp_allocbuffer(FAR struct esp_dev_s *priv) * ****************************************************************************/ -static inline void esp_freebuffer(FAR struct esp_dev_s *priv, - uint8_t *buffer) +static inline void wlan_free_buffer(struct wlan_priv_s *priv, + uint8_t *buffer) { - /* Free the buffer by adding it to the end of the free buffer list */ + struct wlan_rxbuf *rxbuf; + irqstate_t flags; - sq_addlast((FAR sq_entry_t *)buffer, &priv->freeb); + flags = enter_critical_section(); + + rxbuf = container_of(buffer, struct wlan_rxbuf, buffer); + sq_addlast(&rxbuf->entry, &priv->freeb); + + leave_critical_section(flags); } /**************************************************************************** - * Function: esp_isfreebuffer + * Name: wifi_tx_available * * Description: - * Return TRUE if the free buffer list is not empty. + * Check if WiFi can send data. This function will re-send rest data + * which was sent failed. * * Input Parameters: - * priv - Reference to the driver state structure + * priv - Reference to the driver state structure * * Returned Value: - * True if there are one or more buffers in the free buffer list; - * false if the free buffer list is empty + * true if available or false if unavailable * ****************************************************************************/ -static inline bool esp_isfreebuffer(FAR struct esp_dev_s *priv) +static bool wifi_tx_available(FAR struct wlan_priv_s *priv) { - /* Return TRUE if the free buffer list is not empty */ + int ret; - return !sq_empty(&priv->freeb); + if (priv->txrst) + { + ret = esp_wifi_sta_send_data(priv->txbuf, priv->txrst); + if (ret) + { + ninfo("ERROR: Failed to transmit rest frame\n"); + return false; + } + else + { + priv->txrst = 0; + } + } + + return true; } /**************************************************************************** - * Name: esp_transmit + * Name: wlan_transmit * * Description: - * Start hardware transmission. Called either from TX process or - * from watchdog based polling. + * Send the data to WiFi driver. If this sending fails, cache the data + * and re-send it when TX done callback or timer poll function triggers. * * Input Parameters: * priv - Reference to the driver state structure @@ -307,120 +370,229 @@ static inline bool esp_isfreebuffer(FAR struct esp_dev_s *priv) * ****************************************************************************/ -static int esp_transmit(FAR struct esp_dev_s *priv) +static int wlan_transmit(FAR struct wlan_priv_s *priv) { - int ret = 0; - uint8_t *buffer; - uint32_t buffer_len; + int ret; + struct net_driver_s *dev = &priv->dev; + void *buffer = dev->d_buf; + uint32_t len = dev->d_len; - /* Set up all but the last TX descriptor */ - - buffer = priv->esp_dev.d_buf; - buffer_len = priv->esp_dev.d_len; - ret = esp_wifi_sta_send_data(buffer, buffer_len); - - if (ret != 0) + if (!wifi_tx_available(priv)) { - wlerr("ERROR: Failed to transmit frame\n"); - (void)wd_start(&priv->esp_txtimeout, ESP_TXTIMEOUT, - esp_txtimeout_expiry, (uint32_t)priv); + return -ENOBUFS; + } + + ret = esp_wifi_sta_send_data(buffer, len); + if (ret) + { + priv->txrst = len; + if (buffer != priv->txbuf) + { + memcpy(priv->txbuf, buffer, len); + } + + wd_start(&priv->txtimeout, WLAN_TXTOUT, + wlan_txtimeout_expiry, (uint32_t)priv); + return -EIO; } + else + { + priv->txrst = 0; + } return OK; } /**************************************************************************** - * Function: esp_recvframe + * Function: wlan_recvframe * * Description: - * It scans the RX descriptors of the received frame. - * - * NOTE: This function will silently discard any packets containing errors. + * Try to receive RX buffer from RX done buffer queue. * * Input Parameters: - * priv - Reference to the driver state structure + * priv - Reference to the driver state structure * * Returned Value: - * OK if a packet was successfully returned; -EAGAIN if there are no - * further packets available + * RX buffer if success or NULl if no buffer in queue. * ****************************************************************************/ -static int esp_recvframe(FAR struct esp_dev_s *priv) +static struct wlan_rxbuf *wlan_recvframe(FAR struct wlan_priv_s *priv) { - struct net_driver_s *dev = &priv->esp_dev; - uint8_t *buffer; - uint32_t buffer_len = 0; - buffer = dev->d_buf; - buffer_len = dev->d_len; + irqstate_t flags; + sq_entry_t *entry; + struct wlan_rxbuf *rxbuf = NULL; - /* Check if there are free buffers. We cannot receive new frames in this - * design unless there is at least one free buffer. - */ + flags = enter_critical_section(); - if (!esp_isfreebuffer(priv)) + entry = sq_remfirst(&priv->rxb); + if (entry) { - wlerr("ERROR: No free buffers\n"); - return -ENOMEM; + rxbuf = container_of(entry, struct wlan_rxbuf, entry); } - /* Check if any errors are reported in the frame */ + leave_critical_section(flags); - if (buffer == NULL || buffer_len == 0) - { - return -EAGAIN; - } - - return OK; + return rxbuf; } /**************************************************************************** - * Function: esp_receive + * Name: wlan_tx_done * * Description: - * An event was received indicating the availability of a new RX packet + * WiFi TX done callback function. If this is called, it means sending + * next packet. * * Input Parameters: - * priv - Reference to the driver state structure + * ifidx - The interface id that the tx callback has been triggered from. + * data - Pointer to the data transmitted. + * len - Length of the data transmitted. + * status - True if data was transmitted sucessfully or false if failed. * * Returned Value: * None * ****************************************************************************/ -static void esp_receive(FAR struct esp_dev_s *priv) +static void wlan_tx_done(uint8_t ifidx, uint8_t *data, + uint16_t *len, bool status) { - struct net_driver_s *dev = &priv->esp_dev; + FAR struct wlan_priv_s *priv = &g_wlan_priv; - /* Loop while while esp_recvframe() successfully retrieves valid + wd_cancel(&priv->txtimeout); + + wlan_txavail(&priv->dev); +} + +/**************************************************************************** + * Function: wlan_rx_done + * + * Description: + * WiFi RX done callback function. If this is called, it means receiveing + * packet. + * + * Input Parameters: + * buffer - WiFi received packet buffer + * len - Length of received packet + * eb - WiFi receive callback input eb pointer + * + * Returned Value: + * 0 on success or a negated errno on failure + * + ****************************************************************************/ + +static int wlan_rx_done(void *buffer, uint16_t len, void *eb) +{ + struct wlan_rxbuf *rxbuf; + irqstate_t flags; + FAR struct wlan_priv_s *priv = &g_wlan_priv; + + if (!priv->ifup) + { + return 0; + } + + if (len > WLAN_BUF_SIZE) + { + nwarn("ERROR: Wlan receive %d larger than %d\n", + len, WLAN_BUF_SIZE); + return -EINVAL; + } + + rxbuf = wlan_alloc_buffer(priv); + if (!rxbuf) + { + if (eb) + { + esp_wifi_free_eb(eb); + } + + return -ENOBUFS; + } + + memcpy(rxbuf->buffer, buffer, len); + rxbuf->len = len; + + if (eb) + { + esp_wifi_free_eb(eb); + } + + flags = enter_critical_section(); + sq_addlast(&rxbuf->entry, &priv->rxb); + leave_critical_section(flags); + + if (work_available(&priv->rxwork)) + { + work_queue(WLAN_WORK, &priv->rxwork, wlan_rxpoll, priv, 0); + } + + return 0; +} + +/**************************************************************************** + * Function: wlan_rxpoll + * + * Description: + * Try to receive packets from RX done queue and pass packets into IP + * stack and send packets which is from IP stack if necessary. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_rxpoll(FAR void *arg) +{ + struct wlan_rxbuf *rxbuf; + struct eth_hdr_s *eth_hdr; + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; + FAR struct net_driver_s *dev = &priv->dev; +#ifdef WLAN_RX_THRESHOLD + uint32_t rbytes = 0; +#endif + + /* Loop while while wlan_recvframe() successfully retrieves valid * Ethernet frames. */ - while (esp_recvframe(priv) == OK) + net_lock(); + + while ((rxbuf = wlan_recvframe(priv)) != NULL) { + dev->d_buf = rxbuf->buffer; + dev->d_len = rxbuf->len; + +#ifdef WLAN_RX_THRESHOLD + rbytes += rxbuf->len; +#endif + #ifdef CONFIG_NET_PKT /* When packet sockets are enabled, * feed the frame into the packet tap. */ - pkt_input(&priv->esp_dev); + pkt_input(&priv->dev); #endif /* Check if the packet is a valid size for the network * buffer configuration (this should not happen) */ - if (dev->d_len > CONFIG_NET_ETH_PKTSIZE) + if (dev->d_len > WLAN_BUF_SIZE) { - wlwarn("WARNING: DROPPED Too big: %d\n", dev->d_len); + nwarn("WARNING: DROPPED Too big: %d\n", dev->d_len); /* Free dropped packet buffer */ if (dev->d_buf) { - esp_freebuffer(priv, dev->d_buf); + wlan_free_buffer(priv, dev->d_buf); dev->d_buf = NULL; dev->d_len = 0; } @@ -428,110 +600,112 @@ static void esp_receive(FAR struct esp_dev_s *priv) continue; } + eth_hdr = (struct eth_hdr_s *)dev->d_buf; + /* We only accept IP packets of the configured type and ARP packets */ #ifdef CONFIG_NET_IPv4 - if (BUF->type == HTONS(ETHTYPE_IP)) + if (eth_hdr->type == HTONS(ETHTYPE_IP)) { - wlinfo("IPv4 frame\n"); + ninfo("IPv4 frame\n"); /* Handle ARP on input then give the IPv4 packet to the network * layer */ - arp_ipin(&priv->esp_dev); - ipv4_input(&priv->esp_dev); + arp_ipin(&priv->dev); + ipv4_input(&priv->dev); /* If the above function invocation resulted in data * that should be sent out on the network, * the field d_len will set to a value > 0. */ - if (priv->esp_dev.d_len > 0) + if (priv->dev.d_len > 0) { /* Update the Ethernet header with the correct MAC address */ #ifdef CONFIG_NET_IPv6 - if (IFF_IS_IPv4(priv->esp_dev.d_flags)) + if (IFF_IS_IPv4(priv->dev.d_flags)) #endif { - arp_out(&priv->esp_dev); + arp_out(&priv->dev); } #ifdef CONFIG_NET_IPv6 else { - neighbor_out(&priv->esp_dev); + neighbor_out(&priv->dev); } #endif /* And send the packet */ - esp_transmit(priv); + wlan_transmit(priv); } } else #endif #ifdef CONFIG_NET_IPv6 - if (BUF->type == HTONS(ETHTYPE_IP6)) + if (eth_hdr->type == HTONS(ETHTYPE_IP6)) { - wlinfo("Iv6 frame\n"); + ninfo("IPv6 frame\n"); /* Give the IPv6 packet to the network layer */ - ipv6_input(&priv->esp_dev); + ipv6_input(&priv->dev); /* If the above function invocation resulted in data * that should be sent out on the network, the field * d_len will set to a value > 0. */ - if (priv->esp_dev.d_len > 0) + if (priv->dev.d_len > 0) { /* Update the Ethernet header with the correct MAC address */ #ifdef CONFIG_NET_IPv4 - if (IFF_IS_IPv4(priv->esp_dev.d_flags)) + if (IFF_IS_IPv4(priv->dev.d_flags)) { - arp_out(&priv->esp_dev); + arp_out(&priv->dev); } else #endif #ifdef CONFIG_NET_IPv6 { - neighbor_out(&priv->esp_dev); + neighbor_out(&priv->dev); } #endif /* And send the packet */ - esp_transmit(priv); + wlan_transmit(priv); } } else #endif #ifdef CONFIG_NET_ARP - if (BUF->type == htons(ETHTYPE_ARP)) + if (eth_hdr->type == htons(ETHTYPE_ARP)) { - wlinfo("ARP frame\n"); + ninfo("ARP frame\n"); /* Handle ARP packet */ - arp_arpin(&priv->esp_dev); + arp_arpin(&priv->dev); /* If the above function invocation resulted in data * that should be sent out on the network, the field * d_len will set to a value > 0. */ - if (priv->esp_dev.d_len > 0) + if (priv->dev.d_len > 0) { - esp_transmit(priv); + wlan_transmit(priv); } } else #endif { - wlinfo("INFO: Dropped, Unknown type: %04x\n", BUF->type); + ninfo("INFO: Dropped, Unknown type: %04x\n", eth_hdr->type); } /* We are finished with the RX buffer. NOTE: If the buffer is @@ -543,15 +717,32 @@ static void esp_receive(FAR struct esp_dev_s *priv) { /* Free the receive packet buffer */ - esp_freebuffer(priv, dev->d_buf); + wlan_free_buffer(priv, dev->d_buf); dev->d_buf = NULL; dev->d_len = 0; } + +#ifdef WLAN_RX_THRESHOLD + /** + * If received total bytes is larger than receive threshold, + * then do "unlock" to try to active applicantion to receive + * data from low-level buffer of IP stack. + */ + + if (rbytes >= WLAN_RX_THRESHOLD) + { + net_unlock(); + rbytes = 0; + net_lock(); + } +#endif } + + net_unlock(); } /**************************************************************************** - * Name: esp_txpoll + * Name: wlan_txpoll * * Description: * The transmitter is available, check if the network has any outgoing @@ -570,17 +761,17 @@ static void esp_receive(FAR struct esp_dev_s *priv) * ****************************************************************************/ -static int esp_txpoll(FAR struct net_driver_s *dev) +static int wlan_txpoll(FAR struct net_driver_s *dev) { - FAR struct esp_dev_s *priv = (FAR struct esp_dev_s *)dev->d_private; + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; - DEBUGASSERT(priv->esp_dev.d_buf != NULL); + DEBUGASSERT(dev->d_buf != NULL); /* If the polling resulted in data that should be sent out on the network, * the field d_len is set to a value > 0. */ - if (priv->esp_dev.d_len > 0) + if (dev->d_len > 0) { /* Look up the destination MAC address and add it to the Ethernet * header. @@ -588,10 +779,10 @@ static int esp_txpoll(FAR struct net_driver_s *dev) #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 - if (IFF_IS_IPv4(priv->esp_dev.d_flags)) + if (IFF_IS_IPv4(dev->d_flags)) #endif { - arp_out(&priv->esp_dev); + arp_out(dev); } #endif /* CONFIG_NET_IPv4 */ @@ -600,20 +791,14 @@ static int esp_txpoll(FAR struct net_driver_s *dev) else #endif { - neighbor_out(&priv->esp_dev); + neighbor_out(dev); } #endif /* CONFIG_NET_IPv6 */ - if (!devif_loopback(&priv->esp_dev)) + int ret = wlan_transmit(priv); + if (ret) { - /* Send the packet */ - - int ret = esp_transmit(priv); - if (ret != OK) - { - wlerr("TX failed\r\n"); - return -EBUSY; - } + return -EBUSY; } } @@ -625,187 +810,44 @@ static int esp_txpoll(FAR struct net_driver_s *dev) } /**************************************************************************** - * Name: esp_rxpoll - * - * Description: - * Process RX frames - * - * Input Parameters: - * arg - context of device to use - * - * Returned Value: - * OK on success - * - * Assumptions: - * The network is locked. - * - ****************************************************************************/ - -static void esp_rxpoll(FAR void *arg) -{ - FAR struct esp_dev_s *priv = (FAR struct esp_dev_s *)arg; - - if (priv->esp_dev.d_buf == NULL) - { - priv->esp_dev.d_buf = priv->rxbuf; - priv->esp_dev.d_len = priv->rx_len; - } - else - { - wlinfo("priv->esp_dev.d_buf != NULL"); - return; - } - - /* Lock the network and serialize driver operations if necessary. - * NOTE: Serialization is only required in the case where the driver work - * is performed on an LP worker thread and where more than one LP worker - * thread has been configured. - */ - - net_lock(); - - esp_receive(priv); - - if (priv->esp_dev.d_buf) - { - priv->esp_dev.d_buf = NULL; - memset(priv->rxbuf, 0x0, sizeof(priv->rxbuf)); - priv->rx_len = 0; - } - - net_unlock(); -} - -/**************************************************************************** - * Function: esp_dopoll + * Function: wlan_dopoll * * Description: * The function is called in order to perform an out-of-sequence TX poll. * This is done: * - * 1. When new TX data is available (esp_txavail), and + * 1. When new TX data is available (wlan_txavail) * 2. After a TX timeout to restart the sending process - * (esp_txtimeout_expiry). + * (wlan_txtimeout_expiry). * * Input Parameters: - * priv - Reference to the driver state structure + * priv - Reference to the driver state structure * * Returned Value: * None * ****************************************************************************/ -static void esp_dopoll(FAR struct esp_dev_s *priv) +static void wlan_dopoll(FAR struct wlan_priv_s *priv) { - FAR struct net_driver_s *dev = &priv->esp_dev; + FAR struct net_driver_s *dev = &priv->dev; - if (g_tx_ready == true) + if (!wifi_tx_available(priv)) { - /* Check if there is room in the hardware to - * hold another outgoing packet. - */ - - dev->d_buf = esp_allocbuffer(priv); - - /* We can't poll if we have no buffers */ - - if (dev->d_buf) - { - /* If so, then poll the network for new XMIT data */ - - (void)devif_poll(dev, esp_txpoll); - - /* We will, most likely end up with a buffer to be freed. - * But it might not be the same one that we allocated above. - */ - - if (dev->d_buf) - { - esp_freebuffer(priv, dev->d_buf); - dev->d_buf = NULL; - } - } - else - { - wlerr("Alloc buffer error"); - } - } - else - { - wlwarn("Tx is not ready"); + return ; } + + dev->d_buf = priv->txbuf; + + /* If so, then poll the network for new XMIT data */ + + devif_poll(dev, wlan_txpoll); + + dev->d_buf = NULL; } /**************************************************************************** - * Name: esp_netdev_notify_rx - * - * Description: - * Notify callback called when RX frame is available - * - * Input Parameters: - * priv - Reference to the driver state structure - * buffer - Receive buffer - * len - Length of receive buffer - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void esp_netdev_notify_rx(FAR struct esp_dev_s *priv, - void *buffer, uint16_t len) -{ - struct esp_dev_s *priv_dev = priv; - - memcpy(priv_dev->rxbuf, buffer, len); - priv_dev->rx_len = len; - work_queue(ESPWORK, &priv_dev->esp_irqwork, esp_rxpoll, priv_dev, 0); -} - -/**************************************************************************** - * Function: esp_sta_input - * - * Description: - * This function should be called when a packet is ready to be read - * from the interface. It uses the function low_level_input() that - * should handle the actual reception of bytes from the network - * interface. Then the type of the received packet is determined and - * the appropriate input function is called. - * - * Input Parameters: - * buffer - WiFi receive buffer - * len - Length of receive buffer - * eb - WiFi receive callback input eb pointer - * - * Returned Value: - * OK on success; a negated errno on failure - * - ****************************************************************************/ - -static int esp_sta_input(void *buffer, uint16_t len, void *eb) -{ - FAR struct esp_dev_s *priv = &s_esp32_dev; - - if (!buffer || (priv->ifup == false)) - { - if (eb) - { - esp_wifi_free_eb(eb); - } - - return -1; - } - else - { - esp_netdev_notify_rx(priv, buffer, len); - } - - esp_wifi_free_eb(eb); - return 0; -} - -/**************************************************************************** - * Function: esp_txtimeout_work + * Function: wlan_txtimeout_work * * Description: * Perform TX timeout related work from the worker thread @@ -818,24 +860,24 @@ static int esp_sta_input(void *buffer, uint16_t len, void *eb) * ****************************************************************************/ -static void esp_txtimeout_work(void *arg) +static void wlan_txtimeout_work(void *arg) { - struct esp_dev_s *priv = (struct esp_dev_s *)arg; - - /* Reset the hardware. Just take the interface down, then back up again. */ + struct wlan_priv_s *priv = (struct wlan_priv_s *)arg; net_lock(); - esp_ifdown(&priv->esp_dev); - esp_ifup(&priv->esp_dev); + + wlan_ifdown(&priv->dev); + wlan_ifup(&priv->dev); /* Then poll for new XMIT data */ - esp_dopoll(priv); + wlan_dopoll(priv); + net_unlock(); } /**************************************************************************** - * Function: esp_txtimeout_expiry + * Function: wlan_txtimeout_expiry * * Description: * Our TX watchdog timed out. Called from the timer callback handler. @@ -850,19 +892,20 @@ static void esp_txtimeout_work(void *arg) * ****************************************************************************/ -static void esp_txtimeout_expiry(wdparm_t arg) +static void wlan_txtimeout_expiry(wdparm_t arg) { - struct esp_dev_s *priv = (struct esp_dev_s *)arg; - wlinfo("Timeout!\n"); + struct wlan_priv_s *priv = (struct wlan_priv_s *)arg; /* Schedule to perform the TX timeout processing on the worker thread. */ - DEBUGASSERT(work_available(&priv->esp_irqwork)); - work_queue(ESPWORK, &priv->esp_irqwork, esp_txtimeout_work, priv, 0); + if (work_available(&priv->toutwork)) + { + work_queue(WLAN_WORK, &priv->toutwork, wlan_txtimeout_work, priv, 0); + } } /**************************************************************************** - * Name: esp_poll_work + * Name: wlan_poll_work * * Description: * Perform periodic polling from the worker thread @@ -878,10 +921,11 @@ static void esp_txtimeout_expiry(wdparm_t arg) * ****************************************************************************/ -static void esp_poll_work(FAR void *arg) +static void wlan_poll_work(FAR void *arg) { - FAR struct esp_dev_s *priv = (FAR struct esp_dev_s *)arg; - struct net_driver_s *dev = &priv->esp_dev; + int32_t delay = WLAN_WDDELAY; + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; + struct net_driver_s *dev = &priv->dev; /* Lock the network and serialize driver operations if necessary. * NOTE: Serialization is only required in the case where the driver work @@ -893,45 +937,33 @@ static void esp_poll_work(FAR void *arg) /* Check if there is room in the send another TX packet. We cannot perform * the TX poll if he are unable to accept another packet for transmission. + * + * If there is no room, we should reset the timeout value to be 1 to + * trigger the timer as soon as possible. */ - if (g_tx_ready == true) + if (!wifi_tx_available(priv)) { - dev->d_buf = esp_allocbuffer(priv); - - /* We can't poll if we have no buffers */ - - if (dev->d_buf) - { - /* Update TCP timing states and poll - * the network for new XMIT data. - */ - - (void)devif_timer(&priv->esp_dev, ESP_WDDELAY, esp_txpoll); - - /* We will, most likely end up with a buffer to be freed. - * But it might not be the same one that we allocated above. - */ - - if (dev->d_buf) - { - esp_freebuffer(priv, dev->d_buf); - dev->d_buf = NULL; - } - } - else - { - wlerr("ERROR: Failed to TX pkt"); - } + delay = 1; + goto exit; } - wd_start(&priv->esp_txpoll, ESP_WDDELAY, esp_poll_expiry, - (wdparm_t)priv); + dev->d_buf = priv->txbuf; + + /* Update TCP timing states and poll the network for new XMIT data. */ + + devif_timer(&priv->dev, delay, wlan_txpoll); + + dev->d_buf = NULL; + +exit: + wd_start(&priv->txpoll, delay, wlan_poll_expiry, (wdparm_t)priv); + net_unlock(); } /**************************************************************************** - * Name: esp_poll_expiry + * Name: wlan_poll_expiry * * Description: * Periodic timer handler. Called from the timer callback handler. @@ -945,101 +977,18 @@ static void esp_poll_work(FAR void *arg) * ****************************************************************************/ -static void esp_poll_expiry(wdparm_t arg) +static void wlan_poll_expiry(wdparm_t arg) { - FAR struct esp_dev_s *priv = (FAR struct esp_dev_s *)arg; + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; - work_queue(ESPWORK, &priv->esp_pollwork, esp_poll_work, priv, 0); + if (priv->ifup) + { + work_queue(WLAN_WORK, &priv->pollwork, wlan_poll_work, priv, 0); + } } /**************************************************************************** - * Name: esp_ifup - * - * Description: - * NuttX Callback: Bring up the Ethernet interface when an IP address is - * provided - * - * Input Parameters: - * dev - Reference to the NuttX driver state structure - * - * Returned Value: - * None - * - ****************************************************************************/ - -static int esp_ifup(FAR struct net_driver_s *dev) -{ - FAR struct esp_dev_s *priv = (FAR struct esp_dev_s *)dev->d_private; - -#ifdef CONFIG_NET_IPv4 - wlinfo("Bringing up: %d.%d.%d.%d\n", - dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, - (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24); -#endif -#ifdef CONFIG_NET_IPv6 - winfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2], - dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5], - dev->d_ipv6addr[6], dev->d_ipv6addr[7]); -#endif - -#ifdef CONFIG_NET_ICMPv6 - - /* Set up IPv6 multicast address filtering */ - - esp_ipv6multicast(priv); -#endif - - /* Initialize the free buffer list */ - - esp_initbuffer(priv); - - /* Set and activate a timer process */ - - (void)wd_start(&priv->esp_txpoll, ESP_WDDELAY, esp_poll_expiry, - (wdparm_t)priv); - - priv->ifup = true; - - return OK; -} - -/**************************************************************************** - * Name: esp_ifdown - * - * Description: - * NuttX Callback: Stop the interface. - * - * Input Parameters: - * dev - Reference to the NuttX driver state structure - * - * Returned Value: - * None - * - ****************************************************************************/ - -static int esp_ifdown(FAR struct net_driver_s *dev) -{ - FAR struct esp_dev_s *priv = (FAR struct esp_dev_s *)dev->d_private; - irqstate_t flags; - - flags = enter_critical_section(); - - /* Cancel the TX poll timer and TX timeout timers */ - - wd_cancel(&priv->esp_txpoll); - wd_cancel(&priv->esp_txtimeout); - - /* Mark the device "down" */ - - priv->ifup = false; - leave_critical_section(flags); - - return OK; -} - -/**************************************************************************** - * Name: esp_txavail_work + * Name: wlan_txavail_work * * Description: * Perform an out-of-cycle poll on the worker thread. @@ -1055,9 +1004,9 @@ static int esp_ifdown(FAR struct net_driver_s *dev) * ****************************************************************************/ -static void esp_txavail_work(FAR void *arg) +static void wlan_txavail_work(FAR void *arg) { - FAR struct esp_dev_s *priv = (FAR struct esp_dev_s *)arg; + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; /* Lock the network and serialize driver operations if necessary. * NOTE: Serialization is only required in the case where the driver work @@ -1073,14 +1022,113 @@ static void esp_txavail_work(FAR void *arg) { /* Poll the network for new XMIT data */ - esp_dopoll(priv); + wlan_dopoll(priv); } net_unlock(); } /**************************************************************************** - * Name: esp_txavail + * Name: wlan_ifup + * + * Description: + * NuttX Callback: Bring up the Ethernet interface when an IP address is + * provided + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int wlan_ifup(FAR struct net_driver_s *dev) +{ + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; + +#ifdef CONFIG_NET_IPv4 + ninfo("Bringing up: %d.%d.%d.%d\n", + dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24); +#endif +#ifdef CONFIG_NET_IPv6 + winfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2], + dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5], + dev->d_ipv6addr[6], dev->d_ipv6addr[7]); +#endif + + net_lock(); + + if (priv->ifup) + { + net_unlock(); + return OK; + } + +#ifdef CONFIG_NET_ICMPv6 + + /* Set up IPv6 multicast address filtering */ + + wlan_ipv6multicast(priv); +#endif + + wlan_init_buffer(priv); + + /* Set and activate a timer process */ + + wd_start(&priv->txpoll, WLAN_WDDELAY, wlan_poll_expiry, (wdparm_t)priv); + + priv->ifup = true; + + net_unlock(); + + return OK; +} + +/**************************************************************************** + * Name: wlan_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int wlan_ifdown(FAR struct net_driver_s *dev) +{ + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; + + net_lock(); + + if (!priv->ifup) + { + net_unlock(); + return OK; + } + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(&priv->txpoll); + wd_cancel(&priv->txtimeout); + + /* Mark the device "down" */ + + priv->ifup = false; + + net_unlock(); + + return OK; +} + +/**************************************************************************** + * Name: wlan_txavail * * Description: * Driver callback invoked when new TX data is available. This is a @@ -1098,22 +1146,22 @@ static void esp_txavail_work(FAR void *arg) * ****************************************************************************/ -static int esp_txavail(FAR struct net_driver_s *dev) +static int wlan_txavail(FAR struct net_driver_s *dev) { - FAR struct esp_dev_s *priv = (FAR struct esp_dev_s *)dev->d_private; + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; - if (work_available(&priv->esp_pollwork)) + if (work_available(&priv->txwork)) { /* Schedule to serialize the poll on the worker thread. */ - work_queue(ESPWORK, &priv->esp_pollwork, esp_txavail_work, priv, 0); + work_queue(WLAN_WORK, &priv->txwork, wlan_txavail_work, priv, 0); } return OK; } /**************************************************************************** - * Name: esp_addmac + * Name: wlan_addmac * * Description: * NuttX Callback: Add the specified MAC address to the hardware multicast @@ -1129,9 +1177,9 @@ static int esp_txavail(FAR struct net_driver_s *dev) ****************************************************************************/ #if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6) -static int esp_addmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) +static int wlan_addmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) { - FAR struct esp_dev_s *priv = (FAR struct esp_dev_s *)dev->d_private; + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; /* Add the MAC address to the hardware multicast routing table */ @@ -1140,7 +1188,7 @@ static int esp_addmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) #endif /**************************************************************************** - * Name: esp_rmmac + * Name: wlan_rmmac * * Description: * NuttX Callback: Remove the specified MAC address from the @@ -1156,9 +1204,9 @@ static int esp_addmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) ****************************************************************************/ #ifdef CONFIG_NET_MCASTGROUP -static int esp_rmmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) +static int wlan_rmmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) { - FAR struct esp_dev_s *priv = (FAR struct esp_dev_s *)dev->d_private; + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; /* Add the MAC address to the hardware multicast routing table */ @@ -1167,7 +1215,7 @@ static int esp_rmmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) #endif /**************************************************************************** - * Name: esp_ipv6multicast + * Name: wlan_ipv6multicast * * Description: * Configure the IPv6 multicast MAC address. @@ -1181,7 +1229,7 @@ static int esp_rmmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) ****************************************************************************/ #ifdef CONFIG_NET_ICMPv6 -static void esp_ipv6multicast(FAR struct esp_dev_s *priv) +static void wlan_ipv6multicast(FAR struct wlan_priv_s *priv) { FAR struct net_driver_s *dev; uint16_t tmp16; @@ -1202,7 +1250,7 @@ static void esp_ipv6multicast(FAR struct esp_dev_s *priv) mac[0] = 0x33; mac[1] = 0x33; - dev = &priv->esp_dev; + dev = &priv->dev; tmp16 = dev->d_ipv6addr[6]; mac[2] = 0xff; mac[3] = tmp16 >> 8; @@ -1211,10 +1259,10 @@ static void esp_ipv6multicast(FAR struct esp_dev_s *priv) mac[4] = tmp16 & 0xff; mac[5] = tmp16 >> 8; - wlinfo("IPv6 Multicast: %02x:%02x:%02x:%02x:%02x:%02x\n", + ninfo("IPv6 Multicast: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - esp_addmac(dev, mac); + wlan_addmac(dev, mac); #ifdef CONFIG_NET_ICMPv6_AUTOCONF /* Add the IPv6 all link-local nodes Ethernet address. This is the @@ -1222,7 +1270,7 @@ static void esp_ipv6multicast(FAR struct esp_dev_s *priv) * packets. */ - esp_addmac(dev, g_ipv6_ethallnodes.ether_addr_octet); + wlan_addmac(dev, g_ipv6_ethallnodes.ether_addr_octet); #endif /* CONFIG_NET_ICMPv6_AUTOCONF */ #ifdef CONFIG_NET_ICMPv6_ROUTER @@ -1231,13 +1279,13 @@ static void esp_ipv6multicast(FAR struct esp_dev_s *priv) * packets. */ - esp_addmac(dev, g_ipv6_ethallrouters.ether_addr_octet); + wlan_addmac(dev, g_ipv6_ethallrouters.ether_addr_octet); #endif /* CONFIG_NET_ICMPv6_ROUTER */ } #endif /* CONFIG_NET_ICMPv6 */ /**************************************************************************** - * Name: esp_ioctl + * Name: wlan_ioctl * * Description: * Handle network IOCTL commands directed to this device. @@ -1253,8 +1301,9 @@ static void esp_ipv6multicast(FAR struct esp_dev_s *priv) ****************************************************************************/ #ifdef CONFIG_NETDEV_IOCTL -static int esp_ioctl(FAR struct net_driver_s *dev, - int cmd, unsigned long arg) +static int wlan_ioctl(FAR struct net_driver_s *dev, + int cmd, + unsigned long arg) { int ret; struct iw_point *essid; @@ -1273,7 +1322,7 @@ static int esp_ioctl(FAR struct net_driver_s *dev, ret = esp_wifi_notify_subscribe(req->pid, &req->event); if (ret) { - wlerr("ERROR: Failed to subscribe event\n"); + nerr("ERROR: Failed to subscribe event\n"); } } break; @@ -1286,7 +1335,7 @@ static int esp_ioctl(FAR struct net_driver_s *dev, ret = esp_wifi_set_password(ext->key, ext->key_len); if (ret) { - wlerr("ERROR: Failed to set password\n"); + nerr("ERROR: Failed to set password\n"); } } break; @@ -1297,20 +1346,16 @@ static int esp_ioctl(FAR struct net_driver_s *dev, ret = esp_wifi_set_ssid(essid->pointer, essid->length); if (ret) { - wlerr("ERROR: Failed to set SSID\n"); + nerr("ERROR: Failed to set SSID\n"); break; } ret = esp_wifi_connect_internal(); if (ret) { - wlerr("ERROR: Failed to start connecting\n"); + nerr("ERROR: Failed to start connecting\n"); break; } - else - { - g_tx_ready = true; - } } break; case SIOCSIWMODE: @@ -1319,8 +1364,11 @@ static int esp_ioctl(FAR struct net_driver_s *dev, case SIOCSIWAUTH: ret = OK; break; + case SIOCSIWFREQ: + ret = OK; + break; default: - wlerr("ERROR: Unrecognized IOCTL command: %d\n", cmd); + nerr("ERROR: Unrecognized IOCTL command: %d\n", cmd); ret = -ENOTTY; /* Special return value for this case */ break; } @@ -1347,59 +1395,71 @@ static int esp32_net_initialize(unsigned int devno) { int ret; uint8_t eth_mac[6]; - FAR struct esp_dev_s *priv; + FAR struct wlan_priv_s *priv; /* Get the interface structure associated with this interface number. */ - priv = &s_esp32_dev; + priv = &g_wlan_priv; /* Initialize the driver structure */ - memset(priv, 0, sizeof(struct esp_dev_s)); + memset(priv, 0, sizeof(struct wlan_priv_s)); - priv->esp_dev.d_ifup = esp_ifup; /* I/F down callback */ - priv->esp_dev.d_ifdown = esp_ifdown; /* I/F up (new IP address) callback */ - priv->esp_dev.d_txavail = esp_txavail; /* New TX data callback */ + priv->dev.d_ifup = wlan_ifup; /* I/F down callback */ + priv->dev.d_ifdown = wlan_ifdown; /* I/F up (new IP address) callback */ + priv->dev.d_txavail = wlan_txavail; /* New TX data callback */ #ifdef CONFIG_NET_MCASTGROUP - priv->esp_dev.d_addmac = esp_addmac; /* Add multicast MAC address */ - priv->esp_dev.d_rmmac = esp_rmmac; /* Remove multicast MAC address */ + priv->dev.d_addmac = wlan_addmac; /* Add multicast MAC address */ + priv->dev.d_rmmac = wlan_rmmac; /* Remove multicast MAC address */ #endif #ifdef CONFIG_NETDEV_IOCTL - priv->esp_dev.d_ioctl = esp_ioctl; /* Handle network IOCTL commands */ + priv->dev.d_ioctl = wlan_ioctl; /* Handle network IOCTL commands */ #endif /* Used to recover private state from dev */ - priv->esp_dev.d_private = (void *)&s_esp32_dev; + priv->dev.d_private = (void *)&g_wlan_priv; /* Create a watchdog for timing polling for and timing of transmissions */ - /* Initialize network stack interface buffer */ + esp_wifi_sta_read_mac(eth_mac); - priv->esp_dev.d_buf = NULL; - g_tx_ready = false; + memcpy(priv->dev.d_mac.ether.ether_addr_octet, eth_mac, sizeof(eth_mac)); - assert(esp_wifi_adapter_init() == 0); - esp_wifi_sta_register_recv_cb(esp_sta_input); - - /* Register the device with the OS so that socket IOCTLs can be performed */ - - esp_wifi_sta_read_mac(priv->esp_dev.d_mac.ether.ether_addr_octet); - memcpy(eth_mac, priv->esp_dev.d_mac.ether.ether_addr_octet, - sizeof(eth_mac)); - wlinfo("%02X:%02X:%02X:%02X:%02X:%02X \r\n", eth_mac[0], eth_mac[1], - eth_mac[2], eth_mac[3], eth_mac[4], eth_mac[5]); + ninfo("%02X:%02X:%02X:%02X:%02X:%02X \r\n", + eth_mac[0], eth_mac[1], eth_mac[2], + eth_mac[3], eth_mac[4], eth_mac[5]); /* Put the interface in the down state. */ - ret = esp_ifdown(&priv->esp_dev); - if (ret < 0) + wlan_ifdown(&priv->dev); + + ret = netdev_register(&priv->dev, NET_LL_IEEE80211); + if (ret) { - wlerr("ERROR: Initialization of Ethernet block failed: %d\n", ret); + nerr("ERROR: Initialization of Ethernet block failed: %d\n", ret); return ret; } - (void)netdev_register(&s_esp32_dev.esp_dev, NET_LL_IEEE80211); + ret = esp_wifi_adapter_init(); + if (ret) + { + nerr("ERROR: Initialize WiFi adapter error: %d\n", ret); + netdev_unregister(&priv->dev); + return ret; + } + + ret = esp_wifi_sta_register_recv_cb(wlan_rx_done); + if (ret) + { + DEBUGASSERT(0); + } + + ret = esp_wifi_sta_register_txdone_cb(wlan_tx_done); + if (ret) + { + DEBUGASSERT(0); + } return OK; } @@ -1409,10 +1469,10 @@ static int esp32_net_initialize(unsigned int devno) ****************************************************************************/ /**************************************************************************** - * Name: esp32_wlan_initialize + * Name: esp32_wlan_sta_initialize * * Description: - * Initialize the esp32 wlan driver + * Initialize the esp32 WLAN station netcard driver * * Input Parameters: * None @@ -1422,9 +1482,9 @@ static int esp32_net_initialize(unsigned int devno) * ****************************************************************************/ -int esp32_wlan_initialize(void) +int esp32_wlan_sta_initialize(void) { - return esp32_net_initialize(STA_DEVNO); + return esp32_net_initialize(WLAN_STA_DEVNO); } #endif /* CONFIG_ESP32_WIRELESS */ diff --git a/arch/xtensa/src/esp32/esp32_wlan.h b/arch/xtensa/src/esp32/esp32_wlan.h index f9633a98d0..ce492272bc 100644 --- a/arch/xtensa/src/esp32/esp32_wlan.h +++ b/arch/xtensa/src/esp32/esp32_wlan.h @@ -45,10 +45,10 @@ extern "C" ****************************************************************************/ /**************************************************************************** - * Name: esp32_wlan_initialize + * Name: esp32_wlan_sta_initialize * * Description: - * Initialize the esp32 wlan driver + * Initialize the esp32 WLAN station netcard driver * * Input Parameters: * None @@ -56,11 +56,9 @@ extern "C" * Returned Value: * OK on success; Negated errno on failure. * - * Assumptions: - * ****************************************************************************/ -int esp32_wlan_initialize(void); +int esp32_wlan_sta_initialize(void); #endif /* CONFIG_ESP32_WIRELESS */ #ifdef __cplusplus diff --git a/arch/xtensa/src/esp32/hardware/esp32_dport.h b/arch/xtensa/src/esp32/hardware/esp32_dport.h index d5a74becb1..173c6b0257 100644 --- a/arch/xtensa/src/esp32/hardware/esp32_dport.h +++ b/arch/xtensa/src/esp32/hardware/esp32_dport.h @@ -1223,6 +1223,7 @@ /* DPORT_WIFI_RST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ #define DPORT_EMAC_RST_EN (BIT(7)) +#define DPORT_MAC_RST_EN (BIT(2)) #define DPORT_WIFI_RST 0xFFFFFFFF #define DPORT_WIFI_RST_M ((DPORT_WIFI_RST_V)<<(DPORT_WIFI_RST_S)) diff --git a/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c index d3caff86d7..abdbb7ca71 100644 --- a/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c +++ b/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c @@ -207,7 +207,7 @@ int esp32_bringup(void) #endif #ifdef CONFIG_NET - ret = esp32_wlan_initialize(); + ret = esp32_wlan_sta_initialize(); if (ret) { syslog(LOG_ERR, "ERROR: Failed to initialize WiFi\n");