From 458caf27329f52247ebbeabb8ec164e690f27e89 Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Mon, 8 Mar 2021 18:00:09 +0800 Subject: [PATCH] riscv/esp32c3: Add ESP32-C3 WLAN netcard driver --- arch/risc-v/Kconfig | 5 + arch/risc-v/include/esp32c3/irq.h | 4 + arch/risc-v/src/esp32c3/.gitignore | 2 + arch/risc-v/src/esp32c3/Kconfig | 94 + arch/risc-v/src/esp32c3/Make.defs | 41 +- arch/risc-v/src/esp32c3/esp32c3_irq.c | 95 +- arch/risc-v/src/esp32c3/esp32c3_irq.h | 20 + arch/risc-v/src/esp32c3/esp32c3_rt_timer.c | 678 +++ arch/risc-v/src/esp32c3/esp32c3_rt_timer.h | 206 + arch/risc-v/src/esp32c3/esp32c3_tim.c | 36 +- arch/risc-v/src/esp32c3/esp32c3_tim.h | 8 + .../src/esp32c3/esp32c3_tim_lowerhalf.c | 4 +- .../risc-v/src/esp32c3/esp32c3_wifi_adapter.c | 4646 +++++++++++++++++ .../risc-v/src/esp32c3/esp32c3_wifi_adapter.h | 242 + arch/risc-v/src/esp32c3/esp32c3_wlan.c | 1487 ++++++ arch/risc-v/src/esp32c3/esp32c3_wlan.h | 67 + .../src/esp32c3/hardware/esp32c3_syscon.h | 644 +++ .../esp32c3-devkit/configs/wapi/defconfig | 66 + .../esp32c3/esp32c3-devkit/scripts/esp32c3.ld | 8 + .../esp32c3-devkit/scripts/esp32c3_rom.ld | 26 +- .../esp32c3-devkit/src/esp32c3_bringup.c | 11 + .../esp32c3-devkit/src/esp32c3_timer.c | 2 +- 22 files changed, 8365 insertions(+), 27 deletions(-) create mode 100644 arch/risc-v/src/esp32c3/.gitignore create mode 100644 arch/risc-v/src/esp32c3/esp32c3_rt_timer.c create mode 100644 arch/risc-v/src/esp32c3/esp32c3_rt_timer.h create mode 100644 arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c create mode 100644 arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h create mode 100644 arch/risc-v/src/esp32c3/esp32c3_wlan.c create mode 100644 arch/risc-v/src/esp32c3/esp32c3_wlan.h create mode 100644 arch/risc-v/src/esp32c3/hardware/esp32c3_syscon.h create mode 100644 boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index ce24e1c2e6..914de17ea3 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -45,6 +45,11 @@ config ARCH_CHIP_ESP32C3 select RV32IM_HW_MULDIV select ARCH_VECNOTIRQ select ARCH_HAVE_RESET + select LIBC_ARCH_MEMCHR + select LIBC_ARCH_MEMCMP + select LIBC_ARCH_MEMCCMP + select LIBC_ARCH_MEMMOVE + select LIBC_ARCH_MEMSET ---help--- Espressif ESP32-C3 (RV32IMC). diff --git a/arch/risc-v/include/esp32c3/irq.h b/arch/risc-v/include/esp32c3/irq.h index 27a7eb173e..ad6634af63 100644 --- a/arch/risc-v/include/esp32c3/irq.h +++ b/arch/risc-v/include/esp32c3/irq.h @@ -127,6 +127,10 @@ #define ESP32C3_CPUINT_MIN 1 #define ESP32C3_CPUINT_MAX 31 +/* Reserved CPU interrupt for specific drivers */ + +#define ESP32C3_CPUINT_WMAC 1 /* Wi-Fi MAC */ + /* IRQ numbers. */ /* ecall is dispatched like normal interrupts. It occupies an IRQ number. */ diff --git a/arch/risc-v/src/esp32c3/.gitignore b/arch/risc-v/src/esp32c3/.gitignore new file mode 100644 index 0000000000..cdf3df5616 --- /dev/null +++ b/arch/risc-v/src/esp32c3/.gitignore @@ -0,0 +1,2 @@ +/esp-wireless-drivers-3rdparty +/*.zip diff --git a/arch/risc-v/src/esp32c3/Kconfig b/arch/risc-v/src/esp32c3/Kconfig index cecb296af3..07573882cb 100644 --- a/arch/risc-v/src/esp32c3/Kconfig +++ b/arch/risc-v/src/esp32c3/Kconfig @@ -152,6 +152,10 @@ config ESP32C3_CPU_FREQ_MHZ default 80 if ESP32C3_CPU_FREQ_80 default 160 if ESP32C3_CPU_FREQ_160 +config ESP32C3_RT_TIMER + bool "Real-time Timer" + default n + menu "ESP32-C3 Peripheral Support" config ESP32C3_UART @@ -235,6 +239,16 @@ config ESP32C3_RWDT to have the RTC module reset, please, use the Timers' Module WDTs. They will only reset Main System. +config ESP32C3_WIRELESS + bool "Wireless" + default n + select NET + select ARCH_PHY_INTERRUPT + select ESP32C3_RT_TIMER + select ESP32C3_TIMER0 + ---help--- + Enable Wireless support + endmenu # ESP32-C3 Peripheral Support menu "I2C Configuration" @@ -285,4 +299,84 @@ endif # ESP32C3_UART1 endmenu +menu "Real-Time Timer" + depends on ESP32C3_RT_TIMER + +config ESP32C3_RT_TIMER_TASK_NAME + string "Timer task name" + default "rt_timer" + +config ESP32C3_RT_TIMER_TASK_PRIORITY + int "Timer task priority" + default 223 # Lower than high priority workqueue + +config ESP32C3_RT_TIMER_TASK_STACK_SIZE + int "Timer task stack size" + default 2048 + +endmenu # Real-Time Timer + +menu "Wi-Fi configuration" + depends on ESP32C3_WIRELESS + +config ESP32C3_WIFI_STATIC_RXBUF_NUM + int "Wi-Fi static RX buffer number" + default 10 + +config ESP32C3_WIFI_DYNAMIC_RXBUF_NUM + int "Wi-Fi dynamic RX buffer number" + default 32 + +config ESP32C3_WIFI_DYNAMIC_TXBUF_NUM + int "Wi-Fi dynamic TX buffer number" + default 32 + +config ESP32C3_WIFI_TX_AMPDU + bool "Wi-Fi TX AMPDU" + default y + +config ESP32C3_WIFI_RX_AMPDU + bool "Wi-Fi RX AMPDU" + default y + +config ESP32C3_WIFI_RXBA_AMPDU_WZ + int "Wi-Fi RX BA AMPDU windown size" + default 6 + +config ESP32C3_WLAN_RXBUF_NUM + int "WLAN netcard RX buffer number" + default 16 + +config ESP32C3_WIFI_CONNECT_TIMEOUT + int "Connect timeout by second" + default 10 + help + Max waiting time of connecting to AP. + +config ESP32C3_WIFI_SAVE_PARAM + bool "Save Wi-Fi Parameters" + default n + depends on !DISABLE_MOUNTPOINT + 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 ESP32C3_WIFI_FS_MOUNTPT + string "Save Wi-Fi Parameters" + default "/mnt/esp/wifi" + depends on ESP32C3_WIFI_SAVE_PARAM + help + Mount point of Wi-Fi storage file system. + +endmenu # ESP32C3_WIRELESS + endif # ARCH_CHIP_ESP32C3 diff --git a/arch/risc-v/src/esp32c3/Make.defs b/arch/risc-v/src/esp32c3/Make.defs index 37f5b2421f..f142c5a61d 100644 --- a/arch/risc-v/src/esp32c3/Make.defs +++ b/arch/risc-v/src/esp32c3/Make.defs @@ -75,4 +75,43 @@ CHIP_CSRCS += esp32c3_tim.c ifeq ($(CONFIG_TIMER),y) CHIP_CSRCS += esp32c3_tim_lowerhalf.c endif -endif \ No newline at end of file +endif + +ifeq ($(CONFIG_ESP32C3_RT_TIMER),y) +CHIP_CSRCS += esp32c3_rt_timer.c +endif + +ifeq ($(CONFIG_ESP32C3_WIRELESS),y) +WIRELESS_DRV_UNPACK = esp-wireless-drivers-3rdparty +WIRELESS_DRV_ID = 3cc7f67 +WIRELESS_DRV_ZIP = $(WIRELESS_DRV_ID).zip +WIRELESS_DRV_URL = https://github.com/espressif/esp-wireless-drivers-3rdparty/archive + +$(WIRELESS_DRV_ZIP): + $(Q) echo "Downloading: ESP Wireless Drivers" + $(Q) curl -L $(WIRELESS_DRV_URL)/$(WIRELESS_DRV_ZIP) -o chip/$(WIRELESS_DRV_ZIP) + +chip/$(WIRELESS_DRV_UNPACK): $(WIRELESS_DRV_ZIP) + $(Q) echo "Unpacking: ESP Wireless Drivers" + $(Q) unzip -oqq chip/$(WIRELESS_DRV_ZIP) -d chip/ + $(Q) mv chip/$(WIRELESS_DRV_UNPACK)-$(WIRELESS_DRV_ID)* chip/$(WIRELESS_DRV_UNPACK) + $(Q) touch chip/$(WIRELESS_DRV_UNPACK) + +context:: chip/$(WIRELESS_DRV_UNPACK) + +clean_context:: + $(call DELFILE, chip/$(WIRELESS_DRV_ZIP)) + $(call DELDIR, chip/$(WIRELESS_DRV_UNPACK)) + +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)include) +INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)include$(DELIM)esp32c3) +CHIP_CSRCS += esp32c3_wlan.c esp32c3_wifi_adapter.c + +EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)libs$(DELIM)esp32c3 +EXTRA_LIBS += -lcore -lnet80211 -lpp -lsmartconfig -lcoexist -lespnow -lphy -lwpa_supplicant -lwapi + +# Due to some Wi-Fi related libraries, the option is need to avoid linking too much +# unused functions. + +LDFLAGS += --gc-sections +endif diff --git a/arch/risc-v/src/esp32c3/esp32c3_irq.c b/arch/risc-v/src/esp32c3/esp32c3_irq.c index 0f8ce8b758..b91aff946d 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_irq.c +++ b/arch/risc-v/src/esp32c3/esp32c3_irq.c @@ -54,6 +54,18 @@ #define CPUINT_UNASSIGNED 0xff +/* Wi-Fi reserved CPU interrupt bit */ + +#ifdef CONFIG_ESP32C3_WIRELESS +# define CPUINT_WMAC_MAP (1 << ESP32C3_CPUINT_WMAC) +#else +# define CPUINT_WMAC_MAP 0 +#endif + +/* Reserved CPU interrupt bits */ + +#define CPUINT_RESERVED_MAPS (CPUINT_WMAC_MAP) + /**************************************************************************** * Public Data ****************************************************************************/ @@ -82,6 +94,17 @@ void up_irqinitialize(void) memset(g_cpuint_map, CPUINT_UNASSIGNED, ESP32C3_CPUINT_MAX); + /** + * Initialize specific driver's CPU interrupt ID: + * Object | CPU INT | Pheripheral + * | | + * Wi-Fi | 1 | 1 + */ + +#ifdef CONFIG_ESP32C3_WIRELESS + g_cpuint_map[ESP32C3_CPUINT_WMAC] = ESP32C3_PERIPH_WIFI_MAC_NMI; +#endif + /* Clear all peripheral interrupts from "bootloader" */ for (periphid = 0; periphid < ESP32C3_NPERIPHERALS; periphid++) @@ -166,6 +189,50 @@ void up_disable_irq(int cpuint) leave_critical_section(irqstate); } +/**************************************************************************** + * Name: esp32c3_bind_irq + * + * Description: + * Bind IRQ and resource with given parameters. + * + * Input Parameters: + * cpuint - CPU interrupt ID + * periphid - Peripheral ID + * prio - Interrupt priority + * flags - Interrupt flags + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp32c3_bind_irq(uint8_t cpuint, uint8_t periphid, uint8_t prio, + uint32_t flags) +{ + /* Disable the CPU interrupt. */ + + resetbits(1 << cpuint, INTERRUPT_CPU_INT_ENABLE_REG); + + /* Set the interrupt priority. */ + + putreg32(prio, INTERRUPT_CPU_INT_PRI_0_REG + cpuint * 4); + + /* Set the interrupt type (Edge or Level). */ + + if (flags & ESP32C3_INT_EDGE) + { + setbits(1 << cpuint, INTERRUPT_CPU_INT_TYPE_REG); + } + else + { + resetbits(1 << cpuint, INTERRUPT_CPU_INT_TYPE_REG); + } + + /* Map the CPU interrupt ID to the peripheral. */ + + putreg32(cpuint, DR_REG_INTERRUPT_BASE + periphid * 4); +} + /**************************************************************************** * Name: esp32c3_request_irq * @@ -198,6 +265,11 @@ int esp32c3_request_irq(uint8_t periphid, uint8_t prio, uint32_t flags) /* Skip over enabled interrupts. NOTE: bit 0 is reserved. */ regval = getreg32(INTERRUPT_CPU_INT_ENABLE_REG); + + /* Skip over reserved CPU interrupts */ + + regval |= CPUINT_RESERVED_MAPS; + for (cpuint = 1; cpuint <= ESP32C3_CPUINT_MAX; cpuint++) { if (!(regval & (1 << cpuint))) @@ -224,28 +296,9 @@ int esp32c3_request_irq(uint8_t periphid, uint8_t prio, uint32_t flags) g_cpuint_map[cpuint] = periphid; - /* Set the interrupt priority. */ + /* Configure IRQ */ - putreg32(prio, INTERRUPT_CPU_INT_PRI_0_REG + cpuint * 4); - - /* Set the interrupt type (Edge or Level). */ - - if (flags & ESP32C3_INT_EDGE) - { - setbits(1 << cpuint, INTERRUPT_CPU_INT_TYPE_REG); - } - else - { - resetbits(1 << cpuint, INTERRUPT_CPU_INT_TYPE_REG); - } - - /* Map the CPU interrupt ID to the peripheral. */ - - putreg32(cpuint, DR_REG_INTERRUPT_BASE + periphid * 4); - - /* Disable the CPU interrupt. */ - - resetbits(1 << cpuint, INTERRUPT_CPU_INT_ENABLE_REG); + esp32c3_bind_irq(cpuint, periphid, prio, flags); } else { diff --git a/arch/risc-v/src/esp32c3/esp32c3_irq.h b/arch/risc-v/src/esp32c3/esp32c3_irq.h index 72d4f8da2b..719d1d5398 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_irq.h +++ b/arch/risc-v/src/esp32c3/esp32c3_irq.h @@ -47,6 +47,26 @@ void up_irqinitialize(void); +/**************************************************************************** + * Name: esp32c3_bind_irq + * + * Description: + * Bind IRQ and resource with given parameters. + * + * Input Parameters: + * cpuint - CPU interrupt ID + * periphid - Peripheral ID + * prio - Interrupt priority + * flags - Interrupt flags + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp32c3_bind_irq(uint8_t cpuint, uint8_t periphid, uint8_t prio, + uint32_t flags); + /**************************************************************************** * Name: esp32c3_request_irq * diff --git a/arch/risc-v/src/esp32c3/esp32c3_rt_timer.c b/arch/risc-v/src/esp32c3/esp32c3_rt_timer.c new file mode 100644 index 0000000000..97696909b6 --- /dev/null +++ b/arch/risc-v/src/esp32c3/esp32c3_rt_timer.c @@ -0,0 +1,678 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/esp32c3_rt_timer.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this args 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 "hardware/esp32c3_soc.h" +#include "esp32c3_tim.h" +#include "esp32c3_rt_timer.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_SCHED_HPWORKPRIORITY +# if CONFIG_ESP32C3_RT_TIMER_TASK_PRIORITY >= CONFIG_SCHED_HPWORKPRIORITY +# error "RT timer priority should be smaller that high-prio workqueue" +# endif +#endif + +#define RT_TIMER_TASK_NAME CONFIG_ESP32C3_RT_TIMER_TASK_NAME +#define RT_TIMER_TASK_PRIORITY CONFIG_ESP32C3_RT_TIMER_TASK_PRIORITY +#define RT_TIMER_TASK_STACK_SIZE CONFIG_ESP32C3_RT_TIMER_TASK_STACK_SIZE + +#define ESP32C3_TIMER_PRESCALER (APB_CLK_FREQ / (1000 * 1000)) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static int s_pid; + +static sem_t s_toutsem; + +static struct list_node s_runlist; +static struct list_node s_toutlist; + +static struct esp32c3_tim_dev_s *s_esp32c3_tim_dev; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: start_rt_timer + * + * Description: + * Start timer by inserting it into running list and reset hardware timer + * alarm value if this timer in head of list. + * + * Input Parameters: + * timer - RT timer pointer + * timeout - Timeout value + * repeat - If the timer run repeat + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void start_rt_timer(FAR struct rt_timer_s *timer, + uint64_t timeout, + bool repeat) +{ + irqstate_t flags; + struct rt_timer_s *p; + bool inserted = false; + uint64_t counter; + struct esp32c3_tim_dev_s *tim = s_esp32c3_tim_dev; + + flags = enter_critical_section(); + + /* Only idle timer can be started */ + + if (timer->state == RT_TIMER_IDLE) + { + /* Calculate the timer's alarm value */ + + ESP32C3_TIM_GETCTR(tim, &counter); + timer->timeout = timeout; + timer->alarm = timer->timeout + counter; + + if (repeat) + { + timer->flags |= RT_TIMER_REPEAT; + } + else + { + timer->flags &= ~RT_TIMER_REPEAT; + } + + /** Scan timer list and insert the new timer into previous + * node of timer whose alarm value is larger than new one + */ + + list_for_every_entry(&s_runlist, p, struct rt_timer_s, list) + { + if (p->alarm > timer->alarm) + { + list_add_before(&p->list, &timer->list); + inserted = true; + break; + } + } + + /* If not find a larger one, insert new timer into tail of list */ + + if (!inserted) + { + list_add_tail(&s_runlist, &timer->list); + } + + timer->state = RT_TIMER_READY; + + /* If this timer is in head of list */ + + if (timer == container_of(s_runlist.next, struct rt_timer_s, list)) + { + /* Reset hardware timer alarm */ + + ESP32C3_TIM_SETALRVL(tim, timer->alarm); + ESP32C3_TIM_SETALRM(tim, true); + } + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: stop_rt_timer + * + * Description: + * Stop timer by removing it from running list and reset hardware timer + * alarm value if this timer is in head of list. + * + * Input Parameters: + * timer - RT timer pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void stop_rt_timer(FAR struct rt_timer_s *timer) +{ + irqstate_t flags; + bool ishead; + struct rt_timer_s *next_timer; + uint64_t alarm; + struct esp32c3_tim_dev_s *tim = s_esp32c3_tim_dev; + + flags = enter_critical_section(); + + /** + * Function "start" can set timer to be repeat, and function "stop" + * should remove this feature although it is not in ready state. + */ + + timer->flags &= ~RT_TIMER_REPEAT; + + /* Only ready timer can be stopped */ + + if (timer->state == RT_TIMER_READY) + { + /* Check if timer is in head of list */ + + if (timer == container_of(s_runlist.next, struct rt_timer_s, list)) + { + ishead = true; + } + else + { + ishead = false; + } + + list_delete(&timer->list); + timer->state = RT_TIMER_IDLE; + + /* If timer is in in head of list */ + + if (ishead) + { + /* If list is not empty */ + + if (!list_is_empty(&s_runlist)) + { + /* Reset hardware timer alarm value to be next timer's */ + + next_timer = container_of(s_runlist.next, + struct rt_timer_s, + list); + alarm = next_timer->alarm; + + ESP32C3_TIM_SETALRVL(tim, alarm); + ESP32C3_TIM_SETALRM(tim, true); + } + } + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: delete_rt_timer + * + * Description: + * Delete timer by removing it from list, then set the timer's state + * to be "RT_TIMER_DELETE", inserting into work list to let rt-timer + * thread to delete it and free resource. + * + * Input Parameters: + * timer - RT timer pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void delete_rt_timer(FAR struct rt_timer_s *timer) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + if (timer->state == RT_TIMER_READY) + { + stop_rt_timer(timer); + } + else if (timer->state == RT_TIMER_TIMEOUT) + { + list_delete(&timer->list); + } + else if (timer->state == RT_TIMER_DELETE) + { + goto exit; + } + + list_add_after(&s_toutlist, &timer->list); + timer->state = RT_TIMER_DELETE; + +exit: + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: rt_timer_thread + * + * Description: + * RT timer working thread, it wait for a timeout semaphore, scan + * the timeout list and process all timers in this list. + * + * Input Parameters: + * argc - Not used + * argv - Not used + * + * Returned Value: + * 0. + * + ****************************************************************************/ + +static int rt_timer_thread(int argc, FAR char *argv[]) +{ + int ret; + irqstate_t flags; + struct rt_timer_s *timer; + enum rt_timer_state_e raw_state; + + while (1) + { + /* Waiting for timers timeout */ + + ret = nxsem_wait(&s_toutsem); + if (ret) + { + tmrerr("ERROR: Wait s_toutsem error=%d\n", ret); + assert(0); + } + + /* Enter critical to check global timer timeout list */ + + flags = enter_critical_section(); + + /* Process all timers in list */ + + while (!list_is_empty(&s_toutlist)) + { + /* Get first timer in list */ + + timer = container_of(s_toutlist.next, struct rt_timer_s, list); + + /* Cache the raw state to decide how to deal with this timer */ + + raw_state = timer->state; + + /* Delete timer from list */ + + list_delete(&timer->list); + + /* Set timer's state to be let it to able to restart by user */ + + timer->state = RT_TIMER_IDLE; + + /* Leave from critical to start to call "callback" function */ + + leave_critical_section(flags); + + if (raw_state == RT_TIMER_TIMEOUT) + { + timer->callback(timer->arg); + } + else if (raw_state == RT_TIMER_DELETE) + { + kmm_free(timer); + } + + /* Enter critical for next scanning list */ + + flags = enter_critical_section(); + + if (raw_state == RT_TIMER_TIMEOUT) + { + /* Check if timer is repeat */ + + if (timer->flags & RT_TIMER_REPEAT) + { + start_rt_timer(timer, timer->timeout, true); + } + } + } + + leave_critical_section(flags); + } + + return 0; +} + +/**************************************************************************** + * Name: rt_timer_isr + * + * Description: + * Hardware timer interrupt service function. + * + * Input Parameters: + * irq - Not used + * context - Not used + * arg - Not used + * + * Returned Value: + * 0. + * + ****************************************************************************/ + +static int rt_timer_isr(int irq, void *context, void *arg) +{ + irqstate_t flags; + struct rt_timer_s *timer; + uint64_t alarm; + uint64_t counter; + struct esp32c3_tim_dev_s *tim = s_esp32c3_tim_dev; + + /* Clear interrupt register status */ + + ESP32C3_TIM_ACKINT(tim); + + /* Wake up thread to process timeout timers */ + + nxsem_post(&s_toutsem); + + flags = enter_critical_section(); + + /* Check if there is timer running */ + + if (!list_is_empty(&s_runlist)) + { + /** + * When stop/delete timer, in the same time the hardware timer + * interrupt triggers, function "stop/delete" remove the timer + * from running list, so the 1st timer is not which triggers. + */ + + timer = container_of(s_runlist.next, struct rt_timer_s, list); + ESP32C3_TIM_GETCTR(tim, &counter); + if (timer->alarm <= counter) + { + /** + * Remove first timer in running list and add it into + * timeout list. + * + * Set the timer's state to be RT_TIMER_TIMEOUT to avoid + * other operation. + */ + + list_delete(&timer->list); + timer->state = RT_TIMER_TIMEOUT; + list_add_after(&s_toutlist, &timer->list); + + /* Check if thers is timer running */ + + if (!list_is_empty(&s_runlist)) + { + /* Reset hardware timer alarm with next timer's alarm value */ + + timer = container_of(s_runlist.next, struct rt_timer_s, list); + alarm = timer->alarm; + + ESP32C3_TIM_SETALRVL(tim, alarm); + ESP32C3_TIM_SETALRM(tim, true); + } + } + } + + leave_critical_section(flags); + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rt_timer_create + * + * Description: + * Create RT timer by into timer creation arguments + * + * Input Parameters: + * args - Input RT timer creation arguments + * timer_handle - Output RT timer handle pointer + * + * Returned Value: + * 0 is returned on success. Otherwise, a negated errno value is returned. + * + ****************************************************************************/ + +int rt_timer_create(FAR const struct rt_timer_args_s *args, + FAR struct rt_timer_s **timer_handle) +{ + struct rt_timer_s *timer; + + timer = (struct rt_timer_s *)kmm_malloc(sizeof(*timer)); + if (!timer) + { + tmrerr("ERROR: Failed to allocate %d bytes\n", sizeof(*timer)); + return -ENOMEM; + } + + timer->callback = args->callback; + timer->arg = args->arg; + timer->flags = RT_TIMER_NOFLAGS; + timer->state = RT_TIMER_IDLE; + list_initialize(&timer->list); + + *timer_handle = timer; + + return 0; +} + +/**************************************************************************** + * Name: rt_timer_start + * + * Description: + * Start RT timer. + * + * Input Parameters: + * timer - RT timer pointer + * timeout - Timeout value + * repeat - If the timer run repeat + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rt_timer_start(FAR struct rt_timer_s *timer, + uint64_t timeout, + bool repeat) +{ + stop_rt_timer(timer); + + start_rt_timer(timer, timeout, repeat); +} + +/**************************************************************************** + * Name: rt_timer_stop + * + * Description: + * Stop RT timer. + * + * Input Parameters: + * timer - RT timer pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rt_timer_stop(FAR struct rt_timer_s *timer) +{ + stop_rt_timer(timer); +} + +/**************************************************************************** + * Name: rt_timer_delete + * + * Description: + * Stop and delete RT timer. + * + * Input Parameters: + * timer - RT timer pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rt_timer_delete(FAR struct rt_timer_s *timer) +{ + delete_rt_timer(timer); +} + +/**************************************************************************** + * Name: rt_timer_time_us + * + * Description: + * Get time of RT timer by microsecond. + * + * Input Parameters: + * None + * + * Returned Value: + * Time of RT timer by microsecond. + * + ****************************************************************************/ + +uint64_t rt_timer_time_us(void) +{ + uint64_t counter; + struct esp32c3_tim_dev_s *tim = s_esp32c3_tim_dev; + + ESP32C3_TIM_GETCTR(tim, &counter); + + return counter; +} + +/**************************************************************************** + * Name: esp32c3_rt_timer_init + * + * Description: + * Initialize ESP32-C3 RT timer. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 is returned on success. Otherwise, a negated errno value is returned. + * + ****************************************************************************/ + +int esp32c3_rt_timer_init(void) +{ + int pid; + irqstate_t flags; + struct esp32c3_tim_dev_s *tim; + + tim = esp32c3_tim0_init(); + if (!tim) + { + tmrerr("ERROR: Failed to initialize ESP32 timer0\n"); + return -EINVAL; + } + + nxsem_init(&s_toutsem, 0, 0); + + pid = kthread_create(RT_TIMER_TASK_NAME, + RT_TIMER_TASK_PRIORITY, + RT_TIMER_TASK_STACK_SIZE, + rt_timer_thread, + NULL); + if (pid < 0) + { + tmrerr("ERROR: Failed to create RT timer task error=%d\n", pid); + esp32c3_tim_deinit(tim); + return pid; + } + + list_initialize(&s_runlist); + list_initialize(&s_toutlist); + + s_esp32c3_tim_dev = tim; + s_pid = pid; + + flags = enter_critical_section(); + + /** + * ESP32 hardware timer configuration: + * - 1 counter = 1us + * - Counter increase mode + * - Non-reload mode + */ + + ESP32C3_TIM_SETPRE(tim, ESP32C3_TIMER_PRESCALER); + ESP32C3_TIM_SETMODE(tim, ESP32C3_TIM_MODE_UP); + ESP32C3_TIM_SETARLD(tim, false); + ESP32C3_TIM_CLEAR(tim); + + ESP32C3_TIM_SETISR(tim, rt_timer_isr, NULL); + ESP32C3_TIM_ENABLEINT(tim); + + ESP32C3_TIM_START(tim); + + leave_critical_section(flags); + + return 0; +} + +/**************************************************************************** + * Name: esp32c3_rt_timer_deinit + * + * Description: + * Deinitialize ESP32-C3 RT timer. + * + * Input Parameters: + * None + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp32c3_rt_timer_deinit(void) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + ESP32C3_TIM_STOP(s_esp32c3_tim_dev); + s_esp32c3_tim_dev = NULL; + + leave_critical_section(flags); + + kthread_delete(s_pid); + nxsem_destroy(&s_toutsem); +} diff --git a/arch/risc-v/src/esp32c3/esp32c3_rt_timer.h b/arch/risc-v/src/esp32c3/esp32c3_rt_timer.h new file mode 100644 index 0000000000..3957483b9d --- /dev/null +++ b/arch/risc-v/src/esp32c3/esp32c3_rt_timer.h @@ -0,0 +1,206 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/esp32c3_rt_timer.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_RISCV_SRC_ESP32C3_ESP32C3_RT_TIMER_H +#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_RT_TIMER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#define RT_TIMER_NOFLAGS (0) /* Timer support no feature */ +#define RT_TIMER_REPEAT (1 << 0) /* Timer is repeat */ + +/** + * RT timer state + */ + +enum rt_timer_state_e +{ + RT_TIMER_IDLE, /* Timer is not counting */ + RT_TIMER_READY, /* Timer is counting */ + RT_TIMER_TIMEOUT, /* Timer is timeout */ + RT_TIMER_DELETE /* Timer is to be delete */ +}; + +/** + * RT timer data structure + */ + +struct rt_timer_s +{ + uint64_t timeout; /* Timeout value */ + uint64_t alarm; /* Timeout period */ + void (*callback)(void *arg); /* Callback function */ + void *arg; /* Private data */ + uint16_t flags; /* Support feature */ + enum rt_timer_state_e state; /* Mark if timer is started */ + struct list_node list; /* Working list */ +}; + +/** + * RT timer creation arguments data structure + */ + +struct rt_timer_args_s +{ + void (*callback)(void *arg); /* Callback function */ + void *arg; /* Private data */ +}; + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: rt_timer_create + * + * Description: + * Create RT timer by into timer creation arguments + * + * Input Parameters: + * args - Input RT timer creation arguments + * timer_handle - Output RT timer handle pointer + * + * Returned Value: + * 0 is returned on success. Otherwise, a negated errno value is returned. + * + ****************************************************************************/ + +int rt_timer_create(const struct rt_timer_args_s *args, + struct rt_timer_s **timer_handle); + +/**************************************************************************** + * Name: rt_timer_start + * + * Description: + * Start RT timer. + * + * Input Parameters: + * timer - RT timer pointer + * timeout - Timeout value + * repeat - If the timer run repeat + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rt_timer_start(struct rt_timer_s *timer, + uint64_t timeout, + bool repeat); + +/**************************************************************************** + * Name: rt_timer_stop + * + * Description: + * Stop RT timer. + * + * Input Parameters: + * timer - RT timer pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rt_timer_stop(struct rt_timer_s *timer); + +/**************************************************************************** + * Name: rt_timer_delete + * + * Description: + * Stop and delete RT timer. + * + * Input Parameters: + * timer - RT timer pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rt_timer_delete(struct rt_timer_s *timer); + +/**************************************************************************** + * Name: rt_timer_time_us + * + * Description: + * Get time of RT timer by microsecond. + * + * Input Parameters: + * None + * + * Returned Value: + * Time of RT timer by microsecond. + * + ****************************************************************************/ + +uint64_t rt_timer_time_us(void); + +/**************************************************************************** + * Name: esp32c3_rt_timer_init + * + * Description: + * Initialize ESP32-C3 RT timer. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 is returned on success. Otherwise, a negated errno value is returned. + * + ****************************************************************************/ + +int esp32c3_rt_timer_init(void); + +/**************************************************************************** + * Name: esp32c3_rt_timer_deinit + * + * Description: + * Deinitialize ESP32-C3 RT timer. + * + * Input Parameters: + * None + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp32c3_rt_timer_deinit(void); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_RT_TIMER_H */ diff --git a/arch/risc-v/src/esp32c3/esp32c3_tim.c b/arch/risc-v/src/esp32c3/esp32c3_tim.c index f0ce44f329..4ca044d986 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_tim.c +++ b/arch/risc-v/src/esp32c3/esp32c3_tim.c @@ -685,7 +685,7 @@ FAR struct esp32c3_tim_dev_s *esp32c3_tim_init(int timer) switch (timer) { -#if defined(CONFIG_ESP32C3_TIMER0) +#if defined(CONFIG_ESP32C3_TIMER0) && !defined(CONFIG_ESP32C3_RT_TIMER) case 0: { tim = &g_esp32c3_tim0_priv; @@ -738,3 +738,37 @@ void esp32c3_tim_deinit(FAR struct esp32c3_tim_dev_s *dev) tim = (FAR struct esp32c3_tim_priv_s *)dev; tim->inuse = false; } + +/**************************************************************************** + * Name: esp32c3_tim0_init + * + * Description: + * Initialize TIMER0 device, if software real-time timer + * (CONFIG_ESP32C3_RT_TIMER) is enabled. + * + * Parameters: + * None + * + * Returned Values: + * If the initialization is successful, return a pointer to the timer + * driver struct associated to that timer instance. + * In case it fails, return NULL. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32C3_RT_TIMER + +FAR struct esp32c3_tim_dev_s *esp32c3_tim0_init(void) +{ + FAR struct esp32c3_tim_priv_s *tim = &g_esp32c3_tim0_priv; + + if (tim->inuse == true) + { + tmrerr("ERROR: TIMER0 is already in use\n"); + tim = NULL; + } + + return (FAR struct esp32c3_tim_dev_s *)tim; +} + +#endif diff --git a/arch/risc-v/src/esp32c3/esp32c3_tim.h b/arch/risc-v/src/esp32c3/esp32c3_tim.h index 2d427435ae..df5a35792c 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_tim.h +++ b/arch/risc-v/src/esp32c3/esp32c3_tim.h @@ -135,4 +135,12 @@ struct esp32c3_tim_ops_s FAR struct esp32c3_tim_dev_s *esp32c3_tim_init(int timer); void esp32c3_tim_deinit(FAR struct esp32c3_tim_dev_s *dev); +/**************************************************************************** + * The Timer0 is used by RT-Timer of wireless driver, so please don't use it + * in any other components. + ****************************************************************************/ +#ifdef CONFIG_ESP32C3_RT_TIMER +FAR struct esp32c3_tim_dev_s *esp32c3_tim0_init(void); +#endif + #endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_TIM_H */ diff --git a/arch/risc-v/src/esp32c3/esp32c3_tim_lowerhalf.c b/arch/risc-v/src/esp32c3/esp32c3_tim_lowerhalf.c index 8436936b3e..ba6488b5dc 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_tim_lowerhalf.c +++ b/arch/risc-v/src/esp32c3/esp32c3_tim_lowerhalf.c @@ -97,7 +97,7 @@ static const struct timer_ops_s g_esp32c3_timer_ops = .ioctl = NULL, }; -#ifdef CONFIG_ESP32C3_TIMER0 +#if defined(CONFIG_ESP32C3_TIMER0) && !defined(CONFIG_ESP32C3_RT_TIMER) /* TIMER0 lower-half */ static struct esp32c3_timer_lowerhalf_s g_esp32c3_timer0_lowerhalf = @@ -500,7 +500,7 @@ int esp32c3_timer_initialize(FAR const char *devpath, uint8_t timer) switch (timer) { -#ifdef CONFIG_ESP32C3_TIMER0 +#if defined(CONFIG_ESP32C3_TIMER0) && !defined(CONFIG_ESP32C3_RT_TIMER) case 0: { lower = &g_esp32c3_timer0_lowerhalf; diff --git a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c new file mode 100644 index 0000000000..8c5b1bdfe1 --- /dev/null +++ b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c @@ -0,0 +1,4646 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/esp32c3_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 "nuttx/kmalloc.h" +#include +#include "nuttx/spinlock.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hardware/esp32c3_syscon.h" +#include "esp32c3.h" +#include "esp32c3_attr.h" +#include "esp32c3_irq.h" +#include "esp32c3_wifi_adapter.h" +#include "esp32c3_rt_timer.h" + +#include "espidf_wifi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAC_ADDR0_REG (DR_REG_EFUSE_BASE + 0x044) +#define MAC_ADDR1_REG (DR_REG_EFUSE_BASE + 0x048) + +#define PHY_RF_MASK ((1 << PHY_BT_MODULE) | (1 << PHY_WIFI_MODULE)) + +#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM +# define NVS_FS_PREFIX CONFIG_ESP32C3_WIFI_FS_MOUNTPT +# define NVS_DIR_BASE NVS_FS_PREFIX"/wifi." +# define NVS_FILE_MODE 0777 +#endif + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#define WIFI_CONNECT_TIMEOUT CONFIG_ESP32C3_WIFI_CONNECT_TIMEOUT + +#define TIMER_INITIALIZED_VAL (0x5aa5a55a) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* 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 esp32c3_ints_on(uint32_t mask); +static void esp32c3_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, + int clear_on_exit, + int 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(unsigned int size); +static void esp_free(void *ptr); +static uint32_t esp_rand(void); +static int32_t esp_event_post_wrap(esp_event_base_t event_base, + int32_t event_id, + void *event_data, + size_t event_data_size, + uint32_t ticks); +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 void wifi_phy_disable(void); +static void wifi_phy_enable(void); +static void esp_phy_enable_clock(void); +static void esp_phy_disable_clock(void); +static int wifi_phy_update_country_info(const char *country); +static int esp_wifi_read_mac(uint8_t *mac, uint32_t type); +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 int esp_nvs_set_i8(uint32_t handle, const char *key, + int8_t value); +static int esp_nvs_get_i8(uint32_t handle, const char *key, + int8_t *out_value); +static int esp_nvs_set_u8(uint32_t handle, const char *key, + uint8_t value); +static int esp_nvs_get_u8(uint32_t handle, const char *key, + uint8_t *out_value); +static int esp_nvs_set_u16(uint32_t handle, const char *key, + uint16_t value); +static int esp_nvs_get_u16(uint32_t handle, const char *key, + uint16_t *out_value); +static int esp_nvs_open(const char *name, uint32_t open_mode, + uint32_t *out_handle); +static void esp_nvs_close(uint32_t handle); +static int esp_nvs_commit(uint32_t handle); +static int esp_nvs_set_blob(uint32_t handle, const char *key, + const void *value, size_t length); +static int esp_nvs_get_blob(uint32_t handle, const char *key, + void *out_value, size_t *length); +static int esp_nvs_erase_key(uint32_t handle, const char *key); +static int esp_get_random(uint8_t *buf, size_t len); +static int 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); +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(int queue_len, int 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 int esp_coex_wifi_request(uint32_t event, uint32_t latency, + uint32_t duration); +static int esp_coex_wifi_release(uint32_t event); +static unsigned long esp_random_ulong(void); +static int wifi_coex_wifi_set_channel(uint8_t primary, uint8_t secondary); +static int wifi_coex_get_event_duration(uint32_t event, + uint32_t *duration); +static int wifi_coex_get_pti(uint32_t event, uint8_t *pti); +static void wifi_coex_clear_schm_status_bit(uint32_t type, + uint32_t status); +static void wifi_coex_set_schm_status_bit(uint32_t type, + uint32_t status); +static int wifi_coex_set_schm_interval(uint32_t interval); +static uint32_t wifi_coex_get_schm_interval(void); +static uint8_t wifi_coex_get_schm_curr_period(void); +static void *wifi_coex_get_schm_curr_phase(void); +static int wifi_coex_set_schm_curr_phase_idx(int idx); +static int wifi_coex_get_schm_curr_phase_idx(void); + +/**************************************************************************** + * Public Functions declaration + ****************************************************************************/ + +void ets_timer_arm(void *timer, uint32_t tmout, bool repeat); +void ets_timer_disarm(void *timer); +void ets_timer_done(void *timer); +void ets_timer_setfn(void *timer, void *pfunction, void *parg); +void ets_timer_arm_us(void *timer, uint32_t us, bool repeat); + +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, ...); +uint32_t esp_log_timestamp(void); +uint8_t esp_crc8(const uint8_t *p, uint32_t len); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Wi-Fi interrupt private data */ + +static bool g_wifi_irq_bind; + +/* Wi-Fi thread private data */ + +static pthread_key_t g_wifi_thread_key; +static bool g_wifi_tkey_init; + +/* 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; + +/* time stamp updated when the PHY/RF is turned on */ + +static int64_t g_phy_rf_en_ts; + +/* 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 sem_t g_evtexcl_sem = SEM_INITIALIZER(1); +static sem_t g_connect_sem = SEM_INITIALIZER(0); +static bool g_connected; + +static uint8_t g_ssid[32]; +static uint8_t g_password[64]; +static uint8_t g_ssid_len; +static uint8_t g_password_len; + +/**************************************************************************** + * 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 = esp32c3_ints_on, + ._ints_off = esp32c3_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_wrap, + ._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 = wifi_phy_disable, + ._phy_enable = wifi_phy_enable, + ._phy_update_country_info = wifi_phy_update_country_info, + ._read_mac = esp_wifi_read_mac, + ._timer_arm = ets_timer_arm, + ._timer_disarm = ets_timer_disarm, + ._timer_done = ets_timer_done, + ._timer_setfn = ets_timer_setfn, + ._timer_arm_us = ets_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, + ._slowclk_cal_get = esp_clk_slowclk_cal_get_wrapper, + ._random = esp_random_ulong, + ._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, + ._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: esp_errno_trans + * + * Description: + * Transform from nuttx 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 esp_errno_trans(int ret) +{ + if (!ret) + { + return true; + } + else + { + return false; + } +} + +/**************************************************************************** + * 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, FAR 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_event_lock + * + * Description: + * Lock or unlock the event process + * + * Input Parameters: + * lock - true: Lock event process, false: unlock event process + * + * Returned Value: + * The result of lock or unlock the event process + * + ****************************************************************************/ + +static int esp_event_lock(bool lock) +{ + int ret; + + if (lock) + { + ret = nxsem_wait_uninterruptible(&g_evtexcl_sem); + } + else + { + ret = nxsem_post(&g_evtexcl_sem); + } + + return ret; +} + +/**************************************************************************** + * Name: esp_set_isr + * + * 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; + struct irq_adpt *adapter; + + wlinfo("INFO: n=%ld f=%p arg=%p\n", n, f, arg); + + if (g_wifi_irq_bind) + { + return ; + } + + adapter = kmm_malloc(sizeof(struct irq_adpt)); + if (!adapter) + { + DEBUGASSERT(0); + } + + adapter->func = f; + adapter->arg = arg; + + ret = irq_attach(n + ESP32C3_IRQ_FIRSTPERIPH, esp_int_adpt_cb, adapter); + if (ret != OK) + { + DEBUGASSERT(0); + } + + g_wifi_irq_bind = true; +} + +/**************************************************************************** + * Name: esp32c3_ints_on + * + * Description: + * Enable Wi-Fi interrupt + * + * Input Parameters: + * mask - No mean + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32c3_ints_on(uint32_t mask) +{ + int n = __builtin_ffs(mask) - 1; + + up_enable_irq(n); +} + +/**************************************************************************** + * Name: esp32c3_ints_off + * + * Description: + * Disable Wi-Fi interrupt + * + * Input Parameters: + * mask - No mean + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32c3_ints_off(uint32_t mask) +{ + int n = __builtin_ffs(mask) - 1; + + up_disable_irq(n); +} + +/**************************************************************************** + * 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) +{ + return (void *)1; +} + +/**************************************************************************** + * 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) +{ + DEBUGASSERT((int)lock == 1); +} + +/**************************************************************************** + * 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 = enter_critical_section(); + + 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; + + leave_critical_section(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("ERROR: Failed to alloc %d memory\n", tmp); + return NULL; + } + + ret = nxsem_init(sem, 0, init); + if (ret) + { + wlerr("ERROR: 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; + struct timespec timeout; + sem_t *sem = (sem_t *)semphr; + + if (ticks == OSI_FUNCS_TIME_BLOCKING) + { + ret = nxsem_wait(sem); + if (ret) + { + wlerr("ERROR: Failed to wait sem\n"); + } + } + else + { + ret = clock_gettime(CLOCK_REALTIME, &timeout); + if (ret < 0) + { + wlerr("ERROR: Failed to get time\n"); + return false; + } + + if (ticks) + { + esp_update_time(&timeout, ticks); + } + + ret = nxsem_timedwait(sem, &timeout); + if (ret) + { + wlerr("ERROR: Failed to wait sem in %lu ticks\n", ticks); + } + } + + return esp_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("ERROR: Failed to post sem error=%d\n", ret); + } + + return esp_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) +{ + int ret; + void *sem; + + if (g_wifi_tkey_init) + { + ret = pthread_key_create(&g_wifi_thread_key, esp_thread_semphr_free); + if (ret) + { + wlerr("ERROR: Failed to create pthread key\n"); + return NULL; + } + + g_wifi_tkey_init = true; + } + + sem = pthread_getspecific(g_wifi_thread_key); + if (!sem) + { + sem = esp_semphr_create(1, 0); + if (!sem) + { + wlerr("ERROR: Failed to create semaphore\n"); + return NULL; + } + + ret = pthread_setspecific(g_wifi_thread_key, sem); + if (ret) + { + wlerr("ERROR: Failed to set specific\n"); + 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("ERROR: Failed to alloc %d memory\n", tmp); + return NULL; + } + + ret = pthread_mutex_init(mutex, NULL); + if (ret) + { + wlerr("ERROR: 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("ERROR: Failed to initialize attr error=%d\n", ret); + return NULL; + } + + ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + if (ret) + { + wlerr("ERROR: Failed to set attr type error=%d\n", ret); + return NULL; + } + + tmp = sizeof(pthread_mutex_t); + mutex = kmm_malloc(tmp); + if (!mutex) + { + wlerr("ERROR: Failed to alloc %d memory\n", tmp); + return NULL; + } + + ret = pthread_mutex_init(mutex, &attr); + if (ret) + { + wlerr("ERROR: 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("ERROR: Failed to lock mutex error=%d\n", ret); + } + + return esp_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("ERROR: Failed to unlock mutex error=%d\n", ret); + } + + return esp_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("ERROR: 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("ERROR: 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("ERROR: Failed to send message to mqueue error=%d\n", + ret); + } + } + else + { + ret = clock_gettime(CLOCK_REALTIME, &timeout); + if (ret < 0) + { + wlerr("ERROR: 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("ERROR: Failed to timedsend message to mqueue error=%d\n", + ret); + } + } + + return esp_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("ERROR: Failed to receive from mqueue error=%d\n", ret); + } + } + else + { + ret = clock_gettime(CLOCK_REALTIME, &timeout); + if (ret < 0) + { + wlerr("ERROR: 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("ERROR: 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("ERROR: 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) +{ + DEBUGASSERT(0); + + return NULL; +} + +/**************************************************************************** + * Name: esp_event_group_delete + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void esp_event_group_delete(void *event) +{ + DEBUGASSERT(0); +} + +/**************************************************************************** + * Name: esp_event_group_set_bits + * + * Description: + * Don't support + * + ****************************************************************************/ + +static uint32_t esp_event_group_set_bits(void *event, uint32_t bits) +{ + DEBUGASSERT(0); + + 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) +{ + DEBUGASSERT(0); + + 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, + int clear_on_exit, + int wait_for_all_bits, + uint32_t block_time_tick) +{ + DEBUGASSERT(0); + + 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; + + pid = kthread_create(name, prio, stack_depth, entry, + (char * const *)param); + if (pid > 0) + { + if (task_handle) + { + *((int *)task_handle) = pid; + } + } + else + { + wlerr("ERROR: Failed to create task\n"); + } + + return pid > 0 ? true : false; +} + +/**************************************************************************** + * 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 = 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(unsigned int 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 + { + kmm_free(ptr); + } +} + +/**************************************************************************** + * 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_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; + 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(FAR void *arg) +{ + int ret; + irqstate_t flags; + struct evt_adpt *evt_adpt; + struct wifi_notify *notify; + + while (1) + { + flags = enter_critical_section(); + evt_adpt = (struct evt_adpt *)sq_remfirst(&g_wifi_evt_queue); + leave_critical_section(flags); + if (!evt_adpt) + { + break; + } + + switch (evt_adpt->id) + { + case WIFI_ADPT_EVT_STA_START: + ret = esp_wifi_set_ps(WIFI_PS_NONE); + if (ret) + { + wlerr("ERROR: Failed to close PS\n"); + } + ret = esp_wifi_connect(); + if (ret) + { + wlerr("ERROR: Failed to connect\n"); + } + break; + case WIFI_ADPT_EVT_STA_CONNECT: + g_connected = true; + ret = nxsem_post(&g_connect_sem); + if (ret) + { + wlerr("ERROR: Failed to post sem error=%d\n", ret); + } + break; + case WIFI_ADPT_EVT_STA_DISCONNECT: + g_connected = false; + ret = esp_wifi_connect(); + if (ret) + { + wlerr("ERROR: Failed to connect\n"); + } + break; + default: + break; + } + + esp_event_lock(true); + + 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("ERROR: nxsig_notification event ID=%ld failed: %d\n", + evt_adpt->id, ret); + } + } + + esp_event_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); + + esp32c3_bind_irq(intr_num, intr_source, intr_prio, ESP32C3_INT_LEVEL); +} + +/**************************************************************************** + * 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 + * + ****************************************************************************/ + +esp_err_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=%ld data=%p data_size=%u ticks=%lu\n", + event_base, event_id, event_data, event_data_size, ticks); + + id = esp_event_id_map(event_id); + if (id < 0) + { + wlerr("ERROR: No process event %ld\n", event_id); + return -1; + } + + size = event_data_size + sizeof(struct evt_adpt); + evt_adpt = kmm_malloc(size); + if (!evt_adpt) + { + wlerr("ERROR: Failed to alloc %d memory\n", size); + return -1; + } + + evt_adpt->id = id; + memcpy(evt_adpt->buf, event_data, event_data_size); + + flags = enter_critical_section(); + sq_addlast(&evt_adpt->entry, &g_wifi_evt_queue); + leave_critical_section(flags); + + work_queue(LPWORK, &g_wifi_evt_work, esp_evt_work_cb, NULL, 0); + + return 0; +} + +/**************************************************************************** + * Name: esp_event_post_wrap + * + * 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 + * + ****************************************************************************/ + +static int32_t esp_event_post_wrap(esp_event_base_t event_base, + int32_t event_id, + void *event_data, + size_t event_data_size, + uint32_t ticks) +{ + return (int32_t)esp_event_post(event_base, event_id, event_data, + event_data_size, ticks); +} + +/**************************************************************************** + * 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) +{ + int ret; + struct mallinfo info; + + ret = mm_mallinfo(&g_mmheap, &info); + if (ret) + { + wlerr("ERROR: Failed to create task\n"); + return 0; + } + + 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) +{ +} + +/**************************************************************************** + * Name: esp_dport_access_stall_other_cpu_end + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void esp_dport_access_stall_other_cpu_end(void) +{ +} + +/**************************************************************************** + * Name: wifi_apb80m_request + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void wifi_apb80m_request(void) +{ +} + +/**************************************************************************** + * Name: wifi_apb80m_release + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void wifi_apb80m_release(void) +{ +} + +/**************************************************************************** + * Name: wifi_phy_disable + * + * Description: + * Deinitialize PHY hardware + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wifi_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 Wi-Fi/BT common peripheral clock. + * Do not disable clock for hardware RNG. + */ + + esp_phy_disable_clock(); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: wifi_phy_enable + * + * Description: + * Initialize PHY hardware + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wifi_phy_enable(void) +{ + irqstate_t flags; + esp_phy_calibration_data_t *cal_data; + + cal_data = kmm_zalloc(sizeof(esp_phy_calibration_data_t)); + if (!cal_data) + { + wlerr("ERROR: Failed to kmm_zalloc"); + DEBUGASSERT(0); + } + + flags = enter_critical_section(); + + if (g_phy_access_ref == 0) + { + /* Update time stamp */ + + g_phy_rf_en_ts = esp_timer_get_time(); + + esp_phy_enable_clock(); + phy_set_wifi_mode_only(0); + register_chipv7_phy(&phy_init_data, cal_data, PHY_RF_CAL_NONE); + } + + g_phy_access_ref++; + leave_critical_section(flags); + kmm_free(cal_data); +} + +/**************************************************************************** + * Name: esp_phy_enable_clock + * + * Description: + * Enable PHY hardware clock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_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: esp_phy_disable_clock + * + * Description: + * Disable PHY hardware clock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_phy_disable_clock(void) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + if (g_phy_clk_en_cnt) + { + g_phy_clk_en_cnt--; + if (!g_phy_clk_en_cnt) + { + modifyreg32(SYSTEM_WIFI_CLK_EN_REG, + SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M, + 0); + } + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: wifi_phy_update_country_info + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_phy_update_country_info(const char *country) +{ + return -1; +} + +/**************************************************************************** + * 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 + * + ****************************************************************************/ + +esp_err_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 (type > ESP_MAC_WIFI_SOFTAP) + { + wlerr("ERROR: 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 < 6; 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("ERROR: Failed to generate softAP MAC\n"); + return -1; + } + } + + return 0; +} + +/**************************************************************************** + * 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 int esp_wifi_read_mac(uint8_t *mac, uint32_t type) +{ + return esp_read_mac(mac, type); +} + +/**************************************************************************** + * Name: ets_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 + * + ****************************************************************************/ + +void ets_timer_arm(void *ptimer, uint32_t ms, bool repeat) +{ + ets_timer_arm_us(ptimer, ms * 1000, repeat); +} + +/**************************************************************************** + * Name: ets_timer_disarm + * + * Description: + * Disable timer + * + * Input Parameters: + * ptimer - timer data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void ets_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: ets_timer_done + * + * Description: + * Disable and free timer + * + * Input Parameters: + * ptimer - timer data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void ets_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: ets_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 + * + ****************************************************************************/ + +void ets_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("ERROR: Failed to create ets_timer error=%d\n", ret); + } + else + { + ets_timer->priv = esp_timer; + ets_timer->expire = TIMER_INITIALIZED_VAL; + } + } +} + +/**************************************************************************** + * Name: ets_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 + * + ****************************************************************************/ + +void ets_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("ERROR: 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_MAC_RST); + modifyreg32(SYSCON_WIFI_RST_EN_REG, SYSTEM_MAC_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)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 int esp_nvs_set_i8(uint32_t handle, + const char *key, + int8_t value) +{ +#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM + return esp_nvs_set_blob(handle, key, &value, sizeof(int8_t)); +#else + DEBUGASSERT(0); + + 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 int esp_nvs_get_i8(uint32_t handle, + const char *key, + int8_t *out_value) +{ +#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM + size_t len = sizeof(int8_t); + + return esp_nvs_get_blob(handle, key, out_value, &len); +#else + DEBUGASSERT(0); + + 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 int esp_nvs_set_u8(uint32_t handle, + const char *key, + uint8_t value) +{ +#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM + return esp_nvs_set_blob(handle, key, &value, sizeof(uint8_t)); +#else + DEBUGASSERT(0); + + 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 int esp_nvs_get_u8(uint32_t handle, + const char *key, + uint8_t *out_value) +{ +#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM + size_t len = sizeof(uint8_t); + + return esp_nvs_get_blob(handle, key, out_value, &len); +#else + DEBUGASSERT(0); + + 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 int esp_nvs_set_u16(uint32_t handle, + const char *key, + uint16_t value) +{ +#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM + return esp_nvs_set_blob(handle, key, &value, sizeof(uint16_t)); +#else + DEBUGASSERT(0); + + 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 int esp_nvs_get_u16(uint32_t handle, + const char *key, + uint16_t *out_value) +{ +#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM + size_t len = sizeof(uint16_t); + + return esp_nvs_get_blob(handle, key, out_value, &len); +#else + DEBUGASSERT(0); + + 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 int esp_nvs_open(const char *name, + uint32_t open_mode, + uint32_t *out_handle) +{ +#ifdef CONFIG_ESP32C3_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("ERROR: Failed to alloc %d memory\n", tmp); + return -1; + } + + ret = asprintf(&index_name, "%s", name); + if (ret < 0) + { + wlerr("ERROR: 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 + DEBUGASSERT(0); + + 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_ESP32C3_WIFI_SAVE_PARAM + struct nvs_adpt *nvs_adpt = (struct nvs_adpt *)handle; + + kmm_free(nvs_adpt->index_name); + kmm_free(nvs_adpt); +#else + DEBUGASSERT(0); +#endif +} + +/**************************************************************************** + * Name: esp_nvs_commit + * + * Description: + * This function has no practical effect + * + ****************************************************************************/ + +static int 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 int esp_nvs_set_blob(uint32_t handle, + const char *key, + const void *value, + size_t length) +{ +#ifdef CONFIG_ESP32C3_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("ERROR: Failed to create NVS dir string\n"); + return -1; + } + + ret = nx_unlink(dir); + if (ret) + { + if (ret != -ENOENT) + { + wlerr("ERROR: 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("ERROR: Failed to set open %s\n", dir); + kmm_free(dir); + return -1; + } + + ret = file_write(&file, value, length); + if (ret < 0) + { + wlerr("ERROR: Failed to write to %s\n", dir); + kmm_free(dir); + file_close(&file); + return -1; + } + + kmm_free(dir); + file_close(&file); + + return 0; +#else + DEBUGASSERT(0); + + 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 int esp_nvs_get_blob(uint32_t handle, + const char *key, + void *out_value, + size_t *length) +{ +#ifdef CONFIG_ESP32C3_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("ERROR: Failed to create NVS dir string\n"); + return -1; + } + + ret = file_open(&file, dir, O_RDONLY); + if (ret < 0) + { + if (ret == -ENOENT) + { + wlinfo("INFO: No file %s\n", dir); + kmm_free(dir); + return ESP_ERR_NVS_NOT_FOUND; + } + wlerr("ERROR: Failed to get open %s\n", dir); + kmm_free(dir); + return -1; + } + + ret = file_read(&file, out_value, *length); + if (ret <= 0) + { + wlerr("ERROR: 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 + DEBUGASSERT(0); + + 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 int esp_nvs_erase_key(uint32_t handle, const char *key) +{ +#ifdef CONFIG_ESP32C3_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("ERROR: Failed to create NVS dir string\n"); + return -1; + } + + ret = nx_unlink(dir); + if (ret < 0) + { + wlerr("ERROR: Failed to delete NVS file %s\n", dir); + kmm_free(dir); + return -1; + } + + kmm_free(dir); + + return 0; +#else + DEBUGASSERT(0); + + 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 = 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 int 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 int 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("ERROR: Failed to get time of day\n"); + } + + return ret; +} + +/**************************************************************************** + * Name: esp_clk_slowclk_cal_get_wrapper + ****************************************************************************/ + +static uint32_t esp_clk_slowclk_cal_get_wrapper(void) +{ + return 28639; +} + +/**************************************************************************** + * 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 random(); +} + +/**************************************************************************** + * 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) +{ + return kmm_malloc(size); +} + +/**************************************************************************** + * 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) +{ + return kmm_realloc(ptr, size); +} + +/**************************************************************************** + * 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) +{ + return kmm_calloc(n, size); +} + +/**************************************************************************** + * 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) +{ + return kmm_zalloc(size); +} + +/**************************************************************************** + * 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(int queue_len, int item_size) +{ + wifi_static_queue_t *wifi_queue; + + wifi_queue = kmm_malloc(sizeof(wifi_static_queue_t)); + if (!wifi_queue) + { + wlerr("ERROR: Failed to kmm_malloc\n"); + return NULL; + } + + wifi_queue->handle = esp_queue_create(queue_len, item_size); + if (!wifi_queue->handle) + { + wlerr("ERROR: 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) +{ +} + +/**************************************************************************** + * Name: wifi_coex_enable + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_enable(void) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_disable + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void wifi_coex_disable(void) +{ +} + +/**************************************************************************** + * Name: esp_coex_status_get + * + * 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) +{ +} + +/**************************************************************************** + * Name: esp_coex_wifi_request + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int 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 int esp_coex_wifi_release(uint32_t event) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_wifi_set_channel + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_wifi_set_channel(uint8_t primary, uint8_t secondary) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_get_event_duration + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_get_event_duration(uint32_t event, uint32_t *duration) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_get_pti + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_get_pti(uint32_t event, uint8_t *pti) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_clear_schm_status_bit + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void wifi_coex_clear_schm_status_bit(uint32_t type, uint32_t status) +{ +} + +/**************************************************************************** + * Name: wifi_coex_set_schm_status_bit + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void wifi_coex_set_schm_status_bit(uint32_t type, uint32_t status) +{ +} + +/**************************************************************************** + * Name: wifi_coex_set_schm_interval + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_set_schm_interval(uint32_t interval) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_get_schm_interval + * + * Description: + * Don't support + * + ****************************************************************************/ + +static uint32_t wifi_coex_get_schm_interval(void) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_get_schm_curr_period + * + * Description: + * Don't support + * + ****************************************************************************/ + +static uint8_t wifi_coex_get_schm_curr_period(void) +{ + return 0; +} + +/**************************************************************************** + * Name: wifi_coex_get_schm_curr_phase + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void *wifi_coex_get_schm_curr_phase(void) +{ + return NULL; +} + +/**************************************************************************** + * Name: wifi_coex_set_schm_curr_phase_idx + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_set_schm_curr_phase_idx(int idx) +{ + return -1; +} + +/**************************************************************************** + * Name: wifi_coex_get_schm_curr_phase_idx + * + * Description: + * Don't support + * + ****************************************************************************/ + +static int wifi_coex_get_schm_curr_phase_idx(void) +{ + return 0; +} + +/**************************************************************************** + * Name: esp_random_ulong + ****************************************************************************/ + +static unsigned long esp_random_ulong(void) +{ + return random(); +} + +/**************************************************************************** + * Functions needed by libphy.a + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_dport_access_reg_read + * + * Description: + * Read regitser 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_enter_critical + * + * Description: + * Enter critical state + * + * Input Parameters: + * None + * + * Returned Value: + * CPU PS value + * + ****************************************************************************/ + +uint32_t IRAM_ATTR phy_enter_critical(void) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + return flags; +} + +/**************************************************************************** + * Name: phy_exit_critical + * + * Description: + * Exit from critical state + * + * Input Parameters: + * level - CPU PS value + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR phy_exit_critical(uint32_t level) +{ + leave_critical_section(level); +} + +/**************************************************************************** + * 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: 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; +} + +/**************************************************************************** + * Name: esp_mesh_get_topology + * + * Description: + * Don't support + * + ****************************************************************************/ + +void *esp_mesh_get_topology(void) +{ + return NULL; +} + +/**************************************************************************** + * 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 + * + ****************************************************************************/ + +esp_err_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 = rt_timer_create(&rt_timer_args, &rt_timer); + if (ret) + { + wlerr("ERROR: 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 + * + ****************************************************************************/ + +esp_err_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; + + DEBUGASSERT(timeout_us <= UINT32_MAX); + + 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 + * + ****************************************************************************/ + +esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) +{ + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; + + DEBUGASSERT(period <= UINT32_MAX); + + 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 + * + ****************************************************************************/ + +esp_err_t esp_timer_stop(esp_timer_handle_t timer) +{ + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; + + 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 + * + ****************************************************************************/ + +esp_err_t esp_timer_delete(esp_timer_handle_t timer) +{ + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; + + rt_timer_delete(rt_timer); + + return 0; +} + +/**************************************************************************** + * Name: __assert_func + * + * Description: + * Delete timer and free resource + * + * Input Parameters: + * file - assert file + * line - assert line + * func - assert function + * expr - assert condition + * + * Returned Value: + * None + * + ****************************************************************************/ + +void __assert_func(const char *file, int line, + const char *func, const char *expr) +{ + wlerr("ERROR: Assert failed in %s, %s:%d (%s)", + func, file, line, expr); + abort(); +} + +/**************************************************************************** + * 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 + * + ****************************************************************************/ + +esp_err_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 + * + ****************************************************************************/ + +esp_err_t esp_wifi_init(const wifi_init_config_t *config) +{ + esp_err_t ret; + + ret = esp_wifi_init_internal(config); + if (ret) + { + wlerr("ERROR: Failed to initialize Wi-Fi error=%d\n", ret); + return -1; + } + + ret = esp_supplicant_init(); + if (ret) + { + wlerr("ERROR: Failed to initialize WPA supplicant error=%d\n", ret); + esp_wifi_deinit_internal(); + return -1; + } + + 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 + * + ****************************************************************************/ + +esp_err_t esp_wifi_deinit(void) +{ + int ret; + + ret = esp_supplicant_deinit(); + if (ret) + { + wlerr("ERROR: Failed to deinitialize supplicant\n"); + return ret; + } + + ret = esp_wifi_deinit_internal(); + if (ret != 0) + { + wlerr("ERROR: Failed to deinitialize Wi-Fi\n"); + return ret; + } + + return ret; +} + +/**************************************************************************** + * 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: + * 0 if success or others if fail + * + ****************************************************************************/ + +int esp_wifi_sta_send_data(void *pbuf, uint32_t len) +{ + int ret; + + ret = esp_wifi_internal_tx(WIFI_IF_STA, pbuf, len); + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_sta_register_recv_cb + * + * Description: + * Register Wi-Fi receive packet callback function + * + * Input Parameters: + * input_cb - Receive callback function + * + * Returned Value: + * 0 if success or others if fail + * + ****************************************************************************/ + +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 ret; +} + +/**************************************************************************** + * 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_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, FAR struct sigevent *event) +{ + int id; + struct wifi_notify *notify; + int ret = -1; + + wlinfo("PID=%d event=%p\n", pid, event); + + esp_event_lock(true); + + if (event->sigev_notify == SIGEV_SIGNAL) + { + id = esp_event_id_map(event->sigev_signo); + if (id < 0) + { + wlerr("ERROR: No process event %d\n", event->sigev_signo); + } + else + { + notify = &g_wifi_notify[id]; + + if (notify->assigned) + { + wlerr("ERROR: sigev_signo %d has subscribed\n", + event->sigev_signo); + } + else + { + if (pid == 0) + { + pid = getpid(); + wlinfo("Actual PID=%d\n", pid); + } + + notify->pid = pid; + notify->event = *event; + notify->assigned = true; + + ret = 0; + } + } + } + else if (event->sigev_notify == SIGEV_NONE) + { + id = esp_event_id_map(event->sigev_signo); + if (id < 0) + { + wlerr("ERROR: No process event %d\n", event->sigev_signo); + } + else + { + notify = &g_wifi_notify[id]; + + if (!notify->assigned) + { + wlerr("ERROR: sigev_signo %d has not subscribed\n", + event->sigev_signo); + } + else + { + notify->assigned = false; + + ret = 0; + } + } + } + else + { + wlerr("ERROR: sigev_notify %d is invalid\n", event->sigev_signo); + } + + esp_event_lock(false); + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_adapter_init + * + * Description: + * Initialize ESP32C3 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(); + + ret = esp32c3_rt_timer_init(); + if (ret < 0) + { + wlerr("ERROR: Failed to initialize RT timer error=%d\n", ret); + return -1; + } + +#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM + wifi_cfg.nvs_enable = 1; +#else + wifi_cfg.nvs_enable = 0; +#endif + +#ifdef CONFIG_ESP32C3_WIFI_TX_AMPDU + wifi_cfg.ampdu_tx_enable = 1; +#else + wifi_cfg.ampdu_tx_enable = 0; +#endif + +#ifdef CONFIG_ESP32C3_WIFI_RX_AMPDU + wifi_cfg.ampdu_rx_enable = 1; +#else + wifi_cfg.ampdu_rx_enable = 0; +#endif + + wifi_cfg.rx_ba_win = CONFIG_ESP32C3_WIFI_RXBA_AMPDU_WZ; + wifi_cfg.static_rx_buf_num = CONFIG_ESP32C3_WIFI_STATIC_RXBUF_NUM; + wifi_cfg.dynamic_rx_buf_num = CONFIG_ESP32C3_WIFI_DYNAMIC_RXBUF_NUM; + wifi_cfg.dynamic_tx_buf_num = CONFIG_ESP32C3_WIFI_DYNAMIC_TXBUF_NUM; + + modifyreg32(SYSTEM_WIFI_CLK_EN_REG, 0, UINT32_MAX); + + ret = esp_wifi_init(&wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to initialize Wi-Fi error=%d\n", ret); + esp32c3_rt_timer_deinit(); + return -1; + } + + sq_init(&g_wifi_evt_queue); + + return 0; +} + +/**************************************************************************** + * Name: esp_wifi_set_password + * + * Description: + * Set Wi-Fi password + * + * Input Parameters: + * pdata - Password buffer pointer + * len - Password length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_set_password(const uint8_t *pdata, uint8_t len) +{ + memcpy(g_password, pdata, len); + g_password_len = len; + + return 0; +} + +/**************************************************************************** + * Name: esp_wifi_set_ssid + * + * Description: + * Set Wi-Fi SSID + * + * Input Parameters: + * pdata - SSID buffer pointer + * len - SSID length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_set_ssid(const uint8_t *pdata, uint8_t len) +{ + memcpy(g_ssid, pdata, len); + g_ssid_len = len; + + return 0; +} + +/**************************************************************************** + * Name: esp_wifi_connect_internal + * + * Description: + * Trigger Wi-Fi connection action + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_connect_internal(void) +{ + int ret; + wifi_config_t wifi_cfg; + struct timespec timeout; + + if (g_connected) + { + wlinfo("INFO: Wi-Fi has connected AP\n"); + return 0; + } + + ret = esp_wifi_set_mode(WIFI_MODE_STA); + if (ret) + { + wlerr("ERROR: Failed to set station mode error=%d\n", ret); + esp_wifi_deinit(); + return -1; + } + + memset(&wifi_cfg, 0, sizeof(wifi_config_t)); + memcpy((char *)wifi_cfg.sta.ssid, g_ssid, g_ssid_len); + memcpy((char *)wifi_cfg.sta.password, g_password, g_password_len); + + ret = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set Wi-Fi config error=%d\n", ret); + return -1; + } + + ret = esp_wifi_start(); + if (ret) + { + wlerr("ERROR: Failed to set start config error=%d\n", ret); + return -1; + } + + clock_gettime(CLOCK_REALTIME, &timeout); + timeout.tv_sec += WIFI_CONNECT_TIMEOUT; + ret = nxsem_timedwait(&g_connect_sem, &timeout); + if (ret) + { + wlerr("ERROR: Failed to wait sem error=%d\n", ret); + esp_wifi_stop(); + return -1; + } + + if (!g_connected) + { + wlerr("ERROR: Process connection error\n"); + esp_wifi_stop(); + return -1; + } + + return 0; +} + +/**************************************************************************** + * Name: esp_wifi_sta_register_txdone_cb + * + * Description: + * Register the txDone callback function of type wifi_tx_done_cb_t + * + * Input Parameters: + * callback - The callback function + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_sta_register_txdone_cb(void *callback) +{ + return esp_wifi_set_tx_done_cb((wifi_tx_done_cb_t)callback); +} diff --git a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h new file mode 100644 index 0000000000..a1bd411b7b --- /dev/null +++ b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h @@ -0,0 +1,242 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/esp32c3_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_RISCV_SRC_ESP32C3_ESP32C3_WIFI_ADAPTER_H +#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_WIFI_ADAPTER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Wi-Fi event ID */ + +enum wifi_adpt_evt_e +{ + WIFI_ADPT_EVT_STA_START = 0, + WIFI_ADPT_EVT_STA_CONNECT, + WIFI_ADPT_EVT_STA_DISCONNECT, + WIFI_ADPT_EVT_STA_AUTHMODE_CHANGE, + WIFI_ADPT_EVT_STA_STOP, + WIFI_ADPT_EVT_MAX, +}; + +/* Wi-Fi event callback function */ + +typedef void (*wifi_evt_cb_t)(void *p); + +typedef void (* wifi_tx_done_cb_t)(uint8_t ifidx, uint8_t *data, + uint16_t *len, bool txstatus); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_wifi_adapter_init + * + * Description: + * Initialize ESP32 Wi-Fi adapter + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_adapter_init(void); + +/**************************************************************************** + * 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, FAR struct sigevent *event); + +/**************************************************************************** + * 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: + * 0 if success or others if fail + * + ****************************************************************************/ + +int esp_wifi_sta_send_data(void *pbuf, uint32_t len); + +/**************************************************************************** + * Name: esp_wifi_sta_register_recv_cb + * + * Description: + * Register Wi-Fi receive packet callback function + * + * Input Parameters: + * input_cb - Receive callback function + * + * Returned Value: + * 0 if success or others if fail + * + ****************************************************************************/ + +int esp_wifi_sta_register_recv_cb(int (*recv_cb)(void *buffer, + uint16_t len, + void *eb)); + +/**************************************************************************** + * 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_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_set_password + * + * Description: + * Set Wi-Fi password + * + * Input Parameters: + * pdata - Password buffer pointer + * len - Password length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_set_password(const uint8_t *pdata, uint8_t len); + +/**************************************************************************** + * Name: esp_wifi_set_ssid + * + * Description: + * Set Wi-Fi SSID + * + * Input Parameters: + * pdata - SSID buffer pointer + * len - SSID length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_set_ssid(const uint8_t *pdata, uint8_t len); + +/**************************************************************************** + * Name: esp_wifi_connect_internal + * + * Description: + * Trigger Wi-Fi connection action + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_connect_internal(void); + +/**************************************************************************** + * Name: esp_wifi_sta_register_txdone_cb + * + * Description: + * Register the txDone callback function of type wifi_tx_done_cb_t + * + * Input Parameters: + * callback - The callback function + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_sta_register_txdone_cb(void *callback); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_WIFI_ADAPTER_H */ diff --git a/arch/risc-v/src/esp32c3/esp32c3_wlan.c b/arch/risc-v/src/esp32c3/esp32c3_wlan.c new file mode 100644 index 0000000000..50d1306634 --- /dev/null +++ b/arch/risc-v/src/esp32c3/esp32c3_wlan.c @@ -0,0 +1,1487 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/esp32c3_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 +#include +#include +#include +#include +#if defined(CONFIG_NET_PKT) +# include +#endif + +#include "esp32c3_wifi_adapter.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* WLAN station device ID */ + +#define WLAN_STA_DEVNO (0) + +/* TX poll delay = 1 seconds. + * CLK_TCK is the number of clock ticks per second + */ + +#define WLAN_WDDELAY (1 * CLK_TCK) + +/* 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) + +/* Wi-Fi receive buffer number */ + +#define WLAN_RXBUF_NUM (CONFIG_ESP32C3_WLAN_RXBUF_NUM) + +/* Receive threshold which allows the receive function to trigger a scheduler + * to activate the application if possible. + */ + +#ifdef CONFIG_MM_IOB +# define IOBBUF_SIZE (CONFIG_IOB_NBUFFERS * CONFIG_IOB_BUFSIZE) +# if (IOBBUF_SIZE) > (WLAN_BUF_SIZE + 1) +# define WLAN_RX_THRESHOLD (IOBBUF_SIZE - WLAN_BUF_SIZE + 1) +# endif +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Receive buffer */ + +struct wlan_rxbuf +{ + sq_entry_t entry; /* Queue entry */ + + /* Packet data buffer */ + + uint8_t buffer[WLAN_BUF_SIZE]; + uint16_t len; /* Packet data length */ +}; + +/* The wlan_priv_s encapsulates all state information for a single + * hardware interface + */ + +struct wlan_priv_s +{ + bool ifup; /* true:ifup false:ifdown */ + + struct wdog_s txpoll; /* TX poll timer */ + struct wdog_s txtimeout; /* TX timeout timer */ + + struct work_s rxwork; /* Send packet work */ + struct work_s txwork; /* Receive packet work */ + struct work_s pollwork; /* Poll work */ + struct work_s toutwork; /* Send packet timeout work */ + + /* This holds the information visible to the NuttX network */ + + struct net_driver_s dev; + + /* TX buffer */ + + uint8_t txbuf[WLAN_BUF_SIZE]; + + /* Rest of the data in the TX buffer that need to be sent */ + + uint8_t txrst; + + /* RX buffer cache */ + + struct wlan_rxbuf rxbuf[WLAN_RXBUF_NUM]; + + /* RX buffer queue */ + + sq_queue_t rxb; + + /* Free buffer queue */ + + sq_queue_t freeb; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct wlan_priv_s g_wlan_priv; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Common TX logic */ + +static int wlan_transmit(FAR struct wlan_priv_s *priv); +static void wlan_rxpoll(FAR void *arg); +static int wlan_txpoll(FAR struct net_driver_s *dev); +static void wlan_dopoll(FAR struct wlan_priv_s *priv); + +/* Watchdog timer expirations */ + +static void wlan_txtimeout_work(FAR void *arg); +static void wlan_txtimeout_expiry(wdparm_t arg); + +static void wlan_poll_work(FAR void *arg); +static void wlan_poll_expiry(wdparm_t arg); + +/* NuttX callback functions */ + +static int wlan_ifup(struct net_driver_s *dev); +static int wlan_ifdown(struct net_driver_s *dev); + +static void wlan_txavail_work(FAR void *arg); +static int wlan_txavail(struct net_driver_s *dev); + +#if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6) +static int wlan_addmac(struct net_driver_s *dev, FAR const uint8_t *mac); +#endif + +#ifdef CONFIG_NET_MCASTGROUP +static int wlan_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac); +#endif + +#ifdef CONFIG_NETDEV_IOCTL +static int wlan_ioctl(struct net_driver_s *dev, int cmd, + unsigned long arg); +#endif + +static void wlan_tx_done(uint8_t ifidx, uint8_t *data, + uint16_t *len, bool txstatus); +static int wlan_rx_done(void *buffer, uint16_t len, void *eb); + +/**************************************************************************** + * 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_init_buffer + * + * Description: + * Initialize the free buffer list + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void wlan_init_buffer(struct wlan_priv_s *priv) +{ + int i; + irqstate_t flags; + + flags = enter_critical_section(); + + priv->txrst = 0; + + priv->dev.d_buf = NULL; + priv->dev.d_len = 0; + + sq_init(&priv->freeb); + sq_init(&priv->rxb); + + for (i = 0; i < WLAN_RXBUF_NUM; i++) + { + sq_addlast(&priv->rxbuf[i].entry, &priv->freeb); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Function: wlan_alloc_buffer + * + * Description: + * Allocate one buffer from the free buffer queue + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * Pointer to the allocated buffer on success; NULL on failure + * + ****************************************************************************/ + +static inline struct wlan_rxbuf *wlan_alloc_buffer(struct wlan_priv_s *priv) +{ + sq_entry_t *entry; + irqstate_t flags; + struct wlan_rxbuf *rxbuf = NULL; + + flags = enter_critical_section(); + + entry = sq_remfirst(&priv->freeb); + if (entry) + { + rxbuf = container_of(entry, struct wlan_rxbuf, entry); + } + + leave_critical_section(flags); + + return rxbuf; +} + +/**************************************************************************** + * Function: wlan_free_buffer + * + * Description: + * Insert a free Rx buffer into the free queue + * + * Input Parameters: + * priv - Reference to the driver state structure + * buffer - A pointer to the buffer to be freed + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void wlan_free_buffer(struct wlan_priv_s *priv, + uint8_t *buffer) +{ + struct wlan_rxbuf *rxbuf; + irqstate_t flags; + + flags = enter_critical_section(); + + rxbuf = container_of(buffer, struct wlan_rxbuf, buffer); + sq_addlast(&rxbuf->entry, &priv->freeb); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: wifi_tx_available + * + * Description: + * Check if Wi-Fi can send data. This function will re-send the rest of the + * data that we failed to send. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * true if available or false if unavailable + * + ****************************************************************************/ + +static bool wifi_tx_available(FAR struct wlan_priv_s *priv) +{ + int ret; + + if (priv->txrst) + { + ret = esp_wifi_sta_send_data(priv->txbuf, priv->txrst); + if (ret) + { + ninfo("ERROR: Failed to transmit the rest of the frame\n"); + return false; + } + else + { + priv->txrst = 0; + } + } + + return true; +} + +/**************************************************************************** + * Name: wlan_transmit + * + * Description: + * Send the data to Wi-Fi driver. If this sending fails, cache the data + * and re-send it when TX done callback or timer poll function triggers. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +static int wlan_transmit(FAR struct wlan_priv_s *priv) +{ + int ret; + struct net_driver_s *dev = &priv->dev; + void *buffer = dev->d_buf; + uint32_t len = dev->d_len; + + if (!wifi_tx_available(priv)) + { + return -ENOBUFS; + } + + ret = esp_wifi_sta_send_data(buffer, len); + if (ret) + { + priv->txrst = len; + if (buffer != priv->txbuf) + { + memcpy(priv->txbuf, buffer, len); + } + + wd_start(&priv->txtimeout, WLAN_TXTOUT, + wlan_txtimeout_expiry, (uint32_t)priv); + + return -EIO; + } + else + { + priv->txrst = 0; + } + + return OK; +} + +/**************************************************************************** + * Function: wlan_recvframe + * + * Description: + * Try to receive RX buffer from RX done buffer queue. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * RX buffer if success or NULl if no buffer in queue. + * + ****************************************************************************/ + +static struct wlan_rxbuf *wlan_recvframe(FAR struct wlan_priv_s *priv) +{ + irqstate_t flags; + sq_entry_t *entry; + struct wlan_rxbuf *rxbuf = NULL; + + flags = enter_critical_section(); + + entry = sq_remfirst(&priv->rxb); + if (entry) + { + rxbuf = container_of(entry, struct wlan_rxbuf, entry); + } + + leave_critical_section(flags); + + return rxbuf; +} + +/**************************************************************************** + * Name: wlan_tx_done + * + * Description: + * Wi-Fi TX done callback function. If this is called, it means 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_tx_done(uint8_t ifidx, uint8_t *data, + uint16_t *len, bool status) +{ + FAR struct wlan_priv_s *priv = &g_wlan_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: + * 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(void *buffer, uint16_t len, void *eb) +{ + struct wlan_rxbuf *rxbuf; + irqstate_t flags; + FAR struct wlan_priv_s *priv = &g_wlan_priv; + 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; + } + + rxbuf = wlan_alloc_buffer(priv); + if (!rxbuf) + { + ret = -ENOBUFS; + goto out; + } + + memcpy(rxbuf->buffer, buffer, len); + rxbuf->len = len; + + if (eb) + { + esp_wifi_free_eb(eb); + } + + flags = enter_critical_section(); + sq_addlast(&rxbuf->entry, &priv->rxb); + leave_critical_section(flags); + + if (work_available(&priv->rxwork)) + { + work_queue(WLAN_WORK, &priv->rxwork, wlan_rxpoll, priv, 0); + } + + return 0; + +out: + if (eb) + { + esp_wifi_free_eb(eb); + } + + 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(FAR void *arg) +{ + struct wlan_rxbuf *rxbuf; + struct eth_hdr_s *eth_hdr; + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; + FAR struct net_driver_s *dev = &priv->dev; +#ifdef WLAN_RX_THRESHOLD + uint32_t rbytes = 0; +#endif + + /* Loop while while wlan_recvframe() successfully retrieves valid + * Ethernet frames. + */ + + net_lock(); + + while ((rxbuf = wlan_recvframe(priv)) != NULL) + { + dev->d_buf = rxbuf->buffer; + dev->d_len = rxbuf->len; + +#ifdef WLAN_RX_THRESHOLD + rbytes += rxbuf->len; +#endif + +#ifdef CONFIG_NET_PKT + + /* When packet sockets are enabled, + * feed the frame into the packet tap. + */ + + pkt_input(&priv->dev); +#endif + + /* Check if the packet is a valid size for the network + * buffer configuration (this should not happen) + */ + + if (dev->d_len > WLAN_BUF_SIZE) + { + nwarn("WARNING: DROPPED Too big: %d\n", dev->d_len); + + /* Free dropped packet buffer */ + + if (dev->d_buf) + { + wlan_free_buffer(priv, dev->d_buf); + dev->d_buf = NULL; + dev->d_len = 0; + } + + continue; + } + + eth_hdr = (struct eth_hdr_s *)dev->d_buf; + + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv4 + if (eth_hdr->type == HTONS(ETHTYPE_IP)) + { + ninfo("IPv4 frame\n"); + + /* Handle ARP on input then give the IPv4 packet to the network + * layer + */ + + arp_ipin(&priv->dev); + ipv4_input(&priv->dev); + + /* If the above function invocation resulted in data + * that should be sent out on the network, + * the field d_len will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + /* Update the Ethernet header with the correct MAC address */ + +#ifdef CONFIG_NET_IPv6 + if (IFF_IS_IPv4(priv->dev.d_flags)) +#endif + { + arp_out(&priv->dev); + } +#ifdef CONFIG_NET_IPv6 + else + { + neighbor_out(&priv->dev); + } +#endif + + /* And send the packet */ + + wlan_transmit(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) + { + /* Update the Ethernet header with the correct MAC address */ + +#ifdef CONFIG_NET_IPv4 + if (IFF_IS_IPv4(priv->dev.d_flags)) + { + arp_out(&priv->dev); + } + else +#endif +#ifdef CONFIG_NET_IPv6 + { + neighbor_out(&priv->dev); + } +#endif + + /* And send the packet */ + + wlan_transmit(priv); + } + } + else +#endif +#ifdef CONFIG_NET_ARP + if (eth_hdr->type == htons(ETHTYPE_ARP)) + { + ninfo("ARP frame\n"); + + /* Handle ARP packet */ + + arp_arpin(&priv->dev); + + /* If the above function invocation resulted in data + * that should be sent out on the network, the field + * d_len will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + wlan_transmit(priv); + } + } + else +#endif + { + ninfo("INFO: Dropped, Unknown type: %04x\n", eth_hdr->type); + } + + /* We are finished with the RX buffer. NOTE: If the buffer is + * re-used for transmission, the dev->d_buf field will have been + * nullified. + */ + + if (dev->d_buf) + { + /* Free the receive packet buffer */ + + wlan_free_buffer(priv, dev->d_buf); + dev->d_buf = NULL; + dev->d_len = 0; + } + +#ifdef WLAN_RX_THRESHOLD + /** + * If received total bytes is larger than receive threshold, + * then do "unlock" to try to active applicantion to receive + * data from low-level buffer of IP stack. + */ + + if (rbytes >= WLAN_RX_THRESHOLD) + { + net_unlock(); + rbytes = 0; + net_lock(); + } +#endif + } + + net_unlock(); +} + +/**************************************************************************** + * Name: 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 packet 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(FAR struct net_driver_s *dev) +{ + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; + + DEBUGASSERT(dev->d_buf != NULL); + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (dev->d_len > 0) + { + /* Look up the destination MAC address and add it to the Ethernet + * header. + */ + +#ifdef CONFIG_NET_IPv4 +#ifdef CONFIG_NET_IPv6 + if (IFF_IS_IPv4(dev->d_flags)) +#endif + { + arp_out(dev); + } +#endif /* CONFIG_NET_IPv4 */ + +#ifdef CONFIG_NET_IPv6 +#ifdef CONFIG_NET_IPv4 + else +#endif + { + neighbor_out(dev); + } +#endif /* CONFIG_NET_IPv6 */ + + int ret = wlan_transmit(priv); + if (ret) + { + return -EBUSY; + } + } + + /* If zero is returned, the polling will continue until + * all connections have been examined. + */ + + return OK; +} + +/**************************************************************************** + * 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(FAR struct wlan_priv_s *priv) +{ + FAR struct net_driver_s *dev = &priv->dev; + + if (!wifi_tx_available(priv)) + { + return ; + } + + dev->d_buf = priv->txbuf; + + /* If so, then poll the network for new XMIT data */ + + devif_timer(dev, 0, wlan_txpoll); + + dev->d_buf = NULL; +} + +/**************************************************************************** + * 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; + + 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_poll_work + * + * Description: + * Perform periodic polling from the worker thread + * + * Input Parameters: + * arg - The argument passed when work_queue() as called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +static void wlan_poll_work(FAR void *arg) +{ + int32_t delay = WLAN_WDDELAY; + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; + struct net_driver_s *dev = &priv->dev; + + /* Lock the network and serialize driver operations if necessary. + * NOTE: Serialization is only required in the case where the driver work + * is performed on an LP worker thread and where more than one LP worker + * thread has been configured. + */ + + net_lock(); + + /* Check if there is room in the send another TX packet. We cannot perform + * the TX poll if he are unable to accept another packet for transmission. + * + * If there is no room, we should reset the timeout value to be 1 to + * trigger the timer as soon as possible. + */ + + if (!wifi_tx_available(priv)) + { + delay = 1; + goto exit; + } + + dev->d_buf = priv->txbuf; + + /* Update TCP timing states and poll the network for new XMIT data. */ + + devif_timer(&priv->dev, delay, wlan_txpoll); + + dev->d_buf = NULL; + +exit: + wd_start(&priv->txpoll, delay, wlan_poll_expiry, (wdparm_t)priv); + + net_unlock(); +} + +/**************************************************************************** + * Name: wlan_poll_expiry + * + * Description: + * Periodic timer handler. Called from the timer callback handler. + * + * Input Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_poll_expiry(wdparm_t arg) +{ + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; + + if (priv->ifup) + { + work_queue(WLAN_WORK, &priv->pollwork, wlan_poll_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(FAR void *arg) +{ + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; + + /* Lock the network and serialize driver operations if necessary. + * NOTE: Serialization is only required in the case where the driver work + * 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(FAR struct net_driver_s *dev) +{ + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; + +#ifdef CONFIG_NET_IPv4 + ninfo("Bringing up: %d.%d.%d.%d\n", + (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 + winfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2], + dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5], + dev->d_ipv6addr[6], dev->d_ipv6addr[7]); +#endif + + net_lock(); + + if (priv->ifup) + { + net_unlock(); + return OK; + } + +#ifdef CONFIG_NET_ICMPv6 + + /* Set up IPv6 multicast address filtering */ + + wlan_ipv6multicast(priv); +#endif + + wlan_init_buffer(priv); + + /* Set and activate a timer process */ + + wd_start(&priv->txpoll, WLAN_WDDELAY, wlan_poll_expiry, (wdparm_t)priv); + + priv->ifup = true; + + net_unlock(); + + return OK; +} + +/**************************************************************************** + * Name: wlan_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int wlan_ifdown(FAR struct net_driver_s *dev) +{ + FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; + + net_lock(); + + if (!priv->ifup) + { + net_unlock(); + return OK; + } + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(&priv->txpoll); + wd_cancel(&priv->txtimeout); + + /* Mark the device "down" */ + + priv->ifup = false; + + net_unlock(); + + return OK; +} + +/**************************************************************************** + * Name: wlan_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * 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(FAR struct net_driver_s *dev) +{ + FAR struct wlan_priv_s *priv = (FAR 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(FAR struct net_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct wlan_priv_s *priv = (FAR 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(FAR struct net_driver_s *dev, FAR const uint8_t *mac) +{ + FAR struct wlan_priv_s *priv = (FAR 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(FAR struct wlan_priv_s *priv) +{ + FAR 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(FAR struct net_driver_s *dev, + int cmd, + unsigned long arg) +{ + int ret; + struct iw_point *essid; + struct iw_encode_ext *ext; + struct iwreq *iwr = (struct iwreq *)arg; + + /* 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 = esp_wifi_notify_subscribe(req->pid, &req->event); + if (ret) + { + nerr("ERROR: Failed to subscribe event\n"); + } + } + break; +#endif +#endif + + case SIOCSIWENCODEEXT: + { + ext = iwr->u.encoding.pointer; + ret = esp_wifi_set_password(ext->key, ext->key_len); + if (ret) + { + nerr("ERROR: Failed to set password\n"); + } + } + break; + case SIOCSIWESSID: + { + iwr = (struct iwreq *)arg; + essid = &iwr->u.essid; + ret = esp_wifi_set_ssid(essid->pointer, essid->length); + if (ret) + { + nerr("ERROR: Failed to set SSID\n"); + break; + } + + ret = esp_wifi_connect_internal(); + if (ret) + { + nerr("ERROR: Failed to start connecting\n"); + break; + } + } + break; + case SIOCSIWMODE: + ret = OK; + break; + case SIOCSIWAUTH: + ret = OK; + break; + case SIOCSIWFREQ: + ret = OK; + 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: esp32c3_net_initialize + * + * Description: + * Initialize the ESP32-C3 driver + * + * Input Parameters: + * devno - The device number. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +static int esp32c3_net_initialize(unsigned int devno) +{ + int ret; + uint8_t eth_mac[6]; + FAR struct wlan_priv_s *priv; + + /* Get the interface structure associated with this interface number. */ + + priv = &g_wlan_priv; + + /* Initialize the driver structure */ + + memset(priv, 0, sizeof(struct wlan_priv_s)); + + priv->dev.d_ifup = wlan_ifup; /* I/F down callback */ + priv->dev.d_ifdown = wlan_ifdown; /* I/F up (new IP address) callback */ + priv->dev.d_txavail = wlan_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_MCASTGROUP + priv->dev.d_addmac = wlan_addmac; /* Add multicast MAC address */ + priv->dev.d_rmmac = wlan_rmmac; /* Remove multicast MAC address */ +#endif +#ifdef CONFIG_NETDEV_IOCTL + priv->dev.d_ioctl = wlan_ioctl; /* Handle network IOCTL commands */ +#endif + + /* Used to recover private state from dev */ + + priv->dev.d_private = (void *)&g_wlan_priv; + + /* Create a watchdog for timing polling for and timing of transmissions */ + + esp_wifi_sta_read_mac(eth_mac); + + memcpy(priv->dev.d_mac.ether.ether_addr_octet, eth_mac, sizeof(eth_mac)); + + ninfo("%02X:%02X:%02X:%02X:%02X:%02X \r\n", + eth_mac[0], eth_mac[1], eth_mac[2], + eth_mac[3], eth_mac[4], eth_mac[5]); + + /* Put the interface in the down state. */ + + wlan_ifdown(&priv->dev); + + ret = netdev_register(&priv->dev, NET_LL_IEEE80211); + if (ret) + { + nerr("ERROR: Initialization of Ethernet block failed: %d\n", ret); + return ret; + } + + ret = esp_wifi_adapter_init(); + if (ret) + { + nerr("ERROR: Initialize Wi-Fi adapter error: %d\n", ret); + netdev_unregister(&priv->dev); + return ret; + } + + ret = esp_wifi_sta_register_recv_cb(wlan_rx_done); + if (ret) + { + DEBUGASSERT(0); + } + + ret = esp_wifi_sta_register_txdone_cb(wlan_tx_done); + if (ret) + { + DEBUGASSERT(0); + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32c3_wlan_sta_initialize + * + * Description: + * Initialize the ESP32-C3 WLAN station netcard driver + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int esp32c3_wlan_sta_initialize(void) +{ + return esp32c3_net_initialize(WLAN_STA_DEVNO); +} diff --git a/arch/risc-v/src/esp32c3/esp32c3_wlan.h b/arch/risc-v/src/esp32c3/esp32c3_wlan.h new file mode 100644 index 0000000000..de93c468a1 --- /dev/null +++ b/arch/risc-v/src/esp32c3/esp32c3_wlan.h @@ -0,0 +1,67 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/esp32c3_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_RISCV_SRC_ESP32C3_ESP32C3_WLAN_H +#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_WLAN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32c3_wlan_sta_initialize + * + * Description: + * Initialize the ESP32-C3 WLAN station netcard driver + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int esp32c3_wlan_sta_initialize(void); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_WLAN_H */ diff --git a/arch/risc-v/src/esp32c3/hardware/esp32c3_syscon.h b/arch/risc-v/src/esp32c3/hardware/esp32c3_syscon.h new file mode 100644 index 0000000000..568271cc33 --- /dev/null +++ b/arch/risc-v/src/esp32c3/hardware/esp32c3_syscon.h @@ -0,0 +1,644 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/hardware/esp32c3_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_RISCV_SRC_ESP32C3_HARDWARE_ESP32C3_SYSCON_H +#define __ARCH_RISCV_SRC_ESP32C3_HARDWARE_ESP32C3_SYSCON_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "esp32c3_memorymap.h" +#include "esp32c3_soc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define SYSCON_SYSCLK_CONF_REG (DR_REG_SYSCON_BASE + 0x000) + +/* SYSCON_SOC_CLK_SEL : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ + +#define SYSCON_SOC_CLK_SEL 0x00000003 +#define SYSCON_SOC_CLK_SEL_M ((SYSCON_SOC_CLK_SEL_V) << (SYSCON_SOC_CLK_SEL_S)) +#define SYSCON_SOC_CLK_SEL_V 0x3 +#define SYSCON_SOC_CLK_SEL_S 14 + +/* 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 + 0x004) + +/* 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 + 0x008) + +/* 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 + 0x00C) + +/* 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 + 0x010) + +/* 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 + 0x014) + +/* 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 + 0x018) + +/* 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 - 0, 1, 2, 3, 6, 7, 8, 9, 10, 15, 19, 20, 21 + * Bit15 not included here because of the bit now can't be cleared + */ + +#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, 3, 6, 7, 8, 9 + */ + +#define SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M 0x78078F + +/* Digital team to check */ + +/* 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_UNUSED_BIT5 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_BB_REG_RST (BIT(13)) +#define SYSTEM_PWR_REG_RST (BIT(12)) +#define SYSTEM_BLE_REG_RST (BIT(11)) +#define SYSTEM_RW_BTLP_RST (BIT(10)) +#define SYSTEM_RW_BTMAC_RST (BIT(9)) +#define SYSTEM_MACPWR_RST (BIT(8)) +#define SYSTEM_EMAC_RST (BIT(7)) +#define SYSTEM_SDIO_RST (BIT(5)) +#define SYSTEM_BTMAC_RST (BIT(4)) +#define SYSTEM_BT_RST (BIT(3)) +#define SYSTEM_MAC_RST (BIT(2)) +#define SYSTEM_FE_RST (BIT(1)) +#define SYSTEM_BB_RST (BIT(0)) + +#define SYSCON_HOST_INF_SEL_REG (DR_REG_SYSCON_BASE + 0x01C) + +/* 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 + 0x020) + +/* 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_FLASH_ACE0_ATTR_REG (DR_REG_SYSCON_BASE + 0x024) + +/* SYSCON_FLASH_ACE0_ATTR : R/W ;bitpos:[7:0] ;default: 8'hff ; */ + +#define SYSCON_FLASH_ACE0_ATTR 0x000000FF +#define SYSCON_FLASH_ACE0_ATTR_M ((SYSCON_FLASH_ACE0_ATTR_V) << (SYSCON_FLASH_ACE0_ATTR_S)) +#define SYSCON_FLASH_ACE0_ATTR_V 0xFF +#define SYSCON_FLASH_ACE0_ATTR_S 0 + +#define SYSCON_FLASH_ACE1_ATTR_REG (DR_REG_SYSCON_BASE + 0x028) + +/* SYSCON_FLASH_ACE1_ATTR : R/W ;bitpos:[7:0] ;default: 8'hff ; */ + +#define SYSCON_FLASH_ACE1_ATTR 0x000000FF +#define SYSCON_FLASH_ACE1_ATTR_M ((SYSCON_FLASH_ACE1_ATTR_V) << (SYSCON_FLASH_ACE1_ATTR_S)) +#define SYSCON_FLASH_ACE1_ATTR_V 0xFF +#define SYSCON_FLASH_ACE1_ATTR_S 0 + +#define SYSCON_FLASH_ACE2_ATTR_REG (DR_REG_SYSCON_BASE + 0x02C) + +/* SYSCON_FLASH_ACE2_ATTR : R/W ;bitpos:[7:0] ;default: 8'hff ; */ + +#define SYSCON_FLASH_ACE2_ATTR 0x000000FF +#define SYSCON_FLASH_ACE2_ATTR_M ((SYSCON_FLASH_ACE2_ATTR_V) << (SYSCON_FLASH_ACE2_ATTR_S)) +#define SYSCON_FLASH_ACE2_ATTR_V 0xFF +#define SYSCON_FLASH_ACE2_ATTR_S 0 + +#define SYSCON_FLASH_ACE3_ATTR_REG (DR_REG_SYSCON_BASE + 0x030) + +/* SYSCON_FLASH_ACE3_ATTR : R/W ;bitpos:[7:0] ;default: 8'hff ; */ + +#define SYSCON_FLASH_ACE3_ATTR 0x000000FF +#define SYSCON_FLASH_ACE3_ATTR_M ((SYSCON_FLASH_ACE3_ATTR_V) << (SYSCON_FLASH_ACE3_ATTR_S)) +#define SYSCON_FLASH_ACE3_ATTR_V 0xFF +#define SYSCON_FLASH_ACE3_ATTR_S 0 + +#define SYSCON_FLASH_ACE0_ADDR_REG (DR_REG_SYSCON_BASE + 0x034) + +/* 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 + 0x038) + +/* 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 + 0x03C) + +/* 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 + 0x040) + +/* 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 + 0x044) + +/* 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 + 0x048) + +/* 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 + 0x04C) + +/* 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 + 0x050) + +/* 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 + 0x054) + +/* SYSCON_SRAM_ACE0_ATTR : R/W ;bitpos:[7:0] ;default: 8'hff ; */ + +#define SYSCON_SRAM_ACE0_ATTR 0x000000FF +#define SYSCON_SRAM_ACE0_ATTR_M ((SYSCON_SRAM_ACE0_ATTR_V) << (SYSCON_SRAM_ACE0_ATTR_S)) +#define SYSCON_SRAM_ACE0_ATTR_V 0xFF +#define SYSCON_SRAM_ACE0_ATTR_S 0 + +#define SYSCON_SRAM_ACE1_ATTR_REG (DR_REG_SYSCON_BASE + 0x058) + +/* SYSCON_SRAM_ACE1_ATTR : R/W ;bitpos:[7:0] ;default: 8'hff ; */ + +#define SYSCON_SRAM_ACE1_ATTR 0x000000FF +#define SYSCON_SRAM_ACE1_ATTR_M ((SYSCON_SRAM_ACE1_ATTR_V) << (SYSCON_SRAM_ACE1_ATTR_S)) +#define SYSCON_SRAM_ACE1_ATTR_V 0xFF +#define SYSCON_SRAM_ACE1_ATTR_S 0 + +#define SYSCON_SRAM_ACE2_ATTR_REG (DR_REG_SYSCON_BASE + 0x05C) + +/* SYSCON_SRAM_ACE2_ATTR : R/W ;bitpos:[7:0] ;default: 8'hff ; */ + +#define SYSCON_SRAM_ACE2_ATTR 0x000000FF +#define SYSCON_SRAM_ACE2_ATTR_M ((SYSCON_SRAM_ACE2_ATTR_V) << (SYSCON_SRAM_ACE2_ATTR_S)) +#define SYSCON_SRAM_ACE2_ATTR_V 0xFF +#define SYSCON_SRAM_ACE2_ATTR_S 0 + +#define SYSCON_SRAM_ACE3_ATTR_REG (DR_REG_SYSCON_BASE + 0x060) + +/* SYSCON_SRAM_ACE3_ATTR : R/W ;bitpos:[7:0] ;default: 8'hff ; */ + +#define SYSCON_SRAM_ACE3_ATTR 0x000000FF +#define SYSCON_SRAM_ACE3_ATTR_M ((SYSCON_SRAM_ACE3_ATTR_V) << (SYSCON_SRAM_ACE3_ATTR_S)) +#define SYSCON_SRAM_ACE3_ATTR_V 0xFF +#define SYSCON_SRAM_ACE3_ATTR_S 0 + +#define SYSCON_SRAM_ACE0_ADDR_REG (DR_REG_SYSCON_BASE + 0x064) + +/* 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 + 0x068) + +/* 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 + 0x06C) + +/* 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 + 0x070) + +/* 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 + 0x074) + +/* 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 + 0x078) + +/* 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 + 0x07C) + +/* 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 + 0x080) + +/* 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 + 0x084) + +/* 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 + 0x088) + +/* 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 + 0x08C) + +/* 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 + 0x090) + +/* 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 + 0x094) + +/* 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 + 0x098) + +/* 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_DATE_REG (DR_REG_SYSCON_BASE + 0x3FC) + +/* SYSCON_DATE : R/W ;bitpos:[31:0] ;default: 32'h1907100 ; */ + +#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_RISCV_SRC_ESP32C3_HARDWARE_ESP32C3_SYSCON_H */ diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig new file mode 100644 index 0000000000..c92539467f --- /dev/null +++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig @@ -0,0 +1,66 @@ +# +# 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_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_NSH_CMDPARMS is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32c3-devkit" +CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y +CONFIG_ARCH_CHIP="esp32c3" +CONFIG_ARCH_CHIP_ESP32C3=y +CONFIG_ARCH_CHIP_ESP32C3WROOM02=y +CONFIG_ARCH_INTERRUPTSTACK=1536 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DRIVERS_IEEE80211=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_ESP32C3_WIRELESS=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_NAME_MAX=48 +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_PHY_IOCTL=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1514 +CONFIG_NET_ICMP=y +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_TCP=y +CONFIG_NET_UDP=y +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PTHREAD_MUTEX_TYPES=y +CONFIG_RAW_BINARY=y +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_UART0_SERIAL_CONSOLE=y +CONFIG_USER_ENTRYPOINT="nsh_main" +CONFIG_WIRELESS=y +CONFIG_WIRELESS_WAPI=y +CONFIG_WIRELESS_WAPI_CMDTOOL=y +CONFIG_WIRELESS_WAPI_STACKSIZE=4096 diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3.ld b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3.ld index a29d8e35b1..90dbd7a175 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3.ld +++ b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3.ld @@ -36,6 +36,11 @@ SECTIONS *(.iram1) *(.iram1.*) + *(.wifi0iram .wifi0iram.*) + *(.wifirxiram .wifirxiram.*) + *(.wifislpiram .wifislpiram.*) + *(.wifislprxiram .wifislprxiram.*) + } >iram0_0_seg /* This section is required to skip .iram0.text area because iram0_0_seg @@ -134,6 +139,9 @@ SECTIONS *(.rodata) *(.rodata.*) + + *(.srodata.*) + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld index 91e1cf5fb9..c9680ca72c 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld +++ b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld @@ -1527,7 +1527,6 @@ lmacReachShortLimit = 0x4000161c; lmacRecycleMPDU = 0x40001620; lmacRxDone = 0x40001624; lmacSetTxFrame = 0x40001628; -lmacTxDone = 0x4000162c; lmacTxFrame = 0x40001630; mac_tx_set_duration = 0x40001634; mac_tx_set_htsig = 0x40001638; @@ -1933,3 +1932,28 @@ rom_pll_correct_dcap = 0x40001b1c; rom_phy_en_hw_set_freq = 0x40001b20; rom_phy_dis_hw_set_freq = 0x40001b24; rom_pll_vol_cal = 0x40001b28; + +/*************************************** + Group memory and string + ***************************************/ + +memset = 0x40000354; +memcpy = 0x40000358; +memmove = 0x4000035c; +memcmp = 0x40000360; +memccpy = 0x400003c4; +memchr = 0x400003c8; +memrchr = 0x400003cc; +strcpy = 0x40000364; +strncpy = 0x40000368; +strcmp = 0x4000036c; +strncmp = 0x40000370; +strlen = 0x40000374; +strstr = 0x40000378; +bzero = 0x4000037c; + +/*************************************** + Redefine functions + ***************************************/ + +PROVIDE ( esp_rom_delay_us = ets_delay_us ); diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c index acc5965851..029d81ef2a 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c +++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c @@ -37,6 +37,8 @@ #include +#include "esp32c3_wlan.h" + #include "esp32c3-devkit.h" /**************************************************************************** @@ -143,6 +145,15 @@ int esp32c3_bringup(void) } #endif +#ifdef CONFIG_ESP32C3_WIRELESS + ret = esp32c3_wlan_sta_initialize(); + if (ret) + { + syslog(LOG_ERR, "ERROR: Failed to initialize Wi-Fi\n"); + return ret; + } +#endif + /* If we got here then perhaps not all initialization was successful, but * at least enough succeeded to bring-up NSH with perhaps reduced * capabilities. diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_timer.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_timer.c index b88b3d37a5..dc37c220ff 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_timer.c +++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_timer.c @@ -56,7 +56,7 @@ int board_tim_init(void) { int ret = OK; -#ifdef CONFIG_ESP32C3_TIMER0 +#if defined(CONFIG_ESP32C3_TIMER0) && !defined(CONFIG_ESP32C3_RT_TIMER) ret = esp32c3_timer_initialize("/dev/timer0", ESP32C3_TIMER0); if (ret < 0) {