diff --git a/arch/xtensa/include/esp32s3/irq.h b/arch/xtensa/include/esp32s3/irq.h index 1d6016b6792..7f6f49a14c5 100644 --- a/arch/xtensa/include/esp32s3/irq.h +++ b/arch/xtensa/include/esp32s3/irq.h @@ -452,6 +452,7 @@ #define ESP32S3_CPUINT_NMISET 0x00004000 #define ESP32S3_CPUINT_MAC 0 +#define ESP32S3_CPUINT_MAC_NMI 1 #define ESP32S3_CPUINT_TIMER0 6 #define ESP32S3_CPUINT_SOFTWARE0 7 #define ESP32S3_CPUINT_PROFILING 11 diff --git a/arch/xtensa/src/esp32s3/.gitignore b/arch/xtensa/src/esp32s3/.gitignore index 2d7ab9d716b..adabb982b4c 100644 --- a/arch/xtensa/src/esp32s3/.gitignore +++ b/arch/xtensa/src/esp32s3/.gitignore @@ -1 +1,2 @@ /esp-nuttx-bootloader +/esp-wireless-drivers-3rdparty diff --git a/arch/xtensa/src/esp32s3/Kconfig b/arch/xtensa/src/esp32s3/Kconfig index 31b092b380d..17cc7fe4401 100644 --- a/arch/xtensa/src/esp32s3/Kconfig +++ b/arch/xtensa/src/esp32s3/Kconfig @@ -334,6 +334,24 @@ config ESP32S3_UART2 select UART2_SERIALDRIVER select ARCH_HAVE_SERIAL_TERMIOS +config ESP32S3_WIRELESS + bool + default n + select NET + select ARCH_PHY_INTERRUPT + select ESP32S3_RNG + select ESP32S3_RT_TIMER + select ESP32S3_TIMER0 + ---help--- + Enable Wireless support + +config ESP32S3_WIFI + bool "Wi-Fi" + default n + select ESP32S3_WIRELESS + ---help--- + Enable Wi-Fi support + config ESP32S3_I2C0 bool "I2C 0" default n @@ -770,6 +788,158 @@ config ESP32S3_I2CTIMEOMS endmenu # I2C Configuration +menu "Wi-Fi Configuration" + depends on ESP32S3_WIFI + +menu "ESP WPA-Supplicant" + +config WPA_WAPI_PSK + bool "Enable WAPI PSK support" + default n + ---help--- + Select this option to enable WAPI-PSK + which is a Chinese National Standard Encryption for Wireless LANs (GB 15629.11-2003). + +config WPA_SUITE_B_192 + bool "Enable NSA suite B support with 192-bit key" + default n + select ESP_WIFI_GCMP_SUPPORT + select ESP_WIFI_GMAC_SUPPORT + ---help--- + Select this option to enable 192-bit NSA suite-B. + This is necessary to support WPA3 192-bit security. + +config ESP_WPA_DEBUG_PRINT + bool "Print debug messages from Espressif's WPA Supplicant" + default n + ---help--- + Select this option to print logging information from WPA supplicant, + this includes handshake information and key hex dumps depending + on the project logging level. + + Enabling this could increase the build size ~60kb + depending on the project logging level. + +endmenu # ESP WPA-Supplicant + +choice + prompt "ESP32S3 Wi-Fi mode" + default ESP32S3_WIFI_STATION + +config ESP32S3_WIFI_STATION + bool "Station mode" + +endchoice # ESP32S3 Wi-Fi mode + +config ESP32S3_WIFI_STATIC_RXBUF_NUM + int "Wi-Fi static RX buffer number" + default 10 + +config ESP32S3_WIFI_DYNAMIC_RXBUF_NUM + int "Wi-Fi dynamic RX buffer number" + default 32 + +config ESP32S3_WIFI_DYNAMIC_TXBUF_NUM + int "Wi-Fi dynamic TX buffer number" + default 32 + +config ESP32S3_WIFI_TX_AMPDU + bool "Wi-Fi TX AMPDU" + default y + +config ESP32S3_WIFI_RX_AMPDU + bool "Wi-Fi RX AMPDU" + default y + +config ESP32S3_WIFI_RXBA_AMPDU_WZ + int "Wi-Fi RX BA AMPDU windown size" + default 6 + +config ESP_WIFI_GCMP_SUPPORT + bool "WiFi GCMP Support(GCMP128 and GCMP256)" + default n + ---help--- + Select this option to enable GCMP support. GCMP support is compulsory for WiFi Suite-B support. + +config ESP_WIFI_GMAC_SUPPORT + bool "WiFi GMAC Support(GMAC128 and GMAC256)" + default n + ---help--- + Select this option to enable GMAC support. GMAC support is compulsory for WiFi 192-bit certification. + +config ESP32S3_WIFI_CONNECT_TIMEOUT + int "Connect timeout in second" + default 10 + ---help--- + Max waiting time of connecting to AP. + +config ESP32S3_WIFI_SCAN_RESULT_SIZE + int "Scan result buffer" + default 4096 + ---help--- + Maximum scan result buffer size. + +config ESP32S3_WIFI_SAVE_PARAM + bool "Save Wi-Fi Parameters" + default n + depends on ESP32S3_SPIFLASH + ---help--- + If you enable this option, Wi-Fi adapter parameters will be saved + into the file system instead of computing them each time. + + These parameters mainly contains: + - SSID + - Password + - BSSID + - PMK(compute when connecting) + - Author mode + - MAC address + - Wi-Fi hardware configuration parameters + +config ESP32S3_WIFI_FS_MOUNTPT + string "Wi-Fi parameters mount point" + default "/mnt/esp/wifi" + depends on ESP32S3_WIFI_SAVE_PARAM + ---help--- + Mount point of Wi-Fi storage file system. + +config ESP32S3_WIFI_MTD_ENCRYPT + bool "Encrypt Wi-Fi MTD partition" + default y + depends on ESP32S3_SECURE_FLASH_ENC_ENABLED + +config ESP32S3_WIFI_MTD_OFFSET + hex "Wi-Fi MTD partition offset" + default 0x280000 if !ESP32S3_HAVE_OTA_PARTITION + default 0x350000 if ESP32S3_HAVE_OTA_PARTITION + depends on ESP32S3_WIFI_SAVE_PARAM + ---help--- + This is the base address of the Wi-Fi MTD partition. + +config ESP32S3_WIFI_MTD_SIZE + hex "Wi-Fi MTD partition size" + default 0xb0000 + depends on ESP32S3_WIFI_SAVE_PARAM + ---help--- + This is the size of the Wi-Fi MTD partition. + +config ESP32S3_WIFI_STA_DISCONNECT_PM + bool "Power Management for station when disconnected" + default n + ---help--- + Select this option to enable power management for station when disconnected. + Chip will do modem-sleep when RF module is not in use anymore. + +config EXAMPLE_WIFI_LISTEN_INTERVAL + int "Wi-Fi listen interval" + default 3 + ---help--- + Interval for station to listen to beacon from AP. The unit of listen interval is one beacon interval. + For example, if beacon interval is 100 ms and listen interval is 3, the interval for station to listen + to beacon is 300 ms. + +endmenu # ESP32S3_WIFI + menu "Timer/Counter Configuration" depends on ESP32S3_TIMER diff --git a/arch/xtensa/src/esp32s3/Make.defs b/arch/xtensa/src/esp32s3/Make.defs index e0f8c11626f..941ff26a578 100644 --- a/arch/xtensa/src/esp32s3/Make.defs +++ b/arch/xtensa/src/esp32s3/Make.defs @@ -125,3 +125,222 @@ ifeq ($(CONFIG_ESP32S3_TOUCH),y) CHIP_CSRCS += esp32s3_touch.c endif +ifeq ($(CONFIG_ESP32S3_WIRELESS),y) +WIRELESS_DRV_REPO = esp-wireless-drivers-3rdparty +WIRELESS_DRV_BRANCH = release/v2.0 +WIRELESS_DRV_URL = https://github.com/espressif/esp-wireless-drivers-3rdparty.git +WIRELESS_DRV_PATH = $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(WIRELESS_DRV_REPO) + +chip/$(WIRELESS_DRV_REPO): + $(Q) echo "Cloning: ESP Wireless Drivers" + $(Q) git clone --depth=1 --branch $(WIRELESS_DRV_BRANCH) $(WIRELESS_DRV_URL) chip/$(WIRELESS_DRV_REPO) + +context:: chip/$(WIRELESS_DRV_REPO) + $(Q) echo "ESP Wireless Drivers: ${WIRELESS_DRV_BRANCH}" + $(Q) git -C chip/$(WIRELESS_DRV_REPO)/esp-idf reset --hard + $(Q) echo "ESP Wireless Drivers: initialize submodule esp-idf" + $(Q) git -C chip/$(WIRELESS_DRV_REPO) submodule update --init --depth=1 esp-idf + $(Q) echo "ESP Wireless Drivers: initialize submodule mbedtls, esp_phy and esp_phy from esp-idf" + $(Q) git -C chip/$(WIRELESS_DRV_REPO)/esp-idf submodule update --init --depth=1 components/mbedtls/mbedtls components/esp_phy/lib components/esp_wifi/lib + $(Q) git -C chip/$(WIRELESS_DRV_REPO)/esp-idf/components/mbedtls/mbedtls reset --hard + $(Q) echo "ESP Wireless Drivers: apply patches for NuttX" + $(Q) cd chip/$(WIRELESS_DRV_REPO)/esp-idf && git apply ../nuttx/patches/esp-idf/*.patch + $(Q) cd chip/$(WIRELESS_DRV_REPO)/esp-idf/components/mbedtls/mbedtls && git apply ../../../../nuttx/patches/esp-idf/submodules/mbedtls/*.patch + +distclean:: + $(call DELDIR, chip/$(WIRELESS_DRV_REPO)) + +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)nuttx$(DELIM)include$(DELIM)esp32s3) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)esp_wifi$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)esp_phy$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)esp_phy$(DELIM)esp32s3$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)esp_common$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)esp_event$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)nvs_flash$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)esp_system$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)esp_hw_support$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)esp_timer$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)esp_rom$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)esp_rom$(DELIM)include$(DELIM)esp32s3) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)soc$(DELIM)esp32s3$(DELIM)include) + +EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)esp_phy$(DELIM)lib$(DELIM)esp32s3 +EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)esp_wifi$(DELIM)lib$(DELIM)esp32s3 + +EXTRA_LIBS += -lphy + +# Wireless interfaces. + +CHIP_CSRCS += esp32s3_wireless.c +endif + +ifeq ($(CONFIG_ESP32S3_WIFI),y) +CHIP_CSRCS += esp32s3_wlan.c esp32s3_wifi_utils.c esp32s3_wifi_adapter.c +EXTRA_LIBS += -lcore -lnet80211 -lpp + +ifeq ($(CONFIG_WPA_WAPI_PSK),y) +EXTRA_LIBS += -lwapi +endif + +## ESP-IDF's mbedTLS + +VPATH += chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)mbedtls$(DELIM)mbedtls$(DELIM)library + +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)mbedtls$(DELIM)mbedtls$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)mbedtls$(DELIM)mbedtls$(DELIM)library) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)mbedtls$(DELIM)port$(DELIM)include) + +### Define Espressif's configs for mbedTLS + +CFLAGS += ${DEFINE_PREFIX}MBEDTLS_CONFIG_FILE="" + +CHIP_CSRCS += aes.c +CHIP_CSRCS += bignum.c +CHIP_CSRCS += constant_time.c +CHIP_CSRCS += ctr_drbg.c +CHIP_CSRCS += ecp.c +CHIP_CSRCS += ecp_curves.c +CHIP_CSRCS += entropy.c +CHIP_CSRCS += md.c +CHIP_CSRCS += pkcs5.c +CHIP_CSRCS += platform.c +CHIP_CSRCS += platform_util.c +CHIP_CSRCS += sha1.c +CHIP_CSRCS += sha256.c +CHIP_CSRCS += sha512.c + +VPATH += chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)mbedtls$(DELIM)port + +CHIP_CSRCS += esp_hardware.c +CHIP_CSRCS += esp_mem.c +CHIP_CSRCS += esp_timing.c + +VPATH += chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)esp-idf$(DELIM)components$(DELIM)mbedtls$(DELIM)port$(DELIM)md + +CHIP_CSRCS += esp_md.c + +## WPA Supplicant + +WIFI_WPA_SUPPLICANT = chip$(DELIM)$(WIRELESS_DRV_REPO)$(DELIM)esp-idf$(DELIM)components$(DELIM)wpa_supplicant + +CFLAGS += ${DEFINE_PREFIX}CONFIG_CRYPTO_MBEDTLS +CFLAGS += ${DEFINE_PREFIX}CONFIG_ECC +CFLAGS += ${DEFINE_PREFIX}CONFIG_IEEE80211W +CFLAGS += ${DEFINE_PREFIX}CONFIG_WPA3_SAE +CFLAGS += ${DEFINE_PREFIX}EAP_PEER_METHOD +CFLAGS += ${DEFINE_PREFIX}ESPRESSIF_USE +CFLAGS += ${DEFINE_PREFIX}ESP_PLATFORM +CFLAGS += ${DEFINE_PREFIX}ESP_SUPPLICANT +CFLAGS += ${DEFINE_PREFIX}IEEE8021X_EAPOL +CFLAGS += ${DEFINE_PREFIX}USE_WPA2_TASK +CFLAGS += ${DEFINE_PREFIX}__ets__ + +ifeq ($(CONFIG_ESP_WIFI_GCMP_SUPPORT),y) +CFLAGS += ${DEFINE_PREFIX}CONFIG_GCMP +endif + +ifeq ($(CONFIG_ESP_WIFI_GMAC_SUPPORT),y) +CFLAGS += ${DEFINE_PREFIX}CONFIG_GMAC +endif + +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)src) + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)ap + +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)ap) + +CHIP_CSRCS += ap_config.c +CHIP_CSRCS += sta_info.c +CHIP_CSRCS += wpa_auth.c +CHIP_CSRCS += wpa_auth_ie.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)common + +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)common) + +CHIP_CSRCS += dragonfly.c +CHIP_CSRCS += sae.c +CHIP_CSRCS += wpa_common.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)crypto + +CHIP_CSRCS += aes-ccm.c +CHIP_CSRCS += aes-gcm.c +CHIP_CSRCS += aes-omac1.c +CHIP_CSRCS += aes-unwrap.c +CHIP_CSRCS += aes-wrap.c +CHIP_CSRCS += ccmp.c +CHIP_CSRCS += crypto_ops.c +CHIP_CSRCS += des-internal.c +CHIP_CSRCS += dh_groups.c +CHIP_CSRCS += rc4.c +CHIP_CSRCS += sha1-prf.c +CHIP_CSRCS += sha256-kdf.c +CHIP_CSRCS += sha256-prf.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)eap_peer + +CHIP_CSRCS += chap.c +CHIP_CSRCS += eap.c +CHIP_CSRCS += eap_common.c +CHIP_CSRCS += eap_mschapv2.c +CHIP_CSRCS += eap_peap.c +CHIP_CSRCS += eap_peap_common.c +CHIP_CSRCS += eap_tls.c +CHIP_CSRCS += eap_tls_common.c +CHIP_CSRCS += eap_ttls.c +CHIP_CSRCS += mschapv2.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)rsn_supp + +CHIP_CSRCS += pmksa_cache.c +CHIP_CSRCS += wpa.c +CHIP_CSRCS += wpa_ie.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)utils + +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)utils) + +CHIP_CSRCS += base64.c +CHIP_CSRCS += bitfield.c +CHIP_CSRCS += common.c +CHIP_CSRCS += ext_password.c +CHIP_CSRCS += json.c +CHIP_CSRCS += uuid.c +CHIP_CSRCS += wpa_debug.c +CHIP_CSRCS += wpabuf.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)port + +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)port$(DELIM)include) + +CHIP_CSRCS += eloop.c +CHIP_CSRCS += os_xtensa.c + +## ESP Supplicant (Espressif's WPA supplicant extension) + +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)esp_supplicant$(DELIM)include) + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)esp_supplicant$(DELIM)src + +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)esp_supplicant$(DELIM)src) + +CHIP_CSRCS += esp_common.c +CHIP_CSRCS += esp_hostap.c +CHIP_CSRCS += esp_wpa2.c +CHIP_CSRCS += esp_wpa3.c +CHIP_CSRCS += esp_wpa_main.c +CHIP_CSRCS += esp_wpas_glue.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)esp_supplicant$(DELIM)src$(DELIM)crypto + +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)crypto) + +CHIP_CSRCS += crypto_mbedtls.c +CHIP_CSRCS += crypto_mbedtls-bignum.c +CHIP_CSRCS += crypto_mbedtls-ec.c +CHIP_CSRCS += crypto_mbedtls-rsa.c +CHIP_CSRCS += tls_mbedtls.c + +endif diff --git a/arch/xtensa/src/esp32s3/esp32s3_irq.c b/arch/xtensa/src/esp32s3/esp32s3_irq.c index 65d29cc6e4f..0e8abdf90a5 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_irq.c +++ b/arch/xtensa/src/esp32s3/esp32s3_irq.c @@ -107,6 +107,12 @@ #define ESP32S3_MAX_PRIORITY 5 #define ESP32S3_PRIO_INDEX(p) ((p) - ESP32S3_MIN_PRIORITY) +#ifdef CONFIG_ESP32S3_WIFI +# define ESP32S3_WIFI_RESERVE_INT (1 << ESP32S3_CPUINT_MAC) +#else +# define ESP32S3_WIFI_RESERVE_INT 0 +#endif + /**************************************************************************** * Public Data ****************************************************************************/ @@ -152,7 +158,9 @@ static uint32_t g_intenable[CONFIG_SMP_NCPUS]; * devices. */ -static uint32_t g_cpu0_freeints = ESP32S3_CPUINT_PERIPHSET; +static uint32_t g_cpu0_freeints = ESP32S3_CPUINT_PERIPHSET & + ~ESP32S3_WIFI_RESERVE_INT; + #ifdef CONFIG_SMP static uint32_t g_cpu1_freeints = ESP32S3_CPUINT_PERIPHSET; #endif @@ -425,10 +433,21 @@ void up_irqinitialize(void) g_irqmap[XTENSA_IRQ_SWINT] = IRQ_MKMAP(0, ESP32S3_CPUINT_SOFTWARE1); g_irqmap[XTENSA_IRQ_SWINT] = IRQ_MKMAP(1, ESP32S3_CPUINT_SOFTWARE1); +#ifdef CONFIG_ESP32S3_WIFI + g_irqmap[ESP32S3_IRQ_MAC] = IRQ_MKMAP(0, ESP32S3_CPUINT_MAC); +#endif + /* Initialize CPU interrupts */ esp32s3_cpuint_initialize(); + /* Reserve CPU0 interrupt for some special drivers */ + +#ifdef CONFIG_ESP32S3_WIFI + g_cpu0_intmap[ESP32S3_CPUINT_MAC] = CPUINT_ASSIGN(ESP32S3_IRQ_MAC); + xtensa_enable_cpuint(&g_intenable[0], 1 << ESP32S3_CPUINT_MAC); +#endif + #ifdef CONFIG_SMP /* Attach and enable the inter-CPU interrupt */ diff --git a/arch/xtensa/src/esp32s3/esp32s3_rng.c b/arch/xtensa/src/esp32s3/esp32s3_rng.c index 3671a521ec4..6164b40cf95 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_rng.c +++ b/arch/xtensa/src/esp32s3/esp32s3_rng.c @@ -220,7 +220,7 @@ void devrandom_register(void) #ifdef CONFIG_DEV_URANDOM_ARCH void devurandom_register(void) { - register_driver("dev/urandom", &g_rngops, 0444, NULL); + register_driver("/dev/urandom", &g_rngops, 0444, NULL); } #endif diff --git a/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c b/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c new file mode 100644 index 00000000000..d36a54cd512 --- /dev/null +++ b/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c @@ -0,0 +1,5675 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xtensa.h" +#include "xtensa_attr.h" +#include "hardware/esp32s3_system.h" +#include "hardware/esp32s3_rtccntl.h" +#include "hardware/esp32s3_syscon.h" +#include "hardware/esp32s3_soc.h" +#include "esp32s3_irq.h" +#include "esp32s3_wireless.h" +#include "esp32s3_wifi_adapter.h" +#include "esp32s3_rt_timer.h" +#include "esp32s3_wifi_utils.h" +#include "esp32s3_wlan.h" + +#ifdef CONFIG_PM +# include "esp32s3_pm.h" +#endif + +#include "espidf_wifi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define PHY_RF_MASK ((1 << PHY_BT_MODULE) | (1 << PHY_WIFI_MODULE)) + +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM +# define NVS_FS_PREFIX CONFIG_ESP32S3_WIFI_FS_MOUNTPT +# define NVS_DIR_BASE NVS_FS_PREFIX"/wifi." +# define NVS_FILE_MODE 0777 +#endif + +#define WIFI_CONNECT_TIMEOUT CONFIG_ESP32S3_WIFI_CONNECT_TIMEOUT + +#define TIMER_INITIALIZED_VAL (0x5aa5a55a) + +#define ESP_WIFI_11B_MAX_BITRATE 11 +#define ESP_WIFI_11G_MAX_BITRATE 54 +#define ESP_WIFI_11N_MCS7_HT20_BITRATE 72 +#define ESP_WIFI_11N_MCS7_HT40_BITRATE 150 + +#ifndef CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL +#define CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL 3 +#endif + +#define DEFAULT_LISTEN_INTERVAL CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL + +#define RTC_CLK_CAL_FRACT 19 //!< Number of fractional bits in values returned by rtc_clk_cal + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Wi-Fi Station state */ + +enum wifi_sta_state +{ + WIFI_STA_STATE_NULL, + WIFI_STA_STATE_START, + WIFI_STA_STATE_CONNECT, + WIFI_STA_STATE_DISCONNECT, + WIFI_STA_STATE_STOP +}; + +/* Wi-Fi interrupt adapter private data */ + +struct irq_adpt +{ + void (*func)(void *arg); /* Interrupt callback function */ + void *arg; /* Interrupt private data */ +}; + +/* Wi-Fi message queue private data */ + +struct mq_adpt +{ + struct file mq; /* Message queue handle */ + uint32_t msgsize; /* Message size */ + char name[16]; /* Message queue name */ +}; + +/* Wi-Fi time private data */ + +struct time_adpt +{ + time_t sec; /* Second value */ + suseconds_t usec; /* Micro second value */ +}; + +/* Wi-Fi timer private data */ + +struct timer_adpt +{ + struct wdog_s wdog; /* Timer handle */ + struct work_s work; /* Work private data */ + bool repeat; /* Flags indicate if it is cycle */ + uint32_t delay; /* Timeout ticks */ + + /* Timer callback function */ + + void (*func)(void *priv); + void *priv; /* Timer private data */ +}; + +/* Wi-Fi event private data */ + +struct evt_adpt +{ + sq_entry_t entry; /* Sequence entry */ + int32_t id; /* Event ID */ + uint8_t buf[0]; /* Event private data */ +}; + +/* Wi-Fi event notification private data */ + +struct wifi_notify +{ + bool assigned; /* Flag indicate if it is used */ + pid_t pid; /* Signal's target thread PID */ + struct sigevent event; /* Signal event private data */ + struct sigwork_s work; /* Signal work private data */ +}; + +/* Wi-Fi NVS private data */ + +struct nvs_adpt +{ + char *index_name; +}; + +/**************************************************************************** + * 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 esp32s3_ints_on(uint32_t mask); +static void esp32s3_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 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); +static int32_t esp_semphr_give(void *semphr); +static void *esp_thread_semphr_get(void); +static void *esp_mutex_create(void); +static void *esp_recursive_mutex_create(void); +static void esp_mutex_delete(void *mutex_data); +static int32_t esp_mutex_lock(void *mutex_data); +static int32_t esp_mutex_unlock(void *mutex_data); +static void *esp_queue_create(uint32_t queue_len, uint32_t item_size); +static void esp_queue_delete(void *queue); +static int32_t esp_queue_send(void *queue, void *item, + uint32_t block_time_tick); +static int32_t esp_queue_send_from_isr(void *queue, void *item, void *hptw); +static int32_t esp_queue_send_to_back(void *queue, void *item, + uint32_t block_time_tick); +static int32_t esp_queue_send_to_front(void *queue, void *item, + uint32_t block_time_tick); +static int32_t esp_queue_recv(void *queue, void *item, + uint32_t block_time_tick); +static uint32_t esp_queue_msg_waiting(void *queue); +static void *esp_event_group_create(void); +static void esp_event_group_delete(void *event); +static uint32_t esp_event_group_set_bits(void *event, uint32_t bits); +static uint32_t esp_event_group_clear_bits(void *event, uint32_t bits); +static uint32_t esp_event_group_wait_bits(void *event, + uint32_t bits_to_wait_for, + int32_t clear_on_exit, + int32_t wait_for_all_bits, + uint32_t block_time_tick); +static int32_t esp_task_create_pinned_to_core(void *task_func, + const char *name, + uint32_t stack_depth, + void *param, + uint32_t prio, + void *task_handle, + uint32_t core_id); +static int32_t esp_task_create(void *task_func, const char *name, + uint32_t stack_depth, void *param, + uint32_t prio, void *task_handle); +static void esp_task_delete(void *task_handle); +static void esp_task_delay(uint32_t tick); +static int32_t esp_task_ms_to_tick(uint32_t ms); +static void *esp_task_get_current_task(void); +static int32_t esp_task_get_max_priority(void); +static void *esp_malloc(uint32_t size); +static void esp_free(void *ptr); +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 void wifi_apb80m_request(void); +static void wifi_apb80m_release(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 esp32s3_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 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, + int8_t *out_value); +static int32_t esp_nvs_set_u8(uint32_t handle, const char *key, + uint8_t value); +static int32_t esp_nvs_get_u8(uint32_t handle, const char *key, + uint8_t *out_value); +static int32_t esp_nvs_set_u16(uint32_t handle, const char *key, + uint16_t value); +static int32_t esp_nvs_get_u16(uint32_t handle, const char *key, + uint16_t *out_value); +static int32_t esp_nvs_open(const char *name, uint32_t open_mode, + uint32_t *out_handle); +static void esp_nvs_close(uint32_t handle); +static int32_t esp_nvs_commit(uint32_t handle); +static int32_t esp_nvs_set_blob(uint32_t handle, const char *key, + const void *value, size_t length); +static int32_t esp_nvs_get_blob(uint32_t handle, const char *key, + void *out_value, size_t *length); +static int32_t esp_nvs_erase_key(uint32_t handle, const char *key); +static int32_t esp_get_random(uint8_t *buf, size_t len); +static int32_t esp_get_time(void *t); +static uint32_t esp_clk_slowclk_cal_get_wrapper(void); +static void esp_log_writev(uint32_t level, const char *tag, + const char *format, va_list args) + printf_like(3, 0); +static void *esp_malloc_internal(size_t size); +static void *esp_realloc_internal(void *ptr, size_t size); +static void *esp_calloc_internal(size_t n, size_t size); +static void *esp_zalloc_internal(size_t size); +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 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); +static int wifi_coex_register_start_cb_wrapper(int (* cb)(void)); + +/**************************************************************************** + * Public Functions declaration + ****************************************************************************/ + +int64_t esp_timer_get_time(void); +void esp_fill_random(void *buf, size_t len); +void esp_log_write(uint32_t level, const char *tag, const char *format, ...) + printf_like(3, 4); +uint32_t esp_log_timestamp(void); +uint8_t esp_crc8(const uint8_t *p, uint32_t len); +void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Wi-Fi event private data */ + +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 mutex_t g_wifiexcl_lock = NXMUTEX_INITIALIZER; + +/* Wi-Fi adapter reference */ + +static int g_wifi_ref; + +#ifdef ESP32S3_WLAN_HAS_STA + +/* If reconnect automatically */ + +static bool g_sta_reconnect; + +/* If Wi-Fi sta starts */ + +static bool g_sta_started; + +/* If Wi-Fi sta connected */ + +static bool g_sta_connected; + +/* Wi-Fi station TX done callback function */ + +static wifi_txdone_cb_t g_sta_txdone_cb; +#endif /* ESP32S3_WLAN_HAS_STA */ + +/* Device specific lock */ + +static spinlock_t g_lock; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Wi-Fi OS adapter data */ + +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 = esp32s3_ints_on, + ._ints_off = esp32s3_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, + ._wifi_int_restore = esp_wifi_int_restore, + ._task_yield_from_isr = esp_task_yield_from_isr, + ._semphr_create = esp_semphr_create, + ._semphr_delete = esp_semphr_delete, + ._semphr_take = esp_semphr_take, + ._semphr_give = esp_semphr_give, + ._wifi_thread_semphr_get = esp_thread_semphr_get, + ._mutex_create = esp_mutex_create, + ._recursive_mutex_create = esp_recursive_mutex_create, + ._mutex_delete = esp_mutex_delete, + ._mutex_lock = esp_mutex_lock, + ._mutex_unlock = esp_mutex_unlock, + ._queue_create = esp_queue_create, + ._queue_delete = esp_queue_delete, + ._queue_send = esp_queue_send, + ._queue_send_from_isr = esp_queue_send_from_isr, + ._queue_send_to_back = esp_queue_send_to_back, + ._queue_send_to_front = esp_queue_send_to_front, + ._queue_recv = esp_queue_recv, + ._queue_msg_waiting = esp_queue_msg_waiting, + ._event_group_create = esp_event_group_create, + ._event_group_delete = esp_event_group_delete, + ._event_group_set_bits = esp_event_group_set_bits, + ._event_group_clear_bits = esp_event_group_clear_bits, + ._event_group_wait_bits = esp_event_group_wait_bits, + ._task_create_pinned_to_core = esp_task_create_pinned_to_core, + ._task_create = esp_task_create, + ._task_delete = esp_task_delete, + ._task_delay = esp_task_delay, + ._task_ms_to_tick = esp_task_ms_to_tick, + ._task_get_current_task = esp_task_get_current_task, + ._task_get_max_priority = esp_task_get_max_priority, + ._malloc = esp_malloc, + ._free = esp_free, + ._event_post = esp_event_post, + ._get_free_heap_size = esp_get_free_heap_size, + ._rand = esp_rand, + ._dport_access_stall_other_cpu_start_wrap = + esp_dport_access_stall_other_cpu_start, + ._dport_access_stall_other_cpu_end_wrap = + esp_dport_access_stall_other_cpu_end, + ._wifi_apb80m_request = wifi_apb80m_request, + ._wifi_apb80m_release = wifi_apb80m_release, + ._phy_disable = esp32s3_phy_disable, + ._phy_enable = esp32s3_phy_enable, + ._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 = esp32s3_timer_done, + ._timer_setfn = esp_timer_setfn, + ._timer_arm_us = esp_timer_arm_us, + ._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, + ._nvs_set_u8 = esp_nvs_set_u8, + ._nvs_get_u8 = esp_nvs_get_u8, + ._nvs_set_u16 = esp_nvs_set_u16, + ._nvs_get_u16 = esp_nvs_get_u16, + ._nvs_open = esp_nvs_open, + ._nvs_close = esp_nvs_close, + ._nvs_commit = esp_nvs_commit, + ._nvs_set_blob = esp_nvs_set_blob, + ._nvs_get_blob = esp_nvs_get_blob, + ._nvs_erase_key = esp_nvs_erase_key, + ._get_random = esp_get_random, + ._get_time = esp_get_time, + ._random = esp_random_ulong, + ._slowclk_cal_get = esp_clk_slowclk_cal_get_wrapper, + ._log_write = esp_log_write, + ._log_writev = esp_log_writev, + ._log_timestamp = esp_log_timestamp, + ._malloc_internal = esp_malloc_internal, + ._realloc_internal = esp_realloc_internal, + ._calloc_internal = esp_calloc_internal, + ._zalloc_internal = esp_zalloc_internal, + ._wifi_malloc = esp_wifi_malloc, + ._wifi_realloc = esp_wifi_realloc, + ._wifi_calloc = esp_wifi_calloc, + ._wifi_zalloc = esp_wifi_zalloc, + ._wifi_create_queue = esp_wifi_create_queue, + ._wifi_delete_queue = esp_wifi_delete_queue, + ._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, + ._coex_register_start_cb = wifi_coex_register_start_cb_wrapper, + ._magic = ESP_WIFI_OS_ADAPTER_MAGIC, +}; + +/* Wi-Fi feature capacity data */ + +uint64_t g_wifi_feature_caps = CONFIG_FEATURE_WPA3_SAE_BIT; + +/* Wi-Fi TAG string data */ + +ESP_EVENT_DEFINE_BASE(WIFI_EVENT); + +/**************************************************************************** + * Private Functions and Public Functions only used by libraries + ****************************************************************************/ + +/**************************************************************************** + * Name: osi_errno_trans + * + * Description: + * Transform from nuttx Os error code to Wi-Fi adapter error code + * + * Input Parameters: + * ret - NuttX error code + * + * Returned Value: + * Wi-Fi adapter error code + * + ****************************************************************************/ + +static inline int32_t osi_errno_trans(int ret) +{ + if (!ret) + { + return true; + } + else + { + return false; + } +} + +/**************************************************************************** + * Name: osi_errno_trans + * + * Description: + * Transform from ESP Wi-Fi error code to NuttX error code + * + * Input Parameters: + * ret - ESP Wi-Fi error code + * + * Returned Value: + * NuttX error code + * + ****************************************************************************/ + +static int32_t wifi_errno_trans(int ret) +{ + int wifierr; + + /* Unmask component error bits */ + + wifierr = ret & 0xfff; + + if (wifierr == ESP_OK) + { + return OK; + } + else if (wifierr == ESP_ERR_NO_MEM) + { + return -ENOMEM; + } + else if (wifierr == ESP_ERR_INVALID_ARG) + { + return -EINVAL; + } + else if (wifierr == ESP_ERR_INVALID_STATE) + { + return -EIO; + } + else if (wifierr == ESP_ERR_INVALID_SIZE) + { + return -EINVAL; + } + else if (wifierr == ESP_ERR_NOT_FOUND) + { + return -ENOSYS; + } + else if (wifierr == ESP_ERR_NOT_SUPPORTED) + { + return -ENOSYS; + } + else if (wifierr == ESP_ERR_TIMEOUT) + { + return -ETIMEDOUT; + } + else if (wifierr == ESP_ERR_INVALID_MAC) + { + return -EINVAL; + } + else + { + return ERROR; + } +} + +/**************************************************************************** + * Name: esp_int_adpt_cb + * + * Description: + * Wi-Fi interrupt adapter callback function + * + * Input Parameters: + * arg - interrupt adapter private data + * + * Returned Value: + * 0 on success + * + ****************************************************************************/ + +static int esp_int_adpt_cb(int irq, void *context, void *arg) +{ + struct irq_adpt *adapter = (struct irq_adpt *)arg; + + adapter->func(adapter->arg); + + return 0; +} + +/**************************************************************************** + * Name: esp_thread_semphr_free + * + * Description: + * Delete thread self's semaphore + * + * Input Parameters: + * semphr - Semaphore data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_thread_semphr_free(void *semphr) +{ + if (semphr) + { + esp_semphr_delete(semphr); + } +} + +/**************************************************************************** + * Name: esp_update_time + * + * Description: + * Transform ticks to time and add this time to timespec value + * + * Input Parameters: + * timespec - Input timespec data pointer + * ticks - System ticks + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_update_time(struct timespec *timespec, uint32_t ticks) +{ + uint32_t tmp; + + tmp = TICK2SEC(ticks); + timespec->tv_sec += tmp; + + ticks -= SEC2TICK(tmp); + tmp = TICK2NSEC(ticks); + + timespec->tv_nsec += tmp; +} + +/**************************************************************************** + * Name: esp_wifi_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_wifi_lock(bool lock) +{ + int ret; + + if (lock) + { + ret = nxmutex_lock(&g_wifiexcl_lock); + if (ret < 0) + { + wlinfo("Failed to lock Wi-Fi ret=%d\n", ret); + } + } + else + { + ret = nxmutex_unlock(&g_wifiexcl_lock); + if (ret < 0) + { + wlinfo("Failed to unlock Wi-Fi ret=%d\n", ret); + } + } + + return ret; +} + +/**************************************************************************** + * Name: esp_set_isr + * + * Description: + * Register interrupt function + * + * Input Parameters: + * n - Interrupt ID + * f - Interrupt function + * arg - Function private data + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_set_isr(int32_t n, void *f, void *arg) +{ + int ret; + uint32_t tmp; + struct irq_adpt *adapter; + int irq = n + XTENSA_IRQ_FIRSTPERIPH; + + wlinfo("n=%d f=%p arg=%p irq=%d\n", n, f, arg, irq); + + if (g_irqvector[irq].handler && + g_irqvector[irq].handler != irq_unexpected_isr) + { + wlinfo("irq=%d has been set handler=%p\n", irq, + g_irqvector[irq].handler); + return ; + } + + tmp = sizeof(struct irq_adpt); + adapter = kmm_malloc(tmp); + if (!adapter) + { + wlerr("Failed to alloc %d memory\n", tmp); + assert(0); + return ; + } + + adapter->func = f; + adapter->arg = arg; + + ret = irq_attach(irq, esp_int_adpt_cb, adapter); + if (ret) + { + wlerr("Failed to attach IRQ %d\n", irq); + assert(0); + return ; + } +} + +/**************************************************************************** + * Name: esp32s3_ints_on + * + * Description: + * Enable Wi-Fi interrupt + * + * Input Parameters: + * mask - No mean + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32s3_ints_on(uint32_t mask) +{ + int irq = __builtin_ffs(mask) - 1; + + wlinfo("INFO mask=%08x irq=%d\n", mask, irq); + + up_enable_irq(ESP32S3_IRQ_MAC); +} + +/**************************************************************************** + * Name: esp32s3_ints_off + * + * Description: + * Disable Wi-Fi interrupt + * + * Input Parameters: + * mask - No mean + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32s3_ints_off(uint32_t mask) +{ + uint32_t irq = __builtin_ffs(mask) - 1; + + wlinfo("INFO mask=%08x irq=%d\n", mask, irq); + + up_disable_irq(ESP32S3_IRQ_MAC); +} + +/**************************************************************************** + * 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(); +} + +/**************************************************************************** + * Name: esp_spin_lock_create + * + * Description: + * Create spin lock in SMP mode + * + * Input Parameters: + * None + * + * Returned Value: + * Spin lock data pointer + * + ****************************************************************************/ + +static void *esp_spin_lock_create(void) +{ +#ifdef CONFIG_SMP + spinlock_t *lock; + int tmp; + + tmp = sizeof(*lock); + lock = kmm_malloc(tmp); + if (!lock) + { + wlerr("Failed to alloc %d memory\n", tmp); + DEBUGPANIC(); + } + + spin_initialize(lock, SP_UNLOCKED); + + return lock; +#else + /* If return NULL, code may check fail */ + + return (void *)1; +#endif +} + +/**************************************************************************** + * Name: esp_spin_lock_delete + * + * Description: + * Delete spin lock + * + * Input Parameters: + * lock - Spin lock data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_spin_lock_delete(void *lock) +{ +#ifdef CONFIG_SMP + kmm_free(lock); +#else + DEBUGASSERT((int)lock == 1); +#endif +} + +/**************************************************************************** + * Name: esp_wifi_int_disable + * + * Description: + * Enter critical section by disabling interrupts and taking the spin lock + * if in SMP mode. + * + * Input Parameters: + * wifi_int_mux - Spin lock data pointer + * + * Returned Value: + * CPU PS value. + * + ****************************************************************************/ + +static uint32_t IRAM_ATTR esp_wifi_int_disable(void *wifi_int_mux) +{ + irqstate_t flags; + + flags = spin_lock_irqsave((spinlock_t *)wifi_int_mux); + + return (uint32_t)flags; +} + +/**************************************************************************** + * Name: esp_wifi_int_restore + * + * Description: + * Exit from critical section by enabling interrupts and releasing the spin + * lock if in SMP mode. + * + * Input Parameters: + * wifi_int_mux - Spin lock data pointer + * tmp - CPU PS value. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp_wifi_int_restore(void *wifi_int_mux, uint32_t tmp) +{ + irqstate_t flags = (irqstate_t)tmp; + + spin_unlock_irqrestore((spinlock_t *)wifi_int_mux, flags); +} + +/**************************************************************************** + * Name: esp_task_yield_from_isr + * + * Description: + * Do nothing in NuttX + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp_task_yield_from_isr(void) +{ + /* Do nothing */ +} + +/**************************************************************************** + * Name: esp_semphr_create + * + * Description: + * Create and initialize semaphore + * + * Input Parameters: + * max - No mean + * init - semaphore initialization value + * + * Returned Value: + * Semaphore data pointer + * + ****************************************************************************/ + +static void *esp_semphr_create(uint32_t max, uint32_t init) +{ + int ret; + sem_t *sem; + int tmp; + + tmp = sizeof(sem_t); + sem = kmm_malloc(tmp); + if (!sem) + { + wlerr("Failed to alloc %d memory\n", tmp); + return NULL; + } + + ret = nxsem_init(sem, 0, init); + if (ret) + { + wlerr("Failed to initialize sem error=%d\n", ret); + kmm_free(sem); + return NULL; + } + + return sem; +} + +/**************************************************************************** + * Name: esp_semphr_delete + * + * Description: + * Delete semaphore + * + * Input Parameters: + * semphr - Semaphore data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_semphr_delete(void *semphr) +{ + sem_t *sem = (sem_t *)semphr; + + nxsem_destroy(sem); + kmm_free(sem); +} + +/**************************************************************************** + * Name: esp_semphr_take + * + * Description: + * Wait semaphore within a certain period of time + * + * Input Parameters: + * semphr - Semaphore data pointer + * ticks - Wait system ticks + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_semphr_take(void *semphr, uint32_t ticks) +{ + int ret; + sem_t *sem = (sem_t *)semphr; + + if (ticks == OSI_FUNCS_TIME_BLOCKING) + { + ret = nxsem_wait(sem); + if (ret) + { + wlerr("Failed to wait sem\n"); + } + } + else + { + ret = nxsem_tickwait(sem, ticks); + if (ret) + { + wlerr("Failed to wait sem in %d ticks\n", ticks); + } + } + + return osi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_semphr_give + * + * Description: + * Post semaphore + * + * Input Parameters: + * semphr - Semaphore data pointer + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_semphr_give(void *semphr) +{ + int ret; + sem_t *sem = (sem_t *)semphr; + + ret = nxsem_post(sem); + if (ret) + { + wlerr("Failed to post sem error=%d\n", ret); + } + + return osi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_thread_semphr_get + * + * Description: + * Get thread self's semaphore + * + * Input Parameters: + * None + * + * Returned Value: + * Semaphore data pointer + * + ****************************************************************************/ + +static void *esp_thread_semphr_get(void) +{ + static int wifi_task_key = -1; + int ret; + void *sem; + + if (wifi_task_key < 0) + { + ret = task_tls_alloc(esp_thread_semphr_free); + if (ret < 0) + { + wlerr("Failed to create task local key\n"); + return NULL; + } + + wifi_task_key = ret; + } + + sem = (void *)task_tls_get_value(wifi_task_key); + if (sem == NULL) + { + sem = esp_semphr_create(1, 0); + if (!sem) + { + wlerr("Failed to create semaphore\n"); + return NULL; + } + + ret = task_tls_set_value(wifi_task_key, (uintptr_t)sem); + if (ret != OK) + { + wlerr("Failed to save semaphore on task local storage: %d\n", ret); + esp_semphr_delete(sem); + return NULL; + } + } + + return sem; +} + +/**************************************************************************** + * Name: esp_mutex_create + * + * Description: + * Create mutex + * + * Input Parameters: + * None + * + * Returned Value: + * Mutex data pointer + * + ****************************************************************************/ + +static void *esp_mutex_create(void) +{ + int ret; + pthread_mutex_t *mutex; + int tmp; + + tmp = sizeof(pthread_mutex_t); + mutex = kmm_malloc(tmp); + if (!mutex) + { + wlerr("Failed to alloc %d memory\n", tmp); + return NULL; + } + + ret = pthread_mutex_init(mutex, NULL); + if (ret) + { + wlerr("Failed to initialize mutex error=%d\n", ret); + kmm_free(mutex); + return NULL; + } + + return mutex; +} + +/**************************************************************************** + * Name: esp_recursive_mutex_create + * + * Description: + * Create recursive mutex + * + * Input Parameters: + * None + * + * Returned Value: + * Recursive mutex data pointer + * + ****************************************************************************/ + +static void *esp_recursive_mutex_create(void) +{ + int ret; + pthread_mutex_t *mutex; + pthread_mutexattr_t attr; + int tmp; + + ret = pthread_mutexattr_init(&attr); + if (ret) + { + wlerr("Failed to initialize attr error=%d\n", ret); + return NULL; + } + + ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + if (ret) + { + wlerr("Failed to set attr type error=%d\n", ret); + return NULL; + } + + tmp = sizeof(pthread_mutex_t); + mutex = kmm_malloc(tmp); + if (!mutex) + { + wlerr("Failed to alloc %d memory\n", tmp); + return NULL; + } + + ret = pthread_mutex_init(mutex, &attr); + if (ret) + { + wlerr("Failed to initialize mutex error=%d\n", ret); + kmm_free(mutex); + return NULL; + } + + return mutex; +} + +/**************************************************************************** + * Name: esp_mutex_delete + * + * Description: + * Delete mutex + * + * Input Parameters: + * mutex_data - mutex data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_mutex_delete(void *mutex_data) +{ + pthread_mutex_t *mutex = (pthread_mutex_t *)mutex_data; + + pthread_mutex_destroy(mutex); + kmm_free(mutex); +} + +/**************************************************************************** + * Name: esp_mutex_lock + * + * Description: + * Lock mutex + * + * Input Parameters: + * mutex_data - mutex data pointer + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_mutex_lock(void *mutex_data) +{ + int ret; + pthread_mutex_t *mutex = (pthread_mutex_t *)mutex_data; + + ret = pthread_mutex_lock(mutex); + if (ret) + { + wlerr("Failed to lock mutex error=%d\n", ret); + } + + return osi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_mutex_unlock + * + * Description: + * Unlock mutex + * + * Input Parameters: + * mutex_data - mutex data pointer + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_mutex_unlock(void *mutex_data) +{ + int ret; + pthread_mutex_t *mutex = (pthread_mutex_t *)mutex_data; + + ret = pthread_mutex_unlock(mutex); + if (ret) + { + wlerr("Failed to unlock mutex error=%d\n", ret); + } + + return osi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_queue_create + * + * Description: + * Create message queue + * + * Input Parameters: + * queue_len - queue message number + * item_size - message size + * + * Returned Value: + * Message queue data pointer + * + ****************************************************************************/ + +static void *esp_queue_create(uint32_t queue_len, uint32_t item_size) +{ + struct mq_attr attr; + struct mq_adpt *mq_adpt; + int ret; + + mq_adpt = kmm_malloc(sizeof(struct mq_adpt)); + if (!mq_adpt) + { + wlerr("Failed to kmm_malloc\n"); + return NULL; + } + + snprintf(mq_adpt->name, sizeof(mq_adpt->name), + "/tmp/%p", mq_adpt); + + attr.mq_maxmsg = queue_len; + attr.mq_msgsize = item_size; + attr.mq_curmsgs = 0; + attr.mq_flags = 0; + + ret = file_mq_open(&mq_adpt->mq, mq_adpt->name, + O_RDWR | O_CREAT, 0644, &attr); + if (ret < 0) + { + wlerr("Failed to create mqueue\n"); + kmm_free(mq_adpt); + return NULL; + } + + mq_adpt->msgsize = item_size; + + return (void *)mq_adpt; +} + +/**************************************************************************** + * Name: esp_queue_delete + * + * Description: + * Delete message queue + * + * Input Parameters: + * queue - Message queue data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_queue_delete(void *queue) +{ + struct mq_adpt *mq_adpt = (struct mq_adpt *)queue; + + file_mq_close(&mq_adpt->mq); + file_mq_unlink(mq_adpt->name); + kmm_free(mq_adpt); +} + +/**************************************************************************** + * Name: esp_queue_send_generic + * + * Description: + * Generic send message to queue within a certain period of time + * + * Input Parameters: + * queue - Message queue data pointer + * item - Message data pointer + * ticks - Wait ticks + * prio - Message priority + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_queue_send_generic(void *queue, void *item, + uint32_t ticks, int prio) +{ + int ret; + struct timespec timeout; + struct mq_adpt *mq_adpt = (struct mq_adpt *)queue; + + if (ticks == OSI_FUNCS_TIME_BLOCKING || ticks == 0) + { + /* Wi-Fi interrupt function will call this adapter function to send + * message to message queue, so here we should call kernel API + * instead of application API + */ + + ret = file_mq_send(&mq_adpt->mq, (const char *)item, + mq_adpt->msgsize, prio); + if (ret < 0) + { + wlerr("Failed to send message to mqueue error=%d\n", + ret); + } + } + else + { + ret = clock_gettime(CLOCK_REALTIME, &timeout); + if (ret < 0) + { + wlerr("Failed to get time\n"); + return false; + } + + if (ticks) + { + esp_update_time(&timeout, ticks); + } + + ret = file_mq_timedsend(&mq_adpt->mq, (const char *)item, + mq_adpt->msgsize, prio, &timeout); + if (ret < 0) + { + wlerr("Failed to timedsend message to mqueue error=%d\n", + ret); + } + } + + return osi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_queue_send + * + * Description: + * Send message of low priority to queue within a certain period of time + * + * Input Parameters: + * queue - Message queue data pointer + * item - Message data pointer + * ticks - Wait ticks + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_queue_send(void *queue, void *item, uint32_t ticks) +{ + return esp_queue_send_generic(queue, item, ticks, 0); +} + +/**************************************************************************** + * Name: esp_queue_send_from_isr + * + * Description: + * Send message of low priority to queue in ISR within + * a certain period of time + * + * Input Parameters: + * queue - Message queue data pointer + * item - Message data pointer + * hptw - No mean + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_queue_send_from_isr(void *queue, void *item, void *hptw) +{ + /* Force to set the value to be false */ + + *((int *)hptw) = false; + + return esp_queue_send_generic(queue, item, 0, 0); +} + +/**************************************************************************** + * Name: esp_queue_send_to_back + * + * Description: + * Send message of low priority to queue within a certain period of time + * + * Input Parameters: + * queue - Message queue data pointer + * item - Message data pointer + * ticks - Wait ticks + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_queue_send_to_back(void *queue, void *item, + uint32_t ticks) +{ + return esp_queue_send_generic(queue, item, ticks, 0); +} + +/**************************************************************************** + * Name: esp_queue_send_from_to_front + * + * Description: + * Send message of high priority to queue within a certain period of time + * + * Input Parameters: + * queue - Message queue data pointer + * item - Message data pointer + * ticks - Wait ticks + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_queue_send_to_front(void *queue, void *item, + uint32_t ticks) +{ + return esp_queue_send_generic(queue, item, ticks, 1); +} + +/**************************************************************************** + * Name: esp_queue_recv + * + * Description: + * Receive message from queue within a certain period of time + * + * Input Parameters: + * queue - Message queue data pointer + * item - Message data pointer + * ticks - Wait ticks + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_queue_recv(void *queue, void *item, uint32_t ticks) +{ + ssize_t ret; + struct timespec timeout; + unsigned int prio; + struct mq_adpt *mq_adpt = (struct mq_adpt *)queue; + + if (ticks == OSI_FUNCS_TIME_BLOCKING) + { + ret = file_mq_receive(&mq_adpt->mq, (char *)item, + mq_adpt->msgsize, &prio); + if (ret < 0) + { + wlerr("Failed to receive from mqueue error=%d\n", ret); + } + } + else + { + ret = clock_gettime(CLOCK_REALTIME, &timeout); + if (ret < 0) + { + wlerr("Failed to get time\n"); + return false; + } + + if (ticks) + { + esp_update_time(&timeout, ticks); + } + + ret = file_mq_timedreceive(&mq_adpt->mq, (char *)item, + mq_adpt->msgsize, &prio, &timeout); + if (ret < 0) + { + wlerr("Failed to timedreceive from mqueue error=%d\n", + ret); + } + } + + return ret > 0 ? true : false; +} + +/**************************************************************************** + * Name: esp_queue_msg_waiting + * + * Description: + * Get message number in the message queue + * + * Input Parameters: + * queue - Message queue data pointer + * + * Returned Value: + * Message number + * + ****************************************************************************/ + +static uint32_t esp_queue_msg_waiting(void *queue) +{ + int ret; + struct mq_attr attr; + struct mq_adpt *mq_adpt = (struct mq_adpt *)queue; + + ret = file_mq_getattr(&mq_adpt->mq, &attr); + if (ret < 0) + { + wlerr("Failed to get attr from mqueue error=%d\n", ret); + return 0; + } + + return attr.mq_curmsgs; +} + +/**************************************************************************** + * Name: esp_event_group_create + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void *esp_event_group_create(void) +{ + DEBUGPANIC(); + + return NULL; +} + +/**************************************************************************** + * Name: esp_event_group_delete + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void esp_event_group_delete(void *event) +{ + DEBUGPANIC(); +} + +/**************************************************************************** + * Name: esp_event_group_set_bits + * + * Description: + * Don't support + * + ****************************************************************************/ + +static uint32_t esp_event_group_set_bits(void *event, uint32_t bits) +{ + DEBUGPANIC(); + + return false; +} + +/**************************************************************************** + * Name: esp_event_group_clear_bits + * + * Description: + * Don't support + * + ****************************************************************************/ + +static uint32_t esp_event_group_clear_bits(void *event, uint32_t bits) +{ + DEBUGPANIC(); + + return false; +} + +/**************************************************************************** + * Name: esp_event_group_wait_bits + * + * Description: + * Don't support + * + ****************************************************************************/ + +static uint32_t esp_event_group_wait_bits(void *event, + uint32_t bits_to_wait_for, + int32_t clear_on_exit, + int32_t wait_for_all_bits, + uint32_t block_time_tick) +{ + DEBUGPANIC(); + + return false; +} + +/**************************************************************************** + * Name: esp_task_create_pinned_to_core + * + * Description: + * Create task and bind it to target CPU, the task will run when it + * is created + * + * Input Parameters: + * entry - Task entry + * name - Task name + * stack_depth - Task stack size + * param - Task private data + * prio - Task priority + * task_handle - Task handle pointer which is used to pause, resume + * and delete the task + * core_id - CPU which the task runs in + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_task_create_pinned_to_core(void *entry, + const char *name, + uint32_t stack_depth, + void *param, + uint32_t prio, + void *task_handle, + uint32_t core_id) +{ + int pid; +#ifdef CONFIG_SMP + int ret; + cpu_set_t cpuset; +#endif + + pid = kthread_create(name, prio, stack_depth, entry, + (char * const *)param); + if (pid > 0) + { + if (task_handle != NULL) + { + *((int *)task_handle) = pid; + } +#ifdef CONFIG_SMP + if (core_id < CONFIG_SMP_NCPUS) + { + CPU_ZERO(&cpuset); + CPU_SET(core_id, &cpuset); + ret = nxsched_set_affinity(pid, sizeof(cpuset), &cpuset); + if (ret) + { + wlerr("Failed to set affinity error=%d\n", ret); + return false; + } + } +#endif + } + else + { + wlerr("Failed to create task\n"); + } + + return pid > 0; +} + +/**************************************************************************** + * Name: esp_task_create + * + * Description: + * Create task and the task will run when it is created + * + * Input Parameters: + * entry - Task entry + * name - Task name + * stack_depth - Task stack size + * param - Task private data + * prio - Task priority + * task_handle - Task handle pointer which is used to pause, resume + * and delete the task + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_task_create(void *entry, const char *name, + uint32_t stack_depth, void *param, + uint32_t prio, void *task_handle) +{ + return esp_task_create_pinned_to_core(entry, name, stack_depth, param, + prio, task_handle, UINT32_MAX); +} + +/**************************************************************************** + * Name: esp_task_delete + * + * Description: + * Delete the target task + * + * Input Parameters: + * task_handle - Task handle pointer which is used to pause, resume + * and delete the task + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_task_delete(void *task_handle) +{ + pid_t pid = (pid_t)((uintptr_t)task_handle); + + kthread_delete(pid); +} + +/**************************************************************************** + * Name: esp_task_delay + * + * Description: + * Current task wait for some ticks + * + * Input Parameters: + * tick - Waiting ticks + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_task_delay(uint32_t tick) +{ + useconds_t us = TICK2USEC(tick); + + nxsig_usleep(us); +} + +/**************************************************************************** + * Name: esp_task_ms_to_tick + * + * Description: + * Transform from millim seconds to system ticks + * + * Input Parameters: + * ms - Millim seconds + * + * Returned Value: + * System ticks + * + ****************************************************************************/ + +static int32_t esp_task_ms_to_tick(uint32_t ms) +{ + return MSEC2TICK(ms); +} + +/**************************************************************************** + * Name: esp_task_get_current_task + * + * Description: + * Transform from millim seconds to system ticks + * + * Input Parameters: + * ms - Millim seconds + * + * Returned Value: + * System ticks + * + ****************************************************************************/ + +static void *esp_task_get_current_task(void) +{ + pid_t pid = nxsched_getpid(); + + return (void *)((uintptr_t)pid); +} + +/**************************************************************************** + * Name: esp_task_get_max_priority + * + * Description: + * Get OS task maximum priority + * + * Input Parameters: + * None + * + * Returned Value: + * Task maximum priority + * + ****************************************************************************/ + +static int32_t esp_task_get_max_priority(void) +{ + return SCHED_PRIORITY_MAX; +} + +/**************************************************************************** + * Name: esp_malloc + * + * Description: + * Allocate a block of memory + * + * Input Parameters: + * size - memory size + * + * Returned Value: + * Memory pointer + * + ****************************************************************************/ + +static void *esp_malloc(uint32_t size) +{ + return kmm_malloc(size); +} + +/**************************************************************************** + * Name: esp_free + * + * Description: + * Free a block of memory + * + * Input Parameters: + * ptr - memory block + * + * Returned Value: + * No + * + ****************************************************************************/ + +static void esp_free(void *ptr) +{ +#ifdef CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP + if (xtensa_imm_heapmember(ptr)) + { + xtensa_imm_free(ptr); + } + else +#endif +#ifdef CONFIG_MM_KERNEL_HEAP + if (kmm_heapmember(ptr)) +#endif + { + kmm_free(ptr); + } +#ifdef CONFIG_MM_KERNEL_HEAP + else + { + free(ptr); + } +#endif +} + +/**************************************************************************** + * Name: esp_event_id_map + * + * Description: + * Transform from esp-idf event ID to Wi-Fi adapter event ID + * + * Input Parameters: + * event_id - esp-idf event ID + * + * Returned Value: + * Wi-Fi adapter event ID + * + ****************************************************************************/ + +static int esp_event_id_map(int event_id) +{ + int id; + + switch (event_id) + { + case WIFI_EVENT_SCAN_DONE: + id = WIFI_ADPT_EVT_SCAN_DONE; + break; + +#ifdef ESP32S3_WLAN_HAS_STA + case WIFI_EVENT_STA_START: + id = WIFI_ADPT_EVT_STA_START; + break; + + case WIFI_EVENT_STA_CONNECTED: + id = WIFI_ADPT_EVT_STA_CONNECT; + break; + + case WIFI_EVENT_STA_DISCONNECTED: + id = WIFI_ADPT_EVT_STA_DISCONNECT; + break; + + case WIFI_EVENT_STA_AUTHMODE_CHANGE: + id = WIFI_ADPT_EVT_STA_AUTHMODE_CHANGE; + break; + + case WIFI_EVENT_STA_STOP: + id = WIFI_ADPT_EVT_STA_STOP; + break; +#endif /* ESP32S3_WLAN_HAS_STA */ + + default: + return -1; + } + + return id; +} + +/**************************************************************************** + * Name: esp_evt_work_cb + * + * Description: + * Process the cached event + * + * Input Parameters: + * arg - No mean + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_evt_work_cb(void *arg) +{ + int ret; + irqstate_t flags; + struct evt_adpt *evt_adpt; + struct wifi_notify *notify; + + while (1) + { + flags = spin_lock_irqsave(&g_lock); + evt_adpt = (struct evt_adpt *)sq_remfirst(&g_wifi_evt_queue); + spin_unlock_irqrestore(&g_lock, flags); + if (!evt_adpt) + { + break; + } + + esp_wifi_lock(true); + + switch (evt_adpt->id) + { + case WIFI_ADPT_EVT_SCAN_DONE: + esp_wifi_scan_event_parse(); + break; + +#ifdef ESP32S3_WLAN_HAS_STA + case WIFI_ADPT_EVT_STA_START: + wlinfo("Wi-Fi sta start\n"); + g_sta_connected = false; + ret = esp_wifi_set_ps(WIFI_PS_NONE); + if (ret) + { + wlerr("Failed to set power save type\n"); + } + break; + + case WIFI_ADPT_EVT_STA_CONNECT: + wlinfo("Wi-Fi sta connect\n"); + g_sta_connected = true; + ret = esp32s3_wlan_sta_set_linkstatus(true); + if (ret < 0) + { + wlerr("ERROR: Failed to set Wi-Fi station link status\n"); + } + + break; + + case WIFI_ADPT_EVT_STA_DISCONNECT: + wlinfo("Wi-Fi sta disconnect\n"); + g_sta_connected = false; + ret = esp32s3_wlan_sta_set_linkstatus(false); + if (ret < 0) + { + wlerr("ERROR: Failed to set Wi-Fi station link status\n"); + } + + if (g_sta_reconnect) + { + ret = esp_wifi_connect(); + if (ret) + { + wlerr("Failed to connect AP error=%d\n", ret); + } + } + break; + + case WIFI_ADPT_EVT_STA_STOP: + wlinfo("Wi-Fi sta stop\n"); + g_sta_connected = false; + break; +#endif /* ESP32S3_WLAN_HAS_STA */ + + default: + break; + } + + notify = &g_wifi_notify[evt_adpt->id]; + if (notify->assigned) + { + notify->event.sigev_value.sival_ptr = evt_adpt->buf; + + ret = nxsig_notification(notify->pid, ¬ify->event, + SI_QUEUE, ¬ify->work); + if (ret < 0) + { + wlwarn("nxsig_notification event ID=%d failed: %d\n", + evt_adpt->id, ret); + } + } + + esp_wifi_lock(false); + + kmm_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=%" PRId32 ", intr_source=%" PRIu32 + ", intr_num=%" PRIu32 ", intr_prio=%" PRId32 "\n", + cpu_no, intr_source, intr_num, intr_prio); + + /* Force to bind Wi-Fi interrupt to CPU0 */ + + intr_matrix_set(0, intr_source, intr_num); +} + +/**************************************************************************** + * 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 + * + * Description: + * Active work queue and let the work to process the cached event + * + * Input Parameters: + * event_base - Event set name + * event_id - Event ID + * event_data - Event private data + * event_data_size - Event data size + * ticks - Waiting system ticks + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_event_post(esp_event_base_t event_base, + int32_t event_id, + void *event_data, + size_t event_data_size, + uint32_t ticks) +{ + size_t size; + int32_t id; + irqstate_t flags; + struct evt_adpt *evt_adpt; + + wlinfo("Event: base=%s id=%d data=%p data_size=%d ticks=%u\n", event_base, + event_id, event_data, event_data_size, ticks); + + id = esp_event_id_map(event_id); + if (id < 0) + { + wlinfo("No process event %d\n", event_id); + return -1; + } + + size = event_data_size + sizeof(struct evt_adpt); + evt_adpt = kmm_malloc(size); + if (!evt_adpt) + { + wlerr("Failed to alloc %d memory\n", size); + return -1; + } + + evt_adpt->id = id; + memcpy(evt_adpt->buf, event_data, event_data_size); + + flags = spin_lock_irqsave(&g_lock); + sq_addlast(&evt_adpt->entry, &g_wifi_evt_queue); + spin_unlock_irqrestore(&g_lock, flags); + + work_queue(LPWORK, &g_wifi_evt_work, esp_evt_work_cb, NULL, 0); + + return 0; +} + +/**************************************************************************** + * Name: esp_get_free_heap_size + * + * Description: + * Get free heap size by byte + * + * Input Parameters: + * None + * + * Returned Value: + * Free heap size + * + ****************************************************************************/ + +uint32_t esp_get_free_heap_size(void) +{ + struct mallinfo info; + + info = kmm_mallinfo(); + return info.fordblks; +} + +/**************************************************************************** + * Name: esp_dport_access_stall_other_cpu_start + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void esp_dport_access_stall_other_cpu_start(void) +{ +#ifdef CONFIG_SMP + DEBUGPANIC(); +#endif +} + +/**************************************************************************** + * Name: esp_dport_access_stall_other_cpu_end + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void esp_dport_access_stall_other_cpu_end(void) +{ +#ifdef CONFIG_SMP + DEBUGPANIC(); +#endif +} + +/**************************************************************************** + * Name: wifi_apb80m_request + * + * Description: + * Take Wi-Fi lock in auto-sleep + * + ****************************************************************************/ + +static void wifi_apb80m_request(void) +{ +#ifdef CONFIG_ESP32S3_AUTO_SLEEP + esp32s3_pm_lockacquire(); +#endif +} + +/**************************************************************************** + * Name: wifi_apb80m_release + * + * Description: + * Release Wi-Fi lock in auto-sleep + * + ****************************************************************************/ + +static void wifi_apb80m_release(void) +{ +#ifdef CONFIG_ESP32S3_AUTO_SLEEP + esp32s3_pm_lockrelease(); +#endif +} + +/**************************************************************************** + * 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_wifi_read_mac + * + * Description: + * Read MAC address from efuse + * + * Input Parameters: + * mac - MAC address buffer pointer + * type - MAC address type + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_wifi_read_mac(uint8_t *mac, uint32_t type) +{ + return esp_read_mac(mac, type); +} + +/**************************************************************************** + * Name: esp_timer_arm + * + * Description: + * Set timer timeout period and repeat flag + * + * Input Parameters: + * ptimer - timer data pointer + * ms - millim seconds + * repeat - true: run cycle, false: run once + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_timer_arm(void *ptimer, uint32_t ms, bool repeat) +{ + esp_timer_arm_us(ptimer, ms * 1000, repeat); +} + +/**************************************************************************** + * Name: esp_timer_disarm + * + * Description: + * Disable timer + * + * Input Parameters: + * ptimer - timer data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_timer_disarm(void *ptimer) +{ + struct ets_timer *ets_timer = (struct ets_timer *)ptimer; + esp_timer_handle_t esp_timer = (esp_timer_handle_t)ets_timer->priv; + + if (ets_timer->expire == TIMER_INITIALIZED_VAL) + { + esp_timer_stop(esp_timer); + } +} + +/**************************************************************************** + * Name: esp32s3_timer_done + * + * Description: + * Disable and free timer + * + * Input Parameters: + * ptimer - timer data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32s3_timer_done(void *ptimer) +{ + struct ets_timer *ets_timer = (struct ets_timer *)ptimer; + esp_timer_handle_t esp_timer = (esp_timer_handle_t)ets_timer->priv; + + if (ets_timer->expire == TIMER_INITIALIZED_VAL) + { + ets_timer->expire = 0; + esp_timer_delete(esp_timer); + ets_timer->priv = NULL; + } +} + +/**************************************************************************** + * Name: esp_timer_setfn + * + * Description: + * Set timer callback function and private data + * + * Input Parameters: + * ptimer - Timer data pointer + * pfunction - Callback function + * parg - Callback function private data + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_timer_setfn(void *ptimer, void *pfunction, void *parg) +{ + int ret; + esp_timer_handle_t esp_timer; + struct ets_timer *ets_timer = (struct ets_timer *)ptimer; + + if (ets_timer->expire != TIMER_INITIALIZED_VAL) + { + ets_timer->priv = NULL; + } + + if (ets_timer->priv == NULL) + { + const esp_timer_create_args_t create_args = + { + .callback = pfunction, + .arg = parg, + .name = "ETSTimer", + .dispatch_method = ESP_TIMER_TASK + }; + + ret = esp_timer_create(&create_args, &esp_timer); + if (ret) + { + wlerr("Failed to create ets_timer error=%d\n", ret); + } + else + { + ets_timer->priv = esp_timer; + ets_timer->expire = TIMER_INITIALIZED_VAL; + } + } +} + +/**************************************************************************** + * Name: esp_timer_arm_us + * + * Description: + * Set timer timeout period and repeat flag + * + * Input Parameters: + * ptimer - timer data pointer + * us - micro seconds + * repeat - true: run cycle, false: run once + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_timer_arm_us(void *ptimer, uint32_t us, bool repeat) +{ + int ret; + struct ets_timer *ets_timer = (struct ets_timer *)ptimer; + esp_timer_handle_t esp_timer = (esp_timer_handle_t)ets_timer->priv; + + if (ets_timer->expire == TIMER_INITIALIZED_VAL) + { + esp_timer_stop(esp_timer); + if (!repeat) + { + ret = esp_timer_start_once(esp_timer, us); + } + else + { + ret = esp_timer_start_periodic(esp_timer, us); + } + + if (ret) + { + wlerr("Fail to start %s timer error%d\n", + repeat ? "periodic" : "once", + ret); + } + } +} + +/**************************************************************************** + * Name: wifi_reset_mac + * + * Description: + * Reset Wi-Fi hardware MAC + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wifi_reset_mac(void) +{ + modifyreg32(SYSCON_WIFI_RST_EN_REG, 0, SYSTEM_WIFIMAC_RST); + modifyreg32(SYSCON_WIFI_RST_EN_REG, SYSTEM_WIFIMAC_RST, 0); +} + +/**************************************************************************** + * Name: wifi_clock_enable + * + * Description: + * Enable Wi-Fi clock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wifi_clock_enable(void) +{ + modifyreg32(SYSTEM_WIFI_CLK_EN_REG, 0, SYSTEM_WIFI_CLK_WIFI_EN_M); +} + +/**************************************************************************** + * Name: wifi_clock_disable + * + * Description: + * Disable Wi-Fi clock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wifi_clock_disable(void) +{ + modifyreg32(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_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 + * + * Description: + * Get system time of type int64_t + * + * Input Parameters: + * periph - No mean + * + * Returned Value: + * System time + * + ****************************************************************************/ + +int64_t esp_timer_get_time(void) +{ + return (int64_t)esp32s3_rt_timer_time_us(); +} + +/**************************************************************************** + * Name: esp_nvs_set_i8 + * + * Description: + * Save data of type int8_t into file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * value - Stored data + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_set_i8(uint32_t handle, + const char *key, + int8_t value) +{ +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + return esp_nvs_set_blob(handle, key, &value, sizeof(int8_t)); +#else + DEBUGPANIC(); + + return -1; +#endif +} + +/**************************************************************************** + * Name: esp_nvs_get_i8 + * + * Description: + * Read data of type int8_t from file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * out_value - Read buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_get_i8(uint32_t handle, + const char *key, + int8_t *out_value) +{ +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + size_t len = sizeof(int8_t); + + return esp_nvs_get_blob(handle, key, out_value, &len); +#else + DEBUGPANIC(); + + return -1; +#endif +} + +/**************************************************************************** + * Name: esp_nvs_set_u8 + * + * Description: + * Save data of type uint8_t into file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * value - Stored data + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_set_u8(uint32_t handle, + const char *key, + uint8_t value) +{ +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + return esp_nvs_set_blob(handle, key, &value, sizeof(uint8_t)); +#else + DEBUGPANIC(); + + return -1; +#endif +} + +/**************************************************************************** + * Name: esp_nvs_get_u8 + * + * Description: + * Read data of type uint8_t from file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * out_value - Read buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_get_u8(uint32_t handle, + const char *key, + uint8_t *out_value) +{ +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + size_t len = sizeof(uint8_t); + + return esp_nvs_get_blob(handle, key, out_value, &len); +#else + DEBUGPANIC(); + + return -1; +#endif +} + +/**************************************************************************** + * Name: esp_nvs_set_u16 + * + * Description: + * Save data of type uint16_t into file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * value - Stored data + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_set_u16(uint32_t handle, + const char *key, + uint16_t value) +{ +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + return esp_nvs_set_blob(handle, key, &value, sizeof(uint16_t)); +#else + DEBUGPANIC(); + + return -1; +#endif +} + +/**************************************************************************** + * Name: esp_nvs_get_u16 + * + * Description: + * Read data of type uint16_t from file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * out_value - Read buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_get_u16(uint32_t handle, + const char *key, + uint16_t *out_value) +{ +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + size_t len = sizeof(uint16_t); + + return esp_nvs_get_blob(handle, key, out_value, &len); +#else + DEBUGPANIC(); + + return -1; +#endif +} + +/**************************************************************************** + * Name: esp_nvs_open + * + * Description: + * Create a file system storage data object + * + * Input Parameters: + * name - Storage index + * open_mode - Storage mode + * out_handle - Storage handle + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_open(const char *name, + uint32_t open_mode, + uint32_t *out_handle) +{ +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + int ret; + struct nvs_adpt *nvs_adpt; + int tmp; + char *index_name; + + tmp = sizeof(struct nvs_adpt); + nvs_adpt = kmm_malloc(tmp); + if (!nvs_adpt) + { + wlerr("Failed to alloc %d memory\n", tmp); + return -1; + } + + ret = asprintf(&index_name, "%s", name); + if (ret < 0) + { + wlerr("Failed to create NVS index_name string\n"); + kmm_free(nvs_adpt); + return -1; + } + + nvs_adpt->index_name = index_name; + *out_handle = (uint32_t)nvs_adpt; + + return 0; +#else + DEBUGPANIC(); + + return -1; +#endif +} + +/**************************************************************************** + * Name: esp_nvs_close + * + * Description: + * Close storage data object and free resource + * + * Input Parameters: + * handle - NVS handle + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static void esp_nvs_close(uint32_t handle) +{ +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + struct nvs_adpt *nvs_adpt = (struct nvs_adpt *)handle; + + kmm_free(nvs_adpt->index_name); + kmm_free(nvs_adpt); +#else + DEBUGPANIC(); +#endif +} + +/**************************************************************************** + * Name: esp_nvs_commit + * + * Description: + * This function has no practical effect + * + ****************************************************************************/ + +static int32_t esp_nvs_commit(uint32_t handle) +{ + return 0; +} + +/**************************************************************************** + * Name: esp_nvs_set_blob + * + * Description: + * Save a block of data into file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * value - Stored buffer pointer + * length - Buffer length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_set_blob(uint32_t handle, + const char *key, + const void *value, + size_t length) +{ +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + struct file file; + int ret; + char *dir; + struct nvs_adpt *nvs_adpt = (struct nvs_adpt *)handle; + char *index_name = nvs_adpt->index_name; + + ret = asprintf(&dir, NVS_DIR_BASE"%s.%s", index_name, key); + if (ret < 0) + { + wlerr("Failed to create NVS dir string\n"); + return -1; + } + + ret = nx_unlink(dir); + if (ret) + { + if (ret != -ENOENT) + { + wlerr("Failed to unlink %s error=%d\n", dir, ret); + kmm_free(dir); + return -1; + } + } + + ret = file_open(&file, dir, O_WRONLY | O_CREAT, NVS_FILE_MODE); + if (ret < 0) + { + wlerr("Failed to set open %s\n", dir); + kmm_free(dir); + return -1; + } + + ret = file_write(&file, value, length); + if (ret < 0) + { + wlerr("Failed to write to %s\n", dir); + kmm_free(dir); + file_close(&file); + return -1; + } + + kmm_free(dir); + file_close(&file); + + return 0; +#else + DEBUGPANIC(); + + return -1; +#endif +} + +/**************************************************************************** + * Name: esp_nvs_get_blob + * + * Description: + * Read a block of data from file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * out_value - Read buffer pointer + * length - Buffer length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_get_blob(uint32_t handle, + const char *key, + void *out_value, + size_t *length) +{ +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + struct file file; + int ret; + char *dir; + struct nvs_adpt *nvs_adpt = (struct nvs_adpt *)handle; + char *index_name = nvs_adpt->index_name; + + ret = asprintf(&dir, NVS_DIR_BASE"%s.%s", index_name, key); + if (ret < 0) + { + wlerr("Failed to create NVS dir string\n"); + return -1; + } + + ret = file_open(&file, dir, O_RDONLY); + if (ret < 0) + { + if (ret == -ENOENT) + { + wlinfo("No file %s\n", dir); + kmm_free(dir); + return ESP_ERR_NVS_NOT_FOUND; + } + wlerr("Failed to get open %s\n", dir); + kmm_free(dir); + return -1; + } + + ret = file_read(&file, out_value, *length); + if (ret <= 0) + { + wlerr("Failed to write to %s\n", dir); + kmm_free(dir); + file_close(&file); + return -1; + } + else + { + *length = ret; + } + + kmm_free(dir); + file_close(&file); + + return 0; +#else + DEBUGPANIC(); + + return -1; +#endif +} + +/**************************************************************************** + * Name: esp_nvs_erase_key + * + * Description: + * Read a block of data from file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_erase_key(uint32_t handle, const char *key) +{ +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + int ret; + char *dir; + struct nvs_adpt *nvs_adpt = (struct nvs_adpt *)handle; + char *index_name = nvs_adpt->index_name; + + ret = asprintf(&dir, NVS_DIR_BASE"%s.%s", index_name, key); + if (ret < 0) + { + wlerr("Failed to create NVS dir string\n"); + return -1; + } + + ret = nx_unlink(dir); + if (ret < 0) + { + wlerr("Failed to delete NVS file %s\n", dir); + kmm_free(dir); + return -1; + } + + kmm_free(dir); + + return 0; +#else + DEBUGPANIC(); + + return -1; +#endif +} + +/**************************************************************************** + * Name: esp_fill_random + * + * Description: + * Fill random data int given buffer of given length + * + * Input Parameters: + * buf - buffer pointer + * len - buffer length + * + * Returned Value: + * + ****************************************************************************/ + +void esp_fill_random(void *buf, size_t len) +{ + uint8_t *p = (uint8_t *)buf; + uint32_t tmp; + uint32_t n; + + while (len > 0) + { + tmp = esp_random(); + n = len < 4 ? len : 4; + + memcpy(p, &tmp, n); + + p += n; + len -= n; + } +} + +/**************************************************************************** + * Name: esp_get_random + * + * Description: + * Fill random data int given buffer of given length + * + * Input Parameters: + * buf - buffer pointer + * len - buffer length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_get_random(uint8_t *buf, size_t len) +{ + esp_fill_random(buf, len); + + return 0; +} + +/**************************************************************************** + * Name: esp_get_time + * + * Description: + * Get std C time + * + * Input Parameters: + * t - buffer to store time of type timeval + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_get_time(void *t) +{ + int ret; + struct timeval tv; + struct time_adpt *time_adpt = (struct time_adpt *)t; + + ret = gettimeofday(&tv, NULL); + if (!ret) + { + time_adpt->sec = (time_t)tv.tv_sec; + time_adpt->usec = (suseconds_t)tv.tv_usec; + } + else + { + wlerr("Failed to get time of day\n"); + } + + return ret; +} + +/**************************************************************************** + * Name: esp_rand + * + * Description: + * Get random data of type uint32_t + * + * Input Parameters: + * None + * + * Returned Value: + * Random data + * + ****************************************************************************/ + +static uint32_t esp_rand(void) +{ + return esp_random(); +} + +/**************************************************************************** + * Name: esp_clk_slowclk_cal_get_wrapper + * + * Description: + * Get the calibration value of RTC slow clock + * + * Input Parameters: + * None + * + * Returned Value: + * The calibration value obtained using rtc_clk_cal + * + ****************************************************************************/ + +static uint32_t esp_clk_slowclk_cal_get_wrapper(void) +{ + /* The bit width of WiFi light sleep clock calibration is 12 while the one + * of the system is 19. It should shift 19 - 12 = 7. + */ + + if (REG_GET_FIELD(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_XTAL)) + { + uint64_t time_per_us = 1000000ULL; + return (((time_per_us << RTC_CLK_CAL_FRACT) / (MHZ)) >> + (RTC_CLK_CAL_FRACT - SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH)); + } + else + { + return (getreg32(RTC_SLOW_CLK_CAL_REG) >> + (RTC_CLK_CAL_FRACT - SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH)); + } +} + +/**************************************************************************** + * Name: esp_log_writev + * + * Description: + * Output log with by format string and its arguments + * + * Input Parameters: + * level - log level, no mean here + * tag - log TAG, no mean here + * format - format string + * args - arguments list + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_log_writev(uint32_t level, const char *tag, + const char *format, va_list args) +{ + switch (level) + { +#ifdef CONFIG_DEBUG_WIRELESS_ERROR + case ESP_LOG_ERROR: + vsyslog(LOG_ERR, format, args); + break; +#endif +#ifdef CONFIG_DEBUG_WIRELESS_WARN + case ESP_LOG_WARN: + vsyslog(LOG_WARNING, format, args); + break; +#endif +#ifdef CONFIG_DEBUG_WIRELESS_INFO + case ESP_LOG_INFO: + vsyslog(LOG_INFO, format, args); + break; + default: + vsyslog(LOG_DEBUG, format, args); + break; +#endif + } +} + +/**************************************************************************** + * Name: esp_log_write + * + * Description: + * Output log with by format string and its arguments + * + * Input Parameters: + * level - log level, no mean here + * tag - log TAG, no mean here + * format - format string + * + * Returned Value: + * None + * + ****************************************************************************/ + +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); +} + +/**************************************************************************** + * Name: esp_log_timestamp + * + * Description: + * Get system time by millim second + * + * Input Parameters: + * None + * + * Returned Value: + * System time + * + ****************************************************************************/ + +uint32_t esp_log_timestamp(void) +{ + return (uint32_t)(esp_timer_get_time() / 1000); +} + +/**************************************************************************** + * Name: esp_malloc_internal + * + * Description: + * Drivers allocate a block of memory + * + * Input Parameters: + * size - memory size + * + * Returned Value: + * Memory pointer + * + ****************************************************************************/ + +static void *esp_malloc_internal(size_t size) +{ +#ifdef CONFIG_MM_KERNEL_HEAP + return kmm_malloc(size); +#elif defined(CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP) + return xtensa_imm_malloc(size); +#else + void *ptr = kmm_malloc(size); + + if (ptr != NULL) + { + if (esp32s3_ptr_extram(ptr)) + { + kmm_free(ptr); + return NULL; + } + } + + return ptr; +#endif +} + +/**************************************************************************** + * Name: esp_realloc_internal + * + * Description: + * Drivers allocate a block of memory by old memory block + * + * Input Parameters: + * ptr - old memory pointer + * size - memory size + * + * Returned Value: + * New memory pointer + * + ****************************************************************************/ + +static void *esp_realloc_internal(void *ptr, size_t size) +{ +#ifdef CONFIG_MM_KERNEL_HEAP + return kmm_realloc(ptr, size); +#elif defined(CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP) + return xtensa_imm_realloc(ptr, size); +#else + void *old_ptr = ptr; + void *new_ptr = NULL; + size_t old_size = 0; + if (size == 0) + { + kmm_free(ptr); + return NULL; + } + + new_ptr = kmm_malloc(size); + if (new_ptr != NULL) + { + if (esp32s3_ptr_extram(new_ptr)) + { + kmm_free(new_ptr); + return NULL; + } + + old_size = kmm_malloc_size(old_ptr); + DEBUGASSERT(old_size > 0); + memcpy(new_ptr, old_ptr, MIN(old_size, size)); + kmm_free(old_ptr); + return new_ptr; + } + + return NULL; +#endif +} + +/**************************************************************************** + * Name: esp_calloc_internal + * + * Description: + * Drivers allocate some continuous blocks of memory + * + * Input Parameters: + * n - memory block number + * size - memory block size + * + * Returned Value: + * New memory pointer + * + ****************************************************************************/ + +static void *esp_calloc_internal(size_t n, size_t size) +{ +#ifdef CONFIG_MM_KERNEL_HEAP + return kmm_calloc(n, size); +#elif defined(CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP) + return xtensa_imm_calloc(n, size); +#else + void *ptr = kmm_calloc(n, size); + if (esp32s3_ptr_extram(ptr)) + { + kmm_free(ptr); + return NULL; + } + + return ptr; +#endif +} + +/**************************************************************************** + * Name: esp_zalloc_internal + * + * Description: + * Drivers allocate a block of memory and clear it with 0 + * + * Input Parameters: + * size - memory size + * + * Returned Value: + * New memory pointer + * + ****************************************************************************/ + +static void *esp_zalloc_internal(size_t size) +{ +#ifdef CONFIG_MM_KERNEL_HEAP + return kmm_zalloc(size); +#elif defined(CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP) + return xtensa_imm_zalloc(size); +#else + void *ptr = kmm_zalloc(size); + if (esp32s3_ptr_extram(ptr)) + { + kmm_free(ptr); + return NULL; + } + + return ptr; +#endif +} + +/**************************************************************************** + * Name: esp_wifi_malloc + * + * Description: + * Applications allocate a block of memory + * + * Input Parameters: + * size - memory size + * + * Returned Value: + * Memory pointer + * + ****************************************************************************/ + +static void *esp_wifi_malloc(size_t size) +{ + return kmm_malloc(size); +} + +/**************************************************************************** + * Name: esp_wifi_realloc + * + * Description: + * Applications allocate a block of memory by old memory block + * + * Input Parameters: + * ptr - old memory pointer + * size - memory size + * + * Returned Value: + * New memory pointer + * + ****************************************************************************/ + +static void *esp_wifi_realloc(void *ptr, size_t size) +{ + return kmm_realloc(ptr, size); +} + +/**************************************************************************** + * Name: esp_wifi_calloc + * + * Description: + * Applications allocate some continuous blocks of memory + * + * Input Parameters: + * n - memory block number + * size - memory block size + * + * Returned Value: + * New memory pointer + * + ****************************************************************************/ + +static void *esp_wifi_calloc(size_t n, size_t size) +{ + return kmm_calloc(n, size); +} + +/**************************************************************************** + * Name: esp_wifi_zalloc + * + * Description: + * Applications allocate a block of memory and clear it with 0 + * + * Input Parameters: + * size - memory size + * + * Returned Value: + * New memory pointer + * + ****************************************************************************/ + +static void *esp_wifi_zalloc(size_t size) +{ + return kmm_zalloc(size); +} + +/**************************************************************************** + * Name: esp_wifi_create_queue + * + * Description: + * Create Wi-Fi static message queue + * + * Input Parameters: + * queue_len - queue message number + * item_size - message size + * + * Returned Value: + * Wi-Fi static message queue data pointer + * + ****************************************************************************/ + +static void *esp_wifi_create_queue(int32_t queue_len, int32_t item_size) +{ + wifi_static_queue_t *wifi_queue; + + wifi_queue = kmm_malloc(sizeof(wifi_static_queue_t)); + if (!wifi_queue) + { + wlerr("Failed to kmm_malloc\n"); + return NULL; + } + + wifi_queue->handle = esp_queue_create(queue_len, item_size); + if (!wifi_queue->handle) + { + wlerr("Failed to create queue\n"); + kmm_free(wifi_queue); + return NULL; + } + + return wifi_queue; +} + +/**************************************************************************** + * Name: esp_wifi_delete_queue + * + * Description: + * Delete Wi-Fi static message queue + * + * Input Parameters: + * queue - Wi-Fi static message queue data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_wifi_delete_queue(void *queue) +{ + wifi_static_queue_t *wifi_queue = (wifi_static_queue_t *)queue; + + esp_queue_delete(wifi_queue->handle); + kmm_free(wifi_queue); +} + +/**************************************************************************** + * Name: wifi_coex_init + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_init(void) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_deinit + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void wifi_coex_deinit(void) +{ + return; +} + +/**************************************************************************** + * 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) +{ + return; +} + +/**************************************************************************** + * Name: esp_coex_status_get + * + * Description: + * Don't support + * + ****************************************************************************/ + +static uint32_t esp_coex_status_get(void) +{ + return 0; +} + +/**************************************************************************** + * Name: esp_coex_condition_set + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void esp_coex_condition_set(uint32_t type, bool dissatisfy) +{ + return; +} + +/**************************************************************************** + * Name: esp_coex_wifi_request + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int32_t esp_coex_wifi_request(uint32_t event, uint32_t latency, + uint32_t duration) +{ + return 0; +} + +/**************************************************************************** + * Name: esp_coex_wifi_release + * + * Description: + * Don't support + * + ****************************************************************************/ + +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) +{ + return; +} + +/**************************************************************************** + * 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) +{ + return; +} + +/**************************************************************************** + * 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 0; +} + +/**************************************************************************** + * 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: wifi_coex_register_start_cb_wrapper + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_register_start_cb_wrapper(int (* cb)(void)) +{ + return 0; +} + +/**************************************************************************** + * Name: esp_random_ulong + * + * Description: + * A simpler wrapper of esp_random. + * Just convert the return value from uint32_t to unsigned long. + * + ****************************************************************************/ + +static unsigned long esp_random_ulong(void) +{ + return esp_random(); +} + +/**************************************************************************** + * Name: esp_wifi_tx_done_cb + * + * Description: + * Wi-Fi TX done callback function. + * + ****************************************************************************/ + +static IRAM_ATTR void esp_wifi_tx_done_cb(uint8_t ifidx, uint8_t *data, + uint16_t *len, bool txstatus) +{ +#ifdef ESP32S3_WLAN_HAS_STA + if (ifidx == ESP_IF_WIFI_STA) + { + if (g_sta_txdone_cb) + { + g_sta_txdone_cb(data, len, txstatus); + } + } + else +#endif /* ESP32S3_WLAN_HAS_STA */ + { + wlerr("ifidx=%d is error\n", ifidx); + } +} + +/**************************************************************************** + * Name: esp_wifi_set_auth_param + * + * Description: + * Converts a ESP32-S3 authenticate mode values to WEXT authenticate mode. + * + * Input Parameters: + * wifi_auth - ESP32-S3 authenticate mode + * + * Returned Value: + * authenticate mode + * + ****************************************************************************/ + +static int esp_wifi_auth_trans(uint32_t wifi_auth) +{ + int auth_mode = IW_AUTH_WPA_VERSION_DISABLED; + + switch (wifi_auth) + { + case WIFI_AUTH_OPEN: + auth_mode = IW_AUTH_WPA_VERSION_DISABLED; + break; + + case WIFI_AUTH_WPA_PSK: + auth_mode = IW_AUTH_WPA_VERSION_WPA; + break; + + case WIFI_AUTH_WPA2_PSK: + case WIFI_AUTH_WPA_WPA2_PSK: + auth_mode = IW_AUTH_WPA_VERSION_WPA2; + break; + + default: + wlerr("Failed to transfer wireless authmode: %d", wifi_auth); + break; + } + + return auth_mode; +} + +/**************************************************************************** + * Name: esp_wifi_set_auth_param + * + * Description: + * Converts a ESP32-S3 cipher type values to WEXT cipher type values. + * + * Input Parameters: + * wifi_cipher - ESP32-S3 cipher type + * + * Returned Value: + * cipher type + * + ****************************************************************************/ + +static int esp_wifi_cipher_trans(uint32_t wifi_cipher) +{ + int cipher_mode = IW_AUTH_CIPHER_NONE; + + switch (wifi_cipher) + { + case WIFI_CIPHER_TYPE_NONE: + cipher_mode = IW_AUTH_CIPHER_NONE; + break; + + case WIFI_CIPHER_TYPE_WEP40: + cipher_mode = IW_AUTH_CIPHER_WEP40; + break; + + case WIFI_CIPHER_TYPE_WEP104: + cipher_mode = IW_AUTH_CIPHER_WEP104; + break; + + case WIFI_CIPHER_TYPE_TKIP: + cipher_mode = IW_AUTH_CIPHER_TKIP; + break; + + case WIFI_CIPHER_TYPE_CCMP: + case WIFI_CIPHER_TYPE_TKIP_CCMP: + cipher_mode = IW_AUTH_CIPHER_CCMP; + break; + + case WIFI_CIPHER_TYPE_AES_CMAC128: + cipher_mode = IW_AUTH_CIPHER_AES_CMAC; + break; + + default: + wlerr("Failed to transfer wireless authmode: %d", + wifi_cipher); + break; + } + + return cipher_mode; +} + +/**************************************************************************** + * Name: esp_freq_to_channel + * + * Description: + * Converts Wi-Fi frequency to channel. + * + * Input Parameters: + * freq - Wi-Fi frequency + * + * Returned Value: + * Wi-Fi channel + * + ****************************************************************************/ + +static int esp_freq_to_channel(uint16_t freq) +{ + int channel = 0; + if (freq >= 2412 && freq <= 2484) + { + if (freq == 2484) + { + channel = 14; + } + else + { + channel = freq - 2407; + if (channel % 5) + { + return 0; + } + + channel /= 5; + } + + return channel; + } + + if (freq >= 5005 && freq < 5900) + { + if (freq % 5) + { + return 0; + } + + channel = (freq - 5000) / 5; + return channel; + } + + if (freq >= 4905 && freq < 5000) + { + if (freq % 5) + { + return 0; + } + + channel = (freq - 4000) / 5; + return channel; + } + + return 0; +} + +/**************************************************************************** + * Functions needed by libpp.a + ****************************************************************************/ + +/**************************************************************************** + * Name: pp_printf + * + * Description: + * Output format string and its arguments + * + * Input Parameters: + * format - format string + * + * Returned Value: + * 0 + * + ****************************************************************************/ + +int pp_printf(const char *format, ...) +{ +#ifdef CONFIG_DEBUG_WIRELESS_INFO + va_list arg; + + va_start(arg, format); + vsyslog(LOG_INFO, format, arg); + va_end(arg); +#endif + + return 0; +} + +/**************************************************************************** + * Functions needed by libnet80211.a + ****************************************************************************/ + +/**************************************************************************** + * Name: net80211_printf + * + * Description: + * Output format string and its arguments + * + * Input Parameters: + * format - format string + * + * Returned Value: + * 0 + * + ****************************************************************************/ + +int net80211_printf(const char *format, ...) +{ +#ifdef CONFIG_DEBUG_WIRELESS_INFO + va_list arg; + + va_start(arg, format); + vsyslog(LOG_INFO, format, arg); + va_end(arg); +#endif + + return 0; +} + +/**************************************************************************** + * Functions needed by libmesh.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; +} + +/**************************************************************************** + * Functions needed by libwpa_supplicant.a + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_timer_create + * + * Description: + * Create timer with given arguments + * + * Input Parameters: + * create_args - Timer arguments data pointer + * out_handle - Timer handle pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_create(const esp_timer_create_args_t *create_args, + esp_timer_handle_t *out_handle) +{ + int ret; + struct rt_timer_args_s rt_timer_args; + struct rt_timer_s *rt_timer; + + rt_timer_args.arg = create_args->arg; + rt_timer_args.callback = create_args->callback; + + ret = esp32s3_rt_timer_create(&rt_timer_args, &rt_timer); + if (ret) + { + wlerr("Failed to create rt_timer error=%d\n", ret); + return ret; + } + + *out_handle = (esp_timer_handle_t)rt_timer; + + return 0; +} + +/**************************************************************************** + * Name: esp_timer_start_once + * + * Description: + * Start timer with one shot mode + * + * Input Parameters: + * timer - Timer handle pointer + * timeout_us - Timeout value by micro second + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us) +{ + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; + + esp32s3_rt_timer_start(rt_timer, timeout_us, false); + + return 0; +} + +/**************************************************************************** + * Name: esp_timer_start_periodic + * + * Description: + * Start timer with periodic mode + * + * Input Parameters: + * timer - Timer handle pointer + * period - Timeout value by micro second + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) +{ + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; + + esp32s3_rt_timer_start(rt_timer, period, true); + + return 0; +} + +/**************************************************************************** + * Name: esp_timer_stop + * + * Description: + * Stop timer + * + * Input Parameters: + * timer - Timer handle pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_stop(esp_timer_handle_t timer) +{ + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; + + esp32s3_rt_timer_stop(rt_timer); + + return 0; +} + +/**************************************************************************** + * Name: esp_timer_delete + * + * Description: + * Delete timer and free resource + * + * Input Parameters: + * timer - Timer handle pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_delete(esp_timer_handle_t timer) +{ + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; + + esp32s3_rt_timer_delete(rt_timer); + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_event_send_internal + * + * Description: + * Post event message to queue + * + * Input Parameters: + * event_base - Event set name + * event_id - Event ID + * event_data - Event private data + * event_data_size - Event data size + * ticks_to_wait - Waiting system ticks + * + * Returned Value: + * Task maximum priority + * + ****************************************************************************/ + +int32_t esp_event_send_internal(esp_event_base_t event_base, + int32_t event_id, + void *event_data, + size_t event_data_size, + uint32_t ticks_to_wait) +{ + int32_t ret; + + ret = esp_event_post(event_base, event_id, event_data, + event_data_size, ticks_to_wait); + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_init + * + * Description: + * Initialize Wi-Fi + * + * Input Parameters: + * config - Initialization config parameters + * + * Returned Value: + * 0 if success or others if fail + * + ****************************************************************************/ + +int32_t esp_wifi_init(const wifi_init_config_t *config) +{ + int32_t ret; + + modifyreg32(SYSTEM_WIFI_CLK_EN_REG, 0, SYSTEM_WIFI_CLK_EN); + + modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD, 0); + + modifyreg32(SYSCON_WIFI_RST_EN_REG, 0, MODEM_RESET_FIELD_WHEN_PU); + modifyreg32(SYSCON_WIFI_RST_EN_REG, MODEM_RESET_FIELD_WHEN_PU, 0); + + modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO, 0); + + esp_wifi_internal_set_log_level(WIFI_LOG_DEBUG); + + ret = esp_wifi_init_internal(config); + if (ret) + { + wlerr("Failed to initialize Wi-Fi error=%d\n", ret); + return ret; + } + + ret = esp_supplicant_init(); + if (ret) + { + wlerr("Failed to initialize WPA supplicant error=%d\n", ret); + esp_wifi_deinit_internal(); + return ret; + } + + return 0; +} + +/**************************************************************************** + * Name: esp_wifi_deinit + * + * Description: + * Deinitialize Wi-Fi and free resource + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or others if fail + * + ****************************************************************************/ + +int32_t esp_wifi_deinit(void) +{ + int ret; + + ret = esp_supplicant_deinit(); + if (ret) + { + wlerr("Failed to deinitialize supplicant\n"); + return ret; + } + + ret = esp_wifi_deinit_internal(); + if (ret != 0) + { + wlerr("Failed to deinitialize Wi-Fi\n"); + return ret; + } + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_free_eb + * + * Description: + * Free Wi-Fi receive callback input eb pointer + * + * Input Parameters: + * eb - Wi-Fi receive callback input eb pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_free_eb(void *eb) +{ + esp_wifi_internal_free_rx_buffer(eb); +} + +/**************************************************************************** + * Name: esp_wifi_notify_subscribe + * + * Description: + * Enable event notification + * + * Input Parameters: + * pid - Task PID + * event - Signal event data pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_notify_subscribe(pid_t pid, struct sigevent *event) +{ + int id; + struct wifi_notify *notify; + int ret = -1; + + wlinfo("PID=%d event=%p\n", pid, event); + + esp_wifi_lock(true); + + if (event->sigev_notify == SIGEV_SIGNAL) + { + id = esp_event_id_map(event->sigev_signo); + if (id < 0) + { + wlerr("No process event %d\n", event->sigev_signo); + } + else + { + notify = &g_wifi_notify[id]; + + if (notify->assigned) + { + wlerr("sigev_signo %d has subscribed\n", + event->sigev_signo); + } + else + { + if (pid == 0) + { + pid = nxsched_getpid(); + wlinfo("Actual PID=%d\n", pid); + } + + notify->pid = pid; + notify->event = *event; + notify->assigned = true; + + ret = 0; + } + } + } + else if (event->sigev_notify == SIGEV_NONE) + { + id = esp_event_id_map(event->sigev_signo); + if (id < 0) + { + wlerr("No process event %d\n", event->sigev_signo); + } + else + { + notify = &g_wifi_notify[id]; + + if (!notify->assigned) + { + wlerr("sigev_signo %d has not subscribed\n", + event->sigev_signo); + } + else + { + notify->assigned = false; + + ret = 0; + } + } + } + else + { + wlerr("sigev_notify %d is invalid\n", event->sigev_signo); + } + + esp_wifi_lock(false); + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_adapter_init + * + * Description: + * Initialize ESP32-S3 Wi-Fi adapter + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_adapter_init(void) +{ + int ret; + wifi_init_config_t wifi_cfg = WIFI_INIT_CONFIG_DEFAULT(); + + esp_wifi_lock(true); + + if (g_wifi_ref) + { + wlinfo("Wi-Fi adapter is already initialized\n"); + g_wifi_ref++; + esp_wifi_lock(false); + return OK; + } + + sq_init(&g_wifi_evt_queue); + +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + wifi_cfg.nvs_enable = 1; +#else + wifi_cfg.nvs_enable = 0; +#endif + +#ifdef CONFIG_ESP32S3_WIFI_TX_AMPDU + wifi_cfg.ampdu_tx_enable = 1; +#else + wifi_cfg.ampdu_tx_enable = 0; +#endif + +#ifdef CONFIG_ESP32S3_WIFI_RX_AMPDU + wifi_cfg.ampdu_rx_enable = 1; +#else + wifi_cfg.ampdu_rx_enable = 0; +#endif + +#ifdef CONFIG_ESP32S3_WIFI_STA_DISCONNECT_PM + wifi_cfg.sta_disconnected_pm = true; +#else + wifi_cfg.sta_disconnected_pm = false; +#endif + + wifi_cfg.rx_ba_win = CONFIG_ESP32S3_WIFI_RXBA_AMPDU_WZ; + wifi_cfg.static_rx_buf_num = CONFIG_ESP32S3_WIFI_STATIC_RXBUF_NUM; + wifi_cfg.dynamic_rx_buf_num = CONFIG_ESP32S3_WIFI_DYNAMIC_RXBUF_NUM; + wifi_cfg.dynamic_tx_buf_num = CONFIG_ESP32S3_WIFI_DYNAMIC_TXBUF_NUM; + + ret = esp_wifi_init(&wifi_cfg); + if (ret) + { + wlerr("Failed to initialize Wi-Fi error=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_init_wifi; + } + + ret = esp_wifi_set_tx_done_cb(esp_wifi_tx_done_cb); + if (ret) + { + wlerr("Failed to register TX done callback ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_init_txdone; + } + + g_wifi_ref++; + + wlinfo("OK to initialize Wi-Fi adapter\n"); + + esp_wifi_lock(false); + + return OK; + +errout_init_txdone: + esp_wifi_deinit(); +errout_init_wifi: + esp_wifi_lock(false); + + return ret; +} + +/**************************************************************************** + * Station functions + ****************************************************************************/ + +#ifdef ESP32S3_WLAN_HAS_STA + +/**************************************************************************** + * Name: esp_wifi_sta_start + * + * Description: + * Start Wi-Fi station. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_start(void) +{ + int ret; + wifi_mode_t mode; + + esp_wifi_lock(true); + + ret = esp_wifi_stop(); + if (ret) + { + wlinfo("Failed to stop Wi-Fi ret=%d\n", ret); + } + + mode = WIFI_MODE_STA; + + ret = esp_wifi_set_mode(mode); + if (ret) + { + wlerr("Failed to set Wi-Fi mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + + ret = esp_wifi_start(); + if (ret) + { + wlerr("Failed to start Wi-Fi with mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + + g_sta_started = true; + + wlinfo("OK to start Wi-Fi station\n"); + + esp_wifi_lock(false); + return OK; + +errout_set_mode: + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_sta_stop + * + * Description: + * Stop Wi-Fi station. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_stop(void) +{ + int ret; + + esp_wifi_lock(true); + + ret = esp_wifi_stop(); + if (ret) + { + wlinfo("Failed to stop Wi-Fi ret=%d\n", ret); + } + + g_sta_started = false; + + wlinfo("OK to stop Wi-Fi station\n"); + + esp_wifi_lock(false); + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_send_data + * + * Description: + * Use Wi-Fi station interface to send 802.3 frame + * + * Input Parameters: + * pbuf - Packet buffer pointer + * len - Packet length + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_send_data(void *pbuf, uint32_t len) +{ + int ret; + + ret = esp_wifi_internal_tx(WIFI_IF_STA, pbuf, len); + + return wifi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_wifi_sta_register_recv_cb + * + * Description: + * Register Wi-Fi station receive packet callback function + * + * Input Parameters: + * recv_cb - Receive callback function + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_register_recv_cb(int (*recv_cb)(void *buffer, + uint16_t len, + void *eb)) +{ + int ret; + + ret = esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, (wifi_rxcb_t)recv_cb); + + return wifi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_wifi_sta_register_txdone_cb + * + * Description: + * Register the station TX done callback function. + * + * Input Parameters: + * cb - The callback function + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_sta_register_txdone_cb(wifi_txdone_cb_t cb) +{ + g_sta_txdone_cb = cb; +} + +/**************************************************************************** + * Name: esp_wifi_sta_read_mac + * + * Description: + * Read station interface MAC address from efuse + * + * Input Parameters: + * mac - MAC address buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_sta_read_mac(uint8_t *mac) +{ + return esp_read_mac(mac, ESP_MAC_WIFI_STA); +} + +/**************************************************************************** + * Name: esp_wifi_set_password + * + * Description: + * Set/Get Wi-Fi station password + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_password(struct iwreq *iwr, bool set) +{ + int ret; + int size; + wifi_config_t wifi_cfg; + struct iw_encode_ext *ext = iwr->u.encoding.pointer; + uint8_t *pdata; + uint8_t len; +#ifdef CONFIG_DEBUG_WIRELESS_INFO + char buf[PWD_MAX_LEN + 1]; +#endif + + DEBUGASSERT(ext != NULL); + + pdata = ext->key; + len = ext->key_len; + + if (set && len > PWD_MAX_LEN) + { + return -EINVAL; + } + + ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + if (set) + { + memset(wifi_cfg.sta.password, 0x0, PWD_MAX_LEN); + memcpy(wifi_cfg.sta.password, pdata, len); + + wifi_cfg.sta.pmf_cfg.capable = true; + wifi_cfg.sta.listen_interval = DEFAULT_LISTEN_INTERVAL; + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + size = strnlen((char *)wifi_cfg.sta.password, PWD_MAX_LEN); + if (len < size) + { + return -EINVAL; + } + else + { + len = size; + memcpy(pdata, wifi_cfg.sta.password, len); + } + + if (g_sta_connected) + { + wifi_ap_record_t ap_info; + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("Failed to get AP record ret=%d", ret); + return wifi_errno_trans(ret); + } + + switch (ap_info.pairwise_cipher) + { + case WIFI_CIPHER_TYPE_NONE: + ext->alg = IW_ENCODE_ALG_NONE; + break; + + case WIFI_CIPHER_TYPE_WEP40: + case WIFI_CIPHER_TYPE_WEP104: + ext->alg = IW_ENCODE_ALG_WEP; + break; + + case WIFI_CIPHER_TYPE_TKIP: + ext->alg = IW_ENCODE_ALG_TKIP; + break; + + case WIFI_CIPHER_TYPE_CCMP: + case WIFI_CIPHER_TYPE_TKIP_CCMP: + ext->alg = IW_ENCODE_ALG_CCMP; + break; + + case WIFI_CIPHER_TYPE_AES_CMAC128: + ext->alg = IW_ENCODE_ALG_AES_CMAC; + break; + + default: + wlerr("Failed to transfer wireless authmode: %d", + ap_info.pairwise_cipher); + return -EIO; + } + } + } + +#ifdef CONFIG_DEBUG_WIRELESS_INFO + memcpy(buf, pdata, len); + buf[len] = 0; + wlinfo("Wi-Fi station password=%s len=%d\n", buf, len); +#endif + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_essid + * + * Description: + * Set/Get Wi-Fi station ESSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_essid(struct iwreq *iwr, bool set) +{ + int ret; + int size; + wifi_config_t wifi_cfg; + struct iw_point *essid = &iwr->u.essid; + uint8_t *pdata; + uint8_t len; +#ifdef CONFIG_DEBUG_WIRELESS_INFO + char buf[SSID_MAX_LEN + 1]; +#endif + + DEBUGASSERT(essid != NULL); + + pdata = essid->pointer; + len = essid->length; + + if (set && len > SSID_MAX_LEN) + { + return -EINVAL; + } + + ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + if (set) + { + memset(wifi_cfg.sta.ssid, 0x0, SSID_MAX_LEN); + memcpy(wifi_cfg.sta.ssid, pdata, len); + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_OPEN; + wifi_cfg.sta.sae_pwe_h2e = WPA3_SAE_PWE_BOTH; + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + size = strnlen((char *)wifi_cfg.sta.ssid, SSID_MAX_LEN); + if (len < size) + { + return -EINVAL; + } + else + { + len = size; + memcpy(pdata, wifi_cfg.sta.ssid, len); + } + + if (g_sta_connected) + { + essid->flags = IW_ESSID_ON; + } + else + { + essid->flags = IW_ESSID_OFF; + } + } + +#ifdef CONFIG_DEBUG_WIRELESS_INFO + memcpy(buf, pdata, len); + buf[len] = 0; + wlinfo("Wi-Fi station ssid=%s len=%d\n", buf, len); +#endif + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_bssid + * + * Description: + * Set/Get Wi-Fi station BSSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_bssid(struct iwreq *iwr, bool set) +{ + int ret; + wifi_config_t wifi_cfg; + struct sockaddr *sockaddr; + char *pdata; + + ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + sockaddr = &iwr->u.ap_addr; + pdata = sockaddr->sa_data; + + if (set) + { + wifi_cfg.sta.bssid_set = true; + memcpy(wifi_cfg.sta.bssid, pdata, MAC_LEN); + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + memcpy(pdata, wifi_cfg.sta.bssid, MAC_LEN); + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_connect + * + * Description: + * Trigger Wi-Fi station connection action + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_connect(void) +{ + int ret; + uint32_t ticks; + + esp_wifi_lock(true); + + if (g_sta_connected) + { + wlinfo("Wi-Fi has connected AP\n"); + esp_wifi_lock(false); + return OK; + } + + g_sta_reconnect = true; + + ret = esp_wifi_connect(); + if (ret) + { + wlerr("Failed to connect ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_wifi_connect; + } + + esp_wifi_lock(false); + + ticks = SEC2TICK(WIFI_CONNECT_TIMEOUT); + do + { + if (g_sta_connected) + { + break; + } + + esp_task_delay(1); + } + while (ticks--); + + if (!g_sta_connected) + { + g_sta_reconnect = false; + wlinfo("Failed to connect to AP\n"); + return -1; + } + + return OK; + +errout_wifi_connect: + g_sta_reconnect = false; + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_sta_disconnect + * + * Description: + * Trigger Wi-Fi station disconnection action + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_disconnect(void) +{ + int ret; + + esp_wifi_lock(true); + + g_sta_reconnect = false; + + ret = esp_wifi_disconnect(); + if (ret) + { + wlerr("Failed to disconnect ret=%d\n", ret); + ret = wifi_errno_trans(ret); + } + else + { + wlinfo("OK to disconnect Wi-Fi station\n"); + } + + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_sta_mode + * + * Description: + * Set/Get Wi-Fi Station mode code. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_mode(struct iwreq *iwr, bool set) +{ + if (set == false) + { + iwr->u.mode = IW_MODE_INFRA; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_auth + * + * Description: + * Set/Get station authentication mode params. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_auth(struct iwreq *iwr, bool set) +{ + int ret; + int cmd; + wifi_ap_record_t ap_info; + + if (set) + { + return OK; + } + else + { + if (g_sta_connected == false) + { + return -ENOTCONN; + } + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + cmd = iwr->u.param.flags & IW_AUTH_INDEX; + switch (cmd) + { + case IW_AUTH_WPA_VERSION: + iwr->u.param.value = esp_wifi_auth_trans(ap_info.authmode); + break; + + case IW_AUTH_CIPHER_PAIRWISE: + iwr->u.param.value = + esp_wifi_cipher_trans(ap_info.pairwise_cipher); + break; + + case IW_AUTH_CIPHER_GROUP: + iwr->u.param.value = esp_wifi_cipher_trans(ap_info.group_cipher); + break; + + case IW_AUTH_KEY_MGMT: + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_80211_AUTH_ALG: + case IW_AUTH_WPA_ENABLED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + default: + wlerr("Unknown cmd %d\n", cmd); + return -ENOSYS; + } + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_freq + * + * Description: + * Set/Get station frequency. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_freq(struct iwreq *iwr, bool set) +{ + int ret; + wifi_config_t wifi_cfg; + + if (set && (iwr->u.freq.flags == IW_FREQ_FIXED)) + { + ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + wifi_cfg.sta.channel = esp_freq_to_channel(iwr->u.freq.m); + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + if (g_sta_connected) + { + wifi_ap_record_t ap_info; + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.freq.flags = IW_FREQ_FIXED; + iwr->u.freq.e = 0; + iwr->u.freq.m = 2407 + 5 * ap_info.primary; + } + else + { + iwr->u.freq.flags = IW_FREQ_AUTO; + iwr->u.freq.e = 0; + iwr->u.freq.m = 2412; + } + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_bitrate + * + * Description: + * Get station default bit rate (Mbps). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_bitrate(struct iwreq *iwr, bool set) +{ + int ret; + wifi_ap_record_t ap_info; + + if (set) + { + return -ENOSYS; + } + else + { + if (g_sta_connected == false) + { + iwr->u.bitrate.fixed = IW_FREQ_AUTO; + return OK; + } + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.bitrate.fixed = IW_FREQ_FIXED; + if (ap_info.phy_11n) + { + if (ap_info.second) + { + iwr->u.bitrate.value = ESP_WIFI_11N_MCS7_HT40_BITRATE; + } + else + { + iwr->u.bitrate.value = ESP_WIFI_11N_MCS7_HT20_BITRATE; + } + } + else if (ap_info.phy_11g) + { + iwr->u.bitrate.value = ESP_WIFI_11G_MAX_BITRATE; + } + else if (ap_info.phy_11b) + { + iwr->u.bitrate.value = ESP_WIFI_11B_MAX_BITRATE; + } + else + { + return -EIO; + } + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_get_txpower + * + * Description: + * Get station transmit power (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_txpower(struct iwreq *iwr, bool set) +{ + int ret; + int8_t power; + double power_dbm; + + if (set) + { + if (iwr->u.txpower.flags == IW_TXPOW_RELATIVE) + { + power = (int8_t)iwr->u.txpower.value; + } + else + { + if (iwr->u.txpower.flags == IW_TXPOW_MWATT) + { + power_dbm = ceil(10 * log10(iwr->u.txpower.value)); + } + else + { + power_dbm = iwr->u.txpower.value; + } + + power = (int8_t)(power_dbm * 4); + } + + /* The value set by this API will be mapped to the max_tx_power + * of the structure wifi_country_t variable. Param power unit is + * 0.25dBm, range is [8, 84] corresponding to 2dBm - 20dBm. + * Relationship between set value and actual value. + * As follows: {set value range, actual value} = + * {{[8, 19],8}, {[20, 27],20}, {[28, 33],28}, + * {[34, 43],34}, {[44, 51],44}, {[52, 55],52}, + * {[56, 59],56}, {[60, 65],60}, {[66, 71],66}, + * {[72, 79],72}, {[80, 84],80}}. + */ + + if (power < 8 || power > 84) + { + wlerr("Failed to set transmit power =%d\n", power); + return -ENOSYS; + } + + esp_wifi_set_max_tx_power(power); + return OK; + } + else + { + ret = esp_wifi_get_max_tx_power(&power); + if (ret) + { + wlerr("Failed to get transmit power ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.txpower.disabled = 0; + iwr->u.txpower.flags = IW_TXPOW_DBM; + iwr->u.txpower.value = power / 4; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_get_channel_range + * + * Description: + * Get station range of channel parameters. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_channel(struct iwreq *iwr, bool set) +{ + int ret; + int k; + wifi_country_t country; + struct iw_range *range; + + if (set) + { + return -ENOSYS; + } + else + { + ret = esp_wifi_get_country(&country); + if (ret) + { + wlerr("Failed to get country info ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + range = (struct iw_range *)iwr->u.data.pointer; + range->num_frequency = country.nchan; + for (k = 1; k <= range->num_frequency; k++) + { + range->freq[k - 1].i = k; + range->freq[k - 1].e = 0; + range->freq[k - 1].m = 2407 + 5 * k; + } + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_country + * + * Description: + * Configure country info. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_country(struct iwreq *iwr, bool set) +{ + int ret; + char *country_code; + wifi_country_t country; + + if (set) + { + memset(&country, 0x00, sizeof(wifi_country_t)); + country.schan = 1; + country.policy = 0; + + country_code = (char *)iwr->u.data.pointer; + if (strlen(country_code) != 2) + { + wlerr("Invalid input arguments\n"); + return -EINVAL; + } + + if (strncmp(country_code, "US", 3) == 0 || + strncmp(country_code, "CA", 3) == 0) + { + country.nchan = 11; + } + else if(strncmp(country_code, "JP", 3) == 0) + { + country.nchan = 14; + } + else + { + country.nchan = 13; + } + + memcpy(country.cc, country_code, 2); + ret = esp_wifi_set_country(&country); + if (ret) + { + wlerr("Failed to Configure country ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + return -ENOSYS; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_rssi + * + * Description: + * Get Wi-Fi sensitivity (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_rssi(struct iwreq *iwr, bool set) +{ + int ret; + wifi_ap_record_t ap_info; + + if (set) + { + return -ENOSYS; + } + else + { + if (g_sta_connected == false) + { + iwr->u.sens.value = 128; + return OK; + } + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.sens.value = -(ap_info.rssi); + } + + return OK; +} +#endif /* ESP32S3_WLAN_HAS_STA */ + +/**************************************************************************** + * Name: esp_wifi_stop_callback + * + * Description: + * Callback to stop Wi-Fi + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_stop_callback(void) +{ + wlinfo("INFO: Try to stop Wi-Fi\n"); + + int ret = esp_wifi_stop(); + if (ret) + { + wlerr("ERROR: Failed to stop Wi-Fi ret=%d\n", ret); + } + else + { + nxsig_sleep(1); + } +} diff --git a/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.h b/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.h new file mode 100644 index 00000000000..77facda8a50 --- /dev/null +++ b/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.h @@ -0,0 +1,501 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WIFI_ADAPTER_H +#define __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WIFI_ADAPTER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_ESP32S3_WIFI_STATION) +# define ESP32S3_WLAN_HAS_STA +# define ESP32S3_WLAN_STA_DEVNO 0 +# define ESP32S3_WLAN_DEVS 1 +#endif + +#define SSID_MAX_LEN (32) +#define PWD_MAX_LEN (64) + +#define CONFIG_IDF_TARGET_ESP32S3 1 + +/* Define esp_err_t */ + +typedef int esp_err_t; + +/* Wi-Fi event ID */ + +enum wifi_adpt_evt_e +{ + WIFI_ADPT_EVT_SCAN_DONE = 0, + WIFI_ADPT_EVT_STA_START, + WIFI_ADPT_EVT_STA_CONNECT, + WIFI_ADPT_EVT_STA_DISCONNECT, + WIFI_ADPT_EVT_STA_AUTHMODE_CHANGE, + WIFI_ADPT_EVT_STA_STOP, + WIFI_ADPT_EVT_AP_START, + WIFI_ADPT_EVT_AP_STOP, + WIFI_ADPT_EVT_AP_STACONNECTED, + WIFI_ADPT_EVT_AP_STADISCONNECTED, + WIFI_ADPT_EVT_MAX, +}; + +/* Wi-Fi event callback function */ + +typedef void (*wifi_evt_cb_t)(void *p); + +/* Wi-Fi TX done callback function */ + +typedef void (*wifi_txdone_cb_t)(uint8_t *data, uint16_t *len, bool status); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_wifi_adapter_init + * + * Description: + * Initialize ESP32S3 Wi-Fi adapter + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_adapter_init(void); + +/**************************************************************************** + * Name: esp_wifi_free_eb + * + * Description: + * Free Wi-Fi receive callback input eb pointer + * + * Input Parameters: + * eb - Wi-Fi receive callback input eb pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_free_eb(void *eb); + +/**************************************************************************** + * Name: esp_wifi_notify_subscribe + * + * Description: + * Enable event notification + * + * Input Parameters: + * pid - Task PID + * event - Signal event data pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_notify_subscribe(pid_t pid, struct sigevent *event); + +#ifdef ESP32S3_WLAN_HAS_STA + +/**************************************************************************** + * Name: esp_wifi_sta_start + * + * Description: + * Start Wi-Fi station. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_start(void); + +/**************************************************************************** + * Name: esp_wifi_sta_stop + * + * Description: + * Stop Wi-Fi station. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_stop(void); + +/**************************************************************************** + * Name: esp_wifi_sta_send_data + * + * Description: + * Use Wi-Fi station interface to send 802.3 frame + * + * Input Parameters: + * pbuf - Packet buffer pointer + * len - Packet length + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_send_data(void *pbuf, uint32_t len); + +/**************************************************************************** + * Name: esp_wifi_sta_register_recv_cb + * + * Description: + * Regitser Wi-Fi station receive packet callback function + * + * Input Parameters: + * recv_cb - Receive callback function + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_register_recv_cb(int (*recv_cb)(void *buffer, + uint16_t len, + void *eb)); + +/**************************************************************************** + * Name: esp_wifi_sta_register_txdone_cb + * + * Description: + * Register the station TX done callback function. + * + * Input Parameters: + * cb - The callback function + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_sta_register_txdone_cb(wifi_txdone_cb_t cb); + +/**************************************************************************** + * Name: esp_wifi_sta_read_mac + * + * Description: + * Read station interface MAC address from efuse + * + * Input Parameters: + * mac - MAC address buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_sta_read_mac(uint8_t *mac); + +/**************************************************************************** + * Name: esp_wifi_set_password + * + * Description: + * Set/Get Wi-Fi station password + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_password(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_essid + * + * Description: + * Set/Get Wi-Fi station ESSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_essid(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_bssid + * + * Description: + * Set/Get Wi-Fi station BSSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_bssid(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_connect + * + * Description: + * Trigger Wi-Fi station connection action + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_connect(void); + +/**************************************************************************** + * Name: esp_wifi_sta_disconnect + * + * Description: + * Trigger Wi-Fi station disconnection action + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_disconnect(void); + +/**************************************************************************** + * Name: esp_wifi_sta_mode + * + * Description: + * Set/Get Wi-Fi Station mode code. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_mode(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_auth + * + * Description: + * Set/Get station authentication mode params. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_auth(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_freq + * + * Description: + * Get station frequency. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_freq(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_bitrate + * + * Description: + * Get station default bit rate (Mbps). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_bitrate(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_get_txpower + * + * Description: + * Get station transmit power (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_txpower(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_get_channel_range + * + * Description: + * Get station range of channel parameters. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_channel(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_country + * + * Description: + * Configure country info. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_country(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_rssi + * + * Description: + * Get Wi-Fi sensitivity (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_rssi(struct iwreq *iwr, bool set); +#endif /* ESP32S3_WLAN_HAS_STA */ + +/**************************************************************************** + * Name: esp_wifi_stop_callback + * + * Description: + * Callback to stop Wi-Fi + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_stop_callback(void); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WIFI_ADAPTER_H */ diff --git a/arch/xtensa/src/esp32s3/esp32s3_wifi_utils.c b/arch/xtensa/src/esp32s3/esp32s3_wifi_utils.c new file mode 100644 index 00000000000..75781bffe78 --- /dev/null +++ b/arch/xtensa/src/esp32s3/esp32s3_wifi_utils.c @@ -0,0 +1,560 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/esp32s3_wifi_utils.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "esp32s3_wifi_adapter.h" +#include "esp32s3_wifi_utils.h" +#include "esp32s3_wireless.h" +#include "espidf_wifi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Helper to get iw_event size */ + +#define ESP_IW_EVENT_SIZE(field) \ + (offsetof(struct iw_event, u) + sizeof(((union iwreq_data *)0)->field)) + +#ifdef CONFIG_ESP32S3_WIFI_SCAN_RESULT_SIZE +# define WIFI_SCAN_RESULT_SIZE CONFIG_ESP32S3_WIFI_SCAN_RESULT_SIZE +#else +# define WIFI_SCAN_RESULT_SIZE (4096) +#endif + +#define SCAN_TIME_SEC (5) + +/* Maximum number of channels for Wi-Fi 2.4Ghz */ + +#define CHANNEL_MAX_NUM (14) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +enum scan_status_e +{ + ESP_SCAN_DISABLED = 0, + ESP_SCAN_RUN, + ESP_SCAN_DONE +}; + +/* Wi-Fi scan result information */ + +struct wifi_scan_result +{ + enum scan_status_e scan_status; /* Scan status */ + sem_t scan_signal; /* Scan notification signal */ + uint8_t *scan_result; /* Temp buffer that holds results */ + unsigned int scan_result_size; /* Current size of temp buffer */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct wifi_scan_result g_scan_priv = +{ + .scan_signal = SEM_INITIALIZER(0), +}; +static uint8_t g_channel_num = 0; +static uint8_t g_channel_list[CHANNEL_MAX_NUM]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_wifi_start_scan + * + * Description: + * Scan all available APs. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_start_scan(struct iwreq *iwr) +{ + struct wifi_scan_result *priv = &g_scan_priv; + wifi_scan_config_t *config = NULL; + struct iw_scan_req *req; + int ret = 0; + int i; + uint8_t target_mac[MAC_LEN]; + uint8_t target_ssid[SSID_MAX_LEN + 1]; + memset(target_ssid, 0x0, sizeof(SSID_MAX_LEN + 1)); + + if (iwr == NULL) + { + wlerr("ERROR: Invalid ioctl cmd.\n"); + return -EINVAL; + } + + if (g_scan_priv.scan_status != ESP_SCAN_DISABLED) + { + return OK; + } + + config = kmm_calloc(1, sizeof(wifi_scan_config_t)); + if (config == NULL) + { + wlerr("ERROR: Cannot allocate result buffer\n"); + return -ENOMEM; + } + + g_channel_num = 0; + memset(g_channel_list, 0x0, CHANNEL_MAX_NUM); + + if (iwr->u.data.pointer && + iwr->u.data.length >= sizeof(struct iw_scan_req)) + { + req = (struct iw_scan_req *)iwr->u.data.pointer; + config->scan_type = (req->scan_type == IW_SCAN_TYPE_ACTIVE ? + WIFI_SCAN_TYPE_ACTIVE : WIFI_SCAN_TYPE_PASSIVE); + if (iwr->u.data.flags & IW_SCAN_THIS_ESSID && + req->essid_len < sizeof(target_ssid)) + { + /* Scan specific ESSID */ + + config->show_hidden = true; + config->bssid = NULL; + memcpy(&target_ssid[0], req->essid, req->essid_len); + config->ssid = &target_ssid[0]; + config->ssid[req->essid_len] = '\0'; + } + + if (iwr->u.data.flags & IW_SCAN_THIS_FREQ && + req->num_channels > 0) + { + /* Scan specific channels */ + + DEBUGASSERT(req->num_channels <= CHANNEL_MAX_NUM); + g_channel_num = req->num_channels; + if (req->num_channels == 1) + { + config->channel = req->channel_list[0].m; + } + else + { + for (i = 0; i < req->num_channels; i++) + { + g_channel_list[i] = req->channel_list[i].m; + } + } + } + + memset(target_mac, 0xff, MAC_LEN); + if (memcmp(req->bssid.sa_data, target_mac, MAC_LEN) != 0) + { + /* Scan specific bssid */ + + memcpy(target_mac, req->bssid.sa_data, MAC_LEN); + config->bssid = &target_mac[0]; + } + } + else + { + /* Default scan parameters */ + + wlinfo("INFO: Use default scan parameters\n"); + config->scan_type = WIFI_SCAN_TYPE_ACTIVE; /* Active scan */ + } + + esp_wifi_start(); + ret = esp_wifi_scan_start(config, false); + if (ret != OK) + { + wlerr("ERROR: Scan error, ret: %d\n", ret); + } + else + { + /* Allocate buffer to store scan result */ + + if (priv->scan_result == NULL) + { + priv->scan_result = kmm_malloc(WIFI_SCAN_RESULT_SIZE); + if (priv->scan_result == NULL) + { + wlerr("ERROR: Cannot allocate result buffer\n"); + ret = -ENOMEM; + } + else + { + memset(priv->scan_result, 0x0, WIFI_SCAN_RESULT_SIZE); + } + } + } + + if (config != NULL) + { + kmm_free(config); + config = NULL; + wlinfo("INFO: start scan\n"); + } + + g_scan_priv.scan_status = ESP_SCAN_RUN; + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_get_scan_results + * + * Description: + * Get scan result + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_get_scan_results(struct iwreq *iwr) +{ + int ret = OK; + static bool scan_block = false; + struct wifi_scan_result *priv = &g_scan_priv; + + if (g_scan_priv.scan_status == ESP_SCAN_RUN) + { + irqstate_t irqstate = enter_critical_section(); + if (scan_block == false) + { + scan_block = true; + leave_critical_section(irqstate); + nxsem_tickwait(&priv->scan_signal, SEC2TICK(SCAN_TIME_SEC)); + scan_block = false; + } + else + { + leave_critical_section(irqstate); + ret = -EINVAL; + goto exit_failed; + } + } + else if (g_scan_priv.scan_status == ESP_SCAN_DISABLED) + { + return -EINVAL; + } + + if ((iwr == NULL) || (g_scan_priv.scan_status != ESP_SCAN_DONE)) + { + ret = -EINVAL; + goto exit_failed; + } + + if (priv->scan_result == NULL) + { + /* Result have already been requested */ + + ret = OK; + iwr->u.data.length = 0; + goto exit_failed; + } + + if (iwr->u.data.pointer == NULL || + iwr->u.data.length < priv->scan_result_size) + { + /* Stat request, return scan_result_size */ + + ret = -E2BIG; + iwr->u.data.pointer = NULL; + iwr->u.data.length = priv->scan_result_size; + goto exit_failed; + } + + if (priv->scan_result_size <= 0) + { + ret = OK; + iwr->u.data.length = 0; + goto exit_free_buffer; + } + + /* Copy result to user buffer */ + + if (iwr->u.data.length > priv->scan_result_size) + { + iwr->u.data.length = priv->scan_result_size; + } + + memcpy(iwr->u.data.pointer, priv->scan_result, iwr->u.data.length); + +exit_free_buffer: + + /* Free scan result buffer */ + + kmm_free(priv->scan_result); + priv->scan_result = NULL; + priv->scan_result_size = 0; + g_scan_priv.scan_status = ESP_SCAN_DISABLED; + +exit_failed: + if (ret < 0) + { + iwr->u.data.length = 0; + } + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_scan_event_parse + * + * Description: + * Parse scan information + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_scan_event_parse(void) +{ + struct wifi_scan_result *priv = &g_scan_priv; + wifi_ap_record_t *ap_list_buffer = NULL; + uint16_t bss_total = 0; + uint8_t bss_count = 0; + bool parse_done = false; + + if (priv->scan_status != ESP_SCAN_RUN) + { + return; + } + + esp_wifi_scan_get_ap_num(&bss_total); + if (bss_total == 0) + { + priv->scan_status = ESP_SCAN_DONE; + wlinfo("INFO: None AP is scanned\n"); + nxsem_post(&priv->scan_signal); + return; + } + + ap_list_buffer = kmm_calloc(bss_total, sizeof(wifi_ap_record_t)); + if (ap_list_buffer == NULL) + { + priv->scan_status = ESP_SCAN_DONE; + wlerr("ERROR: Failed to calloc buffer to print scan results"); + nxsem_post(&priv->scan_signal); + return; + } + + if (esp_wifi_scan_get_ap_records(&bss_total, + (wifi_ap_record_t *)ap_list_buffer) == OK) + { + struct iw_event *iwe; + unsigned int result_size; + size_t essid_len; + size_t essid_len_aligned; + bool is_target_channel = true; + int i; + + for (bss_count = 0; bss_count < bss_total; bss_count++) + { + if (g_channel_num > 1) + { + is_target_channel = false; + for (i = 0; i < g_channel_num; i++) + { + if (g_channel_list[i] == ap_list_buffer[bss_count].primary) + { + is_target_channel = true; + break; + } + } + } + else + { + is_target_channel = true; + } + + if (is_target_channel == true) + { + result_size = WIFI_SCAN_RESULT_SIZE - priv->scan_result_size; + + /* Copy BSSID */ + + if (result_size < ESP_IW_EVENT_SIZE(ap_addr)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(ap_addr); + iwe->cmd = SIOCGIWAP; + memcpy(&iwe->u.ap_addr.sa_data, + ap_list_buffer[bss_count].bssid, + sizeof(ap_list_buffer[bss_count].bssid)); + iwe->u.ap_addr.sa_family = ARPHRD_ETHER; + priv->scan_result_size += ESP_IW_EVENT_SIZE(ap_addr); + result_size -= ESP_IW_EVENT_SIZE(ap_addr); + + /* Copy ESSID */ + + essid_len = MIN(strlen((const char *) + ap_list_buffer[bss_count].ssid), SSID_MAX_LEN); + essid_len_aligned = (essid_len + 3) & -4; + if (result_size < ESP_IW_EVENT_SIZE(essid) + essid_len_aligned) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(essid) + essid_len_aligned; + iwe->cmd = SIOCGIWESSID; + iwe->u.essid.flags = 0; + iwe->u.essid.length = essid_len; + + /* Special processing for iw_point, set offset + * in pointer field. + */ + + iwe->u.essid.pointer = (void *)sizeof(iwe->u.essid); + memcpy(&iwe->u.essid + 1, + ap_list_buffer[bss_count].ssid, essid_len); + + wlinfo("INFO: ssid %s\n", ap_list_buffer[bss_count].ssid); + + priv->scan_result_size += + ESP_IW_EVENT_SIZE(essid) + essid_len_aligned; + result_size -= ESP_IW_EVENT_SIZE(essid) + essid_len_aligned; + + /* Copy link quality info */ + + if (result_size < ESP_IW_EVENT_SIZE(qual)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(qual); + iwe->cmd = IWEVQUAL; + iwe->u.qual.qual = 0x00; + + wlinfo("INFO: signal %d\n", ap_list_buffer[bss_count].rssi); + + iwe->u.qual.level = ap_list_buffer[bss_count].rssi; + iwe->u.qual.noise = 0x00; + iwe->u.qual.updated = IW_QUAL_DBM | IW_QUAL_ALL_UPDATED; + + priv->scan_result_size += ESP_IW_EVENT_SIZE(qual); + result_size -= ESP_IW_EVENT_SIZE(qual); + + /* Copy AP mode */ + + if (result_size < ESP_IW_EVENT_SIZE(mode)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(mode); + iwe->cmd = SIOCGIWMODE; + iwe->u.mode = IW_MODE_MASTER; + priv->scan_result_size += ESP_IW_EVENT_SIZE(mode); + result_size -= ESP_IW_EVENT_SIZE(mode); + + /* Copy AP encryption mode */ + + if (result_size < ESP_IW_EVENT_SIZE(data)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(data); + iwe->cmd = SIOCGIWENCODE; + iwe->u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + iwe->u.data.length = 0; + iwe->u.essid.pointer = NULL; + + priv->scan_result_size += ESP_IW_EVENT_SIZE(data); + result_size -= ESP_IW_EVENT_SIZE(data); + + /* Copy AP channel */ + + if (result_size < ESP_IW_EVENT_SIZE(freq)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(freq); + iwe->cmd = SIOCGIWFREQ; + iwe->u.freq.e = 0; + iwe->u.freq.m = ap_list_buffer[bss_count].primary; + + priv->scan_result_size += ESP_IW_EVENT_SIZE(freq); + result_size -= ESP_IW_EVENT_SIZE(freq); + } + } + + parse_done = true; + } + +scan_result_full: + + /* Continue instead of break to log dropped AP results */ + + if (parse_done == false) + { + wlerr("ERROR: No more space in scan_result buffer\n"); + } + + if (ap_list_buffer != NULL) + { + kmm_free(ap_list_buffer); + ap_list_buffer = NULL; + } + + priv->scan_status = ESP_SCAN_DONE; + nxsem_post(&priv->scan_signal); +} diff --git a/arch/xtensa/src/esp32s3/esp32s3_wifi_utils.h b/arch/xtensa/src/esp32s3/esp32s3_wifi_utils.h new file mode 100644 index 00000000000..8439e83f813 --- /dev/null +++ b/arch/xtensa/src/esp32s3/esp32s3_wifi_utils.h @@ -0,0 +1,104 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/esp32s3_wifi_utils.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WIFI_UTILS_H +#define __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WIFI_UTILS_H + +#include +#include + +#ifndef __ASSEMBLY__ + +#include + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_wifi_start_scan + * + * Description: + * Scan all available APs. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_start_scan(struct iwreq *iwr); + +/**************************************************************************** + * Name: esp_wifi_get_scan_results + * + * Description: + * Get scan result + * + * Input Parameters: + * req The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_get_scan_results(struct iwreq *iwr); + +/**************************************************************************** + * Name: esp_wifi_scan_event_parse + * + * Description: + * Parse scan information + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_scan_event_parse(void); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WIFI_UTILS_H */ diff --git a/arch/xtensa/src/esp32s3/esp32s3_wireless.c b/arch/xtensa/src/esp32s3/esp32s3_wireless.c new file mode 100644 index 00000000000..0208fd58cd3 --- /dev/null +++ b/arch/xtensa/src/esp32s3/esp32s3_wireless.c @@ -0,0 +1,427 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/esp32s3_wireless.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +#include "xtensa.h" +#include "hardware/esp32s3_soc.h" +#include "hardware/esp32s3_syscon.h" +#include "hardware/esp32s3_efuse.h" +#include "esp32s3_wireless.h" +#include "esp_phy_init.h" +#include "phy_init_data.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAC_ADDR0_REG EFUSE_RD_MAC_SPI_SYS_0_REG +#define MAC_ADDR1_REG EFUSE_RD_MAC_SPI_SYS_1_REG + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline void phy_digital_regs_store(void); +static inline void phy_digital_regs_load(void); + +/**************************************************************************** + * Extern Functions declaration + ****************************************************************************/ + +extern uint8_t esp_crc8(const uint8_t *p, uint32_t len); +extern void phy_wakeup_init(void); +extern void phy_close_rf(void); +extern uint8_t phy_dig_reg_backup(bool init, uint32_t *regs); +extern int register_chipv7_phy(const esp_phy_init_data_t *init_data, + esp_phy_calibration_data_t *cal_data, + esp_phy_calibration_mode_t cal_mode); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Wi-Fi sleep private data */ + +static uint32_t g_phy_clk_en_cnt; + +/* Reference count of enabling PHY */ + +static uint8_t g_phy_access_ref; + +/* Memory to store PHY digital registers */ + +static uint32_t *g_phy_digital_regs_mem = NULL; + +/* Indicate PHY is calibrated or not */ + +static bool g_is_phy_calibrated = false; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: phy_digital_regs_store + * + * Description: + * Store PHY digital registers. + * + ****************************************************************************/ + +static inline void phy_digital_regs_store(void) +{ + if (g_phy_digital_regs_mem == NULL) + { + g_phy_digital_regs_mem = (uint32_t *) + kmm_malloc(SOC_PHY_DIG_REGS_MEM_SIZE); + } + + DEBUGASSERT(g_phy_digital_regs_mem != NULL); + + phy_dig_reg_backup(true, g_phy_digital_regs_mem); +} + +/**************************************************************************** + * Name: phy_digital_regs_load + * + * Description: + * Load PHY digital registers. + * + ****************************************************************************/ + +static inline void phy_digital_regs_load(void) +{ + if (g_phy_digital_regs_mem != NULL) + { + phy_dig_reg_backup(false, g_phy_digital_regs_mem); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Functions needed by libphy.a + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_dport_access_reg_read + * + * Description: + * Read register value safely in SMP + * + * Input Parameters: + * reg - Register address + * + * Returned Value: + * Register value + * + ****************************************************************************/ + +uint32_t IRAM_ATTR esp_dport_access_reg_read(uint32_t reg) +{ + return getreg32(reg); +} + +/**************************************************************************** + * Name: phy_printf + * + * Description: + * Output format string and its arguments + * + * Input Parameters: + * format - format string + * + * Returned Value: + * 0 + * + ****************************************************************************/ + +int phy_printf(const char *format, ...) +{ +#ifdef CONFIG_DEBUG_WIRELESS_INFO + va_list arg; + + va_start(arg, format); + vsyslog(LOG_INFO, format, arg); + va_end(arg); +#endif + + return 0; +} + +/**************************************************************************** + * Name: esp32s3_phy_enable_clock + * + * Description: + * Enable PHY hardware clock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_phy_enable_clock(void) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + if (g_phy_clk_en_cnt == 0) + { + modifyreg32(SYSTEM_WIFI_CLK_EN_REG, 0, + SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M); + } + + g_phy_clk_en_cnt++; + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: esp32s3_phy_disable_clock + * + * Description: + * Disable PHY hardware clock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_phy_disable_clock(void) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + if (g_phy_clk_en_cnt > 0) + { + g_phy_clk_en_cnt--; + if (g_phy_clk_en_cnt == 0) + { + modifyreg32(SYSTEM_WIFI_CLK_EN_REG, + SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M, + 0); + } + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: esp_read_mac + * + * Description: + * Read MAC address from efuse + * + * Input Parameters: + * mac - MAC address buffer pointer + * type - MAC address type + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_read_mac(uint8_t *mac, esp_mac_type_t type) +{ + uint32_t regval[2]; + uint8_t tmp; + uint8_t *data = (uint8_t *)regval; + int i; + + if (mac == NULL) + { + wlerr("mac address param is NULL"); + return -1; + } + + if (type > ESP_MAC_BT) + { + wlerr("Input type is error=%d\n", type); + return -1; + } + + regval[0] = getreg32(MAC_ADDR0_REG); + regval[1] = getreg32(MAC_ADDR1_REG); + + for (i = 0; i < MAC_LEN; i++) + { + mac[i] = data[5 - i]; + } + + if (type == ESP_MAC_WIFI_SOFTAP) + { + tmp = mac[0]; + for (i = 0; i < 64; i++) + { + mac[0] = tmp | 0x02; + mac[0] ^= i << 2; + + if (mac[0] != tmp) + { + break; + } + } + + if (i >= 64) + { + wlerr("Failed to generate SoftAP MAC\n"); + return -1; + } + } + + if (type == ESP_MAC_BT) + { + tmp = mac[0]; + for (i = 0; i < 64; i++) + { + mac[0] = tmp | 0x02; + mac[0] ^= i << 2; + + if (mac[0] != tmp) + { + break; + } + } + + mac[5] += 1; + } + + return 0; +} + +/**************************************************************************** + * Name: esp32s3_phy_disable + * + * Description: + * Deinitialize PHY hardware + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_phy_disable(void) +{ + irqstate_t flags; + flags = enter_critical_section(); + + g_phy_access_ref--; + + if (g_phy_access_ref == 0) + { + /* Disable PHY and RF. */ + + phy_close_rf(); + + /* Disable PHY temperature sensor */ + + phy_xpd_tsens(); + + /* Disable Wi-Fi/BT common peripheral clock. + * Do not disable clock for hardware RNG. + */ + + esp32s3_phy_disable_clock(); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: esp32s3_phy_enable + * + * Description: + * Initialize PHY hardware + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_phy_enable(void) +{ + static bool debug = false; + irqstate_t flags; + esp_phy_calibration_data_t *cal_data; + if (debug == false) + { + char *phy_version = get_phy_version_str(); + wlinfo("phy_version %s\n", phy_version); + debug = true; + } + + cal_data = kmm_zalloc(sizeof(esp_phy_calibration_data_t)); + if (!cal_data) + { + wlerr("ERROR: Failed to allocate PHY calibration data buffer."); + abort(); + } + + flags = enter_critical_section(); + + if (g_phy_access_ref == 0) + { + esp32s3_phy_enable_clock(); + + if (g_is_phy_calibrated == false) + { +#if CONFIG_ESP_PHY_ENABLE_USB + phy_bbpll_en_usb(true); +#endif + wlinfo("calibrating"); + register_chipv7_phy(&phy_init_data, cal_data, PHY_RF_CAL_FULL); + g_is_phy_calibrated = true; + } + else + { + phy_wakeup_init(); + phy_digital_regs_load(); + } + } + + g_phy_access_ref++; + leave_critical_section(flags); + kmm_free(cal_data); +} diff --git a/arch/xtensa/src/esp32s3/esp32s3_wireless.h b/arch/xtensa/src/esp32s3/esp32s3_wireless.h new file mode 100644 index 00000000000..44ed936d412 --- /dev/null +++ b/arch/xtensa/src/esp32s3/esp32s3_wireless.h @@ -0,0 +1,168 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/esp32s3_wireless.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WIRELESS_H +#define __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WIRELESS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "xtensa_attr.h" + +#include "espidf_wifi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Note: Don't remove these definitions, they are needed by the 3rdparty IDF + * headers + */ + +#define CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN 0 +#define CONFIG_MAC_BB_PD 0 + +#define MAC_LEN (6) + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_read_mac + * + * Description: + * Read MAC address from efuse + * + * Input Parameters: + * mac - MAC address buffer pointer + * type - MAC address type + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_read_mac(uint8_t *mac, esp_mac_type_t type); + +/**************************************************************************** + * Name: esp32s3_phy_enable + * + * Description: + * Initialize PHY hardware + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_phy_enable(void); + +/**************************************************************************** + * Name: esp32s3_phy_disable + * + * Description: + * Deinitialize PHY hardware + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_phy_disable(void); + +/**************************************************************************** + * Name: esp32s3_phy_enable_clock + * + * Description: + * Enable PHY clock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_phy_enable_clock(void); + +/**************************************************************************** + * Name: esp32s3_phy_disable_clock + * + * Description: + * Disable PHY clock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_phy_disable_clock(void); + +/**************************************************************************** + * Functions needed by libphy.a + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_dport_access_reg_read + * + * Description: + * Read register value safely in SMP + * + * Input Parameters: + * reg - Register address + * + * Returned Value: + * Register value + * + ****************************************************************************/ + +uint32_t IRAM_ATTR esp_dport_access_reg_read(uint32_t reg); + +/**************************************************************************** + * Name: phy_printf + * + * Description: + * Output format string and its arguments + * + * Input Parameters: + * format - format string + * + * Returned Value: + * 0 + * + ****************************************************************************/ + +int phy_printf(const char *format, ...) printf_like(1, 2); + +#endif /* __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WIRELESS_H */ diff --git a/arch/xtensa/src/esp32s3/esp32s3_wlan.c b/arch/xtensa/src/esp32s3/esp32s3_wlan.c new file mode 100644 index 00000000000..2835b4a6f83 --- /dev/null +++ b/arch/xtensa/src/esp32s3/esp32s3_wlan.c @@ -0,0 +1,1474 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/esp32s3_wlan.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_ESP32S3_WIFI + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_NET_PKT) +# include +#endif + +#include "esp32s3_wlan.h" +#include "esp32s3_wifi_utils.h" +#include "esp32s3_wifi_adapter.h" +#include "esp32s3_wireless.h" +#include "esp32s3_systemreset.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* TX timeout = 1 minute */ + +#define WLAN_TXTOUT (60 * CLK_TCK) + +/* Low-priority work queue 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 WLAN_BUF_SIZE (CONFIG_NET_ETH_PKTSIZE + \ + CONFIG_NET_LL_GUARDSIZE + \ + CONFIG_NET_GUARDSIZE) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* WLAN operations */ + +struct wlan_ops +{ + int (*start)(void); + int (*send)(void *pdata, size_t n); + int (*essid)(struct iwreq *iwr, bool set); + int (*bssid)(struct iwreq *iwr, bool set); + int (*passwd)(struct iwreq *iwr, bool set); + int (*mode)(struct iwreq *iwr, bool set); + int (*auth)(struct iwreq *iwr, bool set); + int (*freq)(struct iwreq *iwr, bool set); + int (*bitrate)(struct iwreq *iwr, bool set); + int (*txpower)(struct iwreq *iwr, bool set); + int (*channel)(struct iwreq *iwr, bool set); + int (*country)(struct iwreq *iwr, bool set); + int (*rssi)(struct iwreq *iwr, bool set); + int (*connect)(void); + int (*disconnect)(void); + int (*event)(pid_t pid, struct sigevent *event); + int (*stop)(void); +}; + +/* The wlan_priv_s encapsulates all state information for a single + * hardware interface + */ + +struct wlan_priv_s +{ + int ref; /* Reference count */ + + bool ifup; /* true:ifup false:ifdown */ + + 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 */ + + const struct wlan_ops *ops; /* WLAN operations */ + + /* This holds the information visible to the NuttX network */ + + struct net_driver_s dev; + + /* RX packet queue */ + + struct iob_queue_s rxb; + + /* TX ready packet queue */ + + struct iob_queue_s txb; + + /* Flat buffer swap */ + + uint8_t flatbuf[WLAN_BUF_SIZE]; + + spinlock_t lock; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Reference count of register Wi-Fi handler */ + +static uint8_t g_callback_register_ref = 0; + +static struct wlan_priv_s g_wlan_priv[ESP32S3_WLAN_DEVS]; + +#ifdef ESP32S3_WLAN_HAS_STA +static const struct wlan_ops g_sta_ops = +{ + .start = esp_wifi_sta_start, + .send = esp_wifi_sta_send_data, + .essid = esp_wifi_sta_essid, + .bssid = esp_wifi_sta_bssid, + .passwd = esp_wifi_sta_password, + .mode = esp_wifi_sta_mode, + .auth = esp_wifi_sta_auth, + .freq = esp_wifi_sta_freq, + .bitrate = esp_wifi_sta_bitrate, + .txpower = esp_wifi_sta_txpower, + .channel = esp_wifi_sta_channel, + .country = esp_wifi_sta_country, + .rssi = esp_wifi_sta_rssi, + .connect = esp_wifi_sta_connect, + .disconnect = esp_wifi_sta_disconnect, + .event = esp_wifi_notify_subscribe, + .stop = esp_wifi_sta_stop +}; +#endif /* ESP32S3_WLAN_HAS_STA */ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Common TX logic */ + +static void wlan_transmit(struct wlan_priv_s *priv); +static void wlan_rxpoll(void *arg); +static int wlan_txpoll(struct net_driver_s *dev); +static void wlan_dopoll(struct wlan_priv_s *priv); + +/* Watchdog timer expirations */ + +static void wlan_txtimeout_work(void *arg); +static void wlan_txtimeout_expiry(wdparm_t arg); + +/* NuttX callback functions */ + +static int wlan_ifup(struct net_driver_s *dev); +static int wlan_ifdown(struct net_driver_s *dev); + +static void wlan_txavail_work(void *arg); +static int wlan_txavail(struct net_driver_s *dev); + +#if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6) +static int wlan_addmac(struct net_driver_s *dev, const uint8_t *mac); +#endif + +#ifdef CONFIG_NET_MCASTGROUP +static int wlan_rmmac(struct net_driver_s *dev, const uint8_t *mac); +#endif + +#ifdef CONFIG_NETDEV_IOCTL +static int wlan_ioctl(struct net_driver_s *dev, int cmd, + unsigned long arg); +#endif + +#ifdef CONFIG_NET_ICMPv6 +static void wlan_ipv6multicast(struct wlan_priv_s *priv); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Note: + * All TX done/RX done/Error trigger functions are not called from + * interrupts, this is much different from ethernet driver, including: + * * wlan_rx_done + * * wlan_tx_done + * + * These functions are called in a Wi-Fi private thread. So we just use + * mutex/semaphore instead of disable interrupt, if necessary. + */ + +/**************************************************************************** + * Function: wlan_cache_txpkt_tail + * + * Description: + * Cache packet from dev->d_buf into tail of TX ready queue. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void wlan_cache_txpkt_tail(struct wlan_priv_s *priv) +{ + iob_tryadd_queue(priv->dev.d_iob, &priv->txb); + netdev_iob_clear(&priv->dev); +} + +/**************************************************************************** + * Function: wlan_recvframe + * + * Description: + * Try to receive RX packet from RX done packet queue. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * RX packet if success or NULl if no packet in queue. + * + ****************************************************************************/ + +static struct iob_s *wlan_recvframe(struct wlan_priv_s *priv) +{ + struct iob_s *iob; + irqstate_t flags; + + flags = spin_lock_irqsave(&priv->lock); + + iob = iob_remove_queue(&priv->rxb); + + spin_unlock_irqrestore(&priv->lock, flags); + + return iob; +} + +/**************************************************************************** + * Name: wlan_transmit + * + * Description: + * Try to send all TX packets in TX ready queue to Wi-Fi driver. If this + * sending fails, then breaks loop and returns. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_transmit(struct wlan_priv_s *priv) +{ + uint16_t llhdrlen = NET_LL_HDRLEN(&priv->dev); + unsigned int offset = CONFIG_NET_LL_GUARDSIZE - llhdrlen; + struct iob_s *iob; + int ret; + + while ((iob = iob_peek_queue(&priv->txb)) != NULL) + { + iob_copyout(priv->flatbuf + llhdrlen, iob, iob->io_pktlen, 0); + memcpy(priv->flatbuf, iob->io_data + offset, llhdrlen); + + ret = priv->ops->send(priv->flatbuf, iob->io_pktlen + llhdrlen); + if (ret == -ENOMEM) + { + wd_start(&priv->txtimeout, WLAN_TXTOUT, + wlan_txtimeout_expiry, (uint32_t)priv); + break; + } + else + { + if (ret < 0) + { + nwarn("WARN: Failed to send pkt, ret: %d\n", ret); + } + + iob_remove_queue(&priv->txb); + + /* And free the I/O buffer chain */ + + iob_free_chain(iob); + } + } +} + +/**************************************************************************** + * Name: wlan_tx_done + * + * Description: + * Wi-Fi TX done callback function. If this is called, it means sending + * next packet. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_tx_done(struct wlan_priv_s *priv) +{ + wd_cancel(&priv->txtimeout); + + wlan_txavail(&priv->dev); +} + +/**************************************************************************** + * Function: wlan_rx_done + * + * Description: + * Wi-Fi RX done callback function. If this is called, it means receiving + * packet. + * + * Input Parameters: + * priv - Reference to the driver state structure + * buffer - Wi-Fi received packet buffer + * len - Length of received packet + * eb - Wi-Fi receive callback input eb pointer + * + * Returned Value: + * 0 on success or a negated errno on failure + * + ****************************************************************************/ + +static int wlan_rx_done(struct wlan_priv_s *priv, void *buffer, + uint16_t len, void *eb) +{ + struct net_driver_s *dev = &priv->dev; + struct iob_s *iob = NULL; + irqstate_t flags; + int ret = 0; + + if (!priv->ifup) + { + goto out; + } + + if (len > WLAN_BUF_SIZE) + { + nwarn("ERROR: Wlan receive %d larger than %d\n", + len, WLAN_BUF_SIZE); + ret = -EINVAL; + goto out; + } + + if (len > iob_navail(false) * CONFIG_IOB_BUFSIZE) + { + ret = -ENOBUFS; + goto out; + } + + iob = iob_tryalloc(false); + if (iob == NULL) + { + ret = -ENOBUFS; + goto out; + } + + iob_reserve(iob, CONFIG_NET_LL_GUARDSIZE - NET_LL_HDRLEN(dev)); + + ret = iob_trycopyin(iob, buffer, len, 0, false); + if (ret != len) + { + ret = -ENOBUFS; + goto out; + } + + flags = spin_lock_irqsave(&priv->lock); + ret = iob_tryadd_queue(iob, &priv->rxb); + spin_unlock_irqrestore(&priv->lock, flags); + + if (ret < 0) + { + ret = -ENOBUFS; + goto out; + } + + if (eb != NULL) + { + esp_wifi_free_eb(eb); + } + + if (work_available(&priv->rxwork)) + { + work_queue(WLAN_WORK, &priv->rxwork, wlan_rxpoll, priv, 0); + } + + return 0; + +out: + if (iob != NULL) + { + iob_free_chain(iob); + } + + if (eb != NULL) + { + esp_wifi_free_eb(eb); + } + + wlan_txavail(&priv->dev); + + return ret; +} + +/**************************************************************************** + * 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(void *arg) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)arg; + struct net_driver_s *dev = &priv->dev; + struct eth_hdr_s *eth_hdr; + struct iob_s *iob; + + /* Try to send all cached TX packets for TX ack and so on */ + + wlan_transmit(priv); + + /* Loop while while iob_remove_queue() successfully retrieves valid + * Ethernet frames. + */ + + net_lock(); + + while ((iob = wlan_recvframe(priv)) != NULL) + { + dev->d_iob = iob; + dev->d_len = iob->io_pktlen; + + iob_reserve(iob, CONFIG_NET_LL_GUARDSIZE); + +#ifdef CONFIG_NET_PKT + + /* When packet sockets are enabled, + * feed the frame into the packet tap. + */ + + pkt_input(&priv->dev); +#endif + + eth_hdr = (struct eth_hdr_s *) + &dev->d_iob->io_data[CONFIG_NET_LL_GUARDSIZE - + NET_LL_HDRLEN(dev)]; + + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv4 + if (eth_hdr->type == HTONS(ETHTYPE_IP)) + { + ninfo("IPv4 frame\n"); + + /* Receive an IPv4 packet from the network device */ + + 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->dev.d_len > 0) + { + /* And send the packet */ + + wlan_cache_txpkt_tail(priv); + } + } + else +#endif +#ifdef CONFIG_NET_IPv6 + if (eth_hdr->type == HTONS(ETHTYPE_IP6)) + { + ninfo("IPv6 frame\n"); + + /* Give the IPv6 packet to the network layer */ + + 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->dev.d_len > 0) + { + /* And send the packet */ + + wlan_cache_txpkt_tail(priv); + } + } + else +#endif +#ifdef CONFIG_NET_ARP + if (eth_hdr->type == HTONS(ETHTYPE_ARP)) + { + ninfo("ARP frame\n"); + + /* Handle ARP packet */ + + arp_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->dev.d_len > 0) + { + wlan_cache_txpkt_tail(priv); + } + } + else +#endif + { + ninfo("INFO: Dropped, Unknown type: %04x\n", eth_hdr->type); + } + + netdev_iob_release(&priv->dev); + } + + /* Try to send all cached TX packets */ + + wlan_transmit(priv); + + net_unlock(); +} + +/**************************************************************************** + * Name: wlan_txpoll + * + * Description: + * The transmitter is available, check if the network has any outgoing + * packets ready to send. This is a callback from devif_poll(). + * devif_poll() may be called: + * + * 1. When the preceding TX packets send times out and the interface is + * reset + * 2. During normal TX polling + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +static int wlan_txpoll(struct net_driver_s *dev) +{ + struct wlan_priv_s *priv = dev->d_private; + + wlan_cache_txpkt_tail(priv); + wlan_transmit(priv); + + /* If zero is returned, the polling will continue until + * all connections have been examined. + */ + + return 1; +} + +/**************************************************************************** + * 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 (wlan_txavail) + * 2. After a TX timeout to restart the sending process + * (wlan_txtimeout_expiry). + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_dopoll(struct wlan_priv_s *priv) +{ + struct net_driver_s *dev = &priv->dev; + + /* Try to let TCP/IP to send all packets to netcard driver */ + + while (devif_poll(dev, wlan_txpoll)); + + /* Try to send all cached TX packets */ + + wlan_transmit(priv); +} + +/**************************************************************************** + * Function: wlan_txtimeout_work + * + * Description: + * Perform TX timeout related work from the worker thread + * + * Input Parameters: + * arg - The argument passed when work_queue() as called. + * + * Returned Value: + * OK on success + * + ****************************************************************************/ + +static void wlan_txtimeout_work(void *arg) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)arg; + + /* Try to send all cached TX packets */ + + wlan_transmit(priv); + + net_lock(); + + wlan_ifdown(&priv->dev); + wlan_ifup(&priv->dev); + + /* Then poll for new XMIT data */ + + wlan_dopoll(priv); + + net_unlock(); +} + +/**************************************************************************** + * Function: wlan_txtimeout_expiry + * + * Description: + * Our TX watchdog timed out. Called from the timer callback handler. + * The last TX never completed. Reset the hardware and start again. + * + * Input Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_txtimeout_expiry(wdparm_t arg) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)arg; + + /* Schedule to perform the TX timeout processing on the worker thread. */ + + if (work_available(&priv->toutwork)) + { + work_queue(WLAN_WORK, &priv->toutwork, wlan_txtimeout_work, priv, 0); + } +} + +/**************************************************************************** + * Name: wlan_txavail_work + * + * Description: + * Perform an out-of-cycle poll on the worker thread. + * + * Input Parameters: + * arg - Reference to the NuttX driver state structure (cast to void*) + * + * Returned Value: + * None + * + * Assumptions: + * Called on the higher priority worker thread. + * + ****************************************************************************/ + +static void wlan_txavail_work(void *arg) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)arg; + + /* Try to send all cached TX packets even if net is down */ + + wlan_transmit(priv); + + /* 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(); + + /* Ignore the notification if the interface is not yet up */ + + if (priv->ifup) + { + /* Poll the network for new XMIT data */ + + wlan_dopoll(priv); + } + + net_unlock(); +} + +/**************************************************************************** + * 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(struct net_driver_s *dev) +{ + int ret; + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + +#ifdef CONFIG_NET_IPv4 + ninfo("Bringing up: %d.%d.%d.%d\n", + (uint8_t)(dev->d_ipaddr), (uint8_t)(dev->d_ipaddr >> 8), + (uint8_t)(dev->d_ipaddr >> 16), (uint8_t)(dev->d_ipaddr >> 24)); +#endif +#ifdef CONFIG_NET_IPv6 + ninfo("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; + } + + ret = priv->ops->start(); + if (ret < 0) + { + net_unlock(); + nerr("ERROR: Failed to start Wi-Fi ret=%d\n", ret); + return ret; + } + +#ifdef CONFIG_NET_ICMPv6 + + /* Set up IPv6 multicast address filtering */ + + wlan_ipv6multicast(priv); +#endif + + IOB_QINIT(&priv->rxb); + IOB_QINIT(&priv->txb); + + priv->dev.d_buf = NULL; + priv->dev.d_len = 0; + + priv->ifup = true; + if (g_callback_register_ref == 0) + { + ret = esp32s3_register_shutdown_handler(esp_wifi_stop_callback); + if (ret < 0) + { + nwarn("WARN: Failed to register handler ret=%d\n", ret); + } + } + + ++g_callback_register_ref; + 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(struct net_driver_s *dev) +{ + int ret; + struct wlan_priv_s *priv = (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->txtimeout); + + /* Mark the device "down" */ + + priv->ifup = false; + + iob_free_queue(&priv->rxb); + iob_free_queue(&priv->txb); + + ret = priv->ops->stop(); + if (ret < 0) + { + nerr("ERROR: Failed to stop Wi-Fi ret=%d\n", ret); + } + + --g_callback_register_ref; + if (g_callback_register_ref == 0) + { + ret = esp32s3_unregister_shutdown_handler(esp_wifi_stop_callback); + if (ret < 0) + { + nwarn("WARN: Failed to unregister handler ret=%d\n", ret); + } + } + + net_unlock(); + + return OK; +} + +/**************************************************************************** + * Name: wlan_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int wlan_txavail(struct net_driver_s *dev) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + + if (work_available(&priv->txwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(WLAN_WORK, &priv->txwork, wlan_txavail_work, priv, 0); + } + + return OK; +} + +/**************************************************************************** + * Name: wlan_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6) +static int wlan_addmac(struct net_driver_s *dev, const uint8_t *mac) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + + return OK; +} +#endif + +/**************************************************************************** + * Name: wlan_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the + * hardware multicast address filtering + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_NET_MCASTGROUP +static int wlan_rmmac(struct net_driver_s *dev, const uint8_t *mac) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + + return OK; +} +#endif + +/**************************************************************************** + * Name: wlan_ipv6multicast + * + * Description: + * Configure the IPv6 multicast MAC address. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ICMPv6 +static void wlan_ipv6multicast(struct wlan_priv_s *priv) +{ + struct net_driver_s *dev; + uint16_t tmp16; + uint8_t mac[6]; + + /* For ICMPv6, we need to add the IPv6 multicast address + * + * For IPv6 multicast addresses, the Ethernet MAC is derived by + * the four low-order octets OR'ed with the MAC 33:33:00:00:00:00, + * so for example the IPv6 address FF02:DEAD:BEEF::1:3 would map + * to the Ethernet MAC address 33:33:00:01:00:03. + * + * NOTES: This appears correct for the ICMPv6 Router Solicitation + * Message, but the ICMPv6 Neighbor Solicitation message seems to + * use 33:33:ff:01:00:03. + */ + + mac[0] = 0x33; + mac[1] = 0x33; + + dev = &priv->dev; + tmp16 = dev->d_ipv6addr[6]; + mac[2] = 0xff; + mac[3] = tmp16 >> 8; + + tmp16 = dev->d_ipv6addr[7]; + mac[4] = tmp16 & 0xff; + mac[5] = tmp16 >> 8; + + ninfo("IPv6 Multicast: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + wlan_addmac(dev, mac); + +#ifdef CONFIG_NET_ICMPv6_AUTOCONF + /* Add the IPv6 all link-local nodes Ethernet address. This is the + * address that we expect to receive ICMPv6 Router Advertisement + * packets. + */ + + wlan_addmac(dev, g_ipv6_ethallnodes.ether_addr_octet); +#endif /* CONFIG_NET_ICMPv6_AUTOCONF */ + +#ifdef CONFIG_NET_ICMPv6_ROUTER + /* Add the IPv6 all link-local routers Ethernet address. This is the + * address that we expect to receive ICMPv6 Router Solicitation + * packets. + */ + + wlan_addmac(dev, g_ipv6_ethallrouters.ether_addr_octet); +#endif /* CONFIG_NET_ICMPv6_ROUTER */ +} +#endif /* CONFIG_NET_ICMPv6 */ + +/**************************************************************************** + * Name: wlan_ioctl + * + * Description: + * Handle network IOCTL commands directed to this device. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * cmd - The IOCTL command + * arg - The argument for the IOCTL command + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NETDEV_IOCTL +static int wlan_ioctl(struct net_driver_s *dev, + int cmd, + unsigned long arg) +{ + int ret; + struct iwreq *iwr = (struct iwreq *)arg; + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + const struct wlan_ops *ops = priv->ops; + + /* Decode and dispatch the driver-specific IOCTL command */ + + switch (cmd) + { +#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_ARCH_PHY_INTERRUPT + case SIOCMIINOTIFY: /* Set up for PHY event notifications */ + { + struct mii_ioctl_notify_s *req = (struct mii_ioctl_notify_s *)arg; + ret = ops->event(req->pid, &req->event); + if (ret < 0) + { + nerr("ERROR: Failed to subscribe event\n"); + } + } + break; +#endif +#endif + + case SIOCSIWENCODEEXT: + ret = ops->passwd(iwr, true); + + break; + + case SIOCGIWENCODEEXT: + ret = ops->passwd(iwr, false); + break; + + case SIOCSIWESSID: + if ((iwr->u.essid.flags == IW_ESSID_ON) || + (iwr->u.essid.flags == IW_ESSID_DELAY_ON)) + { + ret = ops->essid(iwr, true); + if (ret < 0) + { + break; + } + + if (iwr->u.essid.flags == IW_ESSID_ON) + { + ret = ops->connect(); + if (ret < 0) + { + nerr("ERROR: Failed to connect\n"); + break; + } + } + } + else + { + ret = ops->disconnect(); + if (ret < 0) + { + nerr("ERROR: Failed to disconnect\n"); + break; + } + } + + break; + + case SIOCGIWESSID: /* Get ESSID */ + ret = ops->essid(iwr, false); + break; + + case SIOCSIWAP: /* Set access point MAC addresses */ + if (iwr->u.ap_addr.sa_data[0] != 0 && + iwr->u.ap_addr.sa_data[1] != 0 && + iwr->u.ap_addr.sa_data[2] != 0) + { + ret = ops->bssid(iwr, true); + if (ret < 0) + { + nerr("ERROR: Failed to set BSSID\n"); + break; + } + + ret = ops->connect(); + if (ret < 0) + { + nerr("ERROR: Failed to connect\n"); + break; + } + } + else + { + ret = ops->disconnect(); + if (ret < 0) + { + nerr("ERROR: Failed to disconnect\n"); + break; + } + } + + break; + + case SIOCGIWAP: /* Get access point MAC addresses */ + ret = ops->bssid(iwr, false); + break; + + case SIOCSIWSCAN: + ret = esp_wifi_start_scan(iwr); + break; + + case SIOCGIWSCAN: + ret = esp_wifi_get_scan_results(iwr); + break; + + case SIOCSIWCOUNTRY: /* Set country code */ + ret = ops->country(iwr, true); + break; + + case SIOCGIWSENS: /* Get sensitivity (dBm) */ + ret = ops->rssi(iwr, false); + break; + + case SIOCSIWMODE: /* Set operation mode */ + ret = ops->mode(iwr, true); + break; + + case SIOCGIWMODE: /* Get operation mode */ + ret = ops->mode(iwr, false); + break; + + case SIOCSIWAUTH: /* Set authentication mode params */ + ret = ops->auth(iwr, true); + break; + + case SIOCGIWAUTH: /* Get authentication mode params */ + ret = ops->auth(iwr, false); + break; + + case SIOCSIWFREQ: /* Set channel/frequency (MHz) */ + ret = ops->freq(iwr, true); + break; + + case SIOCGIWFREQ: /* Get channel/frequency (MHz) */ + ret = ops->freq(iwr, false); + break; + + case SIOCSIWRATE: /* Set default bit rate (Mbps) */ + wlwarn("WARNING: SIOCSIWRATE not implemented\n"); + ret = -ENOSYS; + break; + + case SIOCGIWRATE: /* Get default bit rate (Mbps) */ + ret = ops->bitrate(iwr, false); + break; + + case SIOCSIWTXPOW: /* Set transmit power (dBm) */ + ret = ops->txpower(iwr, true); + break; + + case SIOCGIWTXPOW: /* Get transmit power (dBm) */ + ret = ops->txpower(iwr, false); + break; + + case SIOCGIWRANGE: /* Get range of parameters */ + ret = ops->channel(iwr, false); + break; + + default: + nerr("ERROR: Unrecognized IOCTL command: %d\n", cmd); + ret = -ENOTTY; /* Special return value for this case */ + break; + } + + return ret; +} +#endif /* CONFIG_NETDEV_IOCTL */ + +/**************************************************************************** + * Name: esp32s3_net_initialize + * + * Description: + * Initialize the ESP32-S3 driver + * + * Input Parameters: + * devno - The device number + * mac_addr - MAC address + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +static int esp32s3_net_initialize(int devno, uint8_t *mac_addr, + const struct wlan_ops *ops) +{ + int ret; + struct wlan_priv_s *priv; + struct net_driver_s *netdev; + + priv = &g_wlan_priv[devno]; + if (priv->ref) + { + priv->ref++; + return OK; + } + + netdev = &priv->dev; + + /* Initialize the driver structure */ + + memset(priv, 0, sizeof(struct wlan_priv_s)); + + netdev->d_ifup = wlan_ifup; /* I/F down callback */ + netdev->d_ifdown = wlan_ifdown; /* I/F up (new IP address) callback */ + netdev->d_txavail = wlan_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_MCASTGROUP + netdev->d_addmac = wlan_addmac; /* Add multicast MAC address */ + netdev->d_rmmac = wlan_rmmac; /* Remove multicast MAC address */ +#endif +#ifdef CONFIG_NETDEV_IOCTL + netdev->d_ioctl = wlan_ioctl; /* Handle network IOCTL commands */ +#endif + + /* Used to recover private state from dev */ + + netdev->d_private = (void *)priv; + + memcpy(netdev->d_mac.ether.ether_addr_octet, mac_addr, MAC_LEN); + + ret = netdev_register(netdev, NET_LL_IEEE80211); + if (ret < 0) + { + nerr("ERROR: Initialization of IEEE 802.11 block failed: %d\n", ret); + return ret; + } + + priv->ops = ops; + + priv->ref++; + + ninfo("INFO: Initialize Wi-Fi adapter No.%d success\n", devno); + + return OK; +} + +/**************************************************************************** + * Function: wlan_sta_rx_done + * + * Description: + * Wi-Fi station RX done callback function. If this is called, it means + * station receiveing packet. + * + * Input Parameters: + * buffer - Wi-Fi received packet buffer + * len - Length of received packet + * eb - Wi-Fi receive callback input eb pointer + * + * Returned Value: + * 0 on success or a negated errno on failure + * + ****************************************************************************/ + +#ifdef ESP32S3_WLAN_HAS_STA +static int wlan_sta_rx_done(void *buffer, uint16_t len, void *eb) +{ + struct wlan_priv_s *priv = &g_wlan_priv[ESP32S3_WLAN_STA_DEVNO]; + + return wlan_rx_done(priv, buffer, len, eb); +} + +/**************************************************************************** + * Name: wlan_sta_tx_done + * + * Description: + * Wi-Fi station TX done callback function. If this is called, it means + * station sending next packet. + * + * Input Parameters: + * 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 successfully or false if failed. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_sta_tx_done(uint8_t *data, uint16_t *len, bool status) +{ + struct wlan_priv_s *priv = &g_wlan_priv[ESP32S3_WLAN_STA_DEVNO]; + + wlan_tx_done(priv); +} +#endif /* ESP32S3_WLAN_HAS_STA */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef ESP32S3_WLAN_HAS_STA + +/**************************************************************************** + * Name: esp32s3_wlan_sta_set_linkstatus + * + * Description: + * Set Wi-Fi station link status + * + * Parameters: + * linkstatus - true Notifies the networking layer about an available + * carrier, false Notifies the networking layer about an + * disappeared carrier. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int esp32s3_wlan_sta_set_linkstatus(bool linkstatus) +{ + int ret = -EINVAL; + FAR struct wlan_priv_s *priv = &g_wlan_priv[ESP32S3_WLAN_STA_DEVNO]; + + if (priv != NULL) + { + if (linkstatus == true) + { + ret = netdev_carrier_on(&priv->dev); + } + else + { + ret = netdev_carrier_off(&priv->dev); + } + + if (ret < 0) + { + nerr("ERROR: Failed to notify the networking layer\n"); + } + } + + return ret; +} + +/**************************************************************************** + * Name: esp32s3_wlan_sta_initialize + * + * Description: + * Initialize the ESP32-S3 WLAN station netcard driver + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int esp32s3_wlan_sta_initialize(void) +{ + int ret; + uint8_t eth_mac[6]; + + ret = esp_wifi_adapter_init(); + if (ret < 0) + { + nerr("ERROR: Initialize Wi-Fi adapter error: %d\n", ret); + return ret; + } + + ret = esp_wifi_sta_read_mac(eth_mac); + if (ret < 0) + { + nerr("ERROR: Failed to read MAC address\n"); + return ret; + } + + ninfo("Wi-Fi station MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + eth_mac[0], eth_mac[1], eth_mac[2], + eth_mac[3], eth_mac[4], eth_mac[5]); + + ret = esp32s3_net_initialize(ESP32S3_WLAN_STA_DEVNO, eth_mac, &g_sta_ops); + if (ret < 0) + { + nerr("ERROR: Failed to initialize net\n"); + return ret; + } + + ret = esp_wifi_sta_register_recv_cb(wlan_sta_rx_done); + if (ret < 0) + { + nerr("ERROR: Failed to register RX callback\n"); + return ret; + } + + esp_wifi_sta_register_txdone_cb(wlan_sta_tx_done); + + ninfo("INFO: Initialize Wi-Fi station success net\n"); + + return OK; +} +#endif /* ESP32S3_WLAN_HAS_STA */ + +#endif /* CONFIG_ESP32S3_WIFI */ diff --git a/arch/xtensa/src/esp32s3/esp32s3_wlan.h b/arch/xtensa/src/esp32s3/esp32s3_wlan.h new file mode 100644 index 00000000000..da9a1ee5c25 --- /dev/null +++ b/arch/xtensa/src/esp32s3/esp32s3_wlan.h @@ -0,0 +1,93 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/esp32s3_wlan.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WLAN_H +#define __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WLAN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "esp32s3_wifi_adapter.h" + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#ifdef CONFIG_ESP32S3_WIFI + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef ESP32S3_WLAN_HAS_STA + +/**************************************************************************** + * Name: esp32s3_wlan_sta_set_linkstatus + * + * Description: + * Set Wi-Fi station link status + * + * Parameters: + * linkstatus - true Notifies the networking layer about an available + * carrier, false Notifies the networking layer about an + * disappeared carrier. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int esp32s3_wlan_sta_set_linkstatus(bool linkstatus); + +/**************************************************************************** + * Name: esp32s3_wlan_sta_initialize + * + * Description: + * Initialize the ESP32-S3 WLAN station netcard driver + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int esp32s3_wlan_sta_initialize(void); +#endif /* ESP32S3_WLAN_HAS_STA */ + +#endif /* CONFIG_ESP32S3_WIFI */ +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WLAN_H */ diff --git a/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h b/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h index 9b61615669d..01ed5dc9e4e 100644 --- a/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h +++ b/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h @@ -1761,6 +1761,8 @@ #define RTC_CNTL_RTC_STORE1_REG (DR_REG_RTCCNTL_BASE + 0x54) +#define RTC_SLOW_CLK_CAL_REG RTC_CNTL_RTC_STORE1_REG + /* RTC_CNTL_RTC_SCRATCH1 : R/W; bitpos: [31:0]; default: 0; * Reserved register */ diff --git a/arch/xtensa/src/esp32s3/hardware/esp32s3_syscon.h b/arch/xtensa/src/esp32s3/hardware/esp32s3_syscon.h new file mode 100644 index 00000000000..ba516f382d3 --- /dev/null +++ b/arch/xtensa/src/esp32s3/hardware/esp32s3_syscon.h @@ -0,0 +1,840 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/hardware/esp32s3_syscon.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32S3_HARDWARE_ESP32S3_SYSCON_H +#define __ARCH_XTENSA_SRC_ESP32S3_HARDWARE_ESP32S3_SYSCON_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "esp32s3_soc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define SYSCON_SYSCLK_CONF_REG (DR_REG_SYSCON_BASE + 0x0) + +/* SYSCON_RST_TICK_CNT : R/W ;bitpos:[12] ;default: 1'b0 ; */ + +#define SYSCON_RST_TICK_CNT (BIT(12)) +#define SYSCON_RST_TICK_CNT_M (BIT(12)) +#define SYSCON_RST_TICK_CNT_V 0x1 +#define SYSCON_RST_TICK_CNT_S 12 + +/* SYSCON_CLK_EN : R/W ;bitpos:[11] ;default: 1'b0 ; */ + +#define SYSCON_CLK_EN (BIT(11)) +#define SYSCON_CLK_EN_M (BIT(11)) +#define SYSCON_CLK_EN_V 0x1 +#define SYSCON_CLK_EN_S 11 + +/* SYSCON_CLK_320M_EN : R/W ;bitpos:[10] ;default: 1'b0 ; */ + +#define SYSCON_CLK_320M_EN (BIT(10)) +#define SYSCON_CLK_320M_EN_M (BIT(10)) +#define SYSCON_CLK_320M_EN_V 0x1 +#define SYSCON_CLK_320M_EN_S 10 + +/* SYSCON_PRE_DIV_CNT : R/W ;bitpos:[9:0] ;default: 10'h1 ; */ + +#define SYSCON_PRE_DIV_CNT 0x000003FF +#define SYSCON_PRE_DIV_CNT_M ((SYSCON_PRE_DIV_CNT_V)<<(SYSCON_PRE_DIV_CNT_S)) +#define SYSCON_PRE_DIV_CNT_V 0x3FF +#define SYSCON_PRE_DIV_CNT_S 0 + +#define SYSCON_TICK_CONF_REG (DR_REG_SYSCON_BASE + 0x4) + +/* SYSCON_TICK_ENABLE : R/W ;bitpos:[16] ;default: 1'd1 ; */ + +#define SYSCON_TICK_ENABLE (BIT(16)) +#define SYSCON_TICK_ENABLE_M (BIT(16)) +#define SYSCON_TICK_ENABLE_V 0x1 +#define SYSCON_TICK_ENABLE_S 16 + +/* SYSCON_CK8M_TICK_NUM : R/W ;bitpos:[15:8] ;default: 8'd7 ; */ + +#define SYSCON_CK8M_TICK_NUM 0x000000FF +#define SYSCON_CK8M_TICK_NUM_M ((SYSCON_CK8M_TICK_NUM_V)<<(SYSCON_CK8M_TICK_NUM_S)) +#define SYSCON_CK8M_TICK_NUM_V 0xFF +#define SYSCON_CK8M_TICK_NUM_S 8 + +/* SYSCON_XTAL_TICK_NUM : R/W ;bitpos:[7:0] ;default: 8'd39 ; */ + +#define SYSCON_XTAL_TICK_NUM 0x000000FF +#define SYSCON_XTAL_TICK_NUM_M ((SYSCON_XTAL_TICK_NUM_V)<<(SYSCON_XTAL_TICK_NUM_S)) +#define SYSCON_XTAL_TICK_NUM_V 0xFF +#define SYSCON_XTAL_TICK_NUM_S 0 + +#define SYSCON_CLK_OUT_EN_REG (DR_REG_SYSCON_BASE + 0x8) + +/* SYSCON_CLK_XTAL_OEN : R/W ;bitpos:[10] ;default: 1'b1 ; */ + +#define SYSCON_CLK_XTAL_OEN (BIT(10)) +#define SYSCON_CLK_XTAL_OEN_M (BIT(10)) +#define SYSCON_CLK_XTAL_OEN_V 0x1 +#define SYSCON_CLK_XTAL_OEN_S 10 + +/* SYSCON_CLK40X_BB_OEN : R/W ;bitpos:[9] ;default: 1'b1 ; */ + +#define SYSCON_CLK40X_BB_OEN (BIT(9)) +#define SYSCON_CLK40X_BB_OEN_M (BIT(9)) +#define SYSCON_CLK40X_BB_OEN_V 0x1 +#define SYSCON_CLK40X_BB_OEN_S 9 + +/* SYSCON_CLK_DAC_CPU_OEN : R/W ;bitpos:[8] ;default: 1'b1 ; */ + +#define SYSCON_CLK_DAC_CPU_OEN (BIT(8)) +#define SYSCON_CLK_DAC_CPU_OEN_M (BIT(8)) +#define SYSCON_CLK_DAC_CPU_OEN_V 0x1 +#define SYSCON_CLK_DAC_CPU_OEN_S 8 + +/* SYSCON_CLK_ADC_INF_OEN : R/W ;bitpos:[7] ;default: 1'b1 ; */ + +#define SYSCON_CLK_ADC_INF_OEN (BIT(7)) +#define SYSCON_CLK_ADC_INF_OEN_M (BIT(7)) +#define SYSCON_CLK_ADC_INF_OEN_V 0x1 +#define SYSCON_CLK_ADC_INF_OEN_S 7 + +/* SYSCON_CLK_320M_OEN : R/W ;bitpos:[6] ;default: 1'b1 ; */ + +#define SYSCON_CLK_320M_OEN (BIT(6)) +#define SYSCON_CLK_320M_OEN_M (BIT(6)) +#define SYSCON_CLK_320M_OEN_V 0x1 +#define SYSCON_CLK_320M_OEN_S 6 + +/* SYSCON_CLK160_OEN : R/W ;bitpos:[5] ;default: 1'b1 ; */ + +#define SYSCON_CLK160_OEN (BIT(5)) +#define SYSCON_CLK160_OEN_M (BIT(5)) +#define SYSCON_CLK160_OEN_V 0x1 +#define SYSCON_CLK160_OEN_S 5 + +/* SYSCON_CLK80_OEN : R/W ;bitpos:[4] ;default: 1'b1 ; */ + +#define SYSCON_CLK80_OEN (BIT(4)) +#define SYSCON_CLK80_OEN_M (BIT(4)) +#define SYSCON_CLK80_OEN_V 0x1 +#define SYSCON_CLK80_OEN_S 4 + +/* SYSCON_CLK_BB_OEN : R/W ;bitpos:[3] ;default: 1'b1 ; */ + +#define SYSCON_CLK_BB_OEN (BIT(3)) +#define SYSCON_CLK_BB_OEN_M (BIT(3)) +#define SYSCON_CLK_BB_OEN_V 0x1 +#define SYSCON_CLK_BB_OEN_S 3 + +/* SYSCON_CLK44_OEN : R/W ;bitpos:[2] ;default: 1'b1 ; */ + +#define SYSCON_CLK44_OEN (BIT(2)) +#define SYSCON_CLK44_OEN_M (BIT(2)) +#define SYSCON_CLK44_OEN_V 0x1 +#define SYSCON_CLK44_OEN_S 2 + +/* SYSCON_CLK22_OEN : R/W ;bitpos:[1] ;default: 1'b1 ; */ + +#define SYSCON_CLK22_OEN (BIT(1)) +#define SYSCON_CLK22_OEN_M (BIT(1)) +#define SYSCON_CLK22_OEN_V 0x1 +#define SYSCON_CLK22_OEN_S 1 + +/* SYSCON_CLK20_OEN : R/W ;bitpos:[0] ;default: 1'b1 ; */ + +#define SYSCON_CLK20_OEN (BIT(0)) +#define SYSCON_CLK20_OEN_M (BIT(0)) +#define SYSCON_CLK20_OEN_V 0x1 +#define SYSCON_CLK20_OEN_S 0 + +#define SYSCON_WIFI_BB_CFG_REG (DR_REG_SYSCON_BASE + 0xC) + +/* SYSCON_WIFI_BB_CFG : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ + +#define SYSCON_WIFI_BB_CFG 0xFFFFFFFF +#define SYSCON_WIFI_BB_CFG_M ((SYSCON_WIFI_BB_CFG_V)<<(SYSCON_WIFI_BB_CFG_S)) +#define SYSCON_WIFI_BB_CFG_V 0xFFFFFFFF +#define SYSCON_WIFI_BB_CFG_S 0 + +#define SYSCON_WIFI_BB_CFG_2_REG (DR_REG_SYSCON_BASE + 0x10) + +/* SYSCON_WIFI_BB_CFG_2 : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ + +#define SYSCON_WIFI_BB_CFG_2 0xFFFFFFFF +#define SYSCON_WIFI_BB_CFG_2_M ((SYSCON_WIFI_BB_CFG_2_V)<<(SYSCON_WIFI_BB_CFG_2_S)) +#define SYSCON_WIFI_BB_CFG_2_V 0xFFFFFFFF +#define SYSCON_WIFI_BB_CFG_2_S 0 + +#define SYSCON_WIFI_CLK_EN_REG (DR_REG_SYSCON_BASE + 0x14) + +/* SYSCON_WIFI_CLK_EN : R/W ;bitpos:[31:0] ;default: 32'hfffce030 ; */ + +#define SYSCON_WIFI_CLK_EN 0xFFFFFFFF +#define SYSCON_WIFI_CLK_EN_M ((SYSCON_WIFI_CLK_EN_V)<<(SYSCON_WIFI_CLK_EN_S)) +#define SYSCON_WIFI_CLK_EN_V 0xFFFFFFFF +#define SYSCON_WIFI_CLK_EN_S 0 + +#define SYSCON_WIFI_RST_EN_REG (DR_REG_SYSCON_BASE + 0x18) + +/* SYSCON_WIFI_RST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ + +#define SYSCON_WIFI_RST 0xFFFFFFFF +#define SYSCON_WIFI_RST_M ((SYSCON_WIFI_RST_V)<<(SYSCON_WIFI_RST_S)) +#define SYSCON_WIFI_RST_V 0xFFFFFFFF +#define SYSCON_WIFI_RST_S 0 + +#define SYSTEM_WIFI_CLK_EN_REG SYSCON_WIFI_CLK_EN_REG + +/* SYSTEM_WIFI_CLK_EN : R/W ;bitpos:[31:0] ;default: 32'hfffce030 ; */ + +#define SYSTEM_WIFI_CLK_EN 0x00FB9FCF +#define SYSTEM_WIFI_CLK_EN_M ((SYSTEM_WIFI_CLK_EN_V) << (SYSTEM_WIFI_CLK_EN_S)) +#define SYSTEM_WIFI_CLK_EN_V 0x00FB9FCF +#define SYSTEM_WIFI_CLK_EN_S 0 + +/* Mask for all Wifi clock bits, 6 */ + +#define SYSTEM_WIFI_CLK_WIFI_EN 0x0 +#define SYSTEM_WIFI_CLK_WIFI_EN_M ((SYSTEM_WIFI_CLK_WIFI_EN_V)<<(SYSTEM_WIFI_CLK_WIFI_EN_S)) +#define SYSTEM_WIFI_CLK_WIFI_EN_V 0x0 +#define SYSTEM_WIFI_CLK_WIFI_EN_S 0 + +/* Mask for all Bluetooth clock bits, 11, 16, 17 */ + +#define SYSTEM_WIFI_CLK_BT_EN 0x0 +#define SYSTEM_WIFI_CLK_BT_EN_M ((SYSTEM_WIFI_CLK_BT_EN_V)<<(SYSTEM_WIFI_CLK_BT_EN_S)) +#define SYSTEM_WIFI_CLK_BT_EN_V 0x0 +#define SYSTEM_WIFI_CLK_BT_EN_S 0 + +/* Mask for clock bits used by both WIFI and Bluetooth, + * bit 0, 1, 2, 3, 7, 8, 9, 10, 19, 20, 21, 22, 23 + */ + +#define SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M 0x78078F + +/* bluetooth baseband bit11 */ + +#define SYSTEM_BT_BASEBAND_EN BIT(11) + +/* bluetooth LC bit16 and bit17 */ + +#define SYSTEM_BT_LC_EN (BIT(16) | BIT(17)) + +/* Remaining single bit clock masks */ + +#define SYSTEM_WIFI_CLK_I2C_CLK_EN BIT(5) +#define SYSTEM_WIFI_CLK_UNUSED_BIT12 BIT(12) +#define SYSTEM_WIFI_CLK_SDIO_HOST_EN BIT(13) +#define SYSTEM_WIFI_CLK_EMAC_EN BIT(14) +#define SYSTEM_WIFI_CLK_RNG_EN BIT(15) + +#define SYSTEM_CORE_RST_EN_REG SYSTEM_WIFI_RST_EN_REG +#define SYSTEM_WIFI_RST_EN_REG SYSCON_WIFI_RST_EN_REG + +/* SYSTEM_WIFI_RST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ + +#define SYSTEM_WIFI_RST 0xFFFFFFFF +#define SYSTEM_WIFI_RST_M ((SYSTEM_WIFI_RST_V) << (SYSTEM_WIFI_RST_S)) +#define SYSTEM_WIFI_RST_V 0xFFFFFFFF +#define SYSTEM_WIFI_RST_S 0 + +#define SYSTEM_WIFIBB_RST BIT(0) +#define SYSTEM_FE_RST BIT(1) +#define SYSTEM_WIFIMAC_RST BIT(2) +#define SYSTEM_BTBB_RST BIT(3) /* Bluetooth Baseband */ +#define SYSTEM_BTMAC_RST BIT(4) /* deprecated */ +#define SYSTEM_SDIO_RST BIT(5) +#define SYSTEM_EMAC_RST BIT(7) +#define SYSTEM_MACPWR_RST BIT(8) +#define SYSTEM_RW_BTMAC_RST BIT(9) /* Bluetooth MAC */ +#define SYSTEM_RW_BTLP_RST BIT(10) /* Bluetooth Low Power Module */ +#define SYSTEM_RW_BTMAC_REG_RST BIT(11) /* Bluetooth MAC Regsiters */ +#define SYSTEM_RW_BTLP_REG_RST BIT(12) /* Bluetooth Low Power Registers */ +#define SYSTEM_BTBB_REG_RST BIT(13) /* Bluetooth Baseband Registers */ + +#define MODEM_RESET_FIELD_WHEN_PU (SYSTEM_WIFIBB_RST | \ + SYSTEM_FE_RST | \ + SYSTEM_WIFIMAC_RST | \ + SYSTEM_BTBB_RST | \ + SYSTEM_BTMAC_RST | \ + SYSTEM_RW_BTMAC_RST | \ + SYSTEM_RW_BTMAC_REG_RST | \ + SYSTEM_BTBB_REG_RST) + +#define SYSCON_HOST_INF_SEL_REG (DR_REG_SYSCON_BASE + 0x1C) + +/* SYSCON_PERI_IO_SWAP : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ + +#define SYSCON_PERI_IO_SWAP 0x000000FF +#define SYSCON_PERI_IO_SWAP_M ((SYSCON_PERI_IO_SWAP_V)<<(SYSCON_PERI_IO_SWAP_S)) +#define SYSCON_PERI_IO_SWAP_V 0xFF +#define SYSCON_PERI_IO_SWAP_S 0 + +#define SYSCON_EXT_MEM_PMS_LOCK_REG (DR_REG_SYSCON_BASE + 0x20) + +/* SYSCON_EXT_MEM_PMS_LOCK : R/W ;bitpos:[0] ;default: 1'b0 ; */ + +#define SYSCON_EXT_MEM_PMS_LOCK (BIT(0)) +#define SYSCON_EXT_MEM_PMS_LOCK_M (BIT(0)) +#define SYSCON_EXT_MEM_PMS_LOCK_V 0x1 +#define SYSCON_EXT_MEM_PMS_LOCK_S 0 + +#define SYSCON_EXT_MEM_WRITEBACK_BYPASS_REG (DR_REG_SYSCON_BASE + 0x24) + +/* SYSCON_WRITEBACK_BYPASS : R/W ;bitpos:[0] ;default: 1'b0 ; + * Set 1 to bypass cache writeback request to external memory so that spi + * will not check its attribute. + */ + +#define SYSCON_WRITEBACK_BYPASS (BIT(0)) +#define SYSCON_WRITEBACK_BYPASS_M (BIT(0)) +#define SYSCON_WRITEBACK_BYPASS_V 0x1 +#define SYSCON_WRITEBACK_BYPASS_S 0 + +#define SYSCON_FLASH_ACE0_ATTR_REG (DR_REG_SYSCON_BASE + 0x28) + +/* SYSCON_FLASH_ACE0_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ + +#define SYSCON_FLASH_ACE0_ATTR 0x000001FF +#define SYSCON_FLASH_ACE0_ATTR_M ((SYSCON_FLASH_ACE0_ATTR_V)<<(SYSCON_FLASH_ACE0_ATTR_S)) +#define SYSCON_FLASH_ACE0_ATTR_V 0x1FF +#define SYSCON_FLASH_ACE0_ATTR_S 0 + +#define SYSCON_FLASH_ACE1_ATTR_REG (DR_REG_SYSCON_BASE + 0x2C) + +/* SYSCON_FLASH_ACE1_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ + +#define SYSCON_FLASH_ACE1_ATTR 0x000001FF +#define SYSCON_FLASH_ACE1_ATTR_M ((SYSCON_FLASH_ACE1_ATTR_V)<<(SYSCON_FLASH_ACE1_ATTR_S)) +#define SYSCON_FLASH_ACE1_ATTR_V 0x1FF +#define SYSCON_FLASH_ACE1_ATTR_S 0 + +#define SYSCON_FLASH_ACE2_ATTR_REG (DR_REG_SYSCON_BASE + 0x30) + +/* SYSCON_FLASH_ACE2_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ + +#define SYSCON_FLASH_ACE2_ATTR 0x000001FF +#define SYSCON_FLASH_ACE2_ATTR_M ((SYSCON_FLASH_ACE2_ATTR_V)<<(SYSCON_FLASH_ACE2_ATTR_S)) +#define SYSCON_FLASH_ACE2_ATTR_V 0x1FF +#define SYSCON_FLASH_ACE2_ATTR_S 0 + +#define SYSCON_FLASH_ACE3_ATTR_REG (DR_REG_SYSCON_BASE + 0x34) + +/* SYSCON_FLASH_ACE3_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ + +#define SYSCON_FLASH_ACE3_ATTR 0x000001FF +#define SYSCON_FLASH_ACE3_ATTR_M ((SYSCON_FLASH_ACE3_ATTR_V)<<(SYSCON_FLASH_ACE3_ATTR_S)) +#define SYSCON_FLASH_ACE3_ATTR_V 0x1FF +#define SYSCON_FLASH_ACE3_ATTR_S 0 + +#define SYSCON_FLASH_ACE0_ADDR_REG (DR_REG_SYSCON_BASE + 0x38) + +/* SYSCON_FLASH_ACE0_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ + +#define SYSCON_FLASH_ACE0_ADDR_S 0xFFFFFFFF +#define SYSCON_FLASH_ACE0_ADDR_S_M ((SYSCON_FLASH_ACE0_ADDR_S_V)<<(SYSCON_FLASH_ACE0_ADDR_S_S)) +#define SYSCON_FLASH_ACE0_ADDR_S_V 0xFFFFFFFF +#define SYSCON_FLASH_ACE0_ADDR_S_S 0 + +#define SYSCON_FLASH_ACE1_ADDR_REG (DR_REG_SYSCON_BASE + 0x3C) + +/* SYSCON_FLASH_ACE1_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h10000000 ; */ + +#define SYSCON_FLASH_ACE1_ADDR_S 0xFFFFFFFF +#define SYSCON_FLASH_ACE1_ADDR_S_M ((SYSCON_FLASH_ACE1_ADDR_S_V)<<(SYSCON_FLASH_ACE1_ADDR_S_S)) +#define SYSCON_FLASH_ACE1_ADDR_S_V 0xFFFFFFFF +#define SYSCON_FLASH_ACE1_ADDR_S_S 0 + +#define SYSCON_FLASH_ACE2_ADDR_REG (DR_REG_SYSCON_BASE + 0x40) + +/* SYSCON_FLASH_ACE2_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h20000000 ; */ + +#define SYSCON_FLASH_ACE2_ADDR_S 0xFFFFFFFF +#define SYSCON_FLASH_ACE2_ADDR_S_M ((SYSCON_FLASH_ACE2_ADDR_S_V)<<(SYSCON_FLASH_ACE2_ADDR_S_S)) +#define SYSCON_FLASH_ACE2_ADDR_S_V 0xFFFFFFFF +#define SYSCON_FLASH_ACE2_ADDR_S_S 0 + +#define SYSCON_FLASH_ACE3_ADDR_REG (DR_REG_SYSCON_BASE + 0x44) + +/* SYSCON_FLASH_ACE3_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h30000000 ; */ + +#define SYSCON_FLASH_ACE3_ADDR_S 0xFFFFFFFF +#define SYSCON_FLASH_ACE3_ADDR_S_M ((SYSCON_FLASH_ACE3_ADDR_S_V)<<(SYSCON_FLASH_ACE3_ADDR_S_S)) +#define SYSCON_FLASH_ACE3_ADDR_S_V 0xFFFFFFFF +#define SYSCON_FLASH_ACE3_ADDR_S_S 0 + +#define SYSCON_FLASH_ACE0_SIZE_REG (DR_REG_SYSCON_BASE + 0x48) +/* SYSCON_FLASH_ACE0_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ + +#define SYSCON_FLASH_ACE0_SIZE 0x0000FFFF +#define SYSCON_FLASH_ACE0_SIZE_M ((SYSCON_FLASH_ACE0_SIZE_V)<<(SYSCON_FLASH_ACE0_SIZE_S)) +#define SYSCON_FLASH_ACE0_SIZE_V 0xFFFF +#define SYSCON_FLASH_ACE0_SIZE_S 0 + +#define SYSCON_FLASH_ACE1_SIZE_REG (DR_REG_SYSCON_BASE + 0x4C) + +/* SYSCON_FLASH_ACE1_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ + +#define SYSCON_FLASH_ACE1_SIZE 0x0000FFFF +#define SYSCON_FLASH_ACE1_SIZE_M ((SYSCON_FLASH_ACE1_SIZE_V)<<(SYSCON_FLASH_ACE1_SIZE_S)) +#define SYSCON_FLASH_ACE1_SIZE_V 0xFFFF +#define SYSCON_FLASH_ACE1_SIZE_S 0 + +#define SYSCON_FLASH_ACE2_SIZE_REG (DR_REG_SYSCON_BASE + 0x50) + +/* SYSCON_FLASH_ACE2_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ + +#define SYSCON_FLASH_ACE2_SIZE 0x0000FFFF +#define SYSCON_FLASH_ACE2_SIZE_M ((SYSCON_FLASH_ACE2_SIZE_V)<<(SYSCON_FLASH_ACE2_SIZE_S)) +#define SYSCON_FLASH_ACE2_SIZE_V 0xFFFF +#define SYSCON_FLASH_ACE2_SIZE_S 0 + +#define SYSCON_FLASH_ACE3_SIZE_REG (DR_REG_SYSCON_BASE + 0x54) + +/* SYSCON_FLASH_ACE3_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ + +#define SYSCON_FLASH_ACE3_SIZE 0x0000FFFF +#define SYSCON_FLASH_ACE3_SIZE_M ((SYSCON_FLASH_ACE3_SIZE_V)<<(SYSCON_FLASH_ACE3_SIZE_S)) +#define SYSCON_FLASH_ACE3_SIZE_V 0xFFFF +#define SYSCON_FLASH_ACE3_SIZE_S 0 + +#define SYSCON_SRAM_ACE0_ATTR_REG (DR_REG_SYSCON_BASE + 0x58) + +/* SYSCON_SRAM_ACE0_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ + +#define SYSCON_SRAM_ACE0_ATTR 0x000001FF +#define SYSCON_SRAM_ACE0_ATTR_M ((SYSCON_SRAM_ACE0_ATTR_V)<<(SYSCON_SRAM_ACE0_ATTR_S)) +#define SYSCON_SRAM_ACE0_ATTR_V 0x1FF +#define SYSCON_SRAM_ACE0_ATTR_S 0 + +#define SYSCON_SRAM_ACE1_ATTR_REG (DR_REG_SYSCON_BASE + 0x5C) + +/* SYSCON_SRAM_ACE1_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ + +#define SYSCON_SRAM_ACE1_ATTR 0x000001FF +#define SYSCON_SRAM_ACE1_ATTR_M ((SYSCON_SRAM_ACE1_ATTR_V)<<(SYSCON_SRAM_ACE1_ATTR_S)) +#define SYSCON_SRAM_ACE1_ATTR_V 0x1FF +#define SYSCON_SRAM_ACE1_ATTR_S 0 + +#define SYSCON_SRAM_ACE2_ATTR_REG (DR_REG_SYSCON_BASE + 0x60) + +/* SYSCON_SRAM_ACE2_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ + +#define SYSCON_SRAM_ACE2_ATTR 0x000001FF +#define SYSCON_SRAM_ACE2_ATTR_M ((SYSCON_SRAM_ACE2_ATTR_V)<<(SYSCON_SRAM_ACE2_ATTR_S)) +#define SYSCON_SRAM_ACE2_ATTR_V 0x1FF +#define SYSCON_SRAM_ACE2_ATTR_S 0 + +#define SYSCON_SRAM_ACE3_ATTR_REG (DR_REG_SYSCON_BASE + 0x64) + +/* SYSCON_SRAM_ACE3_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ + +#define SYSCON_SRAM_ACE3_ATTR 0x000001FF +#define SYSCON_SRAM_ACE3_ATTR_M ((SYSCON_SRAM_ACE3_ATTR_V)<<(SYSCON_SRAM_ACE3_ATTR_S)) +#define SYSCON_SRAM_ACE3_ATTR_V 0x1FF +#define SYSCON_SRAM_ACE3_ATTR_S 0 + +#define SYSCON_SRAM_ACE0_ADDR_REG (DR_REG_SYSCON_BASE + 0x68) + +/* SYSCON_SRAM_ACE0_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ + +#define SYSCON_SRAM_ACE0_ADDR_S 0xFFFFFFFF +#define SYSCON_SRAM_ACE0_ADDR_S_M ((SYSCON_SRAM_ACE0_ADDR_S_V)<<(SYSCON_SRAM_ACE0_ADDR_S_S)) +#define SYSCON_SRAM_ACE0_ADDR_S_V 0xFFFFFFFF +#define SYSCON_SRAM_ACE0_ADDR_S_S 0 + +#define SYSCON_SRAM_ACE1_ADDR_REG (DR_REG_SYSCON_BASE + 0x6C) + +/* SYSCON_SRAM_ACE1_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h10000000 ; */ + +#define SYSCON_SRAM_ACE1_ADDR_S 0xFFFFFFFF +#define SYSCON_SRAM_ACE1_ADDR_S_M ((SYSCON_SRAM_ACE1_ADDR_S_V)<<(SYSCON_SRAM_ACE1_ADDR_S_S)) +#define SYSCON_SRAM_ACE1_ADDR_S_V 0xFFFFFFFF +#define SYSCON_SRAM_ACE1_ADDR_S_S 0 + +#define SYSCON_SRAM_ACE2_ADDR_REG (DR_REG_SYSCON_BASE + 0x70) + +/* SYSCON_SRAM_ACE2_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h20000000 ; */ + +#define SYSCON_SRAM_ACE2_ADDR_S 0xFFFFFFFF +#define SYSCON_SRAM_ACE2_ADDR_S_M ((SYSCON_SRAM_ACE2_ADDR_S_V)<<(SYSCON_SRAM_ACE2_ADDR_S_S)) +#define SYSCON_SRAM_ACE2_ADDR_S_V 0xFFFFFFFF +#define SYSCON_SRAM_ACE2_ADDR_S_S 0 + +#define SYSCON_SRAM_ACE3_ADDR_REG (DR_REG_SYSCON_BASE + 0x74) + +/* SYSCON_SRAM_ACE3_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h30000000 ; */ + +#define SYSCON_SRAM_ACE3_ADDR_S 0xFFFFFFFF +#define SYSCON_SRAM_ACE3_ADDR_S_M ((SYSCON_SRAM_ACE3_ADDR_S_V)<<(SYSCON_SRAM_ACE3_ADDR_S_S)) +#define SYSCON_SRAM_ACE3_ADDR_S_V 0xFFFFFFFF +#define SYSCON_SRAM_ACE3_ADDR_S_S 0 + +#define SYSCON_SRAM_ACE0_SIZE_REG (DR_REG_SYSCON_BASE + 0x78) + +/* SYSCON_SRAM_ACE0_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ + +#define SYSCON_SRAM_ACE0_SIZE 0x0000FFFF +#define SYSCON_SRAM_ACE0_SIZE_M ((SYSCON_SRAM_ACE0_SIZE_V)<<(SYSCON_SRAM_ACE0_SIZE_S)) +#define SYSCON_SRAM_ACE0_SIZE_V 0xFFFF +#define SYSCON_SRAM_ACE0_SIZE_S 0 + +#define SYSCON_SRAM_ACE1_SIZE_REG (DR_REG_SYSCON_BASE + 0x7C) + +/* SYSCON_SRAM_ACE1_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ + +#define SYSCON_SRAM_ACE1_SIZE 0x0000FFFF +#define SYSCON_SRAM_ACE1_SIZE_M ((SYSCON_SRAM_ACE1_SIZE_V)<<(SYSCON_SRAM_ACE1_SIZE_S)) +#define SYSCON_SRAM_ACE1_SIZE_V 0xFFFF +#define SYSCON_SRAM_ACE1_SIZE_S 0 + +#define SYSCON_SRAM_ACE2_SIZE_REG (DR_REG_SYSCON_BASE + 0x80) + +/* SYSCON_SRAM_ACE2_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ + +#define SYSCON_SRAM_ACE2_SIZE 0x0000FFFF +#define SYSCON_SRAM_ACE2_SIZE_M ((SYSCON_SRAM_ACE2_SIZE_V)<<(SYSCON_SRAM_ACE2_SIZE_S)) +#define SYSCON_SRAM_ACE2_SIZE_V 0xFFFF +#define SYSCON_SRAM_ACE2_SIZE_S 0 + +#define SYSCON_SRAM_ACE3_SIZE_REG (DR_REG_SYSCON_BASE + 0x84) + +/* SYSCON_SRAM_ACE3_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ + +#define SYSCON_SRAM_ACE3_SIZE 0x0000FFFF +#define SYSCON_SRAM_ACE3_SIZE_M ((SYSCON_SRAM_ACE3_SIZE_V)<<(SYSCON_SRAM_ACE3_SIZE_S)) +#define SYSCON_SRAM_ACE3_SIZE_V 0xFFFF +#define SYSCON_SRAM_ACE3_SIZE_S 0 + +#define SYSCON_SPI_MEM_PMS_CTRL_REG (DR_REG_SYSCON_BASE + 0x88) + +/* SYSCON_SPI_MEM_REJECT_CDE : RO ;bitpos:[6:2] ;default: 5'h0 ; */ + +#define SYSCON_SPI_MEM_REJECT_CDE 0x0000001F +#define SYSCON_SPI_MEM_REJECT_CDE_M ((SYSCON_SPI_MEM_REJECT_CDE_V)<<(SYSCON_SPI_MEM_REJECT_CDE_S)) +#define SYSCON_SPI_MEM_REJECT_CDE_V 0x1F +#define SYSCON_SPI_MEM_REJECT_CDE_S 2 + +/* SYSCON_SPI_MEM_REJECT_CLR : WOD ;bitpos:[1] ;default: 1'b0 ; */ + +#define SYSCON_SPI_MEM_REJECT_CLR (BIT(1)) +#define SYSCON_SPI_MEM_REJECT_CLR_M (BIT(1)) +#define SYSCON_SPI_MEM_REJECT_CLR_V 0x1 +#define SYSCON_SPI_MEM_REJECT_CLR_S 1 + +/* SYSCON_SPI_MEM_REJECT_INT : RO ;bitpos:[0] ;default: 1'b0 ; */ + +#define SYSCON_SPI_MEM_REJECT_INT (BIT(0)) +#define SYSCON_SPI_MEM_REJECT_INT_M (BIT(0)) +#define SYSCON_SPI_MEM_REJECT_INT_V 0x1 +#define SYSCON_SPI_MEM_REJECT_INT_S 0 + +#define SYSCON_SPI_MEM_REJECT_ADDR_REG (DR_REG_SYSCON_BASE + 0x8C) + +/* SYSCON_SPI_MEM_REJECT_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ + +#define SYSCON_SPI_MEM_REJECT_ADDR 0xFFFFFFFF +#define SYSCON_SPI_MEM_REJECT_ADDR_M ((SYSCON_SPI_MEM_REJECT_ADDR_V)<<(SYSCON_SPI_MEM_REJECT_ADDR_S)) +#define SYSCON_SPI_MEM_REJECT_ADDR_V 0xFFFFFFFF +#define SYSCON_SPI_MEM_REJECT_ADDR_S 0 + +#define SYSCON_SDIO_CTRL_REG (DR_REG_SYSCON_BASE + 0x90) + +/* SYSCON_SDIO_WIN_ACCESS_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ + +#define SYSCON_SDIO_WIN_ACCESS_EN (BIT(0)) +#define SYSCON_SDIO_WIN_ACCESS_EN_M (BIT(0)) +#define SYSCON_SDIO_WIN_ACCESS_EN_V 0x1 +#define SYSCON_SDIO_WIN_ACCESS_EN_S 0 + +#define SYSCON_REDCY_SIG0_REG (DR_REG_SYSCON_BASE + 0x94) + +/* SYSCON_REDCY_ANDOR : RO ;bitpos:[31] ;default: 1'h0 ; */ + +#define SYSCON_REDCY_ANDOR (BIT(31)) +#define SYSCON_REDCY_ANDOR_M (BIT(31)) +#define SYSCON_REDCY_ANDOR_V 0x1 +#define SYSCON_REDCY_ANDOR_S 31 + +/* SYSCON_REDCY_SIG0 : R/W ;bitpos:[30:0] ;default: 31'h0 ; */ + +#define SYSCON_REDCY_SIG0 0x7FFFFFFF +#define SYSCON_REDCY_SIG0_M ((SYSCON_REDCY_SIG0_V)<<(SYSCON_REDCY_SIG0_S)) +#define SYSCON_REDCY_SIG0_V 0x7FFFFFFF +#define SYSCON_REDCY_SIG0_S 0 + +#define SYSCON_REDCY_SIG1_REG (DR_REG_SYSCON_BASE + 0x98) + +/* SYSCON_REDCY_NANDOR : RO ;bitpos:[31] ;default: 1'h0 ; */ + +#define SYSCON_REDCY_NANDOR (BIT(31)) +#define SYSCON_REDCY_NANDOR_M (BIT(31)) +#define SYSCON_REDCY_NANDOR_V 0x1 +#define SYSCON_REDCY_NANDOR_S 31 + +/* SYSCON_REDCY_SIG1 : R/W ;bitpos:[30:0] ;default: 31'h0 ; */ + +#define SYSCON_REDCY_SIG1 0x7FFFFFFF +#define SYSCON_REDCY_SIG1_M ((SYSCON_REDCY_SIG1_V)<<(SYSCON_REDCY_SIG1_S)) +#define SYSCON_REDCY_SIG1_V 0x7FFFFFFF +#define SYSCON_REDCY_SIG1_S 0 + +#define SYSCON_FRONT_END_MEM_PD_REG (DR_REG_SYSCON_BASE + 0x9C) + +/* SYSCON_FREQ_MEM_FORCE_PD : R/W ;bitpos:[7] ;default: 1'b0 ; */ + +#define SYSCON_FREQ_MEM_FORCE_PD (BIT(7)) +#define SYSCON_FREQ_MEM_FORCE_PD_M (BIT(7)) +#define SYSCON_FREQ_MEM_FORCE_PD_V 0x1 +#define SYSCON_FREQ_MEM_FORCE_PD_S 7 + +/* SYSCON_FREQ_MEM_FORCE_PU : R/W ;bitpos:[6] ;default: 1'b1 ; */ + +#define SYSCON_FREQ_MEM_FORCE_PU (BIT(6)) +#define SYSCON_FREQ_MEM_FORCE_PU_M (BIT(6)) +#define SYSCON_FREQ_MEM_FORCE_PU_V 0x1 +#define SYSCON_FREQ_MEM_FORCE_PU_S 6 + +/* SYSCON_DC_MEM_FORCE_PD : R/W ;bitpos:[5] ;default: 1'b0 ; */ + +#define SYSCON_DC_MEM_FORCE_PD (BIT(5)) +#define SYSCON_DC_MEM_FORCE_PD_M (BIT(5)) +#define SYSCON_DC_MEM_FORCE_PD_V 0x1 +#define SYSCON_DC_MEM_FORCE_PD_S 5 + +/* SYSCON_DC_MEM_FORCE_PU : R/W ;bitpos:[4] ;default: 1'b1 ; */ + +#define SYSCON_DC_MEM_FORCE_PU (BIT(4)) +#define SYSCON_DC_MEM_FORCE_PU_M (BIT(4)) +#define SYSCON_DC_MEM_FORCE_PU_V 0x1 +#define SYSCON_DC_MEM_FORCE_PU_S 4 + +/* SYSCON_PBUS_MEM_FORCE_PD : R/W ;bitpos:[3] ;default: 1'b0 ; */ + +#define SYSCON_PBUS_MEM_FORCE_PD (BIT(3)) +#define SYSCON_PBUS_MEM_FORCE_PD_M (BIT(3)) +#define SYSCON_PBUS_MEM_FORCE_PD_V 0x1 +#define SYSCON_PBUS_MEM_FORCE_PD_S 3 + +/* SYSCON_PBUS_MEM_FORCE_PU : R/W ;bitpos:[2] ;default: 1'b1 ; */ + +#define SYSCON_PBUS_MEM_FORCE_PU (BIT(2)) +#define SYSCON_PBUS_MEM_FORCE_PU_M (BIT(2)) +#define SYSCON_PBUS_MEM_FORCE_PU_V 0x1 +#define SYSCON_PBUS_MEM_FORCE_PU_S 2 + +/* SYSCON_AGC_MEM_FORCE_PD : R/W ;bitpos:[1] ;default: 1'b0 ; */ + +#define SYSCON_AGC_MEM_FORCE_PD (BIT(1)) +#define SYSCON_AGC_MEM_FORCE_PD_M (BIT(1)) +#define SYSCON_AGC_MEM_FORCE_PD_V 0x1 +#define SYSCON_AGC_MEM_FORCE_PD_S 1 + +/* SYSCON_AGC_MEM_FORCE_PU : R/W ;bitpos:[0] ;default: 1'b1 ; */ + +#define SYSCON_AGC_MEM_FORCE_PU (BIT(0)) +#define SYSCON_AGC_MEM_FORCE_PU_M (BIT(0)) +#define SYSCON_AGC_MEM_FORCE_PU_V 0x1 +#define SYSCON_AGC_MEM_FORCE_PU_S 0 + +#define SYSCON_SPI_MEM_ECC_CTRL_REG (DR_REG_SYSCON_BASE + 0xA0) + +/* SYSCON_SRAM_PAGE_SIZE : R/W ;bitpos:[21:20] ;default: 2'd2 ; + * Set the page size of the used MSPI external RAM. + * 0: 256 bytes. 1: 512 bytes. 2: 1024 bytes. 3: 2048 bytes. + */ + +#define SYSCON_SRAM_PAGE_SIZE 0x00000003 +#define SYSCON_SRAM_PAGE_SIZE_M ((SYSCON_SRAM_PAGE_SIZE_V)<<(SYSCON_SRAM_PAGE_SIZE_S)) +#define SYSCON_SRAM_PAGE_SIZE_V 0x3 +#define SYSCON_SRAM_PAGE_SIZE_S 20 + +/* SYSCON_FLASH_PAGE_SIZE : R/W ;bitpos:[19:18] ;default: 2'd0 ; + * Set the page size of the used MSPI flash. 0: 256 bytes. 1: 512 bytes. + * 2: 1024 bytes. 3: 2048 bytes. + */ + +#define SYSCON_FLASH_PAGE_SIZE 0x00000003 +#define SYSCON_FLASH_PAGE_SIZE_M ((SYSCON_FLASH_PAGE_SIZE_V)<<(SYSCON_FLASH_PAGE_SIZE_S)) +#define SYSCON_FLASH_PAGE_SIZE_V 0x3 +#define SYSCON_FLASH_PAGE_SIZE_S 18 + +#define SYSCON_CLKGATE_FORCE_ON_REG (DR_REG_SYSCON_BASE + 0xA8) + +/* SYSCON_SRAM_CLKGATE_FORCE_ON : R/W ;bitpos:[13:3] ;default: ~11'b0 ; */ + +#define SYSCON_SRAM_CLKGATE_FORCE_ON 0x000007FF +#define SYSCON_SRAM_CLKGATE_FORCE_ON_M ((SYSCON_SRAM_CLKGATE_FORCE_ON_V)<<(SYSCON_SRAM_CLKGATE_FORCE_ON_S)) +#define SYSCON_SRAM_CLKGATE_FORCE_ON_V 0x7FF +#define SYSCON_SRAM_CLKGATE_FORCE_ON_S 3 + +/* SYSCON_ROM_CLKGATE_FORCE_ON : R/W ;bitpos:[2:0] ;default: ~3'b0 ; */ + +#define SYSCON_ROM_CLKGATE_FORCE_ON 0x00000007 +#define SYSCON_ROM_CLKGATE_FORCE_ON_M ((SYSCON_ROM_CLKGATE_FORCE_ON_V)<<(SYSCON_ROM_CLKGATE_FORCE_ON_S)) +#define SYSCON_ROM_CLKGATE_FORCE_ON_V 0x7 +#define SYSCON_ROM_CLKGATE_FORCE_ON_S 0 + +#define SYSCON_MEM_POWER_DOWN_REG (DR_REG_SYSCON_BASE + 0xAC) + +/* SYSCON_SRAM_POWER_DOWN : R/W ;bitpos:[13:3] ;default: 11'b0 ; */ + +#define SYSCON_SRAM_POWER_DOWN 0x000007FF +#define SYSCON_SRAM_POWER_DOWN_M ((SYSCON_SRAM_POWER_DOWN_V)<<(SYSCON_SRAM_POWER_DOWN_S)) +#define SYSCON_SRAM_POWER_DOWN_V 0x7FF +#define SYSCON_SRAM_POWER_DOWN_S 3 + +/* SYSCON_ROM_POWER_DOWN : R/W ;bitpos:[2:0] ;default: 3'b0 ; */ + +#define SYSCON_ROM_POWER_DOWN 0x00000007 +#define SYSCON_ROM_POWER_DOWN_M ((SYSCON_ROM_POWER_DOWN_V)<<(SYSCON_ROM_POWER_DOWN_S)) +#define SYSCON_ROM_POWER_DOWN_V 0x7 +#define SYSCON_ROM_POWER_DOWN_S 0 + +#define SYSCON_MEM_POWER_UP_REG (DR_REG_SYSCON_BASE + 0xB0) + +/* SYSCON_SRAM_POWER_UP : R/W ;bitpos:[13:3] ;default: ~11'b0 ; */ + +#define SYSCON_SRAM_POWER_UP 0x000007FF +#define SYSCON_SRAM_POWER_UP_M ((SYSCON_SRAM_POWER_UP_V)<<(SYSCON_SRAM_POWER_UP_S)) +#define SYSCON_SRAM_POWER_UP_V 0x7FF +#define SYSCON_SRAM_POWER_UP_S 3 + +/* SYSCON_ROM_POWER_UP : R/W ;bitpos:[2:0] ;default: ~3'b0 ; */ + +#define SYSCON_ROM_POWER_UP 0x00000007 +#define SYSCON_ROM_POWER_UP_M ((SYSCON_ROM_POWER_UP_V)<<(SYSCON_ROM_POWER_UP_S)) +#define SYSCON_ROM_POWER_UP_V 0x7 +#define SYSCON_ROM_POWER_UP_S 0 + +#define SYSCON_RETENTION_CTRL_REG (DR_REG_SYSCON_BASE + 0xB4) + +/* SYSCON_NOBYPASS_CPU_ISO_RST : R/W ;bitpos:[27] ;default: 1'b0 ; */ + +#define SYSCON_NOBYPASS_CPU_ISO_RST (BIT(27)) +#define SYSCON_NOBYPASS_CPU_ISO_RST_M (BIT(27)) +#define SYSCON_NOBYPASS_CPU_ISO_RST_V 0x1 +#define SYSCON_NOBYPASS_CPU_ISO_RST_S 27 + +/* SYSCON_RETENTION_CPU_LINK_ADDR : R/W ;bitpos:[26:0] ;default: 27'd0 ; */ + +#define SYSCON_RETENTION_CPU_LINK_ADDR 0x07FFFFFF +#define SYSCON_RETENTION_CPU_LINK_ADDR_M ((SYSCON_RETENTION_CPU_LINK_ADDR_V)<<(SYSCON_RETENTION_CPU_LINK_ADDR_S)) +#define SYSCON_RETENTION_CPU_LINK_ADDR_V 0x7FFFFFF +#define SYSCON_RETENTION_CPU_LINK_ADDR_S 0 + +#define SYSCON_RETENTION_CTRL1_REG (DR_REG_SYSCON_BASE + 0xB8) + +/* SYSCON_RETENTION_TAG_LINK_ADDR : R/W ;bitpos:[26:0] ;default: 27'd0 ; */ + +#define SYSCON_RETENTION_TAG_LINK_ADDR 0x07FFFFFF +#define SYSCON_RETENTION_TAG_LINK_ADDR_M ((SYSCON_RETENTION_TAG_LINK_ADDR_V)<<(SYSCON_RETENTION_TAG_LINK_ADDR_S)) +#define SYSCON_RETENTION_TAG_LINK_ADDR_V 0x7FFFFFF +#define SYSCON_RETENTION_TAG_LINK_ADDR_S 0 + +#define SYSCON_RETENTION_CTRL2_REG (DR_REG_SYSCON_BASE + 0xBC) + +/* SYSCON_RET_ICACHE_ENABLE : R/W ;bitpos:[31] ;default: 1'b0 ; */ + +#define SYSCON_RET_ICACHE_ENABLE (BIT(31)) +#define SYSCON_RET_ICACHE_ENABLE_M (BIT(31)) +#define SYSCON_RET_ICACHE_ENABLE_V 0x1 +#define SYSCON_RET_ICACHE_ENABLE_S 31 + +/* SYSCON_RET_ICACHE_START_POINT : R/W ;bitpos:[29:22] ;default: 8'd0 ; */ + +#define SYSCON_RET_ICACHE_START_POINT 0x000000FF +#define SYSCON_RET_ICACHE_START_POINT_M ((SYSCON_RET_ICACHE_START_POINT_V)<<(SYSCON_RET_ICACHE_START_POINT_S)) +#define SYSCON_RET_ICACHE_START_POINT_V 0xFF +#define SYSCON_RET_ICACHE_START_POINT_S 22 + +/* SYSCON_RET_ICACHE_VLD_SIZE : R/W ;bitpos:[20:13] ;default: 8'hff ; */ + +#define SYSCON_RET_ICACHE_VLD_SIZE 0x000000FF +#define SYSCON_RET_ICACHE_VLD_SIZE_M ((SYSCON_RET_ICACHE_VLD_SIZE_V)<<(SYSCON_RET_ICACHE_VLD_SIZE_S)) +#define SYSCON_RET_ICACHE_VLD_SIZE_V 0xFF +#define SYSCON_RET_ICACHE_VLD_SIZE_S 13 + +/* SYSCON_RET_ICACHE_SIZE : R/W ;bitpos:[11:4] ;default: 8'hff ; */ + +#define SYSCON_RET_ICACHE_SIZE 0x000000FF +#define SYSCON_RET_ICACHE_SIZE_M ((SYSCON_RET_ICACHE_SIZE_V)<<(SYSCON_RET_ICACHE_SIZE_S)) +#define SYSCON_RET_ICACHE_SIZE_V 0xFF +#define SYSCON_RET_ICACHE_SIZE_S 4 + +#define SYSCON_RETENTION_CTRL3_REG (DR_REG_SYSCON_BASE + 0xC0) + +/* SYSCON_RET_DCACHE_ENABLE : R/W ;bitpos:[31] ;default: 1'b0 ; */ + +#define SYSCON_RET_DCACHE_ENABLE (BIT(31)) +#define SYSCON_RET_DCACHE_ENABLE_M (BIT(31)) +#define SYSCON_RET_DCACHE_ENABLE_V 0x1 +#define SYSCON_RET_DCACHE_ENABLE_S 31 + +/* SYSCON_RET_DCACHE_START_POINT : R/W ;bitpos:[30:22] ;default: 9'd0 ; */ + +#define SYSCON_RET_DCACHE_START_POINT 0x000001FF +#define SYSCON_RET_DCACHE_START_POINT_M ((SYSCON_RET_DCACHE_START_POINT_V)<<(SYSCON_RET_DCACHE_START_POINT_S)) +#define SYSCON_RET_DCACHE_START_POINT_V 0x1FF +#define SYSCON_RET_DCACHE_START_POINT_S 22 + +/* SYSCON_RET_DCACHE_VLD_SIZE : R/W ;bitpos:[21:13] ;default: 9'h1ff ; */ + +#define SYSCON_RET_DCACHE_VLD_SIZE 0x000001FF +#define SYSCON_RET_DCACHE_VLD_SIZE_M ((SYSCON_RET_DCACHE_VLD_SIZE_V)<<(SYSCON_RET_DCACHE_VLD_SIZE_S)) +#define SYSCON_RET_DCACHE_VLD_SIZE_V 0x1FF +#define SYSCON_RET_DCACHE_VLD_SIZE_S 13 + +/* SYSCON_RET_DCACHE_SIZE : R/W ;bitpos:[12:4] ;default: 9'h1ff ; */ + +#define SYSCON_RET_DCACHE_SIZE 0x000001FF +#define SYSCON_RET_DCACHE_SIZE_M ((SYSCON_RET_DCACHE_SIZE_V)<<(SYSCON_RET_DCACHE_SIZE_S)) +#define SYSCON_RET_DCACHE_SIZE_V 0x1FF +#define SYSCON_RET_DCACHE_SIZE_S 4 + +#define SYSCON_RETENTION_CTRL4_REG (DR_REG_SYSCON_BASE + 0xC4) + +/* SYSCON_RETENTION_INV_CFG : R/W ;bitpos:[31:0] ;default: ~32'h0 ; */ + +#define SYSCON_RETENTION_INV_CFG 0xFFFFFFFF +#define SYSCON_RETENTION_INV_CFG_M ((SYSCON_RETENTION_INV_CFG_V)<<(SYSCON_RETENTION_INV_CFG_S)) +#define SYSCON_RETENTION_INV_CFG_V 0xFFFFFFFF +#define SYSCON_RETENTION_INV_CFG_S 0 + +#define SYSCON_RETENTION_CTRL5_REG (DR_REG_SYSCON_BASE + 0xC8) + +/* SYSCON_RETENTION_DISABLE : R/W ;bitpos:[0] ;default: 1'b0 ; */ + +#define SYSCON_RETENTION_DISABLE (BIT(0)) +#define SYSCON_RETENTION_DISABLE_M (BIT(0)) +#define SYSCON_RETENTION_DISABLE_V 0x1 +#define SYSCON_RETENTION_DISABLE_S 0 + +#define SYSCON_DATE_REG (DR_REG_SYSCON_BASE + 0x3FC) + +/* SYSCON_DATE : R/W ;bitpos:[31:0] ;default: 32'h2101150 ; + * Version control. + */ + +#define SYSCON_DATE 0xFFFFFFFF +#define SYSCON_DATE_M ((SYSCON_DATE_V)<<(SYSCON_DATE_S)) +#define SYSCON_DATE_V 0xFFFFFFFF +#define SYSCON_DATE_S 0 + +#endif /* __ARCH_XTENSA_SRC_ESP32S3_HARDWARE_ESP32S3_SYSCON_H */ diff --git a/boards/xtensa/esp32s3/common/include/esp32s3_board_wlan.h b/boards/xtensa/esp32s3/common/include/esp32s3_board_wlan.h new file mode 100644 index 00000000000..99e5bcbcfba --- /dev/null +++ b/boards/xtensa/esp32s3/common/include/esp32s3_board_wlan.h @@ -0,0 +1,73 @@ +/**************************************************************************** + * boards/xtensa/esp32s3/common/include/esp32s3_board_wlan.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_XTENSA_ESP32S3_COMMON_INCLUDE_ESP32S3_BOARD_WLAN_H +#define __BOARDS_XTENSA_ESP32S3_COMMON_INCLUDE_ESP32S3_BOARD_WLAN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_ESP32S3_WIFI + +/**************************************************************************** + * Name: board_wlan_init + * + * Description: + * Configure the wireless subsystem. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_wlan_init(void); + +#endif /* CONFIG_ESP32S3_WIFI */ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_XTENSA_ESP32S3_COMMON_INCLUDE_ESP32S3_BOARD_WLAN_H */ diff --git a/boards/xtensa/esp32s3/common/scripts/legacy_sections.ld b/boards/xtensa/esp32s3/common/scripts/legacy_sections.ld index 476a3f51357..97869c10809 100644 --- a/boards/xtensa/esp32s3/common/scripts/legacy_sections.ld +++ b/boards/xtensa/esp32s3/common/scripts/legacy_sections.ld @@ -18,6 +18,8 @@ * ****************************************************************************/ +#include + /* Default entry point: */ ENTRY(__start); @@ -74,6 +76,13 @@ SECTIONS *(.iram1 .iram1.*) + *(.wifirxiram .wifirxiram.*) + *(.wifi0iram .wifi0iram.*) + *(.wifiorslpiram .wifiorslpiram.*) + *(.wifislpiram .wifislpiram.*) + *(.wifislprxiram .wifislprxiram.*) + *(.phyiram .phyiram.*) + /* align + add 16B for CPU dummy speculative instr. fetch */ . = ALIGN(4) + 16; @@ -148,6 +157,8 @@ SECTIONS KEEP (*(.jcr)) *(.dram1 .dram1.*) + *libphy.a:(.rodata .rodata.*) + _edata = ABSOLUTE(.); . = ALIGN(4); @@ -204,6 +215,13 @@ SECTIONS *(.rodata) *(.rodata.*) +#ifdef CONFIG_ESP32S3_WIRELESS + *(.rodata_wlog_verbose.*) + *(.rodata_wlog_debug.*) + *(.rodata_wlog_info.*) + *(.rodata_wlog_warning.*) + *(.rodata_wlog_error.*) +#endif *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) diff --git a/boards/xtensa/esp32s3/common/src/Make.defs b/boards/xtensa/esp32s3/common/src/Make.defs index f2df128831b..914fa44115e 100644 --- a/boards/xtensa/esp32s3/common/src/Make.defs +++ b/boards/xtensa/esp32s3/common/src/Make.defs @@ -32,6 +32,10 @@ ifeq ($(CONFIG_ESP32S3_SPIFLASH),y) CSRCS += esp32s3_board_spiflash.c endif +ifeq ($(CONFIG_ESP32S3_WIFI),y) + CSRCS += esp32s3_board_wlan.c +endif + ifeq ($(CONFIG_I2C_DRIVER),y) CSRCS += esp32s3_board_i2c.c endif diff --git a/boards/xtensa/esp32s3/common/src/esp32s3_board_spiflash.c b/boards/xtensa/esp32s3/common/src/esp32s3_board_spiflash.c index 75e266b9570..a0d7c529e65 100644 --- a/boards/xtensa/esp32s3/common/src/esp32s3_board_spiflash.c +++ b/boards/xtensa/esp32s3/common/src/esp32s3_board_spiflash.c @@ -46,6 +46,16 @@ #include "esp32s3_spiflash_mtd.h" #include "esp32s3-devkit.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_ESP32S3_WIFI_MTD_ENCRYPT +# define WIFI_ENCRYPT true +#else +# define WIFI_ENCRYPT false +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -245,6 +255,72 @@ static int setup_nxffs(struct mtd_dev_s *mtd, const char *mnt_pt) } #endif +/**************************************************************************** + * Name: init_wifi_partition + * + * Description: + * Initialize partition that is dedicated to Wi-Fi. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM +static int init_wifi_partition(void) +{ + int ret = OK; + struct mtd_dev_s *mtd; + + mtd = esp32s3_spiflash_alloc_mtdpart(CONFIG_ESP32S3_WIFI_MTD_OFFSET, + CONFIG_ESP32S3_WIFI_MTD_SIZE, + WIFI_ENCRYPT); + if (!mtd) + { + ferr("Failed to alloc MTD partition of SPI Flash\n"); + return -ENOMEM; + } + +#if defined (CONFIG_ESP32S3_SPIFLASH_SMARTFS) + + ret = setup_smartfs(1, mtd, CONFIG_ESP32S3_WIFI_FS_MOUNTPT); + if (ret < 0) + { + ferr("Failed to setup smartfs\n"); + return ret; + } + +#elif defined(CONFIG_ESP32S3_SPIFLASH_LITTLEFS) + + const char *path = "/dev/mtdblock1"; + ret = setup_littlefs(path, mtd, CONFIG_ESP32S3_WIFI_FS_MOUNTPT, 0777); + if (ret < 0) + { + ferr("Failed to setup littlefs\n"); + return ret; + } + +#elif defined(CONFIG_ESP32S3_SPIFLASH_SPIFFS) + + const char *path = "/dev/mtdblock1"; + ret = setup_spiffs(path, mtd, CONFIG_ESP32S3_WIFI_FS_MOUNTPT, 0777); + if (ret < 0) + { + ferr("Failed to setup spiffs\n"); + return ret; + } + +#else + + ferr("No supported FS selected. Wi-Fi partition " + "should be mounted before Wi-Fi initialization\n"); + +#endif + + return ret; +} +#endif + /**************************************************************************** * Name: init_storage_partition * @@ -344,6 +420,14 @@ int board_spiflash_init(void) return ret; } +#ifdef CONFIG_ESP32S3_WIFI_SAVE_PARAM + ret = init_wifi_partition(); + if (ret < 0) + { + return ret; + } +#endif + ret = init_storage_partition(); if (ret < 0) { diff --git a/boards/xtensa/esp32s3/common/src/esp32s3_board_wlan.c b/boards/xtensa/esp32s3/common/src/esp32s3_board_wlan.c new file mode 100644 index 00000000000..ffa8b730401 --- /dev/null +++ b/boards/xtensa/esp32s3/common/src/esp32s3_board_wlan.c @@ -0,0 +1,73 @@ +/**************************************************************************** + * boards/xtensa/esp32s3/common/src/esp32s3_board_wlan.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "esp32s3_spiflash.h" +#include "esp32s3_wlan.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_wlan_init + * + * Description: + * Configure the wireless subsystem. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_wlan_init(void) +{ + int ret = OK; + +#ifdef ESP32S3_WLAN_HAS_STA + ret = esp32s3_wlan_sta_initialize(); + if (ret) + { + wlerr("ERROR: Failed to initialize Wi-Fi station\n"); + return ret; + } +#endif /* ESP32S3_WLAN_HAS_STA */ + + return ret; +} + diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/configs/wapi/defconfig b/boards/xtensa/esp32s3/esp32s3-devkit/configs/wapi/defconfig new file mode 100644 index 00000000000..22d35dee42c --- /dev/null +++ b/boards/xtensa/esp32s3/esp32s3-devkit/configs/wapi/defconfig @@ -0,0 +1,83 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_NDEBUG is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ALLOW_BSD_COMPONENTS=y +CONFIG_ARCH="xtensa" +CONFIG_ARCH_BOARD="esp32s3-devkit" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32S3_DEVKIT=y +CONFIG_ARCH_CHIP="esp32s3" +CONFIG_ARCH_CHIP_ESP32S3=y +CONFIG_ARCH_CHIP_ESP32S3WROOM1=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_XTENSA=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEFAULT_TASK_STACKSIZE=4096 +CONFIG_DRIVERS_IEEE80211=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_ESP32S3_RT_TIMER_TASK_STACK_SIZE=4096 +CONFIG_ESP32S3_SPIFLASH=y +CONFIG_ESP32S3_SPIFLASH_SPIFFS=y +CONFIG_ESP32S3_UART0=y +CONFIG_ESP32S3_WIFI=y +CONFIG_ESP32S3_WIFI_SAVE_PARAM=y +CONFIG_EXAMPLES_RANDOM=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=8192 +CONFIG_INTELHEX_BINARY=y +CONFIG_IOB_NBUFFERS=124 +CONFIG_IOB_THROTTLE=24 +CONFIG_NAME_MAX=48 +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_PHY_IOCTL=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NETUTILS_IPERF=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1514 +CONFIG_NET_ICMP=y +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_TCP=y +CONFIG_NET_TCP_DELAYED_ACK=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_UDP=y +CONFIG_NET_UDP_WRITE_BUFFERS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=2048 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PTHREAD_MUTEX_TYPES=y +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SIG_DEFAULT=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=y +CONFIG_TIMER=y +CONFIG_TLS_TASK_NELEM=4 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_WAPI=y +CONFIG_WIRELESS_WAPI_CMDTOOL=y +CONFIG_WIRELESS_WAPI_STACKSIZE=8192 diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c b/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c index 7d93dd20700..83963b5489e 100644 --- a/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c +++ b/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c @@ -42,6 +42,10 @@ # include "esp32s3_board_tim.h" #endif +#ifdef CONFIG_ESP32S3_WIFI +# include "esp32s3_board_wlan.h" +#endif + #ifdef CONFIG_ESP32S3_RT_TIMER # include "esp32s3_rt_timer.h" #endif @@ -206,6 +210,15 @@ int esp32s3_bringup(void) } #endif +#ifdef CONFIG_ESP32S3_WIFI + ret = board_wlan_init(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize wireless subsystem=%d\n", + ret); + } +#endif + #ifdef CONFIG_VIDEO_FB ret = fb_register(0, 0); if (ret < 0)